Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

win_glimp.c File Reference

#include <assert.h>
#include "../renderer/tr_local.h"
#include "../qcommon/qcommon.h"
#include "resource.h"
#include "glw_win.h"
#include "win_local.h"

Include dependency graph for win_glimp.c:

Include dependency graph

Go to the source code of this file.

Defines

#define MAX_PFDS   256
#define OSR2_BUILD_NUMBER   1111
#define TRY_PFD_FAIL_HARD   2
#define TRY_PFD_FAIL_SOFT   1
#define TRY_PFD_SUCCESS   0
#define WINDOW_CLASS_NAME   "Quake 3: Arena"
#define WINDOW_STYLE   (WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_VISIBLE)

Enumerations

enum  rserr_t { RSERR_OK, RSERR_INVALID_FULLSCREEN, RSERR_INVALID_MODE, RSERR_UNKNOWN }

Functions

void GLimp_EndFrame (void)
void GLimp_FrontEndSleep (void)
void GLimp_Init (void)
void GLimp_LogComment (char *comment)
void * GLimp_RendererSleep (void)
void GLimp_RenderThreadWrapper (void)
void GLimp_Shutdown (void)
qboolean GLimp_SpawnRenderThread (void(*function)(void))
void GLimp_WakeRenderer (void *data)
qboolean GLW_CheckOSVersion (void)
int GLW_ChoosePFD (HDC hDC, PIXELFORMATDESCRIPTOR *pPFD)
void GLW_CreatePFD (PIXELFORMATDESCRIPTOR *pPFD, int colorbits, int depthbits, int stencilbits, qboolean stereo)
qboolean GLW_CreateWindow (const char *drivername, int width, int height, int colorbits, qboolean cdsFullscreen)
qboolean GLW_InitDriver (const char *drivername, int colorbits)
void GLW_InitExtensions (void)
qboolean GLW_LoadOpenGL (const char *drivername)
int GLW_MakeContext (PIXELFORMATDESCRIPTOR *pPFD)
rserr_t GLW_SetMode (const char *drivername, int mode, int colorbits, qboolean cdsFullscreen)
qboolean GLW_StartDriverAndSetMode (const char *drivername, int mode, int colorbits, qboolean cdsFullscreen)
void GLW_StartOpenGL (void)
void PrintCDSError (int value)
void QGL_EnableLogging (qboolean enable)
qboolean QGL_Init (const char *dllname)
void QGL_Shutdown (void)
void WG_CheckHardwareGamma (void)
void WG_RestoreGamma (void)

Variables

void(* glimpRenderThread )(void)
glwstate_t glw_state
cvar_tr_allowSoftwareGL
cvar_tr_maskMinidriver
HANDLE renderActiveEvent
HANDLE renderCommandsEvent
HANDLE renderCompletedEvent
HANDLE renderThreadHandle
int renderThreadId
qboolean s_classRegistered = qfalse
void * smpData
int wglErrors


Define Documentation

#define MAX_PFDS   256
 

Definition at line 118 of file win_glimp.c.

Referenced by GLW_ChoosePFD().

#define OSR2_BUILD_NUMBER   1111
 

#define TRY_PFD_FAIL_HARD   2
 

Definition at line 58 of file win_glimp.c.

#define TRY_PFD_FAIL_SOFT   1
 

Definition at line 57 of file win_glimp.c.

#define TRY_PFD_SUCCESS   0
 

Definition at line 56 of file win_glimp.c.

#define WINDOW_CLASS_NAME   "Quake 3: Arena"
 

Definition at line 60 of file win_glimp.c.

#define WINDOW_STYLE   (WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_VISIBLE)
 

Definition at line 576 of file win_glimp.c.

Referenced by GLW_CreateWindow().


Enumeration Type Documentation

enum rserr_t
 

Enumeration values:
RSERR_OK 
RSERR_INVALID_FULLSCREEN 
RSERR_INVALID_MODE 
RSERR_UNKNOWN 

Definition at line 47 of file win_glimp.c.

00047              {
00048     RSERR_OK,
00049 
00050     RSERR_INVALID_FULLSCREEN,
00051     RSERR_INVALID_MODE,
00052 
00053     RSERR_UNKNOWN
00054 } rserr_t;


Function Documentation

void GLimp_EndFrame void   ) 
 

Definition at line 1244 of file win_glimp.c.

References glwstate_t::bufferSwapCount, Com_Printf(), glconfig_t::driverType, ERR_FATAL, glConfig, glwstate_t::glPauseCount, GLSTAMP, glw_state, glwstate_t::hDC, cvar_s::integer, cvar_s::modified, OSX_GLContextClearCurrent, OSX_GLContextIsCurrent, OSX_GLContextSetCurrent, Q_stricmp(), QGL_EnableLogging(), QGLCheckError(), qwglSwapIntervalEXT, r_drawBuffer, r_enablerender, r_logFile, r_swapInterval, ri, glconfig_t::stereoEnabled, and cvar_s::string.

