static unsigned GetFakeWindowExtensions(void) { WNDCLASSEX wc; PIXELFORMATDESCRIPTOR pfd; int pixelformat; HWND wnd; HDC dc; HGLRC rc; unsigned extensions = 0; memset(&wc, 0, sizeof(wc)); wc.cbSize = sizeof(wc); wc.lpfnWndProc = DefWindowProc; wc.hInstance = hGlobalInstance; wc.lpszClassName = FAKE_WINDOW_CLASS; if (!RegisterClassEx(&wc)) goto fail0; wnd = CreateWindow( FAKE_WINDOW_CLASS, FAKE_WINDOW_NAME, 0, 0, 0, 0, 0, NULL, NULL, hGlobalInstance, NULL); if (!wnd) goto fail1; if ((dc = GetDC(wnd)) == NULL) goto fail2; memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cDepthBits = 24; pfd.cStencilBits = 8; pfd.iLayerType = PFD_MAIN_PLANE; if (glw.minidriver) { if ((pixelformat = qwglChoosePixelFormat(dc, &pfd)) == 0) goto fail3; if (qwglSetPixelFormat(dc, pixelformat, &pfd) == FALSE) goto fail3; } else { if ((pixelformat = ChoosePixelFormat(dc, &pfd)) == 0) goto fail3; if (SetPixelFormat(dc, pixelformat, &pfd) == FALSE) goto fail3; } if ((rc = qwglCreateContext(dc)) == NULL) goto fail3; if (qwglMakeCurrent(dc, rc) == FALSE) goto fail4; WGL_InitExtensions(QWGL_ARB_extensions_string); if (!qwglGetExtensionsStringARB) goto fail5; extensions = WGL_ParseExtensionString(qwglGetExtensionsStringARB(dc)); if (extensions & QWGL_ARB_pixel_format) { Com_Printf("...enabling WGL_ARB_pixel_format\n"); WGL_InitExtensions(QWGL_ARB_pixel_format); } fail5: qwglMakeCurrent(NULL, NULL); fail4: qwglDeleteContext(rc); fail3: ReleaseDC(wnd, dc); fail2: DestroyWindow(wnd); fail1: UnregisterClass(FAKE_WINDOW_CLASS, hGlobalInstance); fail0: return extensions; }
/* VID_Init This routine is responsible for initializing the OS specific portions of OpenGL. Under Win32 this means dealing with the pixelformats and doing the wgl interface stuff. */ qboolean VID_Init(void) { const char *extensions; int ret; gl_driver = Cvar_Get("gl_driver", "opengl32", 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); gl_colorbits = Cvar_Get("gl_colorbits", "0", CVAR_REFRESH); gl_depthbits = Cvar_Get("gl_depthbits", "0", CVAR_REFRESH); gl_stencilbits = Cvar_Get("gl_stencilbits", "8", CVAR_REFRESH); gl_multisamples = Cvar_Get("gl_multisamples", "0", CVAR_REFRESH); // don't allow absolute or relative paths FS_SanitizeFilenameVariable(gl_driver); // load and initialize the OpenGL driver ret = LoadGL(gl_driver->string); // attempt to recover if this was a minidriver if (ret == FAIL_SOFT && glw.minidriver) { Com_Printf("...falling back to opengl32\n"); Cvar_Reset(gl_driver); ret = LoadGL(gl_driver->string); } // it failed, abort if (ret) return qfalse; // initialize WGL extensions WGL_InitExtensions(QWGL_ARB_extensions_string); if (qwglGetExtensionsStringARB) extensions = qwglGetExtensionsStringARB(win.dc); else extensions = NULL; // fall back to GL_EXTENSIONS for legacy drivers if (!extensions || !*extensions) extensions = (const char *)qwglGetString(GL_EXTENSIONS); glw.extensions = WGL_ParseExtensionString(extensions); if (glw.extensions & QWGL_EXT_swap_control) { if (glw.extensions & QWGL_EXT_swap_control_tear) Com_Printf("...enabling WGL_EXT_swap_control(_tear)\n"); else Com_Printf("...enabling WGL_EXT_swap_control\n"); 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"); Cvar_Set("gl_swapinterval", "0"); } gl_drawbuffer->changed = gl_drawbuffer_changed; gl_drawbuffer_changed(gl_drawbuffer); VID_SetMode(); return qtrue; }
static int LoadGL(const char *driver) { int colorbits = Cvar_ClampInteger(gl_colorbits, 0, 32); int depthbits = Cvar_ClampInteger(gl_depthbits, 0, 32); int stencilbits = Cvar_ClampInteger(gl_stencilbits, 0, 8); int multisamples = Cvar_ClampInteger(gl_multisamples, 0, 32); int ret; // figure out if we're running on a minidriver or not if (!Q_stricmp(driver, "opengl32") || !Q_stricmp(driver, "opengl32.dll")) { glw.minidriver = qfalse; } else { Com_Printf("...running a minidriver: %s\n", driver); glw.minidriver = qtrue; } // load the OpenGL library and bind to it if (!WGL_Init(driver)) { ReportLastError("WGL_Init"); return FAIL_SOFT; } // check if basic WGL entry points are present if (!qwglCreateContext || !qwglMakeCurrent || !qwglDeleteContext) { Com_EPrintf("Required WGL entry points are missing\n"); goto fail; } if (glw.minidriver) { // check if MCD entry points are present if using a minidriver if (!qwglChoosePixelFormat || !qwglSetPixelFormat || !qwglDescribePixelFormat || !qwglSwapBuffers) { Com_EPrintf("Required MCD entry points are missing\n"); goto fail; } } // check for WGL_ARB_multisample by creating a fake window if (multisamples > 1) { unsigned extensions = GetFakeWindowExtensions(); if (extensions & QWGL_ARB_multisample) { if (extensions & QWGL_ARB_pixel_format) { Com_Printf("...enabling WGL_ARB_pixel_format\n"); Com_Printf("...enabling WGL_ARB_multisample\n"); WGL_InitExtensions(QWGL_ARB_pixel_format); } else { Com_Printf("...ignoring WGL_ARB_multisample, WGL_ARB_pixel_format not found\n"); Cvar_Set("gl_multisamples", "0"); multisamples = 0; } } else { Com_Printf("WGL_ARB_multisample not found\n"); Cvar_Set("gl_multisamples", "0"); multisamples = 0; } } // create window, choose PFD, setup OpenGL context ret = SetupGL(colorbits, depthbits, stencilbits, multisamples); // attempt to recover if (ret == FAIL_SOFT && (colorbits || depthbits || stencilbits || multisamples > 1)) ret = SetupGL(0, 0, 0, 0); if (ret) goto fail; return FAIL_OK; fail: // it failed, clean up WGL_Shutdown(); return FAIL_SOFT; }