diff options
author | Andrey Nazarov <skuller@skuller.net> | 2007-08-14 20:18:08 +0000 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2007-08-14 20:18:08 +0000 |
commit | f294db4ccf45f6274e65260dd6f9a2c5faa94313 (patch) | |
tree | e8cf1ba2bfe9c8417eec17faf912442f52fc4ef2 /source/cl_ref.c |
Initial import of the new Q2PRO tree.
Diffstat (limited to 'source/cl_ref.c')
-rw-r--r-- | source/cl_ref.c | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/source/cl_ref.c b/source/cl_ref.c new file mode 100644 index 0000000..56bd56b --- /dev/null +++ b/source/cl_ref.c @@ -0,0 +1,433 @@ +/* +Copyright (C) 1997-2001 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// Main windowed and fullscreen graphics interface module. This module +// is used for both the software and OpenGL rendering versions of the +// Quake refresh engine. + + +#include "cl_local.h" +#include "vid_public.h" +#include "vid_local.h" + +// Structure containing functions exported from refresh DLL +refAPI_t ref; + +// Console variables that we need to access from this module +cvar_t *vid_ref; // Name of Refresh DLL loaded +cvar_t *vid_placement; +cvar_t *vid_modelist; +cvar_t *vid_fullscreen; + +#define MODE_PLACEMENT 1 +#define MODE_FULLSCREEN 2 +#define MODE_MODELIST 4 +#define MODE_REFRESH 8 + +static int mode_changed; + + +#ifdef REF_HARD_LINKED +qboolean Ref_APISetupCallback( api_type_t type, void *api ); +#else +// Global variables used internally by this module +static void *reflib_library; // Handle to refresh DLL +#endif + +/* +========================================================================== + +HELPER FUNCTIONS + +========================================================================== +*/ + +// 640x480 800x600 1024x768 +// 640x480@75 +// 640x480@75:32 +// 640x480:32@75 +void Video_GetModeFS( vrect_t *rc, int *freq, int *depth ) { + char *s = vid_modelist->string; + int mode = 1; + int w = 640, h = 480, hz = 0, bpp = 0; + + while( *s ) { + w = strtoul( s, &s, 10 ); + if( *s != 'x' ) { + Com_DPrintf( "Mode %d is malformed\n", mode ); + goto malformed; + } + h = strtoul( s + 1, &s, 10 ); + if( *s == '@' ) { + hz = strtoul( s + 1, &s, 10 ); + if( *s == ':' ) { + bpp = strtoul( s + 1, &s, 10 ); + } + } else if( *s == ':' ) { + bpp = strtoul( s + 1, &s, 10 ); + if( *s == '@' ) { + hz = strtoul( s + 1, &s, 10 ); + } + } + if( mode == vid_fullscreen->integer ) { + break; + } + if( *s == 0 ) { + Com_DPrintf( "Mode %d not found\n", vid_fullscreen->integer ); + break; + } + s++; + mode++; + } + + // sanity check + if( w < 1 || w > 8192 || h < 1 || h > 8192 ) { + Com_DPrintf( "Mode %dx%d doesn't look sane\n", w, h ); +malformed: + w = 640; + h = 480; + hz = 0; + bpp = 0; + } + + rc->x = 0; + rc->y = 0; + rc->width = w; + rc->height = h; + + if( freq ) { + *freq = hz; + } + if( depth ) { + *depth = bpp; + } +} + +// 640x480 +// 640x480+0 +// 640x480+0+0 +void Video_GetPlacement( vrect_t *rc ) { + char *s = vid_placement->string; + int w = 640, h = 480, x = 0, y = 0; + + w = strtoul( s, &s, 10 ); + if( *s != 'x' ) { + Com_DPrintf( "Placement string is malformed\n" ); + goto malformed; + } + h = strtoul( s + 1, &s, 10 ); + if( *s == '+' ) { + x = strtoul( s + 1, &s, 10 ); + if( *s == '+' ) { + y = strtoul( s + 1, &s, 10 ); + } + } + + // sanity check + if( x < 0 || x > 8192 || y < 0 || y > 8192 ) { + x = 0; + y = 0; + } + if( w < 1 || w > 8192 || h < 1 || h > 8192 ) { +malformed: + w = 640; + h = 480; + } + + rc->x = x; + rc->y = y; + rc->width = w; + rc->height = h; +} + + +void Video_SetPlacement( vrect_t *rc ) { + char buffer[MAX_QPATH]; + + Com_sprintf( buffer, sizeof( buffer ), "%dx%d+%d+%d", + rc->width, rc->height, rc->x, rc->y ); + Cvar_Set( "vid_placement", buffer ); +} + +/* +========================================================================== + +LOADING / SHUTDOWN + +========================================================================== +*/ + +/* +============== +CL_FreeRefresh +============== +*/ +static void CL_FreeRefresh( void ) { +#ifndef REF_HARD_LINKED + Sys_FreeLibrary( reflib_library ); + reflib_library = NULL; +#endif + memset( &ref, 0, sizeof( ref ) ); + cls.ref_initialized = qfalse; +} + +#ifndef REF_HARD_LINKED + +/* +============== +CL_RefSetupCallback +============== +*/ +static qboolean CL_RefSetupCallback( api_type_t type, void *api ) { + switch( type ) { + case API_CMD: + Cmd_FillAPI( ( cmdAPI_t * )api ); + break; + case API_CVAR: + Cvar_FillAPI( ( cvarAPI_t * )api ); + break; + case API_FS: + FS_FillAPI( ( fsAPI_t * )api ); + break; + case API_COMMON: + Com_FillAPI( ( commonAPI_t * )api ); + break; + case API_SYSTEM: + Sys_FillAPI( ( sysAPI_t * )api ); + break; + case API_VIDEO_SOFTWARE: + Video_FillSWAPI( ( videoAPI_t * )api ); + break; + case API_VIDEO_OPENGL: + Video_FillGLAPI( ( videoAPI_t * )api ); + break; + default: + Com_Error( ERR_FATAL, "CL_RefSetupCallback: bad api type" ); + } + + return qtrue; +} + +#endif + +/* +============== +CL_LoadRefresh +============== +*/ +static qboolean CL_LoadRefresh( const char *name ) { +#ifndef REF_HARD_LINKED + char path[MAX_OSPATH]; + moduleEntry_t entry; + moduleInfo_t info; + moduleCapability_t caps; + APISetupCallback_t callback; +#endif + + if( cls.ref_initialized ) { + ref.Shutdown( qtrue ); + CL_FreeRefresh(); + } + + Com_Printf( "------- Loading %s -------\n", name ); + +#ifdef REF_HARD_LINKED +#ifdef SOFTWARE_RENDERER + Video_FillSWAPI( &video ); +#else + Video_FillGLAPI( &video ); +#endif + + Ref_APISetupCallback( API_REFRESH, &ref ); +#else + + Com_sprintf( path, sizeof( path ), "%s" PATH_SEP_STRING "%s" LIBSUFFIX, + sys_refdir->string, name ); + entry = Sys_LoadLibrary( path, "moduleEntry", &reflib_library ); + if( !entry ) { + Com_WPrintf( "Couldn't load %s\n", name ); + return qfalse; + } + + entry( MQ_GETINFO, &info ); + if( info.api_version != MODULES_APIVERSION ) { + Com_WPrintf( "%s has incompatible api_version: %i, should be %i\n", + name, info.api_version, MODULES_APIVERSION ); + goto fail; + } + + caps = ( moduleCapability_t )entry( MQ_GETCAPS, NULL ); + if( !( caps & MCP_REFRESH ) ) { + Com_WPrintf( "%s doesn't have REFRESH capability\n", name ); + goto fail; + } + + callback = ( APISetupCallback_t )entry( MQ_SETUPAPI, ( void * )CL_RefSetupCallback ); + if( !callback ) { + Com_WPrintf( "%s returned NULL callback\n", name ); + goto fail; + } + + callback( API_REFRESH, &ref ); +#endif + + cls.ref_initialized = qtrue; + if( !ref.Init( qtrue ) ) { + goto fail; + } + + Com_Printf( "------------------------------------\n" ); + + return qtrue; + +fail: + CL_FreeRefresh(); + return qfalse; +} + +/* +============ +CL_PumpEvents +============ +*/ +void CL_PumpEvents( void ) { + if( !cls.ref_initialized ) { + return; + } + + Video_PumpEvents(); + + if( mode_changed ) { +#ifndef REF_HARD_LINKED + if( mode_changed & MODE_REFRESH ) { + Cbuf_AddText( "vid_restart\n" ); + } else +#endif + if( mode_changed & MODE_FULLSCREEN ) { + Video_ModeChanged(); + } else { + if( vid_fullscreen->integer ) { + if( mode_changed & MODE_MODELIST ) { + Video_ModeChanged(); + } + } else { + if( mode_changed & MODE_PLACEMENT ) { + Video_ModeChanged(); + } + } + } + mode_changed = 0; + } +} + +static void vid_placement_changed( cvar_t *self ) { + mode_changed |= MODE_PLACEMENT; +} + +static void vid_fullscreen_changed( cvar_t *self ) { + mode_changed |= MODE_FULLSCREEN; +} + +static void vid_modelist_changed( cvar_t *self ) { + mode_changed |= MODE_MODELIST; +} + +#ifndef REF_HARD_LINKED +static void vid_ref_changed( cvar_t *self ) { + mode_changed |= MODE_REFRESH; +} +#endif + +/* +============ +CL_InitRefresh +============ +*/ +void CL_InitRefresh( void ) { + if( cls.ref_initialized ) { + return; + } + + // Create the video variables so we know how to start the graphics drivers + vid_placement = Cvar_Get( "vid_placement", "640x480", CVAR_ARCHIVE ); + vid_fullscreen = Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE ); + vid_modelist = Cvar_Get( "vid_modelist", "640x480", CVAR_ARCHIVE ); + +#ifdef REF_HARD_LINKED + vid_ref = Cvar_Get( "vid_ref", DEFAULT_REFRESH_DRIVER, CVAR_ROM ); + if( !CL_LoadRefresh( "ref_" DEFAULT_REFRESH_DRIVER ) ) { + Com_Error( ERR_FATAL, "Couldn't load built-in video driver!" ); + } +#else + vid_ref = Cvar_Get( "vid_ref", DEFAULT_REFRESH_DRIVER, CVAR_ARCHIVE ); + + // Start the graphics mode and load refresh DLL + while( 1 ) { + char buffer[MAX_QPATH]; + + Com_sprintf( buffer, sizeof( buffer ), "ref_%s", vid_ref->string ); + if( CL_LoadRefresh( buffer ) ) { + break; + } + + if( !strcmp( vid_ref->string, DEFAULT_REFRESH_DRIVER ) ) { + Com_Error( ERR_FATAL, "Couldn't fall back to %s driver!", buffer ); + } + + Com_Printf( "Falling back to default refresh...\n" ); + Cvar_Set( "vid_ref", DEFAULT_REFRESH_DRIVER ); + } +#endif + + vid_placement->changed = vid_placement_changed; + vid_fullscreen->changed = vid_fullscreen_changed; + vid_modelist->changed = vid_modelist_changed; +#ifndef REF_HARD_LINKED + vid_ref->changed = vid_ref_changed; +#endif + + mode_changed = 0; +} + +/* +============ +CL_ShutdownRefresh +============ +*/ +void CL_ShutdownRefresh( void ) { + if( !cls.ref_initialized ) { + return; + } + + vid_placement->changed = NULL; + vid_fullscreen->changed = NULL; + vid_modelist->changed = NULL; +#ifndef REF_HARD_LINKED + vid_ref->changed = NULL; +#endif + + ref.Shutdown( qtrue ); + CL_FreeRefresh(); + + Z_LeakTest( TAG_RENDERER ); +} + + + |