01245 {
01246     //
01247     // swapinterval stuff
01248     //
01249     if ( r_swapInterval->modified ) {
01250         r_swapInterval->modified = qfalse;
01251 
01252         if ( !glConfig.stereoEnabled ) {    // why?
01253             if ( qwglSwapIntervalEXT ) {
01254                 qwglSwapIntervalEXT( r_swapInterval->integer );
01255             }
01256         }
01257     }
01258 
01259 
01260     // don't flip if drawing to front buffer
01261     if ( Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) != 0 )
01262     {
01263         if ( glConfig.driverType > GLDRV_ICD )
01264         {
01265             if ( !qwglSwapBuffers( glw_state.hDC ) )
01266             {
01267                 ri.Error( ERR_FATAL, "GLimp_EndFrame() - SwapBuffers() failed!\n" );
01268             }
01269         }
01270         else
01271         {
01272             SwapBuffers( glw_state.hDC );
01273         }
01274     }
01275 
01276     // check logging
01277     QGL_EnableLogging( r_logFile->integer );
01278 }

Here is the call graph for this function:

void GLimp_FrontEndSleep void   ) 
 

Definition at line 1637 of file win_glimp.c.

References Com_Printf(), GLSTAMP, glw_state, glwstate_t::hDC, glwstate_t::hGLRC, INFINITE, mainThreadCondition, OSX_GLContextSetCurrent, renderCompletedEvent, smpMutex, and wglErrors.

01637                                  {
01638     WaitForSingleObject( renderCompletedEvent, INFINITE );
01639 
01640     if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) {
01641         wglErrors++;
01642     }
01643 }

Here is the call graph for this function:

void GLimp_Init void   ) 
 

Definition at line 1350 of file win_glimp.c.

References BOOL, Cmd_AddCommand(), CVAR_ARCHIVE, refimport_t::Cvar_Get, CVAR_LATCH, refimport_t::Cvar_Set, cvar_t, glconfig_t::deviceSupportsGamma, ERR_FATAL, glconfig_t::extensions_string, free(), g_wv, glConfig, GLimp_SetMode(), GLImp_Toggle_Renderer_f(), GLW_CheckOSVersion(), GLW_InitExtensions(), GLW_StartOpenGL(), glw_state, glconfig_t::hardwareType, WinVars_t::hInstance, cvar_s::integer, malloc(), memset(), OSX_GLContextClearCurrent, PRINT_ALL, Q_stricmp(), Q_strlwr(), Q_strncpyz(), qfalse, qglGetString, qtrue, r_allowSoftwareGL, r_enablerender, r_fullscreen, r_maskMinidriver, glconfig_t::renderer_string, ri, sscanf(), strcpy(), cvar_s::string, strlen(), strstr(), Sys_QueryVideoMemory(), Sys_StoreGammaTables(), glconfig_t::vendor_string, glconfig_t::version_string, WG_CheckHardwareGamma(), and glwstate_t::wndproc.

01351 {
01352     char    buf[1024];
01353     cvar_t *lastValidRenderer = ri.Cvar_Get( "r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE );
01354     cvar_t  *cv;
01355 
01356     ri.Printf( PRINT_ALL, "Initializing OpenGL subsystem\n" );
01357 
01358     //
01359     // check OS version to see if we can do fullscreen display changes
01360     //
01361     if ( !GLW_CheckOSVersion() )
01362     {
01363         ri.Error( ERR_FATAL, "GLimp_Init() - incorrect operating system\n" );
01364     }
01365 
01366     // save off hInstance and wndproc
01367     cv = ri.Cvar_Get( "win_hinstance", "", 0 );
01368     sscanf( cv->string, "%i", (int *)&g_wv.hInstance );
01369 
01370     cv = ri.Cvar_Get( "win_wndproc", "", 0 );
01371     sscanf( cv->string, "%i", (int *)&glw_state.wndproc );
01372 
01373     r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH );
01374     r_maskMinidriver = ri.Cvar_Get( "r_maskMinidriver", "0", CVAR_LATCH );
01375 
01376     // load appropriate DLL and initialize subsystem
01377     GLW_StartOpenGL();
01378 
01379     // get our config strings
01380     Q_strncpyz( glConfig.vendor_string, qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) );
01381     Q_strncpyz( glConfig.renderer_string, qglGetString (GL_RENDERER), sizeof( glConfig.renderer_string ) );
01382     Q_strncpyz( glConfig.version_string, qglGetString (GL_VERSION), sizeof( glConfig.version_string ) );
01383     Q_strncpyz( glConfig.extensions_string, qglGetString (GL_EXTENSIONS), sizeof( glConfig.extensions_string ) );
01384 
01385     //
01386     // chipset specific configuration
01387     //
01388     Q_strncpyz( buf, glConfig.renderer_string, sizeof(buf) );
01389     Q_strlwr( buf );
01390 
01391     //
01392     // NOTE: if changing cvars, do it within this block.  This allows them
01393     // to be overridden when testing driver fixes, etc. but only sets
01394     // them to their default state when the hardware is first installed/run.
01395     //
01396     if ( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) )
01397     {
01398         glConfig.hardwareType = GLHW_GENERIC;
01399 
01400         ri.Cvar_Set( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST" );
01401 
01402         // VOODOO GRAPHICS w/ 2MB
01403         if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) )
01404         {
01405             ri.Cvar_Set( "r_picmip", "2" );
01406             ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
01407         }
01408         else
01409         {
01410             ri.Cvar_Set( "r_picmip", "1" );
01411 
01412             if ( strstr( buf, "rage 128" ) || strstr( buf, "rage128" ) )
01413             {
01414                 ri.Cvar_Set( "r_finish", "0" );
01415             }
01416             // Savage3D and Savage4 should always have trilinear enabled
01417             else if ( strstr( buf, "savage3d" ) || strstr( buf, "s3 savage4" ) )
01418             {
01419                 ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
01420             }
01421         }
01422     }
01423     
01424     //
01425     // this is where hardware specific workarounds that should be
01426     // detected/initialized every startup should go.
01427     //
01428     if ( strstr( buf, "banshee" ) || strstr( buf, "voodoo3" ) )
01429     {
01430         glConfig.hardwareType = GLHW_3DFX_2D3D;
01431     }
01432     // VOODOO GRAPHICS w/ 2MB
01433     else if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) )
01434     {
01435     }
01436     else if ( strstr( buf, "glzicd" ) )
01437     {
01438     }
01439     else if ( strstr( buf, "rage pro" ) || strstr( buf, "Rage Pro" ) || strstr( buf, "ragepro" ) )
01440     {
01441         glConfig.hardwareType = GLHW_RAGEPRO;
01442     }
01443     else if ( strstr( buf, "rage 128" ) )
01444     {
01445     }
01446     else if ( strstr( buf, "permedia2" ) )
01447     {
01448         glConfig.hardwareType = GLHW_PERMEDIA2;
01449     }
01450     else if ( strstr( buf, "riva 128" ) )
01451     {
01452         glConfig.hardwareType = GLHW_RIVA128;
01453     }
01454     else if ( strstr( buf, "riva tnt " ) )
01455     {
01456     }
01457 
01458     ri.Cvar_Set( "r_lastValidRenderer", glConfig.renderer_string );
01459 
01460     GLW_InitExtensions();
01461     WG_CheckHardwareGamma();
01462 }

