Annotation of quake2/linux/vid_so.c, revision 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.