123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- // Main windowed and fullscreen graphics interface module. This module
- // is used for both the software and OpenGL rendering versions of the
- // Quake refresh engine.
- #define SO_FILE "/etc/quake2.conf"
- #include <assert.h>
- #include <dlfcn.h> // ELF dl loader
- #include <sys/stat.h>
- #include <unistd.h>
- #include <errno.h>
- #include "../client/client.h"
- #include "../linux/rw_linux.h"
- // Structure containing functions exported from refresh DLL
- refexport_t re;
- // Console variables that we need to access from this module
- cvar_t *vid_gamma;
- cvar_t *vid_ref; // Name of Refresh DLL loaded
- cvar_t *vid_xpos; // X coordinate of window position
- cvar_t *vid_ypos; // Y coordinate of window position
- cvar_t *vid_fullscreen;
- // Global variables used internally by this module
- viddef_t viddef; // global video state; used by other modules
- void *reflib_library; // Handle to refresh DLL
- qboolean reflib_active = 0;
- #define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
- /** KEYBOARD **************************************************************/
- void Do_Key_Event(int key, qboolean down);
- void (*KBD_Update_fp)(void);
- void (*KBD_Init_fp)(Key_Event_fp_t fp);
- void (*KBD_Close_fp)(void);
- /** MOUSE *****************************************************************/
- in_state_t in_state;
- void (*RW_IN_Init_fp)(in_state_t *in_state_p);
- void (*RW_IN_Shutdown_fp)(void);
- void (*RW_IN_Activate_fp)(qboolean active);
- void (*RW_IN_Commands_fp)(void);
- void (*RW_IN_Move_fp)(usercmd_t *cmd);
- void (*RW_IN_Frame_fp)(void);
- void Real_IN_Init (void);
- /*
- ==========================================================================
- DLL GLUE
- ==========================================================================
- */
- #define MAXPRINTMSG 4096
- void VID_Printf (int print_level, char *fmt, ...)
- {
- va_list argptr;
- char msg[MAXPRINTMSG];
- static qboolean inupdate;
-
- va_start (argptr,fmt);
- vsprintf (msg,fmt,argptr);
- va_end (argptr);
- if (print_level == PRINT_ALL)
- Com_Printf ("%s", msg);
- else
- Com_DPrintf ("%s", msg);
- }
- void VID_Error (int err_level, char *fmt, ...)
- {
- va_list argptr;
- char msg[MAXPRINTMSG];
- static qboolean inupdate;
-
- va_start (argptr,fmt);
- vsprintf (msg,fmt,argptr);
- va_end (argptr);
- Com_Error (err_level,"%s", msg);
- }
- //==========================================================================
- /*
- ============
- VID_Restart_f
- Console command to re-start the video mode and refresh DLL. We do this
- simply by setting the modified flag for the vid_ref variable, which will
- cause the entire video mode and refresh DLL to be reset on the next frame.
- ============
- */
- void VID_Restart_f (void)
- {
- vid_ref->modified = true;
- }
- /*
- ** VID_GetModeInfo
- */
- typedef struct vidmode_s
- {
- const char *description;
- int width, height;
- int mode;
- } vidmode_t;
- vidmode_t vid_modes[] =
- {
- { "Mode 0: 320x240", 320, 240, 0 },
- { "Mode 1: 400x300", 400, 300, 1 },
- { "Mode 2: 512x384", 512, 384, 2 },
- { "Mode 3: 640x480", 640, 480, 3 },
- { "Mode 4: 800x600", 800, 600, 4 },
- { "Mode 5: 960x720", 960, 720, 5 },
- { "Mode 6: 1024x768", 1024, 768, 6 },
- { "Mode 7: 1152x864", 1152, 864, 7 },
- { "Mode 8: 1280x1024", 1280, 1024, 8 },
- { "Mode 9: 1600x1200", 1600, 1200, 9 }
- };
- qboolean VID_GetModeInfo( int *width, int *height, int mode )
- {
- if ( mode < 0 || mode >= VID_NUM_MODES )
- return false;
- *width = vid_modes[mode].width;
- *height = vid_modes[mode].height;
- return true;
- }
- /*
- ** VID_NewWindow
- */
- void VID_NewWindow ( int width, int height)
- {
- viddef.width = width;
- viddef.height = height;
- }
- void VID_FreeReflib (void)
- {
- if (reflib_library) {
- if (KBD_Close_fp)
- KBD_Close_fp();
- if (RW_IN_Shutdown_fp)
- RW_IN_Shutdown_fp();
- dlclose(reflib_library);
- }
- KBD_Init_fp = NULL;
- KBD_Update_fp = NULL;
- KBD_Close_fp = NULL;
- RW_IN_Init_fp = NULL;
- RW_IN_Shutdown_fp = NULL;
- RW_IN_Activate_fp = NULL;
- RW_IN_Commands_fp = NULL;
- RW_IN_Move_fp = NULL;
- RW_IN_Frame_fp = NULL;
- memset (&re, 0, sizeof(re));
- reflib_library = NULL;
- reflib_active = false;
- }
- /*
- ==============
- VID_LoadRefresh
- ==============
- */
- qboolean VID_LoadRefresh( char *name )
- {
- refimport_t ri;
- GetRefAPI_t GetRefAPI;
- char fn[MAX_OSPATH];
- struct stat st;
- extern uid_t saved_euid;
- FILE *fp;
-
- if ( reflib_active )
- {
- if (KBD_Close_fp)
- KBD_Close_fp();
- if (RW_IN_Shutdown_fp)
- RW_IN_Shutdown_fp();
- KBD_Close_fp = NULL;
- RW_IN_Shutdown_fp = NULL;
- re.Shutdown();
- VID_FreeReflib ();
- }
- Com_Printf( "------- Loading %s -------\n", name );
- //regain root
- seteuid(saved_euid);
- if ((fp = fopen(SO_FILE, "r")) == NULL) {
- Com_Printf( "LoadLibrary(\"%s\") failed: can't open " SO_FILE " (required for location of ref libraries)\n", name);
- return false;
- }
- fgets(fn, sizeof(fn), fp);
- fclose(fp);
- if (*fn && fn[strlen(fn) - 1] == '\n')
- fn[strlen(fn) - 1] = 0;
- strcat(fn, "/");
- strcat(fn, name);
- // permission checking
- if (strstr(fn, "softx") == NULL) { // softx doesn't require root
- if (stat(fn, &st) == -1) {
- Com_Printf( "LoadLibrary(\"%s\") failed: %s\n", name, strerror(errno));
- return false;
- }
- if (st.st_uid != 0) {
- Com_Printf( "LoadLibrary(\"%s\") failed: ref is not owned by root\n", name);
- return false;
- }
- #if 0
- if ((st.st_mode & 0777) & ~0700) {
- Com_Printf( "LoadLibrary(\"%s\") failed: invalid permissions, must be 700 for security considerations\n", name);
- return false;
- }
- #endif
- } else {
- // softx requires we give up root now
- setreuid(getuid(), getuid());
- setegid(getgid());
- }
- if ( ( reflib_library = dlopen( fn, RTLD_NOW ) ) == 0 )
- {
- Com_Printf( "LoadLibrary(\"%s\") failed: %s\n", name , dlerror());
- return false;
- }
- ri.Cmd_AddCommand = Cmd_AddCommand;
- ri.Cmd_RemoveCommand = Cmd_RemoveCommand;
- ri.Cmd_Argc = Cmd_Argc;
- ri.Cmd_Argv = Cmd_Argv;
- ri.Cmd_ExecuteText = Cbuf_ExecuteText;
- ri.Con_Printf = VID_Printf;
- ri.Sys_Error = VID_Error;
- ri.FS_LoadFile = FS_LoadFile;
- ri.FS_FreeFile = FS_FreeFile;
- ri.FS_Gamedir = FS_Gamedir;
- ri.Cvar_Get = Cvar_Get;
- ri.Cvar_Set = Cvar_Set;
- ri.Cvar_SetValue = Cvar_SetValue;
- ri.Vid_GetModeInfo = VID_GetModeInfo;
- ri.Vid_MenuInit = VID_MenuInit;
- ri.Vid_NewWindow = VID_NewWindow;
- if ( ( GetRefAPI = (void *) dlsym( reflib_library, "GetRefAPI" ) ) == 0 )
- Com_Error( ERR_FATAL, "dlsym failed on %s", name );
- re = GetRefAPI( ri );
- if (re.api_version != API_VERSION)
- {
- VID_FreeReflib ();
- Com_Error (ERR_FATAL, "%s has incompatible api_version", name);
- }
- /* Init IN (Mouse) */
- in_state.IN_CenterView_fp = IN_CenterView;
- in_state.Key_Event_fp = Do_Key_Event;
- in_state.viewangles = cl.viewangles;
- in_state.in_strafe_state = &in_strafe.state;
- if ((RW_IN_Init_fp = dlsym(reflib_library, "RW_IN_Init")) == NULL ||
- (RW_IN_Shutdown_fp = dlsym(reflib_library, "RW_IN_Shutdown")) == NULL ||
- (RW_IN_Activate_fp = dlsym(reflib_library, "RW_IN_Activate")) == NULL ||
- (RW_IN_Commands_fp = dlsym(reflib_library, "RW_IN_Commands")) == NULL ||
- (RW_IN_Move_fp = dlsym(reflib_library, "RW_IN_Move")) == NULL ||
- (RW_IN_Frame_fp = dlsym(reflib_library, "RW_IN_Frame")) == NULL)
- Sys_Error("No RW_IN functions in REF.\n");
- Real_IN_Init();
- if ( re.Init( 0, 0 ) == -1 )
- {
- re.Shutdown();
- VID_FreeReflib ();
- return false;
- }
- /* Init KBD */
- #if 1
- if ((KBD_Init_fp = dlsym(reflib_library, "KBD_Init")) == NULL ||
- (KBD_Update_fp = dlsym(reflib_library, "KBD_Update")) == NULL ||
- (KBD_Close_fp = dlsym(reflib_library, "KBD_Close")) == NULL)
- Sys_Error("No KBD functions in REF.\n");
- #else
- {
- void KBD_Init(void);
- void KBD_Update(void);
- void KBD_Close(void);
- KBD_Init_fp = KBD_Init;
- KBD_Update_fp = KBD_Update;
- KBD_Close_fp = KBD_Close;
- }
- #endif
- KBD_Init_fp(Do_Key_Event);
- // give up root now
- setreuid(getuid(), getuid());
- setegid(getgid());
- Com_Printf( "------------------------------------\n");
- reflib_active = true;
- return true;
- }
- /*
- ============
- VID_CheckChanges
- This function gets called once just before drawing each frame, and it's sole purpose in life
- is to check to see if any of the video mode parameters have changed, and if they have to
- update the rendering DLL and/or video mode to match.
- ============
- */
- void VID_CheckChanges (void)
- {
- char name[100];
- cvar_t *sw_mode;
- if ( vid_ref->modified )
- {
- S_StopAllSounds();
- }
- while (vid_ref->modified)
- {
- /*
- ** refresh has changed
- */
- vid_ref->modified = false;
- vid_fullscreen->modified = true;
- cl.refresh_prepped = false;
- cls.disable_screen = true;
- sprintf( name, "ref_%s.so", vid_ref->string );
- if ( !VID_LoadRefresh( name ) )
- {
- if ( strcmp (vid_ref->string, "soft") == 0 ||
- strcmp (vid_ref->string, "softx") == 0 ) {
- Com_Printf("Refresh failed\n");
- sw_mode = Cvar_Get( "sw_mode", "0", 0 );
- if (sw_mode->value != 0) {
- Com_Printf("Trying mode 0\n");
- Cvar_SetValue("sw_mode", 0);
- if ( !VID_LoadRefresh( name ) )
- Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!");
- } else
- Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!");
- }
- Cvar_Set( "vid_ref", "soft" );
- /*
- ** drop the console if we fail to load a refresh
- */
- if ( cls.key_dest != key_console )
- {
- Con_ToggleConsole_f();
- }
- }
- cls.disable_screen = false;
- }
- }
- /*
- ============
- VID_Init
- ============
- */
- void VID_Init (void)
- {
- /* Create the video variables so we know how to start the graphics drivers */
- // if DISPLAY is defined, try X
- if (getenv("DISPLAY"))
- vid_ref = Cvar_Get ("vid_ref", "softx", CVAR_ARCHIVE);
- else
- vid_ref = Cvar_Get ("vid_ref", "soft", CVAR_ARCHIVE);
- vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
- vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
- vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE);
- vid_gamma = Cvar_Get( "vid_gamma", "1", CVAR_ARCHIVE );
- /* Add some console commands that we want to handle */
- Cmd_AddCommand ("vid_restart", VID_Restart_f);
- /* Disable the 3Dfx splash screen */
- putenv("FX_GLIDE_NO_SPLASH=0");
-
- /* Start the graphics mode and load refresh DLL */
- VID_CheckChanges();
- }
- /*
- ============
- VID_Shutdown
- ============
- */
- void VID_Shutdown (void)
- {
- if ( reflib_active )
- {
- if (KBD_Close_fp)
- KBD_Close_fp();
- if (RW_IN_Shutdown_fp)
- RW_IN_Shutdown_fp();
- KBD_Close_fp = NULL;
- RW_IN_Shutdown_fp = NULL;
- re.Shutdown ();
- VID_FreeReflib ();
- }
- }
- /*****************************************************************************/
- /* INPUT */
- /*****************************************************************************/
- cvar_t *in_joystick;
- // This if fake, it's acutally done by the Refresh load
- void IN_Init (void)
- {
- in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE);
- }
- void Real_IN_Init (void)
- {
- if (RW_IN_Init_fp)
- RW_IN_Init_fp(&in_state);
- }
- void IN_Shutdown (void)
- {
- if (RW_IN_Shutdown_fp)
- RW_IN_Shutdown_fp();
- }
- void IN_Commands (void)
- {
- if (RW_IN_Commands_fp)
- RW_IN_Commands_fp();
- }
- void IN_Move (usercmd_t *cmd)
- {
- if (RW_IN_Move_fp)
- RW_IN_Move_fp(cmd);
- }
- void IN_Frame (void)
- {
- if (RW_IN_Frame_fp)
- RW_IN_Frame_fp();
- }
- void IN_Activate (qboolean active)
- {
- if (RW_IN_Activate_fp)
- RW_IN_Activate_fp(active);
- }
- void Do_Key_Event(int key, qboolean down)
- {
- Key_Event(key, down, Sys_Milliseconds());
- }
|