summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2011-02-05 23:17:56 +0300
committerAndrey Nazarov <skuller@skuller.net>2011-02-05 23:34:41 +0300
commitabdde4dc29aafb1eaa62046b45ab7f61a4e4840b (patch)
tree83469df4027a9af2dee69db3fc63e5939c90fd11
parent9611639bf3f31eb2af1eddbe83f9ba6c18550a7e (diff)
Improve WGL and GLimp code.
Report errors in a more visible way. Silence PFD specifics messages. Don't fail WGL_Init if entry points are missing. Check for MCD entry points only if minidriver is detected. Use SwapBuffers instead of wglSwapBuffers unless minidriver is detected. Completely destroy and recreate the main window when recovering from a broken minidriver. Detect software emulation and hardware acceleration the way Q3 does it. Implement ‘gl_drawbuffer’ cvar. Remove unused WGL entry points. Use Com_ParseExtensionString for parsing WGL extensions. Rename qglDrawBuffer and qglGetString to avoid clashes with QGL subsystem.
-rw-r--r--src/win_glimp.c149
-rw-r--r--src/win_glimp.h5
-rw-r--r--src/win_wgl.c107
-rw-r--r--src/win_wgl.h37
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);