📄 win_glimp.c
字号:
else
{
ri.Printf( PRINT_ALL, "...ignoring WGL_3DFX_gamma_control\n" );
}
}
else
{
ri.Printf( PRINT_ALL, "...WGL_3DFX_gamma_control not found\n" );
}
}
/*
** GLW_CheckOSVersion
*/
static qboolean GLW_CheckOSVersion( void )
{
#define OSR2_BUILD_NUMBER 1111
OSVERSIONINFO vinfo;
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
glw_state.allowdisplaydepthchange = qfalse;
if ( GetVersionEx( &vinfo) )
{
if ( vinfo.dwMajorVersion > 4 )
{
glw_state.allowdisplaydepthchange = qtrue;
}
else if ( vinfo.dwMajorVersion == 4 )
{
if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
glw_state.allowdisplaydepthchange = qtrue;
}
else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
{
if ( LOWORD( vinfo.dwBuildNumber ) >= OSR2_BUILD_NUMBER )
{
glw_state.allowdisplaydepthchange = qtrue;
}
}
}
}
else
{
ri.Printf( PRINT_ALL, "GLW_CheckOSVersion() - GetVersionEx failed\n" );
return qfalse;
}
return qtrue;
}
/*
** GLW_LoadOpenGL
**
** GLimp_win.c internal function that attempts to load and use
** a specific OpenGL DLL.
*/
static qboolean GLW_LoadOpenGL( const char *drivername )
{
char buffer[1024];
qboolean cdsFullscreen;
Q_strncpyz( buffer, drivername, sizeof(buffer) );
Q_strlwr(buffer);
//
// determine if we're on a standalone driver
//
if ( strstr( buffer, "opengl32" ) != 0 || r_maskMinidriver->integer )
{
glConfig.driverType = GLDRV_ICD;
}
else
{
glConfig.driverType = GLDRV_STANDALONE;
ri.Printf( PRINT_ALL, "...assuming '%s' is a standalone driver\n", drivername );
if ( strstr( buffer, _3DFX_DRIVER_NAME ) )
{
glConfig.driverType = GLDRV_VOODOO;
}
}
// disable the 3Dfx splash screen
_putenv("FX_GLIDE_NO_SPLASH=0");
//
// load the driver and bind our function pointers to it
//
if ( QGL_Init( buffer ) )
{
cdsFullscreen = r_fullscreen->integer;
// create the window and set up the context
if ( !GLW_StartDriverAndSetMode( drivername, r_mode->integer, r_colorbits->integer, cdsFullscreen ) )
{
// if we're on a 24/32-bit desktop and we're going fullscreen on an ICD,
// try it again but with a 16-bit desktop
if ( glConfig.driverType == GLDRV_ICD )
{
if ( r_colorbits->integer != 16 ||
cdsFullscreen != qtrue ||
r_mode->integer != 3 )
{
if ( !GLW_StartDriverAndSetMode( drivername, 3, 16, qtrue ) )
{
goto fail;
}
}
}
else
{
goto fail;
}
}
if ( glConfig.driverType == GLDRV_VOODOO )
{
glConfig.isFullscreen = qtrue;
}
return qtrue;
}
fail:
QGL_Shutdown();
return qfalse;
}
/*
** GLimp_EndFrame
*/
void GLimp_EndFrame (void)
{
//
// swapinterval stuff
//
if ( r_swapInterval->modified ) {
r_swapInterval->modified = qfalse;
if ( !glConfig.stereoEnabled ) { // why?
if ( qwglSwapIntervalEXT ) {
qwglSwapIntervalEXT( r_swapInterval->integer );
}
}
}
// don't flip if drawing to front buffer
if ( Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) != 0 )
{
if ( glConfig.driverType > GLDRV_ICD )
{
if ( !qwglSwapBuffers( glw_state.hDC ) )
{
ri.Error( ERR_FATAL, "GLimp_EndFrame() - SwapBuffers() failed!\n" );
}
}
else
{
SwapBuffers( glw_state.hDC );
}
}
// check logging
QGL_EnableLogging( r_logFile->integer );
}
static void GLW_StartOpenGL( void )
{
qboolean attemptedOpenGL32 = qfalse;
qboolean attempted3Dfx = qfalse;
//
// load and initialize the specific OpenGL driver
//
if ( !GLW_LoadOpenGL( r_glDriver->string ) )
{
if ( !Q_stricmp( r_glDriver->string, OPENGL_DRIVER_NAME ) )
{
attemptedOpenGL32 = qtrue;
}
else if ( !Q_stricmp( r_glDriver->string, _3DFX_DRIVER_NAME ) )
{
attempted3Dfx = qtrue;
}
if ( !attempted3Dfx )
{
attempted3Dfx = qtrue;
if ( GLW_LoadOpenGL( _3DFX_DRIVER_NAME ) )
{
ri.Cvar_Set( "r_glDriver", _3DFX_DRIVER_NAME );
r_glDriver->modified = qfalse;
}
else
{
if ( !attemptedOpenGL32 )
{
if ( !GLW_LoadOpenGL( OPENGL_DRIVER_NAME ) )
{
ri.Error( ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem\n" );
}
ri.Cvar_Set( "r_glDriver", OPENGL_DRIVER_NAME );
r_glDriver->modified = qfalse;
}
else
{
ri.Error( ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem\n" );
}
}
}
else if ( !attemptedOpenGL32 )
{
attemptedOpenGL32 = qtrue;
if ( GLW_LoadOpenGL( OPENGL_DRIVER_NAME ) )
{
ri.Cvar_Set( "r_glDriver", OPENGL_DRIVER_NAME );
r_glDriver->modified = qfalse;
}
else
{
ri.Error( ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem\n" );
}
}
}
}
/*
** GLimp_Init
**
** This is the platform specific OpenGL initialization function. It
** is responsible for loading OpenGL, initializing it, setting
** extensions, creating a window of the appropriate size, doing
** fullscreen manipulations, etc. Its overall responsibility is
** to make sure that a functional OpenGL subsystem is operating
** when it returns to the ref.
*/
void GLimp_Init( void )
{
char buf[1024];
cvar_t *lastValidRenderer = ri.Cvar_Get( "r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE );
cvar_t *cv;
ri.Printf( PRINT_ALL, "Initializing OpenGL subsystem\n" );
//
// check OS version to see if we can do fullscreen display changes
//
if ( !GLW_CheckOSVersion() )
{
ri.Error( ERR_FATAL, "GLimp_Init() - incorrect operating system\n" );
}
// save off hInstance and wndproc
cv = ri.Cvar_Get( "win_hinstance", "", 0 );
sscanf( cv->string, "%i", (int *)&g_wv.hInstance );
cv = ri.Cvar_Get( "win_wndproc", "", 0 );
sscanf( cv->string, "%i", (int *)&glw_state.wndproc );
r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH );
r_maskMinidriver = ri.Cvar_Get( "r_maskMinidriver", "0", CVAR_LATCH );
// load appropriate DLL and initialize subsystem
GLW_StartOpenGL();
// get our config strings
Q_strncpyz( glConfig.vendor_string, qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) );
Q_strncpyz( glConfig.renderer_string, qglGetString (GL_RENDERER), sizeof( glConfig.renderer_string ) );
Q_strncpyz( glConfig.version_string, qglGetString (GL_VERSION), sizeof( glConfig.version_string ) );
Q_strncpyz( glConfig.extensions_string, qglGetString (GL_EXTENSIONS), sizeof( glConfig.extensions_string ) );
//
// chipset specific configuration
//
Q_strncpyz( buf, glConfig.renderer_string, sizeof(buf) );
Q_strlwr( buf );
//
// NOTE: if changing cvars, do it within this block. This allows them
// to be overridden when testing driver fixes, etc. but only sets
// them to their default state when the hardware is first installed/run.
//
if ( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) )
{
glConfig.hardwareType = GLHW_GENERIC;
ri.Cvar_Set( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST" );
// VOODOO GRAPHICS w/ 2MB
if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) )
{
ri.Cvar_Set( "r_picmip", "2" );
ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
}
else
{
ri.Cvar_Set( "r_picmip", "1" );
if ( strstr( buf, "rage 128" ) || strstr( buf, "rage128" ) )
{
ri.Cvar_Set( "r_finish", "0" );
}
// Savage3D and Savage4 should always have trilinear enabled
else if ( strstr( buf, "savage3d" ) || strstr( buf, "s3 savage4" ) )
{
ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
}
}
}
//
// this is where hardware specific workarounds that should be
// detected/initialized every startup should go.
//
if ( strstr( buf, "banshee" ) || strstr( buf, "voodoo3" ) )
{
glConfig.hardwareType = GLHW_3DFX_2D3D;
}
// VOODOO GRAPHICS w/ 2MB
else if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) )
{
}
else if ( strstr( buf, "glzicd" ) )
{
}
else if ( strstr( buf, "rage pro" ) || strstr( buf, "Rage Pro" ) || strstr( buf, "ragepro" ) )
{
glConfig.hardwareType = GLHW_RAGEPRO;
}
else if ( strstr( buf, "rage 128" ) )
{
}
else if ( strstr( buf, "permedia2" ) )
{
glConfig.hardwareType = GLHW_PERMEDIA2;
}
else if ( strstr( buf, "riva 128" ) )
{
glConfig.hardwareType = GLHW_RIVA128;
}
else if ( strstr( buf, "riva tnt " ) )
{
}
ri.Cvar_Set( "r_lastValidRenderer", glConfig.renderer_string );
GLW_InitExtensions();
WG_CheckHardwareGamma();
}
/*
** GLimp_Shutdown
**
** This routine does all OS specific shutdown procedures for the OpenGL
** subsystem.
*/
void GLimp_Shutdown( void )
{
// const char *strings[] = { "soft", "hard" };
const char *success[] = { "failed", "success" };
int retVal;
// FIXME: Brian, we need better fallbacks from partially initialized failures
if ( !qwglMakeCurrent ) {
return;
}
ri.Printf( PRINT_ALL, "Shutting down OpenGL subsystem\n" );
// restore gamma. We do this first because 3Dfx's extension needs a valid OGL subsystem
WG_RestoreGamma();
// set current context to NULL
if ( qwglMakeCurrent )
{
retVal = qwglMakeCurrent( NULL, NULL ) != 0;
ri.Printf( PRINT_ALL, "...wglMakeCurrent( NULL, NULL ): %s\n", success[retVal] );
}
// delete HGLRC
if ( glw_state.hGLRC )
{
retVal = qwglDeleteContext( glw_state.hGLRC ) != 0;
ri.Printf( PRINT_ALL, "...deleting GL context: %s\n", success[retVal] );
glw_state.hGLRC = NULL;
}
// release DC
if ( glw_state.hDC )
{
retVal = ReleaseDC( g_wv.hWnd, glw_state.hDC ) != 0;
ri.Printf( PRINT_ALL, "...releasing DC: %s\n", success[retVal] );
glw_state.hDC = NULL;
}
// destroy window
if ( g_wv.hWnd )
{
ri.Printf( PRINT_ALL, "...destroying window\n" );
ShowWindow( g_wv.hWnd, SW_HIDE );
DestroyWindow( g_wv.hWnd );
g_wv.hWnd = NULL;
glw_state.pixelFormatSet = qfalse;
}
// close the r_logFile
if ( glw_state.log_fp )
{
fclose( glw_state.log_fp );
glw_state.log_fp = 0;
}
// reset display settings
if ( glw_state.cdsFullscreen )
{
ri.Printf( PRINT_ALL, "...resetting display\n" );
ChangeDisplaySettings( 0, 0 );
glw_state.cdsFullscreen = qfalse;
}
// shutdown QGL subsystem
QGL_Shutdown();
memset( &glConfig, 0, sizeof( glConfig ) );
memset( &glState, 0, sizeof( glState ) );
}
/*
** GLimp_LogComment
*/
void GLimp_LogComment( char *comment )
{
if ( glw_state.log_fp ) {
fprintf( glw_state.log_fp, "%s", comment );
}
}
/*
===========================================================
SMP acceleration
===========================================================
*/
HANDLE renderCommandsEvent;
HANDLE renderCompletedEvent;
HANDLE renderActiveEvent;
void (*glimpRenderThread)( void );
void GLimp_RenderThreadWrapper( void ) {
glimpRenderThread();
// unbind the context before we die
qwglMakeCurrent( glw_state.hDC, NULL );
}
/*
=======================
GLimp_SpawnRenderThread
=======================
*/
HANDLE renderThreadHandle;
int renderThreadId;
qboolean GLimp_SpawnRenderThread( void (*function)( void ) ) {
renderCommandsEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
renderCompletedEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
renderActiveEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
glimpRenderThread = function;
renderThreadHandle = CreateThread(
NULL, // LPSECURITY_ATTRIBUTES lpsa,
0, // DWORD cbStack,
(LPTHREAD_START_ROUTINE)GLimp_RenderThreadWrapper, // LPTHREAD_START_ROUTINE lpStartAddr,
0, // LPVOID lpvThreadParm,
0, // DWORD fdwCreate,
&renderThreadId );
if ( !renderThreadHandle ) {
return qfalse;
}
return qtrue;
}
static void *smpData;
static int wglErrors;
void *GLimp_RendererSleep( void ) {
void *data;
if ( !qwglMakeCurrent( glw_state.hDC, NULL ) ) {
wglErrors++;
}
ResetEvent( renderActiveEvent );
// after this, the front end can exit GLimp_FrontEndSleep
SetEvent( renderCompletedEvent );
WaitForSingleObject( renderCommandsEvent, INFINITE );
if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) {
wglErrors++;
}
ResetEvent( renderCompletedEvent );
ResetEvent( renderCommandsEvent );
data = smpData;
// after this, the main thread can exit GLimp_WakeRenderer
SetEvent( renderActiveEvent );
return data;
}
void GLimp_FrontEndSleep( void ) {
WaitForSingleObject( renderCompletedEvent, INFINITE );
if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) {
wglErrors++;
}
}
void GLimp_WakeRenderer( void *data ) {
smpData = data;
if ( !qwglMakeCurrent( glw_state.hDC, NULL ) ) {
wglErrors++;
}
// after this, the renderer can continue through GLimp_RendererSleep
SetEvent( renderCommandsEvent );
WaitForSingleObject( renderActiveEvent, INFINITE );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -