diff options
-rw-r--r-- | src/win_glimp.c | 149 | ||||
-rw-r--r-- | src/win_glimp.h | 5 | ||||
-rw-r--r-- | src/win_wgl.c | 107 | ||||
-rw-r--r-- | src/win_wgl.h | 37 |
4 files changed, 171 insertions, 127 deletions
diff --git a/src/win_glimp.c b/src/win_glimp.c index 7df65a8..d7c2069 100644 --- a/src/win_glimp.c +++ b/src/win_glimp.c @@ -66,6 +66,9 @@ void VID_Shutdown( void ) { if( gl_swapinterval ) { gl_swapinterval->changed = NULL; } + if( gl_drawbuffer ) { + gl_drawbuffer->changed = NULL; + } memset( &glw, 0, sizeof( glw ) ); } @@ -92,84 +95,101 @@ static qboolean InitGL( void ) { 0, 0, 0 // layer masks ignored }; int pixelformat; - const char *renderer; + const char *what; // figure out if we're running on a minidriver or not if( !Q_stristr( gl_driver->string, "opengl32" ) ) { Com_Printf( "...running a minidriver: %s\n", gl_driver->string ); glw.minidriver = qtrue; + } else { + glw.minidriver = qfalse; } // load OpenGL library - Com_DPrintf( "...initializing WGL: " ); if( !WGL_Init( gl_driver->string ) ) { + what = "WGL_Init"; goto fail1; } - Com_DPrintf( "ok\n" ); - Com_DPrintf( "...setting pixel format: " ); + // set pixel format if( glw.minidriver ) { + // check if certain entry points are present if using a minidriver + if( !qwglChoosePixelFormat || !qwglSetPixelFormat || + !qwglDescribePixelFormat || !qwglSwapBuffers ) + { + Com_EPrintf( "Required MCD entry points are missing\n" ); + goto fail2; + } + if ( ( pixelformat = qwglChoosePixelFormat( win.dc, &pfd ) ) == 0 ) { + what = "wglChoosePixelFormat"; goto fail1; } + if( qwglSetPixelFormat( win.dc, pixelformat, &pfd ) == FALSE ) { + what = "wglSetPixelFormat"; goto fail1; } + qwglDescribePixelFormat( win.dc, pixelformat, sizeof( pfd ), &pfd ); } else { if( ( pixelformat = ChoosePixelFormat( win.dc, &pfd ) ) == 0 ) { + what = "ChoosePixelFormat"; goto fail1; } + if( SetPixelFormat( win.dc, pixelformat, &pfd ) == FALSE ) { + what = "SetPixelFormat"; goto fail1; } + DescribePixelFormat( win.dc, pixelformat, sizeof( pfd ), &pfd ); } - Com_DPrintf( "ok\n" ); + + // check for software emulation + if( pfd.dwFlags & PFD_GENERIC_FORMAT ) { + if( !gl_allow_software->integer ) { + Com_EPrintf( "No hardware OpenGL acceleration detected\n" ); + goto fail2; + } + Com_WPrintf( "...using software emulation\n" ); + } else if( pfd.dwFlags & PFD_GENERIC_ACCELERATED ) { + Com_DPrintf( "...MCD acceleration found\n" ); + win.flags |= QVF_ACCELERATED; + } else { + Com_DPrintf( "...ICD acceleration found\n" ); + win.flags |= QVF_ACCELERATED; + } // startup the OpenGL subsystem by creating a context and making it current - Com_DPrintf( "...creating OpenGL context: " ); if( ( glw.hGLRC = qwglCreateContext( win.dc ) ) == NULL ) { + what = "wglCreateContext"; goto fail1; } - Com_DPrintf( "ok\n" ); - Com_DPrintf( "...making context current: " ); if( !qwglMakeCurrent( win.dc, glw.hGLRC ) ) { + what = "wglMakeCurrent"; goto fail1; } - Com_DPrintf( "ok\n" ); - - renderer = ( const char * )qglGetString( GL_RENDERER ); - - if( pfd.dwFlags & PFD_GENERIC_ACCELERATED ) { - win.flags |= QVF_ACCELERATED; - } else if( !renderer || !renderer[0] || !Q_stricmp( renderer, "gdi generic" ) ) { - Com_EPrintf( "No hardware OpenGL acceleration detected.\n" ); - if( !gl_allow_software->integer ) { - goto fail2; - } - } // print out PFD specifics - Com_Printf( "GL_VENDOR: %s\n", qglGetString( GL_VENDOR ) ); - Com_Printf( "GL_RENDERER: %s\n", renderer ); - Com_Printf( "GL_PFD: color(%d-bits: %d,%d,%d,%d) Z(%d-bit) stencil(%d-bit)\n", + Com_DPrintf( "GL_VENDOR: %s\n", qwglGetString( GL_VENDOR ) ); + Com_DPrintf( "GL_RENDERER: %s\n", qwglGetString( GL_RENDERER ) ); + Com_DPrintf( "GL_PFD: color(%d-bits: %d,%d,%d,%d) Z(%d-bit) stencil(%d-bit)\n", pfd.cColorBits, pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits, pfd.cDepthBits, pfd.cStencilBits ); return qtrue; fail1: - Com_DPrintf( "failed with error %#lx\n", GetLastError() ); -fail2: + Com_EPrintf( "%s failed with error %#lx\n", what, GetLastError() ); if( glw.hGLRC && qwglDeleteContext ) { qwglDeleteContext( glw.hGLRC ); glw.hGLRC = NULL; } +fail2: WGL_Shutdown(); - return qfalse; } @@ -179,6 +199,19 @@ static void gl_swapinterval_changed( cvar_t *self ) { } } +static void gl_drawbuffer_changed( cvar_t *self ) { + if( !Q_stricmp( self->string, "GL_FRONT" ) ) { + glw.drawbuffer = GL_FRONT; + } else if( !Q_stricmp( self->string, "GL_BACK" ) ) { + glw.drawbuffer = GL_BACK; + } else { + Cvar_Reset( self ); + glw.drawbuffer = GL_BACK; + } + + qwglDrawBuffer( glw.drawbuffer ); +} + /* GLimp_Init @@ -188,45 +221,54 @@ doing the wgl interface stuff. */ qboolean VID_Init( void ) { const char *extensions; + unsigned mask; - gl_driver = Cvar_Get( "gl_driver", "opengl32", CVAR_ARCHIVE|CVAR_REFRESH ); + gl_driver = Cvar_Get( "gl_driver", DEFAULT_OPENGL_DRIVER, CVAR_ARCHIVE|CVAR_REFRESH ); gl_drawbuffer = Cvar_Get( "gl_drawbuffer", "GL_BACK", 0 ); gl_swapinterval = Cvar_Get( "gl_swapinterval", "1", CVAR_ARCHIVE ); gl_allow_software = Cvar_Get( "gl_allow_software", "0", 0 ); - // create the window - Win_Init(); + while( 1 ) { + // create the window + Win_Init(); + + // initialize OpenGL context + if( InitGL() ) { + break; + } + + // it failed, clean up + Win_Shutdown(); - // initialize OpenGL context - if( !InitGL() ) { + // see if this was a minidriver if( !glw.minidriver ) { - goto fail; + return qfalse; } + + // attempt to recover Com_Printf( "...attempting to load opengl32\n" ); - Cvar_Set( "gl_driver","opengl32" ); - if( !InitGL() ) { - goto fail; - } + Cvar_Set( "gl_driver", "opengl32" ); } // initialize WGL extensions - extensions = ( const char * )qglGetString( GL_EXTENSIONS ); - if( extensions && strstr( extensions, "WGL_EXT_swap_control" ) ) { + extensions = ( const char * )qwglGetString( GL_EXTENSIONS ); + mask = WGL_ParseExtensionString( extensions ); + + if( mask & QWGL_EXT_swap_control ) { Com_Printf( "...enabling WGL_EXT_swap_control\n" ); - qwglSwapIntervalEXT = ( PFNWGLSWAPINTERWALEXTPROC )qwglGetProcAddress( "wglSwapIntervalEXT" ); + WGL_InitExtensions( QWGL_EXT_swap_control ); gl_swapinterval->changed = gl_swapinterval_changed; gl_swapinterval_changed( gl_swapinterval ); } else { Com_Printf( "WGL_EXT_swap_control not found\n" ); } + gl_drawbuffer->changed = gl_drawbuffer_changed; + gl_drawbuffer_changed( gl_drawbuffer ); + VID_SetMode(); return qtrue; - -fail: - Win_Shutdown(); - return qfalse; } void VID_VideoWait( void ) { @@ -247,11 +289,26 @@ as yet to be determined. Probably better not to make this a GLimp function and instead do a call to GLimp_SwapBuffers. */ void VID_EndFrame( void ) { - if( !qwglSwapBuffers( win.dc ) ) { - int error = GetLastError(); + BOOL ret; + + // don't flip if drawing to front buffer + if( glw.drawbuffer == GL_FRONT ) { + return; + } + + if( glw.minidriver ) { + ret = qwglSwapBuffers( win.dc ); + } else { + ret = SwapBuffers( win.dc ); + } + + if( !ret ) { + DWORD error = GetLastError(); + // this happens sometimes when the window is iconified if( !IsIconic( win.wnd ) ) { - Com_Error( ERR_FATAL, "wglSwapBuffers failed with error %#x", error ); + Com_Error( ERR_FATAL, "%s failed with error %#lx", + glw.minidriver ? "wglSwapBuffers" : "SwapBuffers", error ); } } } diff --git a/src/win_glimp.h b/src/win_glimp.h index c82cb18..34f363d 100644 --- a/src/win_glimp.h +++ b/src/win_glimp.h @@ -26,9 +26,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <GL/glu.h> typedef struct { - HGLRC hGLRC; // handle to GL rendering context + HGLRC hGLRC; // handle to GL rendering context HINSTANCE hinstOpenGL; // handle to GL library - qboolean minidriver; + qboolean minidriver; + GLenum drawbuffer; } glwstate_t; extern glwstate_t glw; diff --git a/src/win_wgl.c b/src/win_wgl.c index 410199d..f165350 100644 --- a/src/win_wgl.c +++ b/src/win_wgl.c @@ -21,26 +21,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "win_glimp.h" #include "win_wgl.h" -//void ( APIENTRY * qglDrawBuffer )(GLenum mode); -const GLubyte * ( APIENTRY * qglGetString )(GLenum name); +void ( APIENTRY * qwglDrawBuffer )(GLenum mode); +const GLubyte * ( APIENTRY * qwglGetString )(GLenum name); int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *); -int ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); -//int ( WINAPI * qwglGetPixelFormat)(HDC); -BOOL ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *); -BOOL ( WINAPI * qwglSwapBuffers)(HDC); +int ( WINAPI * qwglDescribePixelFormat )(HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); +BOOL ( WINAPI * qwglSetPixelFormat )(HDC, int, CONST PIXELFORMATDESCRIPTOR *); +BOOL ( WINAPI * qwglSwapBuffers )(HDC); -//BOOL ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT); -HGLRC ( WINAPI * qwglCreateContext)(HDC); -BOOL ( WINAPI * qwglDeleteContext)(HGLRC); -//HGLRC ( WINAPI * qwglGetCurrentContext)(VOID); -//HDC ( WINAPI * qwglGetCurrentDC)(VOID); -PROC ( WINAPI * qwglGetProcAddress)(LPCSTR); -BOOL ( WINAPI * qwglMakeCurrent)(HDC, HGLRC); +HGLRC ( WINAPI * qwglCreateContext )(HDC); +BOOL ( WINAPI * qwglDeleteContext )(HGLRC); +PROC ( WINAPI * qwglGetProcAddress )(LPCSTR); +BOOL ( WINAPI * qwglMakeCurrent )(HDC, HGLRC); -BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval ); -//BOOL ( WINAPI * qwglGetDeviceGammaRampEXT)( unsigned char *, unsigned char *, unsigned char * ); -//BOOL ( WINAPI * qwglSetDeviceGammaRampEXT)( const unsigned char *, const unsigned char *, const unsigned char * ); +BOOL ( WINAPI * qwglSwapIntervalEXT )(int interval); void WGL_Shutdown( void ) { if( glw.hinstOpenGL ) { @@ -48,73 +42,70 @@ void WGL_Shutdown( void ) { glw.hinstOpenGL = NULL; } - //qglDrawBuffer = NULL; - qglGetString = NULL; + qwglDrawBuffer = NULL; + qwglGetString = NULL; qwglChoosePixelFormat = NULL; qwglDescribePixelFormat = NULL; - //qwglGetPixelFormat = NULL; qwglSetPixelFormat = NULL; qwglSwapBuffers = NULL; - //qwglCopyContext = NULL; qwglCreateContext = NULL; qwglDeleteContext = NULL; - //qwglGetCurrentContext = NULL; - //qwglGetCurrentDC = NULL; qwglGetProcAddress = NULL; qwglMakeCurrent = NULL; - qwglSwapIntervalEXT = NULL; - //qwglGetDeviceGammaRampEXT = NULL; - //qwglSetDeviceGammaRampEXT = NULL; + WGL_ShutdownExtensions( ~0 ); } - -#define GPA( x ) do { \ - q ## x = ( void * )GetProcAddress( glw.hinstOpenGL, #x ); \ - if( !q ## x ) { \ - Com_DPrintf( " %s ", #x ); \ - return qfalse; \ - } \ - } while( 0 ) +#define GPA( x ) ( void * )GetProcAddress( glw.hinstOpenGL, x ); qboolean WGL_Init( const char *dllname ) { if( ( glw.hinstOpenGL = LoadLibrary( dllname ) ) == NULL ) { return qfalse; } - //GPA( glDrawBuffer ); - GPA( glGetString ); - - //GPA( wglCopyContext ); - GPA( wglCreateContext ); - //GPA( wglCreateLayerContext ); - GPA( wglDeleteContext ); - //GPA( wglDescribeLayerPlane ); - //GPA( wglGetCurrentContext ); - //GPA( wglGetCurrentDC ); - //GPA( wglGetLayerPaletteEntries ); - GPA( wglGetProcAddress ); - GPA( wglMakeCurrent ); - //GPA( wglRealizeLayerPalette ); - //GPA( wglSetLayerPaletteEntries ); - //GPA( wglShareLists ); - //GPA( wglSwapLayerBuffers ); + qwglDrawBuffer = GPA( "glDrawBuffer" ); + qwglGetString = GPA( "glGetString" ); - GPA( wglChoosePixelFormat ); - GPA( wglDescribePixelFormat ); - //GPA( wglGetPixelFormat ); - GPA( wglSetPixelFormat ); - GPA( wglSwapBuffers ); + qwglChoosePixelFormat = GPA( "wglChoosePixelFormat" ); + qwglDescribePixelFormat = GPA( "wglDescribePixelFormat" ); + qwglSetPixelFormat = GPA( "wglSetPixelFormat" ); + qwglSwapBuffers = GPA( "wglSwapBuffers" ); - qwglSwapIntervalEXT = NULL; - //qwglGetDeviceGammaRampEXT = NULL; - //qwglSetDeviceGammaRampEXT = NULL; + qwglCreateContext = GPA( "wglCreateContext" ); + qwglDeleteContext = GPA( "wglDeleteContext" ); + qwglGetProcAddress = GPA( "wglGetProcAddress" ); + qwglMakeCurrent = GPA( "wglMakeCurrent" ); return qtrue; } +#undef GPA + +void WGL_ShutdownExtensions( unsigned mask ) { + if( mask & QWGL_EXT_swap_control ) { + qwglSwapIntervalEXT = NULL; + } +} + +#define GPA( x ) ( void * )qwglGetProcAddress( x ) + +void WGL_InitExtensions( unsigned mask ) { + if( mask & QWGL_EXT_swap_control ) { + qwglSwapIntervalEXT = GPA( "wglSwapIntervalEXT" ); + } +} #undef GPA +unsigned WGL_ParseExtensionString( const char *s ) { + // must match defines in win_wgl.h! + static const char *const extnames[] = { + "WGL_EXT_swap_control", + NULL + }; + + return Com_ParseExtensionString( s, extnames ); +} + diff --git a/src/win_wgl.h b/src/win_wgl.h index b69f8be..dc639d9 100644 --- a/src/win_wgl.h +++ b/src/win_wgl.h @@ -22,31 +22,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // win_wgl.h // +#define QWGL_EXT_swap_control (1<<0) + qboolean WGL_Init( const char *dllname ); void WGL_Shutdown( void ); -void *WGL_GetProcAddress( const char *symbol ); - -//extern void ( APIENTRY * qglDrawBuffer )(GLenum mode); -extern const GLubyte * ( APIENTRY * qglGetString )(GLenum name); - -extern int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *); -extern int ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); -//extern int ( WINAPI * qwglGetPixelFormat)(HDC); -extern BOOL ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *); -extern BOOL ( WINAPI * qwglSwapBuffers)(HDC); +void WGL_InitExtensions( unsigned mask ); +void WGL_ShutdownExtensions( unsigned mask ); +unsigned WGL_ParseExtensionString( const char *s ); -//extern BOOL ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT); -extern HGLRC ( WINAPI * qwglCreateContext)(HDC); -extern BOOL ( WINAPI * qwglDeleteContext)(HGLRC); -//extern HGLRC ( WINAPI * qwglGetCurrentContext)(VOID); -//extern HDC ( WINAPI * qwglGetCurrentDC)(VOID); -extern PROC ( WINAPI * qwglGetProcAddress)(LPCSTR); -extern BOOL ( WINAPI * qwglMakeCurrent)(HDC, HGLRC); +extern void ( APIENTRY * qwglDrawBuffer )(GLenum mode); +extern const GLubyte * ( APIENTRY * qwglGetString )(GLenum name); -typedef BOOL ( WINAPI * PFNWGLSWAPINTERWALEXTPROC )( int ); -extern BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval ); +extern int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *); +extern int ( WINAPI * qwglDescribePixelFormat ) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); +extern BOOL ( WINAPI * qwglSetPixelFormat )(HDC, int, CONST PIXELFORMATDESCRIPTOR *); +extern BOOL ( WINAPI * qwglSwapBuffers )(HDC); -//extern BOOL ( WINAPI * qwglGetDeviceGammaRampEXT ) ( unsigned char *pRed, unsigned char *pGreen, unsigned char *pBlue ); -//extern BOOL ( WINAPI * qwglSetDeviceGammaRampEXT ) ( const unsigned char *pRed, const unsigned char *pGreen, const unsigned char *pBlue ); +extern HGLRC ( WINAPI * qwglCreateContext )(HDC); +extern BOOL ( WINAPI * qwglDeleteContext )(HGLRC); +extern PROC ( WINAPI * qwglGetProcAddress )(LPCSTR); +extern BOOL ( WINAPI * qwglMakeCurrent )(HDC, HGLRC); +extern BOOL ( WINAPI * qwglSwapIntervalEXT )(int interval); |