/* =================== 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; }
/* ** GLW_SetMode */ static rserr_t GLW_SetMode( const char *drivername, int mode, int colorbits, qboolean cdsFullscreen ) { HDC hDC; const char *win_fs[] = { "W", "FS" }; int cdsRet; DEVMODE dm; // // print out informational messages // ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, win_fs[cdsFullscreen] ); // // check our desktop attributes // hDC = GetDC( GetDesktopWindow() ); glw_state.desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); glw_state.desktopWidth = GetDeviceCaps( hDC, HORZRES ); glw_state.desktopHeight = GetDeviceCaps( hDC, VERTRES ); ReleaseDC( GetDesktopWindow(), hDC ); // // verify desktop bit depth // if ( glConfig.driverType != GLDRV_VOODOO ) { if ( glw_state.desktopBitsPixel < 15 || glw_state.desktopBitsPixel == 24 ) { if ( colorbits == 0 || ( !cdsFullscreen && colorbits >= 15 ) ) { if ( MessageBox( NULL, "It is highly unlikely that a correct\n" "windowed display can be initialized with\n" "the current desktop display depth. Select\n" "'OK' to try anyway. Press 'Cancel' if you\n" "have a 3Dfx Voodoo, Voodoo-2, or Voodoo Rush\n" "3D accelerator installed, or if you otherwise\n" "wish to quit.", "Low Desktop Color Depth", MB_OKCANCEL | MB_ICONEXCLAMATION ) != IDOK ) { return RSERR_INVALID_MODE; } } } } // do a CDS if needed if ( cdsFullscreen ) { memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); dm.dmPelsWidth = glConfig.vidWidth; dm.dmPelsHeight = glConfig.vidHeight; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; if ( r_displayRefresh->integer != 0 ) { dm.dmDisplayFrequency = r_displayRefresh->integer; dm.dmFields |= DM_DISPLAYFREQUENCY; } // try to change color depth if possible if ( colorbits != 0 ) { if ( glw_state.allowdisplaydepthchange ) { dm.dmBitsPerPel = colorbits; dm.dmFields |= DM_BITSPERPEL; ri.Printf( PRINT_ALL, "...using colorsbits of %d\n", colorbits ); } else { ri.Printf( PRINT_ALL, "WARNING:...changing depth not supported on Win95 < pre-OSR 2.x\n" ); } } else { ri.Printf( PRINT_ALL, "...using desktop display depth of %d\n", glw_state.desktopBitsPixel ); } // // if we're already in fullscreen then just create the window // if ( glw_state.cdsFullscreen ) { ri.Printf( PRINT_ALL, "...already fullscreen, avoiding redundant CDS\n" ); if ( !GLW_CreateWindow ( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue ) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } } // // need to call CDS // else { ri.Printf( PRINT_ALL, "...calling CDS: " ); // try setting the exact mode requested, because some drivers don't report // the low res modes in EnumDisplaySettings, but still work if ( ( cdsRet = ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) { ri.Printf( PRINT_ALL, "ok\n" ); if ( !GLW_CreateWindow ( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } glw_state.cdsFullscreen = qtrue; } else { // // the exact mode failed, so scan EnumDisplaySettings for the next largest mode // DEVMODE devmode; int modeNum; ri.Printf( PRINT_ALL, "failed, " ); PrintCDSError( cdsRet ); ri.Printf( PRINT_ALL, "...trying next higher resolution:" ); // we could do a better matching job here... for ( modeNum = 0 ; ; modeNum++ ) { if ( !EnumDisplaySettings( NULL, modeNum, &devmode ) ) { modeNum = -1; break; } if ( devmode.dmPelsWidth >= glConfig.vidWidth && devmode.dmPelsHeight >= glConfig.vidHeight && devmode.dmBitsPerPel >= 15 ) { break; } } if ( modeNum != -1 && ( cdsRet = ChangeDisplaySettings( &devmode, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) { ri.Printf( PRINT_ALL, " ok\n" ); if ( !GLW_CreateWindow( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } glw_state.cdsFullscreen = qtrue; } else { ri.Printf( PRINT_ALL, " failed, " ); PrintCDSError( cdsRet ); ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); glw_state.cdsFullscreen = qfalse; glConfig.isFullscreen = qfalse; if ( !GLW_CreateWindow( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qfalse) ) { return RSERR_INVALID_MODE; } return RSERR_INVALID_FULLSCREEN; } } } } else { if ( glw_state.cdsFullscreen ) { ChangeDisplaySettings( 0, 0 ); } glw_state.cdsFullscreen = qfalse; if ( !GLW_CreateWindow( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qfalse ) ) { return RSERR_INVALID_MODE; } } // // success, now check display frequency, although this won't be valid on Voodoo(2) // memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); if ( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &dm ) ) { glConfig.displayFrequency = dm.dmDisplayFrequency; } // NOTE: this is overridden later on standalone 3Dfx drivers glConfig.isFullscreen = cdsFullscreen; return RSERR_OK; }
/* =================== GLW_SetFullScreen =================== */ static bool GLW_SetFullScreen( glimpParms_t parms ) { #if 0 // for some reason, bounds checker claims that windows is // writing past the bounds of dm in the get display frequency call union { DEVMODE dm; byte filler[1024]; } hack; #endif DEVMODE dm; int cdsRet; DEVMODE devmode; int modeNum; bool matched; // first make sure the user is not trying to select a mode that his card/monitor can't handle matched = false; for ( modeNum = 0 ; ; modeNum++ ) { if ( !EnumDisplaySettings( NULL, modeNum, &devmode ) ) { if ( matched ) { // we got a resolution match, but not a frequency match // so disable the frequency requirement common->Printf( "...^3%dhz is unsupported at %dx%d^0\n", parms.displayHz, parms.width, parms.height ); parms.displayHz = 0; break; } common->Printf( "...^3%dx%d is unsupported in 32 bit^0\n", parms.width, parms.height ); return false; } if ( (int)devmode.dmPelsWidth >= parms.width && (int)devmode.dmPelsHeight >= parms.height && devmode.dmBitsPerPel == 32 ) { matched = true; if ( parms.displayHz == 0 || devmode.dmDisplayFrequency == parms.displayHz ) { break; } } } memset( &dm, 0, sizeof( 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: " ); // try setting the exact mode requested, because some drivers don't report // the low res modes in EnumDisplaySettings, but still work if ( ( cdsRet = ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) { common->Printf( "ok\n" ); win32.cdsFullscreen = true; return true; } // // the exact mode failed, so scan EnumDisplaySettings for the next largest mode // common->Printf( "^3failed^0, " ); PrintCDSError( cdsRet ); common->Printf( "...trying next higher resolution:" ); // we could do a better matching job here... for ( modeNum = 0 ; ; modeNum++ ) { if ( !EnumDisplaySettings( NULL, modeNum, &devmode ) ) { break; } if ( (int)devmode.dmPelsWidth >= parms.width && (int)devmode.dmPelsHeight >= parms.height && devmode.dmBitsPerPel == 32 ) { if ( ( cdsRet = ChangeDisplaySettings( &devmode, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) { common->Printf( "ok\n" ); win32.cdsFullscreen = true; return true; } break; } } common->Printf( "\n...^3no high res mode found^0\n" ); return false; }
rserr_t GLimp_SetMode( int mode, int colorbits, bool fullscreen ) { const char* win_fs[] = { "W", "FS" }; // // print out informational messages // common->Printf( "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { common->Printf( " invalid mode\n" ); return RSERR_INVALID_MODE; } common->Printf( " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, win_fs[ fullscreen ] ); // // check our desktop attributes // HDC hDC = GetDC( GetDesktopWindow() ); desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); desktopWidth = GetDeviceCaps( hDC, HORZRES ); desktopHeight = GetDeviceCaps( hDC, VERTRES ); ReleaseDC( GetDesktopWindow(), hDC ); // // verify desktop bit depth // if ( desktopBitsPixel < 15 || desktopBitsPixel == 24 ) { if ( colorbits == 0 || ( !cdsFullscreen && colorbits >= 15 ) ) { if ( MessageBox( NULL, "It is highly unlikely that a correct\n" "windowed display can be initialized with\n" "the current desktop display depth. Select\n" "'OK' to try anyway. Press 'Cancel' if you otherwise\n" "wish to quit.", "Low Desktop Color Depth", MB_OKCANCEL | MB_ICONEXCLAMATION ) != IDOK ) { return RSERR_INVALID_MODE; } } } DEVMODE dm; // do a CDS if needed if ( fullscreen ) { Com_Memset( &dm, 0, sizeof ( dm ) ); dm.dmSize = sizeof ( dm ); dm.dmPelsWidth = glConfig.vidWidth; dm.dmPelsHeight = glConfig.vidHeight; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; if ( r_displayRefresh->integer != 0 ) { dm.dmDisplayFrequency = r_displayRefresh->integer; dm.dmFields |= DM_DISPLAYFREQUENCY; } // try to change color depth if possible if ( colorbits != 0 ) { dm.dmBitsPerPel = colorbits; dm.dmFields |= DM_BITSPERPEL; common->Printf( "...using colorsbits of %d\n", colorbits ); } else { common->Printf( "...using desktop display depth of %d\n", desktopBitsPixel ); } // // If we're already in fullscreen then just create the window. // if ( cdsFullscreen ) { common->Printf( "...already fullscreen, avoiding redundant CDS\n" ); if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, true ) ) { common->Printf( "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); cdsFullscreen = false; return RSERR_INVALID_MODE; } } // // need to call CDS // else { common->Printf( "...calling CDS: " ); // try setting the exact mode requested, because some drivers don't report // the low res modes in EnumDisplaySettings, but still work int cdsRet = ChangeDisplaySettings( &dm, CDS_FULLSCREEN ); if ( cdsRet == DISP_CHANGE_SUCCESSFUL ) { common->Printf( "ok\n" ); if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, true ) ) { common->Printf( "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } cdsFullscreen = true; } else { common->Printf( "failed, " ); PrintCDSError( cdsRet ); // // the exact mode failed, so scan EnumDisplaySettings for the next largest mode // common->Printf( "...trying next higher resolution:" ); // we could do a better matching job here... DEVMODE devmode; int modeNum; for ( modeNum = 0;; modeNum++ ) { if ( !EnumDisplaySettings( NULL, modeNum, &devmode ) ) { modeNum = -1; break; } if ( devmode.dmPelsWidth >= glConfig.vidWidth && devmode.dmPelsHeight >= glConfig.vidHeight && devmode.dmBitsPerPel >= 15 ) { break; } } if ( modeNum != -1 ) { cdsRet = ChangeDisplaySettings( &devmode, CDS_FULLSCREEN ); } if ( modeNum != -1 && cdsRet == DISP_CHANGE_SUCCESSFUL ) { common->Printf( " ok\n" ); if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, true ) ) { common->Printf( "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } cdsFullscreen = true; } else { common->Printf( " failed, " ); PrintCDSError( cdsRet ); common->Printf( "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); cdsFullscreen = false; glConfig.isFullscreen = false; if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, false ) ) { return RSERR_INVALID_MODE; } return RSERR_INVALID_FULLSCREEN; } } } } else { if ( cdsFullscreen ) { ChangeDisplaySettings( 0, 0 ); } cdsFullscreen = false; if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, false ) ) { return RSERR_INVALID_MODE; } } // // success, now check display frequency // Com_Memset( &dm, 0, sizeof ( dm ) ); dm.dmSize = sizeof ( dm ); if ( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &dm ) ) { glConfig.displayFrequency = dm.dmDisplayFrequency; } glConfig.isFullscreen = fullscreen; return RSERR_OK; }
/* ** GLW_SetMode */ static rserr_t GLW_SetMode( int mode, int colorbits, qboolean cdsFullscreen ) { HDC hDC; const char *win_fs[] = { "W", "FS" }; int cdsRet; DEVMODE dm; // // print out informational messages // ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, win_fs[cdsFullscreen] ); // // check our desktop attributes // hDC = GetDC( GetDesktopWindow() ); glw_state.desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); glw_state.desktopWidth = GetDeviceCaps( hDC, HORZRES ); glw_state.desktopHeight = GetDeviceCaps( hDC, VERTRES ); ReleaseDC( GetDesktopWindow(), hDC ); // // verify desktop bit depth // if ( glw_state.desktopBitsPixel < 15 || glw_state.desktopBitsPixel == 24 ) { if ( colorbits == 0 || ( !cdsFullscreen && colorbits >= 15 ) ) { // since I can't be bothered trying to mess around with asian codepages and MBCS stuff for a windows // error box that'll only appear if something's seriously f****d then I'm going to fallback to // english text when these would otherwise be used... // char sErrorHead[1024]; // ott extern qboolean Language_IsAsian(void); Q_strncpyz(sErrorHead, Language_IsAsian() ? "Low Desktop Color Depth" : SP_GetStringTextString("CON_TEXT_LOW_DESKTOP_COLOUR_DEPTH"), sizeof(sErrorHead) ); const char *psErrorBody = Language_IsAsian() ? "It is highly unlikely that a correct windowed\n" "display can be initialized with the current\n" "desktop display depth. Select 'OK' to try\n" "anyway. Select 'Cancel' to try a fullscreen\n" "mode instead." : SP_GetStringTextString("CON_TEXT_TRY_ANYWAY"); if ( MessageBox( NULL, psErrorBody, sErrorHead, MB_OKCANCEL | MB_ICONEXCLAMATION ) != IDOK ) { return RSERR_INVALID_MODE; } } } // do a CDS if needed if ( cdsFullscreen ) { memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); dm.dmPelsWidth = glConfig.vidWidth; dm.dmPelsHeight = glConfig.vidHeight; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; if ( r_displayRefresh->integer != 0 ) { dm.dmDisplayFrequency = r_displayRefresh->integer; dm.dmFields |= DM_DISPLAYFREQUENCY; } // try to change color depth if possible if ( colorbits != 0 ) { if ( glw_state.allowdisplaydepthchange ) { dm.dmBitsPerPel = colorbits; dm.dmFields |= DM_BITSPERPEL; ri.Printf( PRINT_ALL, "...using colorsbits of %d\n", colorbits ); } else { ri.Printf( PRINT_ALL, "WARNING:...changing depth not supported on Win95 < pre-OSR 2.x\n" ); } } else { ri.Printf( PRINT_ALL, "...using desktop display depth of %d\n", glw_state.desktopBitsPixel ); } // // if we're already in fullscreen then just create the window // if ( glw_state.cdsFullscreen ) { ri.Printf( PRINT_ALL, "...already fullscreen, avoiding redundant CDS\n" ); if ( !GLW_CreateWindow ( glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue ) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } } // // need to call CDS // else { ri.Printf( PRINT_ALL, "...calling CDS: " ); // try setting the exact mode requested, because some drivers don't report // the low res modes in EnumDisplaySettings, but still work if ( ( cdsRet = ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) { ri.Printf( PRINT_ALL, "ok\n" ); if ( !GLW_CreateWindow ( glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } glw_state.cdsFullscreen = qtrue; } else { // // the exact mode failed, so scan EnumDisplaySettings for the next largest mode // DEVMODE devmode; int modeNum; ri.Printf( PRINT_ALL, "failed, " ); PrintCDSError( cdsRet ); ri.Printf( PRINT_ALL, "...trying next higher resolution:" ); // we could do a better matching job here... for ( modeNum = 0 ; ; modeNum++ ) { if ( !EnumDisplaySettings( NULL, modeNum, &devmode ) ) { modeNum = -1; break; } if ( devmode.dmPelsWidth >= glConfig.vidWidth && devmode.dmPelsHeight >= glConfig.vidHeight && devmode.dmBitsPerPel >= 15 ) { break; } } if ( modeNum != -1 && ( cdsRet = ChangeDisplaySettings( &devmode, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) { ri.Printf( PRINT_ALL, " ok\n" ); if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } glw_state.cdsFullscreen = qtrue; } else { ri.Printf( PRINT_ALL, " failed, " ); PrintCDSError( cdsRet ); ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); /* jfm: i took out the following code to allow fallback to mode 3, with this code it goes half windowed and just doesn't work. glw_state.cdsFullscreen = qfalse; glConfig.isFullscreen = qfalse; if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, qfalse) ) { return RSERR_INVALID_MODE; } */ return RSERR_INVALID_FULLSCREEN; } } } } else { if ( glw_state.cdsFullscreen ) { ChangeDisplaySettings( 0, 0 ); } glw_state.cdsFullscreen = qfalse; if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, qfalse ) ) { return RSERR_INVALID_MODE; } } // // success, now check display frequency, although this won't be valid on Voodoo(2) // memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); if ( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &dm ) ) { glConfig.displayFrequency = dm.dmDisplayFrequency; } // NOTE: this is overridden later on standalone 3Dfx drivers glConfig.isFullscreen = cdsFullscreen; return RSERR_OK; }