- vid_userefreshrate: when 0, a sane default is tried to be used
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 1 Feb 2008 08:56:31 +0000 (08:56 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 1 Feb 2008 08:56:31 +0000 (08:56 +0000)
- win32: list valid modes, and use the closest match
- win32: vid_forcerefreshrate: don't do the listing, but just try to set it anyway

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8060 d7cf8633-e32d-0410-b094-e92efae38249

menu.c
vid.h
vid_shared.c
vid_wgl.c

diff --git a/menu.c b/menu.c
index c0e71be..2cdae63 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -2795,7 +2795,7 @@ video_resolution_t video_resolutions[] =
 
 #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)
@@ -2852,7 +2852,7 @@ static void M_Video_Draw (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));
@@ -2867,28 +2867,32 @@ static void M_Video_Draw (void)
        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));
@@ -2924,22 +2928,25 @@ static void M_Menu_Video_AdjustSliders (int dir)
                        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;
        }
@@ -2956,6 +2963,7 @@ static void M_Video_Key (int key, char ascii)
                        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 ();
diff --git a/vid.h b/vid.h
index 29ab878..aac4edc 100644 (file)
--- a/vid.h
+++ b/vid.h
@@ -34,6 +34,7 @@ typedef struct viddef_s
        int bitsperpixel;
        int fullscreen;
        int refreshrate;
+       qboolean userefreshrate;
        int stereobuffer;
 } viddef_t;
 
@@ -53,6 +54,7 @@ extern cvar_t vid_width;
 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;
index 33c194b..da1a2e1 100644 (file)
@@ -83,6 +83,7 @@ cvar_t vid_width = {CVAR_SAVE, "vid_width", "640", "resolution"};
 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"};
@@ -1051,6 +1052,7 @@ void VID_Shared_Init(void)
        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);
@@ -1071,7 +1073,7 @@ int VID_Mode(int fullscreen, int width, int height, int bpp, int refreshrate, in
 {
        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;
@@ -1079,11 +1081,13 @@ int VID_Mode(int fullscreen, int width, int height, int bpp, int refreshrate, in
                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;
        }
index 4f97d31..638c834 100644 (file)
--- a/vid_wgl.c
+++ b/vid_wgl.c
@@ -78,7 +78,7 @@ static dllfunction_t wglswapintervalfuncs[] =
        {NULL, NULL}
 };
 
-static DEVMODE gdevmode;
+static DEVMODE gdevmode, initialdevmode;
 static qboolean vid_initialized = false;
 static qboolean vid_wassuspended = false;
 static qboolean vid_usingmouse = false;
@@ -202,6 +202,8 @@ static cvar_t joy_yawsensitivity = {0, "joyyawsensitivity", "-1.0", "how fast th
 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;
 
@@ -696,6 +698,9 @@ void VID_Init(void)
        if (!RegisterClass (&wc))
                Con_Printf ("Couldn't register window class\n");
 
+       memset(&initialdevmode, 0, sizeof(initialdevmode));
+       EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &initialdevmode);
+
        IN_Init();
 }
 
@@ -731,6 +736,8 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int refreshrat
        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");
@@ -766,13 +773,107 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int refreshrat
        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);
@@ -1774,6 +1875,7 @@ static void IN_Init(void)
        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");
 }