Here is the call graph for this function:

void GLimp_LogComment char *  comment  ) 
 

Definition at line 1545 of file win_glimp.c.

References fprintf(), glw_state, and glwstate_t::log_fp.

Referenced by DrawTris(), GL_SelectTexture(), RB_EndSurface(), RB_StageIteratorGeneric(), RB_StageIteratorLightmappedMultitexture(), RB_StageIteratorVertexLitTexture(), RB_SwapBuffers(), and RE_RenderScene().

01546 {
01547     if ( glw_state.log_fp ) {
01548         fprintf( glw_state.log_fp, "%s", comment );
01549     }
01550 }

Here is the call graph for this function:

void* GLimp_RendererSleep void   ) 
 

Definition at line 1607 of file win_glimp.c.

References data, GLSTAMP, glw_state, glwstate_t::hDC, glwstate_t::hGLRC, INFINITE, mainThreadCondition, NULL, OSX_GLContextClearCurrent, OSX_GLContextSetCurrent, renderActiveEvent, renderCommandsEvent, renderCompletedEvent, renderThreadCondition, smpData, smpDataChanged, smpMutex, and wglErrors.

01607                                   {
01608     void    *data;
01609 
01610     if ( !qwglMakeCurrent( glw_state.hDC, NULL ) ) {
01611         wglErrors++;
01612     }
01613 
01614     ResetEvent( renderActiveEvent );
01615 
01616     // after this, the front end can exit GLimp_FrontEndSleep
01617     SetEvent( renderCompletedEvent );
01618 
01619     WaitForSingleObject( renderCommandsEvent, INFINITE );
01620 
01621     if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) {
01622         wglErrors++;
01623     }
01624 
01625     ResetEvent( renderCompletedEvent );
01626     ResetEvent( renderCommandsEvent );
01627 
01628     data = smpData;
01629 
01630     // after this, the main thread can exit GLimp_WakeRenderer
01631     SetEvent( renderActiveEvent );
01632 
01633     return data;
01634 }

void GLimp_RenderThreadWrapper void   ) 
 

Definition at line 1567 of file win_glimp.c.

References glimpRenderThread, glw_state, glwstate_t::hDC, and NULL.

01567                                        {
01568     glimpRenderThread();
01569 
01570     // unbind the context before we die
01571     qwglMakeCurrent( glw_state.hDC, NULL );
01572 }

void GLimp_Shutdown void   ) 
 

Definition at line 1470 of file win_glimp.c.

References _GLimp_RestoreOriginalVideoSettings(), glwgamma_t::blue, glwstate_t::cdsFullscreen, Com_Printf(), glconfig_t::deviceSupportsGamma, glwstate_t::displayCount, fclose(), free(), g_wv, glConfig, glState, glw_state, glwgamma_t::green, glwstate_t::hDC, glwstate_t::hGLRC, WinVars_t::hWnd, glwstate_t::inGameTable, glwstate_t::log_fp, memset(), NULL, glwstate_t::originalDisplayGammaTables, OSX_GetCGLContext, OSX_GetNSGLContext, OSX_GLContextClearCurrent, OSX_SetGLContext, glwstate_t::pixelFormatSet, PRINT_ALL, QGL_Shutdown(), glwgamma_t::red, ri, Sys_DisplayToUse(), Sys_FadeScreen(), Sys_UnfadeScreens(), glwstate_t::tempTable, WG_RestoreGamma(), and glwstate_t::window.

