static int GLW_MakeContext( PIXELFORMATDESCRIPTOR *pPFD ) { // // don't putz around with pixelformat if it's already set (e.g. this is a soft // reset of the graphics system) // if ( !glw_state.pixelFormatSet ) { int pixelformat; // // 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 (glw_state.nPendingPF) pixelformat = glw_state.nPendingPF; else if ( ( pixelformat = GLW_ChoosePFD( glw_state.hDC, pPFD ) ) == 0 ) { ri.Printf( PRINT_ALL, "...GLW_ChoosePFD failed\n"); return TRY_PFD_FAIL_SOFT; } ri.Printf( PRINT_DEVELOPER, "...PIXELFORMAT %d selected\n", pixelformat ); DescribePixelFormat( glw_state.hDC, pixelformat, sizeof( *pPFD ), pPFD ); if ( SetPixelFormat( glw_state.hDC, pixelformat, pPFD ) == FALSE ) { ri.Printf( PRINT_ALL, "...SetPixelFormat failed\n", glw_state.hDC ); return TRY_PFD_FAIL_SOFT; } glw_state.pixelFormatSet = qtrue; } // // startup the OpenGL subsystem by creating a context and making it current // if ( !glw_state.hGLRC ) { if ( ( glw_state.hGLRC = qwglCreateContext( glw_state.hDC ) ) == 0 ) { ri.Printf( PRINT_ALL, "...GL context creation failure\n" ); return TRY_PFD_FAIL_HARD; } ri.Printf( PRINT_DEVELOPER, "...GL context created\n" ); if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) { qwglDeleteContext( glw_state.hGLRC ); glw_state.hGLRC = NULL; ri.Printf( PRINT_ALL, "...GL context creation currency failure\n" ); return TRY_PFD_FAIL_HARD; } ri.Printf( PRINT_DEVELOPER, "...GL context creation made current\n" ); } return TRY_PFD_SUCCESS; }
static int GLW_MakeContext( PIXELFORMATDESCRIPTOR* pPFD ) { // // don't putz around with pixelformat if it's already set (e.g. this is a soft // reset of the graphics system) // if ( !pixelFormatSet ) { // // choose, set, and describe our desired pixel format. // int pixelformat = GLW_ChoosePFD( maindc, pPFD ); if ( pixelformat == 0 ) { common->Printf( "...GLW_ChoosePFD failed\n" ); return TRY_PFD_FAIL_SOFT; } common->Printf( "...PIXELFORMAT %d selected\n", pixelformat ); DescribePixelFormat( maindc, pixelformat, sizeof ( *pPFD ), pPFD ); if ( SetPixelFormat( maindc, pixelformat, pPFD ) == FALSE ) { common->Printf( "...SetPixelFormat failed\n" ); return TRY_PFD_FAIL_SOFT; } pixelFormatSet = true; } // // startup the OpenGL subsystem by creating a context and making it current // if ( !baseRC ) { common->Printf( "...creating GL context: " ); if ( ( baseRC = wglCreateContext( maindc ) ) == 0 ) { common->Printf( "failed\n" ); return TRY_PFD_FAIL_HARD; } common->Printf( "succeeded\n" ); common->Printf( "...making context current: " ); if ( !wglMakeCurrent( maindc, baseRC ) ) { wglDeleteContext( baseRC ); baseRC = NULL; common->Printf( "failed\n" ); return TRY_PFD_FAIL_HARD; } common->Printf( "succeeded\n" ); } return TRY_PFD_SUCCESS; }
static int GLW_GetDisplayLevel( HDC dc ) { int i; PIXELFORMATDESCRIPTOR pfd; pfd = GLW_DEFAULT_PFD; i = GLW_ChoosePFD( dc, &pfd ); if( !i ) return 0; pfd.nSize = sizeof( pfd ); DescribePixelFormat( dc, i, sizeof( PIXELFORMATDESCRIPTOR ), &pfd ); if( (pfd.dwFlags & PFD_SUPPORT_OPENGL) == 0 ) return 0; if( pfd.dwFlags & PFD_GENERIC_FORMAT ) return 1; //software GL return 2; //full GL }
HGLRC GL_GenerateRC(HDC hDC, bool bDoubleBuffer/* = true*/) { HGLRC hRC = NULL; if (1/*RunningNT() || bCalledFromMainCellView*/) { static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // size of this struct 1, // struct version PFD_DRAW_TO_WINDOW | // draw to window (not bitmap) // PFD_DOUBLEBUFFER | // double buffered mode PFD_SUPPORT_OPENGL, // support opengl in window PFD_TYPE_RGBA, // RGBA colour mode 24, // want 24bit colour 0,0,0,0,0,0, // not used to select mode 0,0, // not used to select mode 0,0,0,0,0, // not used to select mode 32, // size of depth buffer 0, // not used to select mode 0, // not used to select mode PFD_MAIN_PLANE, // draw in main plane 0, // not used to select mode 0,0,0 // not used to select mode }; if (bDoubleBuffer) { pfd.dwFlags |= PFD_DOUBLEBUFFER; } // choose a pixel format that best matches the one we want... // int iPixelFormat = GLW_ChoosePFD(hDC,&pfd); // try and choose best hardware mode if (iPixelFormat == 0) { // nothing decent found, fall bac to whatever crap the system recommends... // iPixelFormat = ChoosePixelFormat(hDC,&pfd); } // // set the pixel format for this device context... // //JAC FIXME - assertion failed //VERIFY(SetPixelFormat(hDC, iPixelFormat, &pfd)); SetPixelFormat(hDC, iPixelFormat, &pfd); // // create the rendering context... // hRC = wglCreateContext(hDC); if (hRC) { // // make the rendering context current, init, then deselect... // VERIFY(wglMakeCurrent(hDC,hRC)); // first one in creates the global RC, everyone else shares lists with it... // if (g_hRC) { ASSERT_GL; VERIFY(wglShareLists(g_hRC,hRC)); ASSERT_GL; } else { g_hRC = hRC; g_hDC = hDC; // record vendor strings for later display... // csGLVendor = glGetString (GL_VENDOR); csGLRenderer = glGetString (GL_RENDERER); csGLVersion = glGetString (GL_VERSION); csGLExtensions = glGetString (GL_EXTENSIONS); // // for the moment I'll insist on 24 bits and up (texture loading reasons, plus GL issues) // { HDC _hDC = GetDC( GetDesktopWindow() ); int iDesktopBitDepth = GetDeviceCaps( _hDC, BITSPIXEL ); if (iDesktopBitDepth == 8) { WarningBox(va("Your desktop is only %d bit!,\n\nChange the bitdepth to 16 or more (65536 colours or over) and re-run.",iDesktopBitDepth)); } ReleaseDC( GetDesktopWindow(), _hDC ); } } // VERIFY(wglMakeCurrent(NULL,NULL)); // leave context running! } } return hRC; }
static void GLW_CreateGLWnd( void ) { int x, y, w, h; HWND hParent; float aspect; DWORD s, es; skinDef_t *skin; int refresh = 0; int colorDepth = 0; WinVars_t *winVars = (WinVars_t*)ri.PlatformGetVars(); if( winVars->hWnd ) return; x = 0; y = 0; if( r_fullscreen->integer ) { int mode_id; char * res = r_fsmode->string; w = atoi( COM_Parse( &res ) ); h = atoi( COM_Parse( &res ) ); aspect = (float)w / (float)h; sql_prepare( &com_db, "SELECT x, y FROM monitors SEARCH dev_name ?" ); sql_bindtext( &com_db, 1, r_fsmonitor->string ); if( sql_step( &com_db ) ) { x = sql_columnasint( &com_db, 0 ); y = sql_columnasint( &com_db, 1 ); } sql_done( &com_db ); //find the settings mode id mode_id = -1; sql_prepare( &com_db, "SELECT id FROM fsmodes SEARCH dev_name ?1 WHERE w=?2 AND h=?3" ); sql_bindtext( &com_db, 1, r_fsmonitor->string ); sql_bindint( &com_db, 2, w ); sql_bindint( &com_db, 3, h ); if( sql_step( &com_db ) ) mode_id = sql_columnasint( &com_db, 0 ); sql_done( &com_db ); //get a matching color mode sql_prepare( &com_db, "SELECT bpp FROM fsmodes_ext SEARCH id ?1" ); sql_bindint( &com_db, 1, mode_id ); while( sql_step( &com_db ) ) { int bpp = sql_columnasint( &com_db, 0 ); if( r_colorbits->integer ) { if( bpp == r_colorbits->integer ) { //take an exact match colorDepth = bpp; break; } if( bpp > r_colorbits->integer ) { if( colorDepth < r_colorbits->integer || bpp < colorDepth ) //if we must go over, take the smallest value that goes over colorDepth = bpp; } else if( bpp > colorDepth ) colorDepth = bpp; } else if( bpp > colorDepth ) colorDepth = bpp; } sql_done( &com_db ); //get a matching refresh rate sql_prepare( &com_db, "SELECT hz FROM fsmodes_ext SEARCH id ?1 WHERE bpp=?2" ); sql_bindint( &com_db, 1, mode_id ); sql_bindint( &com_db, 2, colorDepth ); while( sql_step( &com_db ) ) { int hz = sql_columnasint( &com_db, 0 ); if( r_displayRefresh->integer ) { if( hz == r_displayRefresh->integer ) { //take an exact match refresh = hz; break; } if( hz > r_displayRefresh->integer ) { if( refresh < r_displayRefresh->integer || hz < refresh ) //if we must go over, take the smallest value that goes over refresh = hz; } else if( hz > refresh ) refresh = hz; } else if( hz > refresh ) //take the highest refresh rate refresh = hz; } sql_done( &com_db ); } else { if( !R_GetModeInfo( &w, &h, &aspect, r_mode->integer ) ) { //fall back to special modes w = 0; h = 0; } } /* Clean out old display mode changes. Note that we *don't* skip this when we're going back into fullscreen as it tends to produce some aweful bugs on some Windows installations. */ if( glw_state.cdsFullscreen ) ChangeDisplaySettings( NULL, 0 ); //window style bits es = 0; s = 0; skin = NULL; if( r_fullscreen->integer ) { //go into full screen mode RECT rc; HMONITOR monitor; MONITORINFOEX monitorInfo; hParent = 0; //make sure we're set up for multimon goodness if( winVars->hWndHost ) { GetWindowRect( winVars->hWndHost, &rc ); } else { rc.left = x; rc.top = y; rc.right = x + w; rc.bottom = y + h; } monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST ); monitorInfo.cbSize = sizeof( monitorInfo ); GetMonitorInfo( monitor, (LPMONITORINFO)&monitorInfo ); //if we got an invalid mode then use desktop resolution if( w == 0 ) w = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; if( h == 0 ) h = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; //change that monitor's display size to <w, h> //set the window rect to cover the display //skip the festival of desktop flickering if not changing resolution if( (monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left) != w || (monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top) != h ) { DEVMODE dm; memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); dm.dmPelsWidth = w; dm.dmPelsHeight = h; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; if( refresh != 0 ) { dm.dmDisplayFrequency = refresh; dm.dmFields |= DM_DISPLAYFREQUENCY; } if( colorDepth != 0 ) { dm.dmBitsPerPel = colorDepth; dm.dmFields |= DM_BITSPERPEL; } if( ChangeDisplaySettingsEx( monitorInfo.szDevice, &dm, NULL, CDS_FULLSCREEN, NULL ) != DISP_CHANGE_SUCCESSFUL ) { //try again without color bits and frequency dm.dmFields &= ~(DM_BITSPERPEL | DM_DISPLAYFREQUENCY); dm.dmBitsPerPel = 0; dm.dmDisplayFrequency = 0; if( ChangeDisplaySettingsEx( monitorInfo.szDevice, &dm, NULL, CDS_FULLSCREEN, NULL ) != DISP_CHANGE_SUCCESSFUL ) //failed... ri.Printf( PRINT_WARNING, "Invalid fullscreen resolution, running at desktop resolution" ); } } //get the new monitor info monitorInfo.cbSize = sizeof( monitorInfo ); GetMonitorInfo( monitor, (LPMONITORINFO)&monitorInfo ); x = monitorInfo.rcMonitor.left; y = monitorInfo.rcMonitor.top; w = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; h = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; s = WS_POPUP; es = WS_EX_APPWINDOW | WS_EX_TOPMOST; glw_state.cdsFullscreen = qtrue; } else if( winVars->hWndHost ) { RECT rc; hParent = winVars->hWndHost; GetClientRect( winVars->hWndHost, &rc ); x = rc.left; y = rc.top; w = rc.right - rc.left; h = rc.bottom - rc.top; s = WS_CHILD; es = WS_EX_NOPARENTNOTIFY; } else { RECT rc; HMONITOR monitor; MONITORINFO monitorInfo; qboolean usedefault = qfalse; if( w == 0 ) w = 640; if( h == 0 ) h = 480; vid_xpos = ri.Cvar_Get( "vid_xpos", va("%d",CW_USEDEFAULT), CVAR_ARCHIVE ); vid_ypos = ri.Cvar_Get( "vid_ypos", "0", CVAR_ARCHIVE ); x = vid_xpos->integer; y = vid_ypos->integer; if ( x == CW_USEDEFAULT ) { x = 0; usedefault = qtrue; } rc.left = x; rc.top = y; rc.right = x + w; rc.bottom = y + h; hParent = 0; if( r_skin->string[0] ) skin = Skin_Load( r_skin->string ); //account for the border frame if( skin ) { s = WS_POPUP; es = WS_EX_APPWINDOW; Skin_AdjustWindowRect( &rc, skin ); AdjustWindowRectEx( &rc, s, FALSE, es ); } else { s = WS_OVERLAPPED | WS_SYSMENU | WS_BORDER | WS_CAPTION; es = WS_EX_APPWINDOW; AdjustWindowRectEx( &rc, s, FALSE, es ); } x = rc.left; y = rc.top; w = rc.right - rc.left; h = rc.bottom - rc.top; //constrain to a monitor //this is important as we can't get a //pixel format if we're entirely off screen monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST ); monitorInfo.cbSize = sizeof( monitorInfo ); GetMonitorInfo( monitor, &monitorInfo ); //if we're not actually intersecting the monitor //(shoved off of the screen I guess) move back onto it if( x > monitorInfo.rcWork.right ) //left window edge past right screen edge x = monitorInfo.rcWork.right - w; if( x + w < monitorInfo.rcWork.left ) //right window edge past left screen edge x = monitorInfo.rcWork.left; if( y > monitorInfo.rcWork.bottom ) //top window edge past bottom screen edge y = monitorInfo.rcWork.bottom - h; if( y + h < monitorInfo.rcWork.top ) //bottom window edge past top screen edge y = monitorInfo.rcWork.top; glw_state.cdsFullscreen = qfalse; if ( usedefault ) { x = monitorInfo.rcMonitor.left + ((monitorInfo.rcMonitor.right-monitorInfo.rcMonitor.left)-w)/2; y = monitorInfo.rcMonitor.top + ((monitorInfo.rcMonitor.bottom-monitorInfo.rcMonitor.top)-h)/2; } } winVars->hWnd = NULL; if( skin ) { Skin_RegisterClass(); winVars->hWnd = Skin_CreateWnd( skin, x, y, w, h ); } if( !winVars->hWnd ) { GLW_RegisterClass(); winVars->hWnd = CreateWindowEx( es, WINDOW_CLASS_NAME, WINDOW_CAPTION, s, x, y, w, h, hParent, NULL, winVars->hInstance, NULL ); } //the window now owns the skin and will free it if( !winVars->hWnd ) ri.Error( ERR_FATAL, "GLW: could not create window" ); SetWindowPos( winVars->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW ); ShowWindow( winVars->hWnd, SW_SHOWNORMAL ); SetFocus( winVars->hWnd ); //get the window to draw once (get rid of graphical clutter) UpdateWindow( winVars->hWnd ); //fire up the GL glw_state.hDC = GetDC( winVars->hWnd ); if( !glw_state.hDC ) ri.Error( ERR_FATAL, "GLW: could not get window DC" ); //set up the pixel format { int pixelFormat; PIXELFORMATDESCRIPTOR pfd; GLW_CreatePFD( &pfd ); pixelFormat = GLW_ChoosePFDEx( &pfd ); if( !pixelFormat ) { pixelFormat = GLW_ChoosePFD( glw_state.hDC, &pfd ); glConfig.fsaaSamples = 1; } if( !pixelFormat ) ri.Error( ERR_FATAL, "GLW: no valid pixel format" ); pfd.nSize = sizeof( pfd ); DescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( pfd ), &pfd ); if( !SetPixelFormat( glw_state.hDC, pixelFormat, &pfd ) ) ri.Error( ERR_FATAL, "GLW: could not set pixel format" ); glConfig.colorBits = pfd.cColorBits; glConfig.depthBits = pfd.cDepthBits; glConfig.stencilBits = pfd.cStencilBits; glConfig.stereoEnabled = (pfd.dwFlags & PFD_STEREO) ? qtrue : qfalse; ri.Printf( PRINT_ALL, "Using Pixel Format %i\n", pixelFormat ); } glw_state.hGLRC = wglCreateContext( glw_state.hDC ); if( !glw_state.hGLRC || !wglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) ri.Error( ERR_FATAL, "GLW: could not initialize GL" ); GLW_CheckExtensions(); //R_PerfInit(); { //get the actual sizes, in case Windows constrained our window RECT rc; GetClientRect( winVars->hWnd, &rc ); w = rc.right - rc.left; h = rc.bottom - rc.top; //fill in some glConfig stuff which *will* be referenced //by various subsystem init functions (i.e. Cg, bloom) glConfig.vidWidth = w; glConfig.vidHeight = h; glConfig.windowAspect = aspect; } glConfig.deviceSupportsGamma = qfalse; glConfig.isFullscreen = glw_state.cdsFullscreen ? qtrue : qfalse; glConfig.xscale = glConfig.vidWidth / 640.0f; glConfig.yscale = glConfig.vidHeight / 480.0f; if( glConfig.vidWidth * 480 > glConfig.vidHeight * 640 ) { // wide screen glConfig.xscale = glConfig.yscale; glConfig.xbias = ((float)glConfig.vidWidth - (640.0F * glConfig.xscale)) * 0.5F; } else { // no wide screen glConfig.xbias = 0.0f; } }