diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cl_ref.c | 8 | ||||
-rw-r--r-- | src/vid_local.h | 1 | ||||
-rw-r--r-- | src/vid_sdl.c | 4 | ||||
-rw-r--r-- | src/vid_win.c | 258 |
4 files changed, 232 insertions, 39 deletions
diff --git a/src/cl_ref.c b/src/cl_ref.c index 74f0597..38464b3 100644 --- a/src/cl_ref.c +++ b/src/cl_ref.c @@ -266,17 +266,23 @@ CL_InitRefresh ============ */ void CL_InitRefresh( void ) { + char *modelist; + if( cls.ref_initialized ) { return; } + modelist = VID_GetDefaultModeList(); + // Create the video variables so we know how to start the graphics drivers vid_ref = Cvar_Get( "vid_ref", VID_REF, CVAR_ROM ); vid_fullscreen = Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE ); _vid_fullscreen = Cvar_Get( "_vid_fullscreen", "1", CVAR_ARCHIVE ); - vid_modelist = Cvar_Get( "vid_modelist", VID_MODELIST, 0 ); + vid_modelist = Cvar_Get( "vid_modelist", modelist, 0 ); vid_geometry = Cvar_Get( "vid_geometry", VID_GEOMETRY, CVAR_ARCHIVE ); + Z_Free( modelist ); + if( vid_fullscreen->integer ) { Cvar_Set( "_vid_fullscreen", vid_fullscreen->string ); } else if( !_vid_fullscreen->integer ) { diff --git a/src/vid_local.h b/src/vid_local.h index 9c084d6..3e8c4d4 100644 --- a/src/vid_local.h +++ b/src/vid_local.h @@ -29,6 +29,7 @@ extern cvar_t *_vid_fullscreen; // void VID_PumpEvents( void ); void VID_SetMode( void ); +char *VID_GetDefaultModeList( void ); // // cl_ref.c diff --git a/src/vid_sdl.c b/src/vid_sdl.c index 4a0acd5..aa37966 100644 --- a/src/vid_sdl.c +++ b/src/vid_sdl.c @@ -222,6 +222,10 @@ success: return qtrue; } +char *VID_GetDefaultModeList( void ) { + return Z_CopyString(VID_MODELIST); +} + /* ============ VID_SetMode diff --git a/src/vid_win.c b/src/vid_win.c index 7fd9f82..7ad24e6 100644 --- a/src/vid_win.c +++ b/src/vid_win.c @@ -132,65 +132,247 @@ void Win_ModeChanged( void ) { /* ============ -Win_SetMode +VID_GetDefaultModeList ============ */ -void Win_SetMode( void ) { - DEVMODE dm; + +typedef struct { + int width, height; + int freq, depth; + qboolean desktop; +} vidmode_t; + +#define MAX_MODES 256 + +static int modecmp(const void *p1, const void *p2) +{ + const vidmode_t *m1 = (const vidmode_t *)p1; + const vidmode_t *m2 = (const vidmode_t *)p2; + + // desktop resolution is always first + if (m1->desktop) + return -1; + + return m2->width * m2->height - m1->width * m1->height; +} + +// should have at least width and height +#define DM_USABLE(dm) \ + (((dm)->dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) == (DM_PELSWIDTH | DM_PELSHEIGHT)) + +static void process_mode(vidmode_t *modes, int *num_modes, const DEVMODE *dm, const DEVMODE *desktop) +{ + int freq = 0, depth = 0; + vidmode_t *m; + int i; + + if (!DM_USABLE(dm)) + return; + + // sanity check width and height + if (dm->dmPelsWidth < 64 || dm->dmPelsHeight < 64) + return; + if (dm->dmPelsWidth > 8192 || dm->dmPelsHeight > 8192) + return; + + if (dm->dmFields & DM_DISPLAYFLAGS) { + if (dm->dmDisplayFlags & (DM_GRAYSCALE | DM_INTERLACED)) + return; + } + + if (dm->dmFields & DM_DISPLAYFREQUENCY) { + if (dm->dmDisplayFrequency <= 1 || dm->dmDisplayFrequency > 1000) + return; + freq = dm->dmDisplayFrequency; + } + + if (dm->dmFields & DM_BITSPERPEL) { + if (dm->dmBitsPerPel < 8 || dm->dmBitsPerPel > 32) + return; + // completely ignore non-desktop bit depths for now + if ((desktop->dmFields & DM_BITSPERPEL) && dm->dmBitsPerPel != desktop->dmBitsPerPel) + return; + depth = dm->dmBitsPerPel; + } + + // see if we already have this resolution + for (i = 0; i < *num_modes; i++) { + m = &modes[i]; + if (m->width == dm->dmPelsWidth && m->height == dm->dmPelsHeight) { + if (freq > m->freq) + m->freq = freq; + if (depth > m->depth) + m->depth = depth; + return; + } + } + + // add new resolution + if (*num_modes >= MAX_MODES) + return; + + m = &modes[(*num_modes)++]; + m->width = dm->dmPelsWidth; + m->height = dm->dmPelsHeight; + m->freq = freq; + m->depth = depth; + m->desktop = qfalse; + if (dm->dmPelsWidth == desktop->dmPelsWidth && dm->dmPelsHeight == desktop->dmPelsHeight) + m->desktop = qtrue; +} + +char *VID_GetDefaultModeList(void) +{ + DEVMODE desktop, dm; + vidmode_t modes[MAX_MODES], *m; + int i, num_modes; + size_t size, len; + char *buf; + + memset(&desktop, 0, sizeof(desktop)); + desktop.dmSize = sizeof(desktop); + + if (!EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &desktop)) + return Z_CopyString(VID_MODELIST); + + num_modes = 0; + for (i = 0; i < MAX_MODES*4; i++) { + memset(&dm, 0, sizeof(dm)); + dm.dmSize = sizeof(dm); + + if (!EnumDisplaySettings(NULL, i, &dm)) + break; + + process_mode(modes, &num_modes, &dm, &desktop); + } + + if (!num_modes) + return Z_CopyString(VID_MODELIST); + + qsort(modes, num_modes, sizeof(modes[0]), modecmp); + + size = num_modes * 20 + 1; + buf = Z_Malloc(size); + + len = 0; + for (i = 0; i < num_modes; i++) { + m = &modes[i]; + + len += Q_scnprintf(buf + len, size - len, "%dx%d", m->width, m->height); + + if (m->freq && (desktop.dmFields & DM_DISPLAYFREQUENCY) && m->freq != desktop.dmDisplayFrequency) + len += Q_scnprintf(buf + len, size - len, "@%d", m->freq); + + if (m->depth && (desktop.dmFields & DM_BITSPERPEL) && m->depth != desktop.dmBitsPerPel) + len += Q_scnprintf(buf + len, size - len, ":%d", m->depth); + + if (len < size - 1 && i < num_modes - 1) + buf[len++] = ' '; + } + buf[len] = 0; + + return buf; +} + +// use desktop frequency by default if using desktop resolution +static int get_desktop_frequency( const DEVMODE *desktop ) { + const int mask = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; + + if( (desktop->dmFields & mask) != mask ) + return 0; + if( desktop->dmPelsWidth != win.rc.width ) + return 0; + if( desktop->dmPelsHeight != win.rc.height ) + return 0; + + return desktop->dmDisplayFrequency; +} + +static qboolean set_fullscreen_mode( void ) { + DEVMODE desktop, dm; LONG ret; int freq, depth; - if( vid_fullscreen->integer > 0 ) { - // parse vid_modelist specification - VID_GetModeFS( &win.rc, &freq, &depth ); + memset( &desktop, 0, sizeof( desktop ) ); + desktop.dmSize = sizeof( desktop ); + + EnumDisplaySettings( NULL, ENUM_REGISTRY_SETTINGS, &desktop ); + // parse vid_modelist specification + if( VID_GetFullscreen( &win.rc, &freq, &depth ) ) { Com_DPrintf( "...setting fullscreen mode: %dx%d\n", win.rc.width, win.rc.height ); + } else if( DM_USABLE( &desktop ) ) { + win.rc.width = desktop.dmPelsWidth; + win.rc.height = desktop.dmPelsHeight; + Com_DPrintf( "...falling back to desktop mode: %dx%d\n", + win.rc.width, win.rc.height ); + } else { + Com_DPrintf( "...falling back to default mode: %dx%d\n", + win.rc.width, win.rc.height ); + } - memset( &dm, 0, sizeof( dm ) ); - dm.dmSize = sizeof( dm ); - dm.dmPelsWidth = win.rc.width; - dm.dmPelsHeight = win.rc.height; - dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + memset( &dm, 0, sizeof( dm ) ); + dm.dmSize = sizeof( dm ); + dm.dmPelsWidth = win.rc.width; + dm.dmPelsHeight = win.rc.height; + dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; - if( freq ) { + if( freq ) { + dm.dmDisplayFrequency = freq; + dm.dmFields |= DM_DISPLAYFREQUENCY; + Com_DPrintf( "...using display frequency of %d\n", freq ); + } else { + freq = get_desktop_frequency( &desktop ); + if( freq > 1 ) { dm.dmDisplayFrequency = freq; dm.dmFields |= DM_DISPLAYFREQUENCY; - Com_DPrintf( "...using display frequency of %d\n", freq ); + Com_DPrintf( "...using desktop display frequency of %d\n", freq ); } + } - if( depth ) { - dm.dmBitsPerPel = depth; - dm.dmFields |= DM_BITSPERPEL; - Com_DPrintf( "...using bitdepth of %d\n", depth ); -#ifdef _DEBUG - } else if( developer->integer ) { - HDC hdc; - int bitspixel; + if( depth ) { + dm.dmBitsPerPel = depth; + dm.dmFields |= DM_BITSPERPEL; + Com_DPrintf( "...using bitdepth of %d\n", depth ); + } else if( desktop.dmFields & DM_BITSPERPEL ) { + dm.dmBitsPerPel = desktop.dmBitsPerPel; + dm.dmFields |= DM_BITSPERPEL; + Com_DPrintf( "...using desktop bitdepth of %lu\n", desktop.dmBitsPerPel ); + } - hdc = GetDC( NULL ); - bitspixel = GetDeviceCaps( hdc, BITSPIXEL ); - ReleaseDC( NULL, hdc ); + Com_DPrintf( "...calling CDS: " ); + ret = ChangeDisplaySettings( &dm, CDS_FULLSCREEN ); + if( ret != DISP_CHANGE_SUCCESSFUL ) { + Com_DPrintf( "failed with error %ld\n", ret ); + return qfalse; + } + Com_DPrintf( "ok\n" ); - Com_DPrintf( "...using desktop bitdepth of %d\n", bitspixel ); -#endif - } + win.dm = dm; + win.flags |= QVF_FULLSCREEN; + Win_SetPosition(); + win.mode_changed = 0; - Com_DPrintf( "...calling CDS: " ); - ret = ChangeDisplaySettings( &dm, CDS_FULLSCREEN ); - if( ret == DISP_CHANGE_SUCCESSFUL ) { - Com_DPrintf( "ok\n" ); - win.dm = dm; - win.flags |= QVF_FULLSCREEN; - Win_SetPosition(); - win.mode_changed = 0; + return qtrue; +} + +/* +============ +Win_SetMode +============ +*/ +void Win_SetMode( void ) { + // set full screen mode if requested + if( vid_fullscreen->integer > 0 ) { + if( set_fullscreen_mode() ) { return; } - Com_DPrintf( "failed with error %ld\n", ret ); Cvar_Reset( vid_fullscreen ); Com_Printf( "Full screen mode %dx%d failed.\n", win.rc.width, win.rc.height ); + // fall back to windowed mode } // parse vid_geometry specification @@ -204,7 +386,7 @@ void Win_SetMode( void ) { if( win.rc.width < 320 ) win.rc.width = 320; if( win.rc.height < 240 ) win.rc.height = 240; - Com_DPrintf( "...setting windowed mode: %dx%d+%d+%d\n", + Com_DPrintf( "...setting windowed mode: %dx%d%+d%+d\n", win.rc.width, win.rc.height, win.rc.x, win.rc.y ); ChangeDisplaySettings( NULL, 0 ); @@ -929,7 +1111,7 @@ void Win_Shutdown( void ) { } if( win.flags & QVF_FULLSCREEN ) { - ChangeDisplaySettings( 0, 0 ); + ChangeDisplaySettings( NULL, 0 ); } memset( &win, 0, sizeof( win ) ); |