01471 {
01472 //  const char *strings[] = { "soft", "hard" };
01473     const char *success[] = { "failed", "success" };
01474     int retVal;
01475 
01476     // FIXME: Brian, we need better fallbacks from partially initialized failures
01477     if ( !qwglMakeCurrent ) {
01478         return;
01479     }
01480 
01481     ri.Printf( PRINT_ALL, "Shutting down OpenGL subsystem\n" );
01482 
01483     // restore gamma.  We do this first because 3Dfx's extension needs a valid OGL subsystem
01484     WG_RestoreGamma();
01485 
01486     // set current context to NULL
01487     if ( qwglMakeCurrent )
01488     {
01489         retVal = qwglMakeCurrent( NULL, NULL ) != 0;
01490 
01491         ri.Printf( PRINT_ALL, "...wglMakeCurrent( NULL, NULL ): %s\n", success[retVal] );
01492     }
01493 
01494     // delete HGLRC
01495     if ( glw_state.hGLRC )
01496     {
01497         retVal = qwglDeleteContext( glw_state.hGLRC ) != 0;
01498         ri.Printf( PRINT_ALL, "...deleting GL context: %s\n", success[retVal] );
01499         glw_state.hGLRC = NULL;
01500     }
01501 
01502     // release DC
01503     if ( glw_state.hDC )
01504     {
01505         retVal = ReleaseDC( g_wv.hWnd, glw_state.hDC ) != 0;
01506         ri.Printf( PRINT_ALL, "...releasing DC: %s\n", success[retVal] );
01507         glw_state.hDC   = NULL;
01508     }
01509 
01510     // destroy window
01511     if ( g_wv.hWnd )
01512     {
01513         ri.Printf( PRINT_ALL, "...destroying window\n" );
01514         ShowWindow( g_wv.hWnd, SW_HIDE );
01515         DestroyWindow( g_wv.hWnd );
01516         g_wv.hWnd = NULL;
01517         glw_state.pixelFormatSet = qfalse;
01518     }
01519 
01520     // close the r_logFile
01521     if ( glw_state.log_fp )
01522     {
01523         fclose( glw_state.log_fp );
01524         glw_state.log_fp = 0;
01525     }
01526 
01527     // reset display settings
01528     if ( glw_state.cdsFullscreen )
01529     {
01530         ri.Printf( PRINT_ALL, "...resetting display\n" );
01531         ChangeDisplaySettings( 0, 0 );
01532         glw_state.cdsFullscreen = qfalse;
01533     }
01534 
01535     // shutdown QGL subsystem
01536     QGL_Shutdown();
01537 
01538     memset( &glConfig, 0, sizeof( glConfig ) );
01539     memset( &glState, 0, sizeof( glState ) );
01540 }

Here is the call graph for this function:

qboolean GLimp_SpawnRenderThread void(*)(void)  function  ) 
 

Definition at line 1581 of file win_glimp.c.

References FALSE, GLimp_RenderThreadWrapper(), glimpRenderThread, mainThreadCondition, NULL, PRINT_ALL, qboolean, renderActiveEvent, renderCommandsEvent, renderCompletedEvent, renderThreadCondition, renderThreadHandle, renderThreadId, ri, smpMutex, strerror(), and TRUE.

Referenced by R_InitCommandBuffers().

01581                                                              {
01582 
01583     renderCommandsEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
01584     renderCompletedEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
01585     renderActiveEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
01586 
01587     glimpRenderThread = function;
01588 
01589     renderThreadHandle = CreateThread(
01590        NULL,    // LPSECURITY_ATTRIBUTES lpsa,
01591        0,       // DWORD cbStack,
01592        (LPTHREAD_START_ROUTINE)GLimp_RenderThreadWrapper,   // LPTHREAD_START_ROUTINE lpStartAddr,
01593        0,           // LPVOID lpvThreadParm,
01594        0,           //   DWORD fdwCreate,
01595        &renderThreadId );
01596 
01597     if ( !renderThreadHandle ) {
01598         return qfalse;
01599     }
01600 
01601     return qtrue;
01602 }

Here is the call graph for this function:

void GLimp_WakeRenderer void *  data  ) 
 

Definition at line 1646 of file win_glimp.c.

References assert, data, GLSTAMP, glw_state, glwstate_t::hDC, INFINITE, NULL, OSX_GLContextClearCurrent, renderActiveEvent, renderCommandsEvent, renderThreadCondition, smpData, smpDataChanged, smpMutex, and wglErrors.

Referenced by R_IssueRenderCommands(), and R_ShutdownCommandBuffers().

01646                                       {
01647     smpData = data;
01648 
01649     if ( !qwglMakeCurrent( glw_state.hDC, NULL ) ) {
01650         wglErrors++;
01651     }
01652 
01653     // after this, the renderer can continue through GLimp_RendererSleep
01654     SetEvent( renderCommandsEvent );
01655 
01656     WaitForSingleObject( renderActiveEvent, INFINITE );
01657 }

qboolean GLW_CheckOSVersion void   )  [static]
 

Definition at line 1121 of file win_glimp.c.

References glwstate_t::allowdisplaydepthchange, glw_state, PRINT_ALL, qboolean, and ri.

Referenced by GLimp_Init().

