#define VIDEO_ITEMS 10
static int video_cursor = 0;
-static int video_cursor_table[] = {56, 68, 88, 100, 112, 132, 162, 170, 178, 186};
+static int video_cursor_table[] = {56, 68, 88, 100, 108, 116, 136, 166, 174, 182, 190};
static int video_resolution;
void M_Menu_Video_f (void)
// Current Resolution
M_Print(16, video_cursor_table[0], " Current Resolution");
- if (vid_supportrefreshrate && vid.fullscreen)
+ if (vid_supportrefreshrate && vid.userefreshrate && vid.fullscreen)
M_Print(220, video_cursor_table[0], va("%dx%d %dhz", vid.width, vid.height, vid.refreshrate));
else
M_Print(220, video_cursor_table[0], va("%dx%d", vid.width, vid.height));
M_Print(220, video_cursor_table[2], (vid_bitsperpixel.integer == 32) ? "32" : "16");
// Refresh Rate
- M_ItemPrint(16, video_cursor_table[3], " Refresh Rate", vid_supportrefreshrate);
- M_DrawSlider(220, video_cursor_table[3], vid_refreshrate.integer, 60, 150);
+ M_ItemPrint(16, video_cursor_table[3], " Use Refresh Rate", vid_supportrefreshrate);
+ M_DrawCheckbox(220, video_cursor_table[3], vid_userefreshrate.integer);
+
+ // Refresh Rate
+ M_ItemPrint(16, video_cursor_table[4], " Refresh Rate", vid_supportrefreshrate && vid_userefreshrate.integer);
+ M_DrawSlider(220, video_cursor_table[4], vid_refreshrate.integer, 60, 150);
// Fullscreen
- M_Print(16, video_cursor_table[4], " Fullscreen");
- M_DrawCheckbox(220, video_cursor_table[4], vid_fullscreen.integer);
+ M_Print(16, video_cursor_table[5], " Fullscreen");
+ M_DrawCheckbox(220, video_cursor_table[5], vid_fullscreen.integer);
// "Apply" button
- M_Print(220, video_cursor_table[5], "Apply");
+ M_Print(220, video_cursor_table[6], "Apply");
// Vertical Sync
- M_ItemPrint(16, video_cursor_table[6], " Vertical Sync", gl_videosyncavailable);
- M_DrawCheckbox(220, video_cursor_table[6], vid_vsync.integer);
+ M_ItemPrint(16, video_cursor_table[7], " Vertical Sync", gl_videosyncavailable);
+ M_DrawCheckbox(220, video_cursor_table[7], vid_vsync.integer);
- M_ItemPrint(16, video_cursor_table[7], " Anisotropic Filter", gl_support_anisotropy);
- M_DrawSlider(220, video_cursor_table[7], gl_texture_anisotropy.integer, 1, gl_max_anisotropy);
+ M_ItemPrint(16, video_cursor_table[8], " Anisotropic Filter", gl_support_anisotropy);
+ M_DrawSlider(220, video_cursor_table[8], gl_texture_anisotropy.integer, 1, gl_max_anisotropy);
- M_ItemPrint(16, video_cursor_table[8], " Texture Quality", true);
- M_DrawSlider(220, video_cursor_table[8], gl_picmip.value, 3, 0);
+ M_ItemPrint(16, video_cursor_table[9], " Texture Quality", true);
+ M_DrawSlider(220, video_cursor_table[9], gl_picmip.value, 3, 0);
- M_ItemPrint(16, video_cursor_table[9], " Texture Compression", gl_support_texture_compression);
- M_DrawCheckbox(220, video_cursor_table[9], gl_texturecompression.integer);
+ M_ItemPrint(16, video_cursor_table[10], " Texture Compression", gl_support_texture_compression);
+ M_DrawCheckbox(220, video_cursor_table[10], gl_texturecompression.integer);
// Cursor
M_DrawCharacter(200, video_cursor_table[video_cursor], 12+((int)(realtime*4)&1));
break;
// Refresh Rate
case 3:
- Cvar_SetValueQuick (&vid_refreshrate, vid_refreshrate.integer + dir);
+ Cvar_SetValueQuick (&vid_userefreshrate, !vid_userefreshrate.integer);
break;
case 4:
+ Cvar_SetValueQuick (&vid_refreshrate, bound(60, vid_refreshrate.integer + dir, 150));
+ break;
+ case 5:
Cvar_SetValueQuick (&vid_fullscreen, !vid_fullscreen.integer);
break;
- case 6:
+ case 7:
Cvar_SetValueQuick (&vid_vsync, !vid_vsync.integer);
break;
- case 7:
+ case 8:
Cvar_SetValueQuick (&gl_texture_anisotropy, bound(1, gl_texture_anisotropy.value * (dir < 0 ? 0.5 : 2.0), gl_max_anisotropy));
break;
- case 8:
+ case 9:
Cvar_SetValueQuick (&gl_picmip, bound(0, gl_picmip.value - dir, 3));
break;
- case 9:
+ case 10:
Cvar_SetValueQuick (&gl_texturecompression, !gl_texturecompression.integer);
break;
}
Cvar_SetValueQuick(&vid_bitsperpixel, vid.bitsperpixel);
if (vid_supportrefreshrate)
Cvar_SetValueQuick(&vid_refreshrate, vid.refreshrate);
+ Cvar_SetValueQuick(&vid_userefreshrate, vid.userefreshrate);
S_LocalSound ("sound/misc/menu1.wav");
M_Menu_Options_f ();
int bitsperpixel;
int fullscreen;
int refreshrate;
+ qboolean userefreshrate;
int stereobuffer;
} viddef_t;
extern cvar_t vid_height;
extern cvar_t vid_bitsperpixel;
extern cvar_t vid_refreshrate;
+extern cvar_t vid_userefreshrate;
extern cvar_t vid_vsync;
extern cvar_t vid_mouse;
extern cvar_t vid_grabkeyboard;
cvar_t vid_height = {CVAR_SAVE, "vid_height", "480", "resolution"};
cvar_t vid_bitsperpixel = {CVAR_SAVE, "vid_bitsperpixel", "32", "how many bits per pixel to render at (32 or 16, 32 is recommended)"};
cvar_t vid_refreshrate = {CVAR_SAVE, "vid_refreshrate", "60", "refresh rate to use, in hz (higher values flicker less, if supported by your monitor)"};
+cvar_t vid_userefreshrate = {CVAR_SAVE, "vid_userefreshrate", "0", "set this to 1 to make vid_refreshrate used, or to 0 to let the engine choose a sane default"};
cvar_t vid_stereobuffer = {CVAR_SAVE, "vid_stereobuffer", "0", "enables 'quad-buffered' stereo rendering for stereo shutterglasses, HMD (head mounted display) devices, or polarized stereo LCDs, if supported by your drivers"};
cvar_t vid_vsync = {CVAR_SAVE, "vid_vsync", "0", "sync to vertical blank, prevents 'tearing' (seeing part of one frame and part of another on the screen at the same time), automatically disabled when doing timedemo benchmarks"};
Cvar_RegisterVariable(&vid_height);
Cvar_RegisterVariable(&vid_bitsperpixel);
Cvar_RegisterVariable(&vid_refreshrate);
+ Cvar_RegisterVariable(&vid_userefreshrate);
Cvar_RegisterVariable(&vid_stereobuffer);
Cvar_RegisterVariable(&vid_vsync);
Cvar_RegisterVariable(&vid_mouse);
{
cl_ignoremousemoves = 2;
Con_Printf("Video: %s %dx%dx%dx%dhz%s\n", fullscreen ? "fullscreen" : "window", width, height, bpp, refreshrate, stereobuffer ? " stereo" : "");
- if (VID_InitMode(fullscreen, width, height, bpp, refreshrate, stereobuffer))
+ if (VID_InitMode(fullscreen, width, height, bpp, vid_userefreshrate.integer ? max(1, refreshrate) : 0, stereobuffer))
{
vid.fullscreen = fullscreen;
vid.width = width;
vid.bitsperpixel = bpp;
vid.refreshrate = refreshrate;
vid.stereobuffer = stereobuffer;
+ vid.userefreshrate = vid_userefreshrate.integer;
Cvar_SetValueQuick(&vid_fullscreen, fullscreen);
Cvar_SetValueQuick(&vid_width, width);
Cvar_SetValueQuick(&vid_height, height);
Cvar_SetValueQuick(&vid_bitsperpixel, bpp);
- Cvar_SetValueQuick(&vid_refreshrate, refreshrate);
+ if(vid_userefreshrate.integer)
+ Cvar_SetValueQuick(&vid_refreshrate, refreshrate);
Cvar_SetValueQuick(&vid_stereobuffer, stereobuffer);
return true;
}
{NULL, NULL}
};
-static DEVMODE gdevmode;
+static DEVMODE gdevmode, initialdevmode;
static qboolean vid_initialized = false;
static qboolean vid_wassuspended = false;
static qboolean vid_usingmouse = false;
static cvar_t joy_wwhack1 = {0, "joywwhack1", "0.0", "special hack for wingman warrior"};
static cvar_t joy_wwhack2 = {0, "joywwhack2", "0.0", "special hack for wingman warrior"};
+static cvar_t vid_forcerefreshrate = {0, "vid_forcerefreshrate", "0", "try to set the given vid_refreshrate even if Windows doesn't list it as valid video mode"};
+
static qboolean joy_avail, joy_advancedinit, joy_haspov;
static DWORD joy_oldbuttonstate, joy_oldpovstate;
if (!RegisterClass (&wc))
Con_Printf ("Couldn't register window class\n");
+ memset(&initialdevmode, 0, sizeof(initialdevmode));
+ EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &initialdevmode);
+
IN_Init();
}
int CenterX, CenterY;
const char *gldrivername;
int depth;
+ DEVMODE thismode;
+ qboolean foundmode, foundgoodmode;
if (vid_initialized)
Sys_Error("VID_InitMode called when video is already initialised");
vid_isfullscreen = false;
if (fullscreen)
{
- gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
- gdevmode.dmBitsPerPel = bpp;
- gdevmode.dmPelsWidth = width;
- gdevmode.dmPelsHeight = height;
- gdevmode.dmDisplayFrequency = refreshrate;
- gdevmode.dmSize = sizeof (gdevmode);
- if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
+ if(vid_forcerefreshrate.integer)
+ {
+ foundmode = true;
+ gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+ gdevmode.dmBitsPerPel = bpp;
+ gdevmode.dmPelsWidth = width;
+ gdevmode.dmPelsHeight = height;
+ gdevmode.dmSize = sizeof (gdevmode);
+ if(refreshrate)
+ {
+ gdevmode.dmFields |= DM_DISPLAYFREQUENCY;
+ gdevmode.dmDisplayFrequency = refreshrate;
+ }
+ }
+ else
+ {
+ if(refreshrate == 0)
+ refreshrate = initialdevmode.dmDisplayFrequency; // default vid_refreshrate to the rate of the desktop
+
+ foundmode = false;
+ foundgoodmode = false;
+
+ thismode.dmSize = sizeof(thismode);
+ thismode.dmDriverExtra = 0;
+ for(i = 0; EnumDisplaySettings(NULL, i, &thismode); ++i)
+ {
+ if(~thismode.dmFields & (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY))
+ {
+ Con_DPrintf("enumerating modes yielded a bogus item... please debug this\n");
+ continue;
+ }
+ if(developer.integer >= 100)
+ Con_Printf("Found mode %dx%dx%dbpp %dHz... ", (int)thismode.dmPelsWidth, (int)thismode.dmPelsHeight, (int)thismode.dmBitsPerPel, (int)thismode.dmDisplayFrequency);
+ if(thismode.dmBitsPerPel != (DWORD)bpp)
+ {
+ if(developer.integer >= 100)
+ Con_Printf("wrong bpp\n");
+ continue;
+ }
+ if(thismode.dmPelsWidth != (DWORD)width)
+ {
+ if(developer.integer >= 100)
+ Con_Printf("wrong width\n");
+ continue;
+ }
+ if(thismode.dmPelsHeight != (DWORD)height)
+ {
+ if(developer.integer >= 100)
+ Con_Printf("wrong height\n");
+ continue;
+ }
+
+ if(foundgoodmode)
+ {
+ // if we have a good mode, make sure this mode is better than the previous one, and allowed by the refreshrate
+ if(thismode.dmDisplayFrequency > (DWORD)refreshrate)
+ {
+ if(developer.integer >= 100)
+ Con_Printf("too high refresh rate\n");
+ continue;
+ }
+ else if(thismode.dmDisplayFrequency <= gdevmode.dmDisplayFrequency)
+ {
+ if(developer.integer >= 100)
+ Con_Printf("doesn't beat previous best match (too low)\n");
+ continue;
+ }
+ }
+ else if(foundmode)
+ {
+ // we do have one, but it isn't good... make sure it has a lower frequency than the previous one
+ if(thismode.dmDisplayFrequency >= gdevmode.dmDisplayFrequency)
+ {
+ if(developer.integer >= 100)
+ Con_Printf("doesn't beat previous best match (too high)\n");
+ continue;
+ }
+ }
+ // otherwise, take anything
+
+ memcpy(&gdevmode, &thismode, sizeof(gdevmode));
+ if(thismode.dmDisplayFrequency <= (DWORD)refreshrate)
+ foundgoodmode = true;
+ else
+ {
+ if(developer.integer >= 100)
+ Con_Printf("(out of range)\n");
+ }
+ foundmode = true;
+ if(developer.integer >= 100)
+ Con_Printf("accepted\n");
+ }
+ }
+
+ if (!foundmode)
+ {
+ VID_Shutdown();
+ Con_Printf("Unable to find the requested mode %dx%dx%dbpp\n", width, height, bpp);
+ return false;
+ }
+ else if(ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
VID_Shutdown();
Con_Printf("Unable to change to requested mode %dx%dx%dbpp\n", width, height, bpp);
Cvar_RegisterVariable (&joy_yawsensitivity);
Cvar_RegisterVariable (&joy_wwhack1);
Cvar_RegisterVariable (&joy_wwhack2);
+ Cvar_RegisterVariable (&vid_forcerefreshrate);
Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f, "applies current joyadv* cvar settings to the joystick driver");
}