123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- /*
- ** WIN_GLIMP.C
- **
- ** This file contains ALL Win32 specific stuff having to do with the
- ** OpenGL refresh. When a port is being made the following functions
- ** must be implemented by the port:
- **
- ** GLimp_SwapBuffers
- ** GLimp_Init
- ** GLimp_Shutdown
- ** GLimp_SetGamma
- **
- ** Note that the GLW_xxx functions are Windows specific GL-subsystem
- ** related functions that are relevant ONLY to win_glimp.c
- */
- #pragma hdrstop
- #include "../../idlib/precompiled.h"
- #include "win_local.h"
- #include "rc/doom_resource.h"
- #include "../../renderer/tr_local.h"
- // WGL_ARB_extensions_string
- PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
- // WGL_EXT_swap_interval
- PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
- // WGL_ARB_pixel_format
- PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB;
- PFNWGLGETPIXELFORMATATTRIBFVARBPROC wglGetPixelFormatAttribfvARB;
- PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
- // WGL_ARB_create_context
- PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
- idCVar r_useOpenGL32( "r_useOpenGL32", "1", CVAR_INTEGER, "0 = OpenGL 2.0, 1 = OpenGL 3.2 compatibility profile, 2 = OpenGL 3.2 core profile", 0, 2 );
- //
- // function declaration
- //
- bool QGL_Init( const char *dllname );
- void QGL_Shutdown();
- /*
- ========================
- GLimp_TestSwapBuffers
- ========================
- */
- void GLimp_TestSwapBuffers( const idCmdArgs &args ) {
- idLib::Printf( "GLimp_TimeSwapBuffers\n" );
- static const int MAX_FRAMES = 5;
- uint64 timestamps[MAX_FRAMES];
- qglDisable( GL_SCISSOR_TEST );
- int frameMilliseconds = 16;
- for ( int swapInterval = 2 ; swapInterval >= -1 ; swapInterval-- ) {
- wglSwapIntervalEXT( swapInterval );
- for ( int i = 0 ; i < MAX_FRAMES ; i++ ) {
- if ( swapInterval == -1 ) {
- Sys_Sleep( frameMilliseconds );
- }
- if ( i & 1 ) {
- qglClearColor( 0, 1, 0, 1 );
- } else {
- qglClearColor( 1, 0, 0, 1 );
- }
- qglClear( GL_COLOR_BUFFER_BIT );
- qwglSwapBuffers( win32.hDC );
- qglFinish();
- timestamps[i] = Sys_Microseconds();
- }
- idLib::Printf( "\nswapinterval %i\n", swapInterval );
- for ( int i = 1 ; i < MAX_FRAMES ; i++ ) {
- idLib::Printf( "%i microseconds\n", (int)(timestamps[i] - timestamps[i-1]) );
- }
- }
- }
- /*
- ========================
- GLimp_GetOldGammaRamp
- ========================
- */
- static void GLimp_SaveGamma() {
- HDC hDC;
- BOOL success;
- hDC = GetDC( GetDesktopWindow() );
- success = GetDeviceGammaRamp( hDC, win32.oldHardwareGamma );
- common->DPrintf( "...getting default gamma ramp: %s\n", success ? "success" : "failed" );
- ReleaseDC( GetDesktopWindow(), hDC );
- }
- /*
- ========================
- GLimp_RestoreGamma
- ========================
- */
- static void GLimp_RestoreGamma() {
- HDC hDC;
- BOOL success;
- // if we never read in a reasonable looking
- // table, don't write it out
- if ( win32.oldHardwareGamma[0][255] == 0 ) {
- return;
- }
- hDC = GetDC( GetDesktopWindow() );
- success = SetDeviceGammaRamp( hDC, win32.oldHardwareGamma );
- common->DPrintf ( "...restoring hardware gamma: %s\n", success ? "success" : "failed" );
- ReleaseDC( GetDesktopWindow(), hDC );
- }
- /*
- ========================
- GLimp_SetGamma
- The renderer calls this when the user adjusts r_gamma or r_brightness
- ========================
- */
- void GLimp_SetGamma( unsigned short red[256], unsigned short green[256], unsigned short blue[256] ) {
- unsigned short table[3][256];
- int i;
- if ( !win32.hDC ) {
- return;
- }
- for ( i = 0; i < 256; i++ ) {
- table[0][i] = red[i];
- table[1][i] = green[i];
- table[2][i] = blue[i];
- }
- if ( !SetDeviceGammaRamp( win32.hDC, table ) ) {
- common->Printf( "WARNING: SetDeviceGammaRamp failed.\n" );
- }
- }
- /*
- =============================================================================
- WglExtension Grabbing
- This is gross -- creating a window just to get a context to get the wgl extensions
- =============================================================================
- */
- /*
- ========================
- R_CheckWinExtension
- ========================
- */
- bool R_CheckWinExtension( const char * name ) {
- if ( !strstr( glConfig.wgl_extensions_string, name ) ) {
- idLib::Printf( "X..%s not found\n", name );
- return false;
- }
- idLib::Printf( "...using %s\n", name );
- return true;
- }
- /*
- ====================
- FakeWndProc
- Only used to get wglExtensions
- ====================
- */
- LONG WINAPI FakeWndProc (
- HWND hWnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- if ( uMsg == WM_DESTROY ) {
- PostQuitMessage(0);
- }
- if ( uMsg != WM_CREATE ) {
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
- }
- const static PIXELFORMATDESCRIPTOR pfd = {
- sizeof(PIXELFORMATDESCRIPTOR),
- 1,
- PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
- PFD_TYPE_RGBA,
- 24,
- 0, 0, 0, 0, 0, 0,
- 8, 0,
- 0, 0, 0, 0,
- 24, 8,
- 0,
- PFD_MAIN_PLANE,
- 0,
- 0,
- 0,
- 0,
- };
- int pixelFormat;
- HDC hDC;
- HGLRC hGLRC;
- hDC = GetDC(hWnd);
- // Set up OpenGL
- pixelFormat = ChoosePixelFormat(hDC, &pfd);
- SetPixelFormat(hDC, pixelFormat, &pfd);
- hGLRC = qwglCreateContext(hDC);
- qwglMakeCurrent(hDC, hGLRC);
- // free things
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(hGLRC);
- ReleaseDC(hWnd, hDC);
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
- }
- /*
- ==================
- GLW_GetWGLExtensionsWithFakeWindow
- ==================
- */
- void GLW_CheckWGLExtensions( HDC hDC ) {
- wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
- GLimp_ExtensionPointer("wglGetExtensionsStringARB");
- if ( wglGetExtensionsStringARB ) {
- glConfig.wgl_extensions_string = (const char *) wglGetExtensionsStringARB(hDC);
- } else {
- glConfig.wgl_extensions_string = "";
- }
- // WGL_EXT_swap_control
- wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) GLimp_ExtensionPointer( "wglSwapIntervalEXT" );
- r_swapInterval.SetModified(); // force a set next frame
- // WGL_EXT_swap_control_tear
- glConfig.swapControlTearAvailable = R_CheckWinExtension( "WGL_EXT_swap_control_tear" );
- // WGL_ARB_pixel_format
- wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)GLimp_ExtensionPointer("wglGetPixelFormatAttribivARB");
- wglGetPixelFormatAttribfvARB = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)GLimp_ExtensionPointer("wglGetPixelFormatAttribfvARB");
- wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)GLimp_ExtensionPointer("wglChoosePixelFormatARB");
- // wglCreateContextAttribsARB
- wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress( "wglCreateContextAttribsARB" );
- }
- /*
- ==================
- GLW_GetWGLExtensionsWithFakeWindow
- ==================
- */
- static void GLW_GetWGLExtensionsWithFakeWindow() {
- HWND hWnd;
- MSG msg;
- // Create a window for the sole purpose of getting
- // a valid context to get the wglextensions
- hWnd = CreateWindow(WIN32_FAKE_WINDOW_CLASS_NAME, GAME_NAME,
- WS_OVERLAPPEDWINDOW,
- 40, 40,
- 640,
- 480,
- NULL, NULL, win32.hInstance, NULL );
- if ( !hWnd ) {
- common->FatalError( "GLW_GetWGLExtensionsWithFakeWindow: Couldn't create fake window" );
- }
- HDC hDC = GetDC( hWnd );
- HGLRC gRC = wglCreateContext( hDC );
- wglMakeCurrent( hDC, gRC );
- GLW_CheckWGLExtensions( hDC );
- wglDeleteContext( gRC );
- ReleaseDC( hWnd, hDC );
- DestroyWindow( hWnd );
- while ( GetMessage( &msg, NULL, 0, 0 ) ) {
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- }
- //=============================================================================
- /*
- ====================
- GLW_WM_CREATE
- ====================
- */
- void GLW_WM_CREATE( HWND hWnd ) {
- }
- /*
- ========================
- CreateOpenGLContextOnDC
- ========================
- */
- static HGLRC CreateOpenGLContextOnDC( const HDC hdc, const bool debugContext ) {
- int useOpenGL32 = r_useOpenGL32.GetInteger();
- HGLRC m_hrc = NULL;
- for ( int i = 0; i < 2; i++ ) {
- const int glMajorVersion = ( useOpenGL32 != 0 ) ? 3 : 2;
- const int glMinorVersion = ( useOpenGL32 != 0 ) ? 2 : 0;
- const int glDebugFlag = debugContext ? WGL_CONTEXT_DEBUG_BIT_ARB : 0;
- const int glProfileMask = ( useOpenGL32 != 0 ) ? WGL_CONTEXT_PROFILE_MASK_ARB : 0;
- const int glProfile = ( useOpenGL32 == 1 ) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : ( ( useOpenGL32 == 2 ) ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : 0 );
- const int attribs[] =
- {
- WGL_CONTEXT_MAJOR_VERSION_ARB, glMajorVersion,
- WGL_CONTEXT_MINOR_VERSION_ARB, glMinorVersion,
- WGL_CONTEXT_FLAGS_ARB, glDebugFlag,
- glProfileMask, glProfile,
- 0
- };
- m_hrc = wglCreateContextAttribsARB( hdc, 0, attribs );
- if ( m_hrc != NULL ) {
- idLib::Printf( "created OpenGL %d.%d context\n", glMajorVersion, glMinorVersion );
- break;
- }
- idLib::Printf( "failed to create OpenGL %d.%d context\n", glMajorVersion, glMinorVersion );
- useOpenGL32 = 0; // fall back to OpenGL 2.0
- }
- if ( m_hrc == NULL ) {
- int err = GetLastError();
- switch( err ) {
- case ERROR_INVALID_VERSION_ARB: idLib::Printf( "ERROR_INVALID_VERSION_ARB\n" ); break;
- case ERROR_INVALID_PROFILE_ARB: idLib::Printf( "ERROR_INVALID_PROFILE_ARB\n" ); break;
- default: idLib::Printf( "unknown error: 0x%x\n", err ); break;
- }
- }
- return m_hrc;
- }
- /*
- ====================
- GLW_ChoosePixelFormat
- Returns -1 on failure, or a pixel format
- ====================
- */
- static int GLW_ChoosePixelFormat( const HDC hdc, const int multisamples, const bool stereo3D ) {
- FLOAT fAttributes[] = { 0, 0 };
- int iAttributes[] = {
- WGL_SAMPLE_BUFFERS_ARB, ( ( multisamples > 1 ) ? 1 : 0 ),
- WGL_SAMPLES_ARB, multisamples,
- WGL_DOUBLE_BUFFER_ARB, TRUE,
- WGL_STENCIL_BITS_ARB, 8,
- WGL_DEPTH_BITS_ARB, 24,
- WGL_RED_BITS_ARB, 8,
- WGL_BLUE_BITS_ARB, 8,
- WGL_GREEN_BITS_ARB, 8,
- WGL_ALPHA_BITS_ARB, 8,
- WGL_STEREO_ARB, ( stereo3D ? TRUE : FALSE ),
- 0, 0
- };
- int pixelFormat;
- UINT numFormats;
- if ( !wglChoosePixelFormatARB( hdc, iAttributes, fAttributes, 1, &pixelFormat, &numFormats ) ) {
- return -1;
- }
- return pixelFormat;
- }
- /*
- ====================
- GLW_InitDriver
- Set the pixelformat for the window before it is
- shown, and create the rendering context
- ====================
- */
- static bool GLW_InitDriver( glimpParms_t parms ) {
- PIXELFORMATDESCRIPTOR src =
- {
- sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
- 1, // version number
- PFD_DRAW_TO_WINDOW | // support window
- PFD_SUPPORT_OPENGL | // support OpenGL
- PFD_DOUBLEBUFFER, // double buffered
- PFD_TYPE_RGBA, // RGBA type
- 32, // 32-bit color depth
- 0, 0, 0, 0, 0, 0, // color bits ignored
- 8, // 8 bit destination alpha
- 0, // shift bit ignored
- 0, // no accumulation buffer
- 0, 0, 0, 0, // accum bits ignored
- 24, // 24-bit z-buffer
- 8, // 8-bit stencil buffer
- 0, // no auxiliary buffer
- PFD_MAIN_PLANE, // main layer
- 0, // reserved
- 0, 0, 0 // layer masks ignored
- };
- common->Printf( "Initializing OpenGL driver\n" );
- //
- // get a DC for our window if we don't already have one allocated
- //
- if ( win32.hDC == NULL ) {
- common->Printf( "...getting DC: " );
- if ( ( win32.hDC = GetDC( win32.hWnd ) ) == NULL ) {
- common->Printf( "^3failed^0\n" );
- return false;
- }
- common->Printf( "succeeded\n" );
- }
- // the multisample path uses the wgl
- if ( wglChoosePixelFormatARB ) {
- win32.pixelformat = GLW_ChoosePixelFormat( win32.hDC, parms.multiSamples, parms.stereo );
- } else {
- // this is the "classic" choose pixel format path
- common->Printf( "Using classic ChoosePixelFormat\n" );
- // eventually we may need to have more fallbacks, but for
- // now, ask for everything
- if ( parms.stereo ) {
- common->Printf( "...attempting to use stereo\n" );
- src.dwFlags |= PFD_STEREO;
- }
- //
- // choose, set, and describe our desired pixel format. If we're
- // using a minidriver then we need to bypass the GDI functions,
- // otherwise use the GDI functions.
- //
- if ( ( win32.pixelformat = ChoosePixelFormat( win32.hDC, &src ) ) == 0 ) {
- common->Printf( "...^3GLW_ChoosePFD failed^0\n");
- return false;
- }
- common->Printf( "...PIXELFORMAT %d selected\n", win32.pixelformat );
- }
- // get the full info
- DescribePixelFormat( win32.hDC, win32.pixelformat, sizeof( win32.pfd ), &win32.pfd );
- glConfig.colorBits = win32.pfd.cColorBits;
- glConfig.depthBits = win32.pfd.cDepthBits;
- glConfig.stencilBits = win32.pfd.cStencilBits;
- // XP seems to set this incorrectly
- if ( !glConfig.stencilBits ) {
- glConfig.stencilBits = 8;
- }
- // the same SetPixelFormat is used either way
- if ( SetPixelFormat( win32.hDC, win32.pixelformat, &win32.pfd ) == FALSE ) {
- common->Printf( "...^3SetPixelFormat failed^0\n", win32.hDC );
- return false;
- }
- //
- // startup the OpenGL subsystem by creating a context and making it current
- //
- common->Printf( "...creating GL context: " );
- win32.hGLRC = CreateOpenGLContextOnDC( win32.hDC, r_debugContext.GetBool() );
- if ( win32.hGLRC == 0 ) {
- common->Printf( "^3failed^0\n" );
- return false;
- }
- common->Printf( "succeeded\n" );
- common->Printf( "...making context current: " );
- if ( !qwglMakeCurrent( win32.hDC, win32.hGLRC ) ) {
- qwglDeleteContext( win32.hGLRC );
- win32.hGLRC = NULL;
- common->Printf( "^3failed^0\n" );
- return false;
- }
- common->Printf( "succeeded\n" );
- return true;
- }
- /*
- ====================
- GLW_CreateWindowClasses
- ====================
- */
- static void GLW_CreateWindowClasses() {
- WNDCLASS wc;
- //
- // register the window class if necessary
- //
- if ( win32.windowClassRegistered ) {
- return;
- }
- memset( &wc, 0, sizeof( wc ) );
- wc.style = 0;
- wc.lpfnWndProc = (WNDPROC) MainWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = win32.hInstance;
- wc.hIcon = LoadIcon( win32.hInstance, MAKEINTRESOURCE(IDI_ICON1));
- wc.hCursor = NULL;
- wc.hbrBackground = (struct HBRUSH__ *)COLOR_GRAYTEXT;
- wc.lpszMenuName = 0;
- wc.lpszClassName = WIN32_WINDOW_CLASS_NAME;
- if ( !RegisterClass( &wc ) ) {
- common->FatalError( "GLW_CreateWindow: could not register window class" );
- }
- common->Printf( "...registered window class\n" );
- // now register the fake window class that is only used
- // to get wgl extensions
- wc.style = 0;
- wc.lpfnWndProc = (WNDPROC) FakeWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = win32.hInstance;
- wc.hIcon = LoadIcon( win32.hInstance, MAKEINTRESOURCE(IDI_ICON1));
- wc.hCursor = LoadCursor (NULL,IDC_ARROW);
- wc.hbrBackground = (struct HBRUSH__ *)COLOR_GRAYTEXT;
- wc.lpszMenuName = 0;
- wc.lpszClassName = WIN32_FAKE_WINDOW_CLASS_NAME;
- if ( !RegisterClass( &wc ) ) {
- common->FatalError( "GLW_CreateWindow: could not register window class" );
- }
- common->Printf( "...registered fake window class\n" );
- win32.windowClassRegistered = true;
- }
- /*
- ========================
- GetDisplayName
- ========================
- */
- static const char * GetDisplayName( const int deviceNum ) {
- static DISPLAY_DEVICE device;
- device.cb = sizeof( device );
- if ( !EnumDisplayDevices(
- 0, // lpDevice
- deviceNum,
- &device,
- 0 /* dwFlags */ ) ) {
- return NULL;
- }
- return device.DeviceName;
- }
- /*
- ========================
- GetDeviceName
- ========================
- */
- static idStr GetDeviceName( const int deviceNum ) {
- DISPLAY_DEVICE device = {};
- device.cb = sizeof( device );
- if ( !EnumDisplayDevices(
- 0, // lpDevice
- deviceNum,
- &device,
- 0 /* dwFlags */ ) ) {
- return false;
- }
- // get the monitor for this display
- if ( ! (device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP ) ) {
- return false;
- }
- return idStr( device.DeviceName );
- }
- /*
- ========================
- GetDisplayCoordinates
- ========================
- */
- static bool GetDisplayCoordinates( const int deviceNum, int & x, int & y, int & width, int & height, int & displayHz ) {
- idStr deviceName = GetDeviceName( deviceNum );
- if ( deviceName.Length() == 0 ) {
- return false;
- }
- DISPLAY_DEVICE device = {};
- device.cb = sizeof( device );
- if ( !EnumDisplayDevices(
- 0, // lpDevice
- deviceNum,
- &device,
- 0 /* dwFlags */ ) ) {
- return false;
- }
- DISPLAY_DEVICE monitor;
- monitor.cb = sizeof( monitor );
- if ( !EnumDisplayDevices(
- deviceName.c_str(),
- 0,
- &monitor,
- 0 /* dwFlags */ ) ) {
- return false;
- }
- DEVMODE devmode;
- devmode.dmSize = sizeof( devmode );
- if ( !EnumDisplaySettings( deviceName.c_str(),ENUM_CURRENT_SETTINGS, &devmode ) ) {
- return false;
- }
- common->Printf( "display device: %i\n", deviceNum );
- common->Printf( " DeviceName : %s\n", device.DeviceName );
- common->Printf( " DeviceString: %s\n", device.DeviceString );
- common->Printf( " StateFlags : 0x%x\n", device.StateFlags );
- common->Printf( " DeviceID : %s\n", device.DeviceID );
- common->Printf( " DeviceKey : %s\n", device.DeviceKey );
- common->Printf( " DeviceName : %s\n", monitor.DeviceName );
- common->Printf( " DeviceString: %s\n", monitor.DeviceString );
- common->Printf( " StateFlags : 0x%x\n", monitor.StateFlags );
- common->Printf( " DeviceID : %s\n", monitor.DeviceID );
- common->Printf( " DeviceKey : %s\n", monitor.DeviceKey );
- common->Printf( " dmPosition.x : %i\n", devmode.dmPosition.x );
- common->Printf( " dmPosition.y : %i\n", devmode.dmPosition.y );
- common->Printf( " dmBitsPerPel : %i\n", devmode.dmBitsPerPel );
- common->Printf( " dmPelsWidth : %i\n", devmode.dmPelsWidth );
- common->Printf( " dmPelsHeight : %i\n", devmode.dmPelsHeight );
- common->Printf( " dmDisplayFlags : 0x%x\n", devmode.dmDisplayFlags );
- common->Printf( " dmDisplayFrequency: %i\n", devmode.dmDisplayFrequency );
- x = devmode.dmPosition.x;
- y = devmode.dmPosition.y;
- width = devmode.dmPelsWidth;
- height = devmode.dmPelsHeight;
- displayHz = devmode.dmDisplayFrequency;
- return true;
- }
- /*
- ====================
- DMDFO
- ====================
- */
- static const char * DMDFO( int dmDisplayFixedOutput ) {
- switch( dmDisplayFixedOutput ) {
- case DMDFO_DEFAULT: return "DMDFO_DEFAULT";
- case DMDFO_CENTER: return "DMDFO_CENTER";
- case DMDFO_STRETCH: return "DMDFO_STRETCH";
- }
- return "UNKNOWN";
- }
- /*
- ====================
- PrintDevMode
- ====================
- */
- static void PrintDevMode( DEVMODE & devmode ) {
- common->Printf( " dmPosition.x : %i\n", devmode.dmPosition.x );
- common->Printf( " dmPosition.y : %i\n", devmode.dmPosition.y );
- common->Printf( " dmBitsPerPel : %i\n", devmode.dmBitsPerPel );
- common->Printf( " dmPelsWidth : %i\n", devmode.dmPelsWidth );
- common->Printf( " dmPelsHeight : %i\n", devmode.dmPelsHeight );
- common->Printf( " dmDisplayFixedOutput: %s\n", DMDFO( devmode.dmDisplayFixedOutput ) );
- common->Printf( " dmDisplayFlags : 0x%x\n", devmode.dmDisplayFlags );
- common->Printf( " dmDisplayFrequency : %i\n", devmode.dmDisplayFrequency );
- }
- /*
- ====================
- DumpAllDisplayDevices
- ====================
- */
- void DumpAllDisplayDevices() {
- common->Printf( "\n" );
- for ( int deviceNum = 0 ; ; deviceNum++ ) {
- DISPLAY_DEVICE device = {};
- device.cb = sizeof( device );
- if ( !EnumDisplayDevices(
- 0, // lpDevice
- deviceNum,
- &device,
- 0 /* dwFlags */ ) ) {
- break;
- }
- common->Printf( "display device: %i\n", deviceNum );
- common->Printf( " DeviceName : %s\n", device.DeviceName );
- common->Printf( " DeviceString: %s\n", device.DeviceString );
- common->Printf( " StateFlags : 0x%x\n", device.StateFlags );
- common->Printf( " DeviceID : %s\n", device.DeviceID );
- common->Printf( " DeviceKey : %s\n", device.DeviceKey );
- for ( int monitorNum = 0 ; ; monitorNum++ ) {
- DISPLAY_DEVICE monitor = {};
- monitor.cb = sizeof( monitor );
- if ( !EnumDisplayDevices(
- device.DeviceName,
- monitorNum,
- &monitor,
- 0 /* dwFlags */ ) ) {
- break;
- }
- common->Printf( " DeviceName : %s\n", monitor.DeviceName );
- common->Printf( " DeviceString: %s\n", monitor.DeviceString );
- common->Printf( " StateFlags : 0x%x\n", monitor.StateFlags );
- common->Printf( " DeviceID : %s\n", monitor.DeviceID );
- common->Printf( " DeviceKey : %s\n", monitor.DeviceKey );
- DEVMODE currentDevmode = {};
- if ( !EnumDisplaySettings( device.DeviceName,ENUM_CURRENT_SETTINGS, ¤tDevmode ) ) {
- common->Printf( "ERROR: EnumDisplaySettings(ENUM_CURRENT_SETTINGS) failed!\n" );
- }
- common->Printf( " -------------------\n" );
- common->Printf( " ENUM_CURRENT_SETTINGS\n" );
- PrintDevMode( currentDevmode );
- DEVMODE registryDevmode = {};
- if ( !EnumDisplaySettings( device.DeviceName,ENUM_REGISTRY_SETTINGS, ®istryDevmode ) ) {
- common->Printf( "ERROR: EnumDisplaySettings(ENUM_CURRENT_SETTINGS) failed!\n" );
- }
- common->Printf( " -------------------\n" );
- common->Printf( " ENUM_CURRENT_SETTINGS\n" );
- PrintDevMode( registryDevmode );
- for ( int modeNum = 0 ; ; modeNum++ ) {
- DEVMODE devmode = {};
- if ( !EnumDisplaySettings( device.DeviceName,modeNum, &devmode ) ) {
- break;
- }
- if ( devmode.dmBitsPerPel != 32 ) {
- continue;
- }
- if ( devmode.dmDisplayFrequency < 60 ) {
- continue;
- }
- if ( devmode.dmPelsHeight < 720 ) {
- continue;
- }
- common->Printf( " -------------------\n" );
- common->Printf( " modeNum : %i\n", modeNum );
- PrintDevMode( devmode );
- }
- }
- }
- common->Printf( "\n" );
- }
- /*
- ====================
- R_GetModeListForDisplay
- ====================
- */
- bool R_GetModeListForDisplay( const int requestedDisplayNum, idList<vidMode_t> & modeList ) {
- modeList.Clear();
- bool verbose = false;
- for ( int displayNum = requestedDisplayNum; ; displayNum++ ) {
- DISPLAY_DEVICE device;
- device.cb = sizeof( device );
- if ( !EnumDisplayDevices(
- 0, // lpDevice
- displayNum,
- &device,
- 0 /* dwFlags */ ) ) {
- return false;
- }
- // get the monitor for this display
- if ( ! (device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP ) ) {
- continue;
- }
- DISPLAY_DEVICE monitor;
- monitor.cb = sizeof( monitor );
- if ( !EnumDisplayDevices(
- device.DeviceName,
- 0,
- &monitor,
- 0 /* dwFlags */ ) ) {
- continue;
- }
- DEVMODE devmode;
- devmode.dmSize = sizeof( devmode );
- if ( verbose ) {
- common->Printf( "display device: %i\n", displayNum );
- common->Printf( " DeviceName : %s\n", device.DeviceName );
- common->Printf( " DeviceString: %s\n", device.DeviceString );
- common->Printf( " StateFlags : 0x%x\n", device.StateFlags );
- common->Printf( " DeviceID : %s\n", device.DeviceID );
- common->Printf( " DeviceKey : %s\n", device.DeviceKey );
- common->Printf( " DeviceName : %s\n", monitor.DeviceName );
- common->Printf( " DeviceString: %s\n", monitor.DeviceString );
- common->Printf( " StateFlags : 0x%x\n", monitor.StateFlags );
- common->Printf( " DeviceID : %s\n", monitor.DeviceID );
- common->Printf( " DeviceKey : %s\n", monitor.DeviceKey );
- }
- for ( int modeNum = 0 ; ; modeNum++ ) {
- if ( !EnumDisplaySettings( device.DeviceName,modeNum, &devmode ) ) {
- break;
- }
- if ( devmode.dmBitsPerPel != 32 ) {
- continue;
- }
- if ( ( devmode.dmDisplayFrequency != 60 ) && ( devmode.dmDisplayFrequency != 120 ) ) {
- continue;
- }
- if ( devmode.dmPelsHeight < 720 ) {
- continue;
- }
- if ( verbose ) {
- common->Printf( " -------------------\n" );
- common->Printf( " modeNum : %i\n", modeNum );
- common->Printf( " dmPosition.x : %i\n", devmode.dmPosition.x );
- common->Printf( " dmPosition.y : %i\n", devmode.dmPosition.y );
- common->Printf( " dmBitsPerPel : %i\n", devmode.dmBitsPerPel );
- common->Printf( " dmPelsWidth : %i\n", devmode.dmPelsWidth );
- common->Printf( " dmPelsHeight : %i\n", devmode.dmPelsHeight );
- common->Printf( " dmDisplayFixedOutput: %s\n", DMDFO( devmode.dmDisplayFixedOutput ) );
- common->Printf( " dmDisplayFlags : 0x%x\n", devmode.dmDisplayFlags );
- common->Printf( " dmDisplayFrequency : %i\n", devmode.dmDisplayFrequency );
- }
- vidMode_t mode;
- mode.width = devmode.dmPelsWidth;
- mode.height = devmode.dmPelsHeight;
- mode.displayHz = devmode.dmDisplayFrequency;
- modeList.AddUnique( mode );
- }
- if ( modeList.Num() > 0 ) {
- class idSort_VidMode : public idSort_Quick< vidMode_t, idSort_VidMode > {
- public:
- int Compare( const vidMode_t & a, const vidMode_t & b ) const {
- int wd = a.width - b.width;
- int hd = a.height - b.height;
- int fd = a.displayHz - b.displayHz;
- return ( hd != 0 ) ? hd : ( wd != 0 ) ? wd : fd;
- }
- };
- // sort with lowest resolution first
- modeList.SortWithTemplate( idSort_VidMode() );
- return true;
- }
- }
- // Never gets here
- }
- /*
- ====================
- GLW_GetWindowDimensions
- ====================
- */
- static bool GLW_GetWindowDimensions( const glimpParms_t parms, int &x, int &y, int &w, int &h ) {
- //
- // compute width and height
- //
- if ( parms.fullScreen != 0 ) {
- if ( parms.fullScreen == -1 ) {
- // borderless window at specific location, as for spanning
- // multiple monitor outputs
- x = parms.x;
- y = parms.y;
- w = parms.width;
- h = parms.height;
- } else {
- // get the current monitor position and size on the desktop, assuming
- // any required ChangeDisplaySettings has already been done
- int displayHz = 0;
- if ( !GetDisplayCoordinates( parms.fullScreen - 1, x, y, w, h, displayHz ) ) {
- return false;
- }
- }
- } else {
- RECT r;
- // adjust width and height for window border
- r.bottom = parms.height;
- r.left = 0;
- r.top = 0;
- r.right = parms.width;
- AdjustWindowRect (&r, WINDOW_STYLE|WS_SYSMENU, FALSE);
- w = r.right - r.left;
- h = r.bottom - r.top;
- x = parms.x;
- y = parms.y;
- }
- return true;
- }
- /*
- =======================
- GLW_CreateWindow
- Responsible for creating the Win32 window.
- If fullscreen, it won't have a border
- =======================
- */
- static bool GLW_CreateWindow( glimpParms_t parms ) {
- int x, y, w, h;
- if ( !GLW_GetWindowDimensions( parms, x, y, w, h ) ) {
- return false;
- }
- int stylebits;
- int exstyle;
- if ( parms.fullScreen != 0 ) {
- exstyle = WS_EX_TOPMOST;
- stylebits = WS_POPUP|WS_VISIBLE|WS_SYSMENU;
- } else {
- exstyle = 0;
- stylebits = WINDOW_STYLE|WS_SYSMENU;
- }
- win32.hWnd = CreateWindowEx (
- exstyle,
- WIN32_WINDOW_CLASS_NAME,
- GAME_NAME,
- stylebits,
- x, y, w, h,
- NULL,
- NULL,
- win32.hInstance,
- NULL);
- if ( !win32.hWnd ) {
- common->Printf( "^3GLW_CreateWindow() - Couldn't create window^0\n" );
- return false;
- }
- ::SetTimer( win32.hWnd, 0, 100, NULL );
- ShowWindow( win32.hWnd, SW_SHOW );
- UpdateWindow( win32.hWnd );
- common->Printf( "...created window @ %d,%d (%dx%d)\n", x, y, w, h );
- // makeCurrent NULL frees the DC, so get another
- win32.hDC = GetDC( win32.hWnd );
- if ( !win32.hDC ) {
- common->Printf( "^3GLW_CreateWindow() - GetDC()failed^0\n" );
- return false;
- }
- // Check to see if we can get a stereo pixel format, even if we aren't going to use it,
- // so the menu option can be
- if ( GLW_ChoosePixelFormat( win32.hDC, parms.multiSamples, true ) != -1 ) {
- glConfig.stereoPixelFormatAvailable = true;
- } else {
- glConfig.stereoPixelFormatAvailable = false;
- }
- if ( !GLW_InitDriver( parms ) ) {
- ShowWindow( win32.hWnd, SW_HIDE );
- DestroyWindow( win32.hWnd );
- win32.hWnd = NULL;
- return false;
- }
- SetForegroundWindow( win32.hWnd );
- SetFocus( win32.hWnd );
- glConfig.isFullscreen = parms.fullScreen;
- return true;
- }
- /*
- ===================
- PrintCDSError
- ===================
- */
- static void PrintCDSError( int value ) {
- switch ( value ) {
- case DISP_CHANGE_RESTART:
- common->Printf( "restart required\n" );
- break;
- case DISP_CHANGE_BADPARAM:
- common->Printf( "bad param\n" );
- break;
- case DISP_CHANGE_BADFLAGS:
- common->Printf( "bad flags\n" );
- break;
- case DISP_CHANGE_FAILED:
- common->Printf( "DISP_CHANGE_FAILED\n" );
- break;
- case DISP_CHANGE_BADMODE:
- common->Printf( "bad mode\n" );
- break;
- case DISP_CHANGE_NOTUPDATED:
- common->Printf( "not updated\n" );
- break;
- default:
- common->Printf( "unknown error %d\n", value );
- break;
- }
- }
- /*
- ===================
- GLW_ChangeDislaySettingsIfNeeded
- Optionally ChangeDisplaySettings to get a different fullscreen resolution.
- Default uses the full desktop resolution.
- ===================
- */
- static bool GLW_ChangeDislaySettingsIfNeeded( glimpParms_t parms ) {
- // If we had previously changed the display settings on a different monitor,
- // go back to standard.
- if ( win32.cdsFullscreen != 0 && win32.cdsFullscreen != parms.fullScreen ) {
- win32.cdsFullscreen = 0;
- ChangeDisplaySettings( 0, 0 );
- Sys_Sleep( 1000 ); // Give the driver some time to think about this change
- }
- // 0 is dragable mode on desktop, -1 is borderless window on desktop
- if ( parms.fullScreen <= 0 ) {
- return true;
- }
- // if we are already in the right resolution, don't do a ChangeDisplaySettings
- int x, y, width, height, displayHz;
- if ( !GetDisplayCoordinates( parms.fullScreen - 1, x, y, width, height, displayHz ) ) {
- return false;
- }
- if ( width == parms.width && height == parms.height && ( displayHz == parms.displayHz || parms.displayHz == 0 ) ) {
- return true;
- }
- DEVMODE dm = {};
- dm.dmSize = sizeof( dm );
- dm.dmPelsWidth = parms.width;
- dm.dmPelsHeight = parms.height;
- dm.dmBitsPerPel = 32;
- dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
- if ( parms.displayHz != 0 ) {
- dm.dmDisplayFrequency = parms.displayHz;
- dm.dmFields |= DM_DISPLAYFREQUENCY;
- }
-
- common->Printf( "...calling CDS: " );
-
- const char * const deviceName = GetDisplayName( parms.fullScreen - 1 );
- int cdsRet;
- if ( ( cdsRet = ChangeDisplaySettingsEx(
- deviceName,
- &dm,
- NULL,
- CDS_FULLSCREEN,
- NULL) ) == DISP_CHANGE_SUCCESSFUL ) {
- common->Printf( "ok\n" );
- win32.cdsFullscreen = parms.fullScreen;
- return true;
- }
- common->Printf( "^3failed^0, " );
- PrintCDSError( cdsRet );
- return false;
- }
- /*
- ===================
- GLimp_Init
- This is the platform specific OpenGL initialization function. It
- is responsible for loading OpenGL, initializing it,
- 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.
- If there is any failure, the renderer will revert back to safe
- parameters and try again.
- ===================
- */
- bool GLimp_Init( glimpParms_t parms ) {
- const char *driverName;
- HDC hDC;
- cmdSystem->AddCommand( "testSwapBuffers", GLimp_TestSwapBuffers, CMD_FL_SYSTEM, "Times swapbuffer options" );
- common->Printf( "Initializing OpenGL subsystem with multisamples:%i stereo:%i fullscreen:%i\n",
- parms.multiSamples, parms.stereo, parms.fullScreen );
- // check our desktop attributes
- hDC = GetDC( GetDesktopWindow() );
- win32.desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL );
- win32.desktopWidth = GetDeviceCaps( hDC, HORZRES );
- win32.desktopHeight = GetDeviceCaps( hDC, VERTRES );
- ReleaseDC( GetDesktopWindow(), hDC );
- // we can't run in a window unless it is 32 bpp
- if ( win32.desktopBitsPixel < 32 && parms.fullScreen <= 0 ) {
- common->Printf("^3Windowed mode requires 32 bit desktop depth^0\n");
- return false;
- }
- // save the hardware gamma so it can be
- // restored on exit
- GLimp_SaveGamma();
- // create our window classes if we haven't already
- GLW_CreateWindowClasses();
- // this will load the dll and set all our qgl* function pointers,
- // but doesn't create a window
- // r_glDriver is only intended for using instrumented OpenGL
- // dlls. Normal users should never have to use it, and it is
- // not archived.
- driverName = r_glDriver.GetString()[0] ? r_glDriver.GetString() : "opengl32";
- if ( !QGL_Init( driverName ) ) {
- common->Printf( "^3GLimp_Init() could not load r_glDriver \"%s\"^0\n", driverName );
- return false;
- }
- // getting the wgl extensions involves creating a fake window to get a context,
- // which is pretty disgusting, and seems to mess with the AGP VAR allocation
- GLW_GetWGLExtensionsWithFakeWindow();
- // Optionally ChangeDisplaySettings to get a different fullscreen resolution.
- if ( !GLW_ChangeDislaySettingsIfNeeded( parms ) ) {
- GLimp_Shutdown();
- return false;
- }
- // try to create a window with the correct pixel format
- // and init the renderer context
- if ( !GLW_CreateWindow( parms ) ) {
- GLimp_Shutdown();
- return false;
- }
- glConfig.isFullscreen = parms.fullScreen;
- glConfig.isStereoPixelFormat = parms.stereo;
- glConfig.nativeScreenWidth = parms.width;
- glConfig.nativeScreenHeight = parms.height;
- glConfig.multisamples = parms.multiSamples;
- glConfig.pixelAspect = 1.0f; // FIXME: some monitor modes may be distorted
- // should side-by-side stereo modes be consider aspect 0.5?
- // get the screen size, which may not be reliable...
- // If we use the windowDC, I get my 30" monitor, even though the window is
- // on a 27" monitor, so get a dedicated DC for the full screen device name.
- const idStr deviceName = GetDeviceName( Max( 0, parms.fullScreen - 1 ) );
- HDC deviceDC = CreateDC( deviceName.c_str(), deviceName.c_str(), NULL, NULL );
- const int mmWide = GetDeviceCaps( win32.hDC, HORZSIZE );
- DeleteDC( deviceDC );
- if ( mmWide == 0 ) {
- glConfig.physicalScreenWidthInCentimeters = 100.0f;
- } else {
- glConfig.physicalScreenWidthInCentimeters = 0.1f * mmWide;
- }
- // wglSwapinterval, etc
- GLW_CheckWGLExtensions( win32.hDC );
- // check logging
- GLimp_EnableLogging( ( r_logFile.GetInteger() != 0 ) );
- return true;
- }
- /*
- ===================
- GLimp_SetScreenParms
- Sets up the screen based on passed parms..
- ===================
- */
- bool GLimp_SetScreenParms( glimpParms_t parms ) {
- // Optionally ChangeDisplaySettings to get a different fullscreen resolution.
- if ( !GLW_ChangeDislaySettingsIfNeeded( parms ) ) {
- return false;
- }
- int x, y, w, h;
- if ( !GLW_GetWindowDimensions( parms, x, y, w, h ) ) {
- return false;
- }
- int exstyle;
- int stylebits;
- if ( parms.fullScreen ) {
- exstyle = WS_EX_TOPMOST;
- stylebits = WS_POPUP|WS_VISIBLE|WS_SYSMENU;
- } else {
- exstyle = 0;
- stylebits = WINDOW_STYLE|WS_SYSMENU;
- }
- SetWindowLong( win32.hWnd, GWL_STYLE, stylebits );
- SetWindowLong( win32.hWnd, GWL_EXSTYLE, exstyle );
- SetWindowPos( win32.hWnd, parms.fullScreen ? HWND_TOPMOST : HWND_NOTOPMOST, x, y, w, h, SWP_SHOWWINDOW );
- glConfig.isFullscreen = parms.fullScreen;
- glConfig.pixelAspect = 1.0f; // FIXME: some monitor modes may be distorted
- glConfig.isFullscreen = parms.fullScreen;
- glConfig.nativeScreenWidth = parms.width;
- glConfig.nativeScreenHeight = parms.height;
- return true;
- }
- /*
- ===================
- GLimp_Shutdown
- This routine does all OS specific shutdown procedures for the OpenGL
- subsystem.
- ===================
- */
- void GLimp_Shutdown() {
- const char *success[] = { "failed", "success" };
- int retVal;
- common->Printf( "Shutting down OpenGL subsystem\n" );
- // set current context to NULL
- if ( qwglMakeCurrent ) {
- retVal = qwglMakeCurrent( NULL, NULL ) != 0;
- common->Printf( "...wglMakeCurrent( NULL, NULL ): %s\n", success[retVal] );
- }
- // delete HGLRC
- if ( win32.hGLRC ) {
- retVal = qwglDeleteContext( win32.hGLRC ) != 0;
- common->Printf( "...deleting GL context: %s\n", success[retVal] );
- win32.hGLRC = NULL;
- }
- // release DC
- if ( win32.hDC ) {
- retVal = ReleaseDC( win32.hWnd, win32.hDC ) != 0;
- common->Printf( "...releasing DC: %s\n", success[retVal] );
- win32.hDC = NULL;
- }
- // destroy window
- if ( win32.hWnd ) {
- common->Printf( "...destroying window\n" );
- ShowWindow( win32.hWnd, SW_HIDE );
- DestroyWindow( win32.hWnd );
- win32.hWnd = NULL;
- }
- // reset display settings
- if ( win32.cdsFullscreen ) {
- common->Printf( "...resetting display\n" );
- ChangeDisplaySettings( 0, 0 );
- win32.cdsFullscreen = 0;
- }
- // close the thread so the handle doesn't dangle
- if ( win32.renderThreadHandle ) {
- common->Printf( "...closing smp thread\n" );
- CloseHandle( win32.renderThreadHandle );
- win32.renderThreadHandle = NULL;
- }
- // restore gamma
- GLimp_RestoreGamma();
- // shutdown QGL subsystem
- QGL_Shutdown();
- }
- /*
- =====================
- GLimp_SwapBuffers
- =====================
- */
- void GLimp_SwapBuffers() {
- if ( r_swapInterval.IsModified() ) {
- r_swapInterval.ClearModified();
- int interval = 0;
- if ( r_swapInterval.GetInteger() == 1 ) {
- interval = ( glConfig.swapControlTearAvailable ) ? -1 : 1;
- } else if ( r_swapInterval.GetInteger() == 2 ) {
- interval = 1;
- }
- if ( wglSwapIntervalEXT ) {
- wglSwapIntervalEXT( interval );
- }
- }
- qwglSwapBuffers( win32.hDC );
- }
- /*
- ===========================================================
- SMP acceleration
- ===========================================================
- */
- /*
- ===================
- GLimp_ActivateContext
- ===================
- */
- void GLimp_ActivateContext() {
- if ( !qwglMakeCurrent( win32.hDC, win32.hGLRC ) ) {
- win32.wglErrors++;
- }
- }
- /*
- ===================
- GLimp_DeactivateContext
- ===================
- */
- void GLimp_DeactivateContext() {
- qglFinish();
- if ( !qwglMakeCurrent( win32.hDC, NULL ) ) {
- win32.wglErrors++;
- }
- }
- /*
- ===================
- GLimp_RenderThreadWrapper
- ===================
- */
- static void GLimp_RenderThreadWrapper() {
- win32.glimpRenderThread();
- // unbind the context before we die
- qwglMakeCurrent( win32.hDC, NULL );
- }
- /*
- =======================
- GLimp_SpawnRenderThread
- Returns false if the system only has a single processor
- =======================
- */
- bool GLimp_SpawnRenderThread( void (*function)() ) {
- SYSTEM_INFO info;
- // check number of processors
- GetSystemInfo( &info );
- if ( info.dwNumberOfProcessors < 2 ) {
- return false;
- }
-
- // create the IPC elements
- win32.renderCommandsEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
- win32.renderCompletedEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
- win32.renderActiveEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
- win32.glimpRenderThread = function;
- win32.renderThreadHandle = CreateThread(
- NULL, // LPSECURITY_ATTRIBUTES lpsa,
- 0, // DWORD cbStack,
- (LPTHREAD_START_ROUTINE)GLimp_RenderThreadWrapper, // LPTHREAD_START_ROUTINE lpStartAddr,
- 0, // LPVOID lpvThreadParm,
- 0, // DWORD fdwCreate,
- &win32.renderThreadId );
- if ( !win32.renderThreadHandle ) {
- common->Error( "GLimp_SpawnRenderThread: failed" );
- }
- SetThreadPriority( win32.renderThreadHandle, THREAD_PRIORITY_ABOVE_NORMAL );
- #if 0
- // make sure they always run on different processors
- SetThreadAffinityMask( GetCurrentThread, 1 );
- SetThreadAffinityMask( win32.renderThreadHandle, 2 );
- #endif
- return true;
- }
- //#define DEBUG_PRINTS
- /*
- ===================
- GLimp_BackEndSleep
- ===================
- */
- void *GLimp_BackEndSleep() {
- void *data;
- #ifdef DEBUG_PRINTS
- OutputDebugString( "-->GLimp_BackEndSleep\n" );
- #endif
- ResetEvent( win32.renderActiveEvent );
- // after this, the front end can exit GLimp_FrontEndSleep
- SetEvent( win32.renderCompletedEvent );
- WaitForSingleObject( win32.renderCommandsEvent, INFINITE );
- ResetEvent( win32.renderCompletedEvent );
- ResetEvent( win32.renderCommandsEvent );
- data = win32.smpData;
- // after this, the main thread can exit GLimp_WakeRenderer
- SetEvent( win32.renderActiveEvent );
- #ifdef DEBUG_PRINTS
- OutputDebugString( "<--GLimp_BackEndSleep\n" );
- #endif
- return data;
- }
- /*
- ===================
- GLimp_FrontEndSleep
- ===================
- */
- void GLimp_FrontEndSleep() {
- #ifdef DEBUG_PRINTS
- OutputDebugString( "-->GLimp_FrontEndSleep\n" );
- #endif
- WaitForSingleObject( win32.renderCompletedEvent, INFINITE );
- #ifdef DEBUG_PRINTS
- OutputDebugString( "<--GLimp_FrontEndSleep\n" );
- #endif
- }
- volatile bool renderThreadActive;
- /*
- ===================
- GLimp_WakeBackEnd
- ===================
- */
- void GLimp_WakeBackEnd( void *data ) {
- int r;
- #ifdef DEBUG_PRINTS
- OutputDebugString( "-->GLimp_WakeBackEnd\n" );
- #endif
- win32.smpData = data;
- if ( renderThreadActive ) {
- common->FatalError( "GLimp_WakeBackEnd: already active" );
- }
- r = WaitForSingleObject( win32.renderActiveEvent, 0 );
- if ( r == WAIT_OBJECT_0 ) {
- common->FatalError( "GLimp_WakeBackEnd: already signaled" );
- }
- r = WaitForSingleObject( win32.renderCommandsEvent, 0 );
- if ( r == WAIT_OBJECT_0 ) {
- common->FatalError( "GLimp_WakeBackEnd: commands already signaled" );
- }
- // after this, the renderer can continue through GLimp_RendererSleep
- SetEvent( win32.renderCommandsEvent );
- r = WaitForSingleObject( win32.renderActiveEvent, 5000 );
- if ( r == WAIT_TIMEOUT ) {
- common->FatalError( "GLimp_WakeBackEnd: WAIT_TIMEOUT" );
- }
- #ifdef DEBUG_PRINTS
- OutputDebugString( "<--GLimp_WakeBackEnd\n" );
- #endif
- }
- /*
- ===================
- GLimp_ExtensionPointer
- Returns a function pointer for an OpenGL extension entry point
- ===================
- */
- GLExtension_t GLimp_ExtensionPointer( const char *name ) {
- void (*proc)();
- proc = (GLExtension_t)qwglGetProcAddress( name );
- if ( !proc ) {
- common->Printf( "Couldn't find proc address for: %s\n", name );
- }
- return proc;
- }
|