01122 {
01123 #define OSR2_BUILD_NUMBER 1111
01124 
01125     OSVERSIONINFO   vinfo;
01126 
01127     vinfo.dwOSVersionInfoSize = sizeof(vinfo);
01128 
01129     glw_state.allowdisplaydepthchange = qfalse;
01130 
01131     if ( GetVersionEx( &vinfo) )
01132     {
01133         if ( vinfo.dwMajorVersion > 4 )
01134         {
01135             glw_state.allowdisplaydepthchange = qtrue;
01136         }
01137         else if ( vinfo.dwMajorVersion == 4 )
01138         {
01139             if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
01140             {
01141                 glw_state.allowdisplaydepthchange = qtrue;
01142             }
01143             else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
01144             {
01145                 if ( LOWORD( vinfo.dwBuildNumber ) >= OSR2_BUILD_NUMBER )
01146                 {
01147                     glw_state.allowdisplaydepthchange = qtrue;
01148                 }
01149             }
01150         }
01151     }
01152     else
01153     {
01154         ri.Printf( PRINT_ALL, "GLW_CheckOSVersion() - GetVersionEx failed\n" );
01155         return qfalse;
01156     }
01157 
01158     return qtrue;
01159 }

int GLW_ChoosePFD HDC  hDC,
PIXELFORMATDESCRIPTOR *  pPFD
[static]
 

Definition at line 120 of file win_glimp.c.

References glconfig_t::driverType, glConfig, i, cvar_s::integer, MAX_PFDS, PRINT_ALL, PRINT_WARNING, r_allowSoftwareGL, r_verbose, and ri.

Referenced by GLW_MakeContext().

00121 {
00122     PIXELFORMATDESCRIPTOR pfds[MAX_PFDS+1];
00123     int maxPFD = 0;
00124     int i;
00125     int bestMatch = 0;
00126 
00127     ri.Printf( PRINT_ALL, "...GLW_ChoosePFD( %d, %d, %d )\n", ( int ) pPFD->cColorBits, ( int ) pPFD->cDepthBits, ( int ) pPFD->cStencilBits );
00128 
00129     // count number of PFDs
00130     if ( glConfig.driverType > GLDRV_ICD )
00131     {
00132         maxPFD = qwglDescribePixelFormat( hDC, 1, sizeof( PIXELFORMATDESCRIPTOR ), &pfds[0] );
00133     }
00134     else
00135     {
00136         maxPFD = DescribePixelFormat( hDC, 1, sizeof( PIXELFORMATDESCRIPTOR ), &pfds[0] );
00137     }
00138     if ( maxPFD > MAX_PFDS )
00139     {
00140         ri.Printf( PRINT_WARNING, "...numPFDs > MAX_PFDS (%d > %d)\n", maxPFD, MAX_PFDS );
00141         maxPFD = MAX_PFDS;
00142     }
00143 
00144     ri.Printf( PRINT_ALL, "...%d PFDs found\n", maxPFD - 1 );
00145 
00146     // grab information
00147     for ( i = 1; i <= maxPFD; i++ )
00148     {
00149         if ( glConfig.driverType > GLDRV_ICD )
00150         {
00151             qwglDescribePixelFormat( hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), &pfds[i] );
00152         }
00153         else
00154         {
00155             DescribePixelFormat( hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), &pfds[i] );
00156         }
00157     }
00158 
00159     // look for a best match
00160     for ( i = 1; i <= maxPFD; i++ )
00161     {
00162         //
00163         // make sure this has hardware acceleration
00164         //
00165         if ( ( pfds[i].dwFlags & PFD_GENERIC_FORMAT ) != 0 ) 
00166         {
00167             if ( !r_allowSoftwareGL->integer )
00168             {
00169                 if ( r_verbose->integer )
00170                 {
00171                     ri.Printf( PRINT_ALL, "...PFD %d rejected, software acceleration\n", i );
00172                 }
00173                 continue;
00174             }
00175         }
00176 
00177         // verify pixel type
00178         if ( pfds[i].iPixelType != PFD_TYPE_RGBA )
00179         {
00180             if ( r_verbose->integer )
00181             {
00182                 ri.Printf( PRINT_ALL, "...PFD %d rejected, not RGBA\n", i );
00183             }
00184             continue;
00185         }
00186 
00187         // verify proper flags
00188         if ( ( ( pfds[i].dwFlags & pPFD->dwFlags ) & pPFD->dwFlags ) != pPFD->dwFlags ) 
00189         {
00190             if ( r_verbose->integer )
00191             {
00192                 ri.Printf( PRINT_ALL, "...PFD %d rejected, improper flags (%x instead of %x)\n", i, pfds[i].dwFlags, pPFD->dwFlags );
00193             }
00194             continue;
00195         }
00196 
00197         // verify enough bits
00198         if ( pfds[i].cDepthBits < 15 )
00199         {
00200             continue;
00201         }
00202         if ( ( pfds[i].cStencilBits < 4 ) && ( pPFD->cStencilBits > 0 ) )
00203         {
00204             continue;
00205         }
00206 
00207         //
00208         // selection criteria (in order of priority):
00209         // 
00210         //  PFD_STEREO
00211         //  colorBits
00212         //  depthBits
00213         //  stencilBits
00214         //
00215         if ( bestMatch )
00216         {
00217             // check stereo
00218             if ( ( pfds[i].dwFlags & PFD_STEREO ) && ( !( pfds[bestMatch].dwFlags & PFD_STEREO ) ) && ( pPFD->dwFlags & PFD_STEREO ) )
00219             {
00220                 bestMatch = i;
00221                 continue;
00222             }
00223             
00224             if ( !( pfds[i].dwFlags & PFD_STEREO ) && ( pfds[bestMatch].dwFlags & PFD_STEREO ) && ( pPFD->dwFlags & PFD_STEREO ) )
00225             {
00226                 bestMatch = i;
00227                 continue;
00228             }
00229 
00230             // check color
00231             if ( pfds[bestMatch].cColorBits != pPFD->cColorBits )
00232             {
00233                 // prefer perfect match
00234                 if ( pfds[i].cColorBits == pPFD->cColorBits )
00235                 {
00236                     bestMatch = i;
00237                     continue;
00238                 }
00239                 // otherwise if this PFD has more bits than our best, use it
00240                 else if ( pfds[i].cColorBits > pfds[bestMatch].cColorBits )
00241                 {
00242                     bestMatch = i;
00243                     continue;
00244                 }
00245             }
00246 
00247             // check depth
00248             if ( pfds[bestMatch].cDepthBits != pPFD->cDepthBits )
00249             {
00250                 // prefer perfect match
00251                 if ( pfds[i].cDepthBits == pPFD->cDepthBits )
00252                 {
00253                     bestMatch = i;
00254                     continue;
00255                 }
00256                 // otherwise if this PFD has more bits than our best, use it
00257                 else if ( pfds[i].cDepthBits > pfds[bestMatch].cDepthBits )
00258                 {
00259                     bestMatch = i;
00260                     continue;
00261                 }
00262             }
00263 
00264             // check stencil
00265             if ( pfds[bestMatch].cStencilBits != pPFD->cStencilBits )
00266             {
00267                 // prefer perfect match
00268                 if ( pfds[i].cStencilBits == pPFD->cStencilBits )
00269                 {
00270                     bestMatch = i;
00271                     continue;
00272                 }
00273                 // otherwise if this PFD has more bits than our best, use it
00274                 else if ( ( pfds[i].cStencilBits > pfds[bestMatch].cStencilBits ) && 
00275                      ( pPFD->cStencilBits > 0 ) )
00276                 {
00277                     bestMatch = i;
00278                     continue;
00279                 }
00280             }
00281         }
00282         else
00283         {
00284             bestMatch = i;
00285         }
00286     }
00287     
00288     if ( !bestMatch )
00289         return 0;
00290 
00291     if ( ( pfds[bestMatch].dwFlags & PFD_GENERIC_FORMAT ) != 0 )
00292     {
00293         if ( !r_allowSoftwareGL->integer )
00294         {
00295             ri.Printf( PRINT_ALL, "...no hardware acceleration found\n" );
00296             return 0;
00297         }
00298         else
00299         {
00300             ri.Printf( PRINT_ALL, "...using software emulation\n" );
00301         }
00302     }
00303     else if ( pfds[bestMatch].dwFlags & PFD_GENERIC_ACCELERATED )
00304     {
00305         ri.Printf( PRINT_ALL, "...MCD acceleration found\n" );
00306     }
00307     else
00308     {
00309         ri.Printf( PRINT_ALL, "...hardware acceleration found\n" );
00310     }
00311 
00312     *pPFD = pfds[bestMatch];
00313 
00314     return bestMatch;
00315 }

