Annotation of quake2/linux/vid_so.c, revision 1.1.1.1

1.1       root        1: // Main windowed and fullscreen graphics interface module. This module
                      2: // is used for both the software and OpenGL rendering versions of the
                      3: // Quake refresh engine.
                      4: 
                      5: #define SO_FILE "/etc/quake2.conf"
                      6: 
                      7: #include <assert.h>
                      8: #include <dlfcn.h> // ELF dl loader
                      9: #include <sys/stat.h>
                     10: #include <unistd.h>
                     11: #include <errno.h>
                     12: 
                     13: #include "../client/client.h"
                     14: 
                     15: #include "../linux/rw_linux.h"
                     16: 
                     17: // Structure containing functions exported from refresh DLL
                     18: refexport_t    re;
                     19: 
                     20: // Console variables that we need to access from this module
                     21: cvar_t         *vid_gamma;
                     22: cvar_t         *vid_ref;                       // Name of Refresh DLL loaded
                     23: cvar_t         *vid_xpos;                      // X coordinate of window position
                     24: cvar_t         *vid_ypos;                      // Y coordinate of window position
                     25: cvar_t         *vid_fullscreen;
                     26: 
                     27: // Global variables used internally by this module
                     28: viddef_t       viddef;                         // global video state; used by other modules
                     29: void           *reflib_library;                // Handle to refresh DLL 
                     30: qboolean       reflib_active = 0;
                     31: 
                     32: #define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
                     33: 
                     34: /** KEYBOARD **************************************************************/
                     35: 
                     36: void Do_Key_Event(int key, qboolean down);
                     37: 
                     38: void (*KBD_Update_fp)(void);
                     39: void (*KBD_Init_fp)(Key_Event_fp_t fp);
                     40: void (*KBD_Close_fp)(void);
                     41: 
                     42: /** MOUSE *****************************************************************/
                     43: 
                     44: in_state_t in_state;
                     45: 
                     46: void (*RW_IN_Init_fp)(in_state_t *in_state_p);
                     47: void (*RW_IN_Shutdown_fp)(void);
                     48: void (*RW_IN_Activate_fp)(qboolean active);
                     49: void (*RW_IN_Commands_fp)(void);
                     50: void (*RW_IN_Move_fp)(usercmd_t *cmd);
                     51: void (*RW_IN_Frame_fp)(void);
                     52: 
                     53: void Real_IN_Init (void);
                     54: 
                     55: /*
                     56: ==========================================================================
                     57: 
                     58: DLL GLUE
                     59: 
                     60: ==========================================================================
                     61: */
                     62: 
                     63: #define        MAXPRINTMSG     4096
                     64: void VID_Printf (int print_level, char *fmt, ...)
                     65: {
                     66:        va_list         argptr;
                     67:        char            msg[MAXPRINTMSG];
                     68:        static qboolean inupdate;
                     69:        
                     70:        va_start (argptr,fmt);
                     71:        vsprintf (msg,fmt,argptr);
                     72:        va_end (argptr);
                     73: 
                     74:        if (print_level == PRINT_ALL)
                     75:                Com_Printf ("%s", msg);
                     76:        else
                     77:                Com_DPrintf ("%s", msg);
                     78: }
                     79: 
                     80: void VID_Error (int err_level, char *fmt, ...)
                     81: {
                     82:        va_list         argptr;
                     83:        char            msg[MAXPRINTMSG];
                     84:        static qboolean inupdate;
                     85:        
                     86:        va_start (argptr,fmt);
                     87:        vsprintf (msg,fmt,argptr);
                     88:        va_end (argptr);
                     89: 
                     90:        Com_Error (err_level,"%s", msg);
                     91: }
                     92: 
                     93: //==========================================================================
                     94: 
                     95: /*
                     96: ============
                     97: VID_Restart_f
                     98: 
                     99: Console command to re-start the video mode and refresh DLL. We do this
                    100: simply by setting the modified flag for the vid_ref variable, which will
                    101: cause the entire video mode and refresh DLL to be reset on the next frame.
                    102: ============
                    103: */
                    104: void VID_Restart_f (void)
                    105: {
                    106:        vid_ref->modified = true;
                    107: }
                    108: 
                    109: /*
                    110: ** VID_GetModeInfo
                    111: */
                    112: typedef struct vidmode_s
                    113: {
                    114:        const char *description;
                    115:        int         width, height;
                    116:        int         mode;
                    117: } vidmode_t;
                    118: 
                    119: vidmode_t vid_modes[] =
                    120: {
                    121:        { "Mode 0: 320x240",   320, 240,   0 },
                    122:        { "Mode 1: 400x300",   400, 300,   1 },
                    123:        { "Mode 2: 512x384",   512, 384,   2 },
                    124:        { "Mode 3: 640x480",   640, 480,   3 },
                    125:        { "Mode 4: 800x600",   800, 600,   4 },
                    126:        { "Mode 5: 960x720",   960, 720,   5 },
                    127:        { "Mode 6: 1024x768",  1024, 768,  6 },
                    128:        { "Mode 7: 1152x864",  1152, 864,  7 },
                    129:        { "Mode 8: 1280x1024",  1280, 1024, 8 },
                    130:        { "Mode 9: 1600x1200", 1600, 1200, 9 }
                    131: };
                    132: 
                    133: qboolean VID_GetModeInfo( int *width, int *height, int mode )
                    134: {
                    135:        if ( mode < 0 || mode >= VID_NUM_MODES )
                    136:                return false;
                    137: 
                    138:        *width  = vid_modes[mode].width;
                    139:        *height = vid_modes[mode].height;
                    140: 
                    141:        return true;
                    142: }
                    143: 
                    144: /*
                    145: ** VID_NewWindow
                    146: */
                    147: void VID_NewWindow ( int width, int height)
                    148: {
                    149:        viddef.width  = width;
                    150:        viddef.height = height;
                    151: }
                    152: 
                    153: void VID_FreeReflib (void)
                    154: {
                    155:        if (reflib_library) {
                    156:                if (KBD_Close_fp)
                    157:                        KBD_Close_fp();
                    158:                if (RW_IN_Shutdown_fp)
                    159:                        RW_IN_Shutdown_fp();
                    160:                dlclose(reflib_library);
                    161:        }
                    162: 
                    163:        KBD_Init_fp = NULL;
                    164:        KBD_Update_fp = NULL;
                    165:        KBD_Close_fp = NULL;
                    166:        RW_IN_Init_fp = NULL;
                    167:        RW_IN_Shutdown_fp = NULL;
                    168:        RW_IN_Activate_fp = NULL;
                    169:        RW_IN_Commands_fp = NULL;
                    170:        RW_IN_Move_fp = NULL;
                    171:        RW_IN_Frame_fp = NULL;
                    172: 
                    173:        memset (&re, 0, sizeof(re));
                    174:        reflib_library = NULL;
                    175:        reflib_active  = false;
                    176: }
                    177: 
                    178: /*
                    179: ==============
                    180: VID_LoadRefresh
                    181: ==============
                    182: */
                    183: qboolean VID_LoadRefresh( char *name )
                    184: {
                    185:        refimport_t     ri;
                    186:        GetRefAPI_t     GetRefAPI;
                    187:        char    fn[MAX_OSPATH];
                    188:        struct stat st;
                    189:        extern uid_t saved_euid;
                    190:        FILE *fp;
                    191:        
                    192:        if ( reflib_active )
                    193:        {
                    194:                if (KBD_Close_fp)
                    195:                        KBD_Close_fp();
                    196:                if (RW_IN_Shutdown_fp)
                    197:                        RW_IN_Shutdown_fp();
                    198:                KBD_Close_fp = NULL;
                    199:                RW_IN_Shutdown_fp = NULL;
                    200:                re.Shutdown();
                    201:                VID_FreeReflib ();
                    202:        }
                    203: 
                    204:        Com_Printf( "------- Loading %s -------\n", name );
                    205: 
                    206:        //regain root
                    207:        seteuid(saved_euid);
                    208: 
                    209:        if ((fp = fopen(SO_FILE, "r")) == NULL) {
                    210:                Com_Printf( "LoadLibrary(\"%s\") failed: can't open " SO_FILE " (required for location of ref libraries)\n", name);
                    211:                return false;
                    212:        }
                    213:        fgets(fn, sizeof(fn), fp);
                    214:        fclose(fp);
                    215:        if (*fn && fn[strlen(fn) - 1] == '\n')
                    216:                fn[strlen(fn) - 1] = 0;
                    217: 
                    218:        strcat(fn, "/");
                    219:        strcat(fn, name);
                    220: 
                    221:        // permission checking
                    222:        if (strstr(fn, "softx") == NULL) { // softx doesn't require root
                    223:                if (stat(fn, &st) == -1) {
                    224:                        Com_Printf( "LoadLibrary(\"%s\") failed: %s\n", name, strerror(errno));
                    225:                        return false;
                    226:                }
                    227:                if (st.st_uid != 0) {
                    228:                        Com_Printf( "LoadLibrary(\"%s\") failed: ref is not owned by root\n", name);
                    229:                        return false;
                    230:                }
                    231: #if 0
                    232:                if ((st.st_mode & 0777) & ~0700) {
                    233:                        Com_Printf( "LoadLibrary(\"%s\") failed: invalid permissions, must be 700 for security considerations\n", name);
                    234:                        return false;
                    235:                }
                    236: #endif
                    237:        } else {
                    238:                // softx requires we give up root now
                    239:                setreuid(getuid(), getuid());
                    240:                setegid(getgid());
                    241:        }
                    242: 
                    243:        if ( ( reflib_library = dlopen( fn, RTLD_NOW ) ) == 0 )
                    244:        {
                    245:                Com_Printf( "LoadLibrary(\"%s\") failed: %s\n", name , dlerror());
                    246:                return false;
                    247:        }
                    248: 
                    249:        ri.Cmd_AddCommand = Cmd_AddCommand;
                    250:        ri.Cmd_RemoveCommand = Cmd_RemoveCommand;
                    251:        ri.Cmd_Argc = Cmd_Argc;
                    252:        ri.Cmd_Argv = Cmd_Argv;
                    253:        ri.Cmd_ExecuteText = Cbuf_ExecuteText;
                    254:        ri.Con_Printf = VID_Printf;
                    255:        ri.Sys_Error = VID_Error;
                    256:        ri.FS_LoadFile = FS_LoadFile;
                    257:        ri.FS_FreeFile = FS_FreeFile;
                    258:        ri.FS_Gamedir = FS_Gamedir;
                    259:        ri.Cvar_Get = Cvar_Get;
                    260:        ri.Cvar_Set = Cvar_Set;
                    261:        ri.Cvar_SetValue = Cvar_SetValue;
                    262:        ri.Vid_GetModeInfo = VID_GetModeInfo;
                    263:        ri.Vid_MenuInit = VID_MenuInit;
                    264:        ri.Vid_NewWindow = VID_NewWindow;
                    265: 
                    266:        if ( ( GetRefAPI = (void *) dlsym( reflib_library, "GetRefAPI" ) ) == 0 )
                    267:                Com_Error( ERR_FATAL, "dlsym failed on %s", name );
                    268: 
                    269:        re = GetRefAPI( ri );
                    270: 
                    271:        if (re.api_version != API_VERSION)
                    272:        {
                    273:                VID_FreeReflib ();
                    274:                Com_Error (ERR_FATAL, "%s has incompatible api_version", name);
                    275:        }
                    276: 
                    277:        /* Init IN (Mouse) */
                    278:        in_state.IN_CenterView_fp = IN_CenterView;
                    279:        in_state.Key_Event_fp = Do_Key_Event;
                    280:        in_state.viewangles = cl.viewangles;
                    281:        in_state.in_strafe_state = &in_strafe.state;
                    282: 
                    283:        if ((RW_IN_Init_fp = dlsym(reflib_library, "RW_IN_Init")) == NULL ||
                    284:                (RW_IN_Shutdown_fp = dlsym(reflib_library, "RW_IN_Shutdown")) == NULL ||
                    285:                (RW_IN_Activate_fp = dlsym(reflib_library, "RW_IN_Activate")) == NULL ||
                    286:                (RW_IN_Commands_fp = dlsym(reflib_library, "RW_IN_Commands")) == NULL ||
                    287:                (RW_IN_Move_fp = dlsym(reflib_library, "RW_IN_Move")) == NULL ||
                    288:                (RW_IN_Frame_fp = dlsym(reflib_library, "RW_IN_Frame")) == NULL)
                    289:                Sys_Error("No RW_IN functions in REF.\n");
                    290: 
                    291:        Real_IN_Init();
                    292: 
                    293:        if ( re.Init( 0, 0 ) == -1 )
                    294:        {
                    295:                re.Shutdown();
                    296:                VID_FreeReflib ();
                    297:                return false;
                    298:        }
                    299: 
                    300:        /* Init KBD */
                    301: #if 1
                    302:        if ((KBD_Init_fp = dlsym(reflib_library, "KBD_Init")) == NULL ||
                    303:                (KBD_Update_fp = dlsym(reflib_library, "KBD_Update")) == NULL ||
                    304:                (KBD_Close_fp = dlsym(reflib_library, "KBD_Close")) == NULL)
                    305:                Sys_Error("No KBD functions in REF.\n");
                    306: #else
                    307:        {
                    308:                void KBD_Init(void);
                    309:                void KBD_Update(void);
                    310:                void KBD_Close(void);
                    311: 
                    312:                KBD_Init_fp = KBD_Init;
                    313:                KBD_Update_fp = KBD_Update;
                    314:                KBD_Close_fp = KBD_Close;
                    315:        }
                    316: #endif
                    317:        KBD_Init_fp(Do_Key_Event);
                    318: 
                    319:        // give up root now
                    320:        setreuid(getuid(), getuid());
                    321:        setegid(getgid());
                    322: 
                    323:        Com_Printf( "------------------------------------\n");
                    324:        reflib_active = true;
                    325:        return true;
                    326: }
                    327: 
                    328: /*
                    329: ============
                    330: VID_CheckChanges
                    331: 
                    332: This function gets called once just before drawing each frame, and it's sole purpose in life
                    333: is to check to see if any of the video mode parameters have changed, and if they have to 
                    334: update the rendering DLL and/or video mode to match.
                    335: ============
                    336: */
                    337: void VID_CheckChanges (void)
                    338: {
                    339:        char name[100];
                    340:        cvar_t *sw_mode;
                    341: 
                    342:        if ( vid_ref->modified )
                    343:        {
                    344:                S_StopAllSounds();
                    345:        }
                    346: 
                    347:        while (vid_ref->modified)
                    348:        {
                    349:                /*
                    350:                ** refresh has changed
                    351:                */
                    352:                vid_ref->modified = false;
                    353:                vid_fullscreen->modified = true;
                    354:                cl.refresh_prepped = false;
                    355:                cls.disable_screen = true;
                    356: 
                    357:                sprintf( name, "ref_%s.so", vid_ref->string );
                    358:                if ( !VID_LoadRefresh( name ) )
                    359:                {
                    360:                        if ( strcmp (vid_ref->string, "soft") == 0 ||
                    361:                                strcmp (vid_ref->string, "softx") == 0 ) {
                    362: Com_Printf("Refresh failed\n");
                    363:                                sw_mode = Cvar_Get( "sw_mode", "0", 0 );
                    364:                                if (sw_mode->value != 0) {
                    365: Com_Printf("Trying mode 0\n");
                    366:                                        Cvar_SetValue("sw_mode", 0);
                    367:                                        if ( !VID_LoadRefresh( name ) )
                    368:                                                Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!");
                    369:                                } else
                    370:                                        Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!");
                    371:                        }
                    372: 
                    373:                        Cvar_Set( "vid_ref", "soft" );
                    374: 
                    375:                        /*
                    376:                        ** drop the console if we fail to load a refresh
                    377:                        */
                    378:                        if ( cls.key_dest != key_console )
                    379:                        {
                    380:                                Con_ToggleConsole_f();
                    381:                        }
                    382:                }
                    383:                cls.disable_screen = false;
                    384:        }
                    385: 
                    386: }
                    387: 
                    388: /*
                    389: ============
                    390: VID_Init
                    391: ============
                    392: */
                    393: void VID_Init (void)
                    394: {
                    395:        /* Create the video variables so we know how to start the graphics drivers */
                    396:        // if DISPLAY is defined, try X
                    397:        if (getenv("DISPLAY"))
                    398:                vid_ref = Cvar_Get ("vid_ref", "softx", CVAR_ARCHIVE);
                    399:        else
                    400:                vid_ref = Cvar_Get ("vid_ref", "soft", CVAR_ARCHIVE);
                    401:        vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
                    402:        vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
                    403:        vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE);
                    404:        vid_gamma = Cvar_Get( "vid_gamma", "1", CVAR_ARCHIVE );
                    405: 
                    406:        /* Add some console commands that we want to handle */
                    407:        Cmd_AddCommand ("vid_restart", VID_Restart_f);
                    408: 
                    409:        /* Disable the 3Dfx splash screen */
                    410:        putenv("FX_GLIDE_NO_SPLASH=0");
                    411:                
                    412:        /* Start the graphics mode and load refresh DLL */
                    413:        VID_CheckChanges();
                    414: }
                    415: 
                    416: /*
                    417: ============
                    418: VID_Shutdown
                    419: ============
                    420: */
                    421: void VID_Shutdown (void)
                    422: {
                    423:        if ( reflib_active )
                    424:        {
                    425:                if (KBD_Close_fp)
                    426:                        KBD_Close_fp();
                    427:                if (RW_IN_Shutdown_fp)
                    428:                        RW_IN_Shutdown_fp();
                    429:                KBD_Close_fp = NULL;
                    430:                RW_IN_Shutdown_fp = NULL;
                    431:                re.Shutdown ();
                    432:                VID_FreeReflib ();
                    433:        }
                    434: }
                    435: 
                    436: 
                    437: /*****************************************************************************/
                    438: /* INPUT                                                                     */
                    439: /*****************************************************************************/
                    440: 
                    441: cvar_t *in_joystick;
                    442: 
                    443: // This if fake, it's acutally done by the Refresh load
                    444: void IN_Init (void)
                    445: {
                    446:        in_joystick     = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE);
                    447: }
                    448: 
                    449: void Real_IN_Init (void)
                    450: {
                    451:        if (RW_IN_Init_fp)
                    452:                RW_IN_Init_fp(&in_state);
                    453: }
                    454: 
                    455: void IN_Shutdown (void)
                    456: {
                    457:        if (RW_IN_Shutdown_fp)
                    458:                RW_IN_Shutdown_fp();
                    459: }
                    460: 
                    461: void IN_Commands (void)
                    462: {
                    463:        if (RW_IN_Commands_fp)
                    464:                RW_IN_Commands_fp();
                    465: }
                    466: 
                    467: void IN_Move (usercmd_t *cmd)
                    468: {
                    469:        if (RW_IN_Move_fp)
                    470:                RW_IN_Move_fp(cmd);
                    471: }
                    472: 
                    473: void IN_Frame (void)
                    474: {
                    475:        if (RW_IN_Frame_fp)
                    476:                RW_IN_Frame_fp();
                    477: }
                    478: 
                    479: void IN_Activate (qboolean active)
                    480: {
                    481:        if (RW_IN_Activate_fp)
                    482:                RW_IN_Activate_fp(active);
                    483: }
                    484: 
                    485: void Do_Key_Event(int key, qboolean down)
                    486: {
                    487:        Key_Event(key, down, Sys_Milliseconds());
                    488: }
                    489: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.