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

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

unix.superglobalmegacorp.com

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