void GLW_CreatePFD PIXELFORMATDESCRIPTOR *  pPFD,
int  colorbits,
int  depthbits,
int  stencilbits,
qboolean  stereo
[static]
 

Definition at line 322 of file win_glimp.c.

References glConfig, PRINT_ALL, ri, src, and glconfig_t::stereoEnabled.

Referenced by GLW_InitDriver().

00323 {
00324     PIXELFORMATDESCRIPTOR src = 
00325     {
00326         sizeof(PIXELFORMATDESCRIPTOR),  // size of this pfd
00327         1,                              // version number
00328         PFD_DRAW_TO_WINDOW |            // support window
00329         PFD_SUPPORT_OPENGL |            // support OpenGL
00330         PFD_DOUBLEBUFFER,               // double buffered
00331         PFD_TYPE_RGBA,                  // RGBA type
00332         24,                             // 24-bit color depth
00333         0, 0, 0, 0, 0, 0,               // color bits ignored
00334         0,                              // no alpha buffer
00335         0,                              // shift bit ignored
00336         0,                              // no accumulation buffer
00337         0, 0, 0, 0,                     // accum bits ignored
00338         24,                             // 24-bit z-buffer  
00339         8,                              // 8-bit stencil buffer
00340         0,                              // no auxiliary buffer
00341         PFD_MAIN_PLANE,                 // main layer
00342         0,                              // reserved
00343         0, 0, 0                         // layer masks ignored
00344     };
00345 
00346     src.cColorBits = colorbits;
00347     src.cDepthBits = depthbits;
00348     src.cStencilBits = stencilbits;
00349 
00350     if ( stereo )
00351     {
00352         ri.Printf( PRINT_ALL, "...attempting to use stereo\n" );
00353         src.dwFlags |= PFD_STEREO;
00354         glConfig.stereoEnabled = qtrue;
00355     }
00356     else
00357     {
00358         glConfig.stereoEnabled = qfalse;
00359     }
00360 
00361     *pPFD = src;
00362 }

qboolean GLW_CreateWindow const char *  drivername,
int  width,
int  height,
int  colorbits,
qboolean  cdsFullscreen
[static]
 

Definition at line 577 of file win_glimp.c.

References _3DFX_DRIVER_NAME, refimport_t::Cvar_Get, cvar_t, glwstate_t::desktopHeight, glwstate_t::desktopWidth, ERR_FATAL, FALSE, g_wv, GLW_InitDriver(), glw_state, h(), WinVars_t::hInstance, glwstate_t::hInstance, WinVars_t::hWnd, IDI_ICON1, cvar_s::integer, memset(), NULL, PRINT_ALL, Q_stricmp(), qboolean, r, ri, s_classRegistered, vid_xpos, vid_ypos, w, WINDOW_CLASS_NAME, WINDOW_STYLE, glwstate_t::wndproc, x, and y.

Referenced by GLW_SetMode().

00578 {
00579     RECT            r;
00580     cvar_t          *vid_xpos, *vid_ypos;
00581     int             stylebits;
00582     int             x, y, w, h;
00583     int             exstyle;
00584 
00585     //
00586     // register the window class if necessary
00587     //
00588     if ( !s_classRegistered )
00589     {
00590         WNDCLASS wc;
00591 
00592         memset( &wc, 0, sizeof( wc ) );
00593 
00594         wc.style         = 0;
00595         wc.lpfnWndProc   = (WNDPROC) glw_state.wndproc;
00596         wc.cbClsExtra    = 0;
00597         wc.cbWndExtra    = 0;
00598         wc.hInstance     = g_wv.hInstance;
00599         wc.hIcon         = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1));
00600         wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
00601         wc.hbrBackground = (void *)COLOR_GRAYTEXT;
00602         wc.lpszMenuName  = 0;
00603         wc.lpszClassName = WINDOW_CLASS_NAME;
00604 
00605         if ( !RegisterClass( &wc ) )
00606         {
00607             ri.Error( ERR_FATAL, "GLW_CreateWindow: could not register window class" );
00608         }
00609         s_classRegistered = qtrue;
00610         ri.Printf( PRINT_ALL, "...registered window class\n" );
00611     }
00612 
00613     //
00614     // create the HWND if one does not already exist
00615     //
00616     if ( !g_wv.hWnd )
00617     {
00618         //
00619         // compute width and height
00620         //
00621         r.left = 0;
00622         r.top = 0;
00623         r.right  = width;
00624         r.bottom = height;
00625 
00626         if ( cdsFullscreen || !Q_stricmp( _3DFX_DRIVER_NAME, drivername ) )
00627         {
00628             exstyle = WS_EX_TOPMOST;
00629             stylebits = WS_POPUP|WS_VISIBLE|WS_SYSMENU;
00630         }
00631         else
00632         {
00633             exstyle = 0;
00634             stylebits = WINDOW_STYLE|WS_SYSMENU;
00635             AdjustWindowRect (&r, stylebits, FALSE);
00636         }
00637 
00638         w = r.right - r.left;
00639         h = r.bottom - r.top;
00640 
00641         if ( cdsFullscreen || !Q_stricmp( _3DFX_DRIVER_NAME, drivername ) )
00642         {
00643             x = 0;
00644             y = 0;
00645         }
00646         else
00647         {
00648             vid_xpos = ri.Cvar_Get ("vid_xpos", "", 0);
00649             vid_ypos = ri.Cvar_Get ("vid_ypos", "", 0);
00650             x = vid_xpos->integer;
00651             y = vid_ypos->integer;
00652 
00653             // adjust window coordinates if necessary 
00654             // so that the window is completely on screen
00655             if ( x < 0 )
00656                 x = 0;
00657             if ( y < 0 )
00658                 y = 0;
00659 
00660             if ( w < glw_state.desktopWidth &&
00661                  h < glw_state.desktopHeight )
00662             {
00663                 if ( x + w > glw_state.desktopWidth )
00664                     x = ( glw_state.desktopWidth - w );
00665                 if ( y + h > glw_state.desktopHeight )
00666                     y = ( glw_state.desktopHeight - h );
00667             }
00668         }
00669 
00670         g_wv.hWnd = CreateWindowEx (
00671              exstyle, 
00672              WINDOW_CLASS_NAME,
00673              "Quake 3: Arena",
00674              stylebits,
00675              x, y, w, h,
00676              NULL,
00677              NULL,
00678              g_wv.hInstance,
00679              NULL);
00680 
00681         if ( !g_wv.hWnd )
00682         {
00683             ri.Error (ERR_FATAL, "GLW_CreateWindow() - Couldn't create window");
00684         }
00685     
00686         ShowWindow( g_wv.hWnd, SW_SHOW );
00687         UpdateWindow( g_wv.hWnd );
00688         ri.Printf( PRINT_ALL, "...created window@%d,%d (%dx%d)\n", x, y, w, h );
00689     }
00690     else
00691     {
00692         ri.Printf( PRINT_ALL, "...window already present, CreateWindowEx skipped\n" );
00693     }
00694 
00695     if ( !GLW_InitDriver( drivername, colorbits ) )
00696     {
00697         ShowWindow( g_wv.hWnd, SW_HIDE );
00698         DestroyWindow( g_wv.hWnd );
00699         g_wv.hWnd = NULL;
00700 
00701         return qfalse;
00702     }
00703 
00704     SetForegroundWindow( g_wv.hWnd );
00705     SetFocus( g_wv.hWnd );
00706 
00707     return qtrue;
00708 }

Here is the call graph for this function:

qboolean GLW_InitDriver const char *  drivername,
int  colorbits
[static]
 

Definition at line 447 of file win_glimp.c.

References glconfig_t::colorBits, glconfig_t::depthBits, glwstate_t::desktopBitsPixel, g_wv, glConfig, GLW_CreatePFD(), GLW_MakeContext(), glw_state, glwstate_t::hDC, WinVars_t::hWnd, cvar_s::integer, glwstate_t::pixelFormatSet, PRINT_ALL, PRINT_WARNING, qboolean, r_colorbits, r_depthbits, r_stencilbits, r_stereo, ri, glconfig_t::stencilBits, and glconfig_t::stereoEnabled.

Referenced by GLW_CreateWindow().

00448 {
00449     int     tpfd;
00450     int     depthbits, stencilbits;
00451     static PIXELFORMATDESCRIPTOR pfd;       // save between frames since 'tr' gets cleared
00452 
00453     ri.Printf( PRINT_ALL, "Initializing OpenGL driver\n" );
00454 
00455     //
00456     // get a DC for our window if we don't already have one allocated
00457     //
00458     if ( glw_state.hDC == NULL )
00459     {
00460         ri.Printf( PRINT_ALL, "...getting DC: " );
00461 
00462         if ( ( glw_state.hDC = GetDC( g_wv.hWnd ) ) == NULL )
00463         {
00464             ri.Printf( PRINT_ALL, "failed\n" );
00465             return qfalse;
00466         }
00467         ri.Printf( PRINT_ALL, "succeeded\n" );
00468     }
00469 
00470     if ( colorbits == 0 )
00471     {
00472         colorbits = glw_state.desktopBitsPixel;
00473     }
00474 
00475     //
00476     // implicitly assume Z-buffer depth == desktop color depth
00477     //
00478     if ( r_depthbits->integer == 0 ) {
00479         if ( colorbits > 16 ) {
00480             depthbits = 24;
00481         } else {
00482             depthbits = 16;
00483         }
00484     } else {
00485         depthbits = r_depthbits->integer;
00486     }
00487 
00488     //
00489     // do not allow stencil if Z-buffer depth likely won't contain it
00490     //
00491     stencilbits = r_stencilbits->integer;
00492     if ( depthbits < 24 )
00493     {
00494         stencilbits = 0;
00495     }
00496 
00497     //
00498     // make two attempts to set the PIXELFORMAT
00499     //
00500 
00501     //
00502     // first attempt: r_colorbits, depthbits, and r_stencilbits
00503     //
00504     if ( !glw_state.pixelFormatSet )
00505     {
00506         GLW_CreatePFD( &pfd, colorbits, depthbits, stencilbits, r_stereo->integer );
00507         if ( ( tpfd = GLW_MakeContext( &pfd ) ) != TRY_PFD_SUCCESS )
00508         {
00509             if ( tpfd == TRY_PFD_FAIL_HARD )
00510             {
00511                 ri.Printf( PRINT_WARNING, "...failed hard\n" );
00512                 return qfalse;
00513             }
00514 
00515             //
00516             // punt if we've already tried the desktop bit depth and no stencil bits
00517             //
00518             if ( ( r_colorbits->integer == glw_state.desktopBitsPixel ) &&
00519                  ( stencilbits == 0 ) )
00520             {
00521                 ReleaseDC( g_wv.hWnd, glw_state.hDC );
00522                 glw_state.hDC = NULL;
00523 
00524                 ri.Printf( PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n" );
00525 
00526                 return qfalse;
00527             }
00528 
00529             //
00530             // second attempt: desktop's color bits and no stencil
00531             //
00532             if ( colorbits > glw_state.desktopBitsPixel )
00533             {
00534                 colorbits = glw_state.desktopBitsPixel;
00535             }
00536             GLW_CreatePFD( &pfd, colorbits, depthbits, 0, r_stereo->integer );
00537             if ( GLW_MakeContext( &pfd ) != TRY_PFD_SUCCESS )
00538             {
00539                 if ( glw_state.hDC )
00540                 {
00541                     ReleaseDC( g_wv.hWnd, glw_state.hDC );
00542                     glw_state.hDC = NULL;
00543                 }
00544 
00545                 ri.Printf( PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n" );
00546 
00547                 return qfalse;
00548             }
00549         }
00550 
00551         /*
00552         ** report if stereo is desired but unavailable
00553         */
00554         if ( !( pfd.dwFlags & PFD_STEREO ) && ( r_stereo->integer != 0 ) ) 
00555         {
00556             ri.Printf( PRINT_ALL, "...failed to select stereo pixel format\n" );
00557             glConfig.stereoEnabled = qfalse;
00558         }
00559     }
00560 
00561     /*
00562     ** store PFD specifics 
00563     */
00564     glConfig.colorBits = ( int ) pfd.cColorBits;
00565     glConfig.depthBits = ( int ) pfd.cDepthBits;
00566     glConfig.stencilBits = ( int ) pfd.cStencilBits;
00567 
00568     return qtrue;
00569 }

Here is the call graph for this function: