[PATCH 3/3] gdi32: Report real VREFRESH values for GetDeviceCaps() with display DCs.

Zhiyi Zhang zzhang at codeweavers.com
Wed Jan 20 02:40:11 CST 2021


Even though MSDN says 0 and 1 are both valid and they represent the default refresh rate of display
hardware. Some games rely on the value being the real refresh rate and use it to cap frame rates.

Fix an issue that Sakuna: Of Rice and Ruin reports monitors of 1Hz and cap to 1fps.

Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/gdi32/driver.c   | 25 ++++++++++++++++++++++++-
 dlls/gdi32/tests/dc.c |  4 ----
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index bb98c554238..e146a3a4f85 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -82,6 +82,7 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
 static CRITICAL_SECTION driver_section = { &critsect_debug, -1, 0, 0, 0, 0 };
 
 static BOOL (WINAPI *pEnumDisplayMonitors)(HDC, LPRECT, MONITORENUMPROC, LPARAM);
+static BOOL (WINAPI *pEnumDisplaySettingsW)(LPCWSTR, DWORD, LPDEVMODEW);
 static HWND (WINAPI *pGetDesktopWindow)(void);
 static BOOL (WINAPI *pGetMonitorInfoW)(HMONITOR, LPMONITORINFO);
 static INT (WINAPI *pGetSystemMetrics)(INT);
@@ -245,6 +246,7 @@ void CDECL __wine_set_display_driver( HMODULE module )
     pGetMonitorInfoW = (void *)GetProcAddress( user32, "GetMonitorInfoW" );
     pGetSystemMetrics = (void *)GetProcAddress( user32, "GetSystemMetrics" );
     pEnumDisplayMonitors = (void *)GetProcAddress( user32, "EnumDisplayMonitors" );
+    pEnumDisplaySettingsW = (void *)GetProcAddress( user32, "EnumDisplaySettingsW" );
     pSetThreadDpiAwarenessContext = (void *)GetProcAddress( user32, "SetThreadDpiAwarenessContext" );
 }
 
@@ -471,7 +473,28 @@ static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap )
     case PHYSICALOFFSETY: return 0;
     case SCALINGFACTORX:  return 0;
     case SCALINGFACTORY:  return 0;
-    case VREFRESH:        return GetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY ? 1 : 0;
+    case VREFRESH:
+    {
+        DEVMODEW devmode;
+        WCHAR *display;
+        DC *dc;
+
+        if (GetDeviceCaps( dev->hdc, TECHNOLOGY ) != DT_RASDISPLAY)
+            return 0;
+
+        if (pEnumDisplaySettingsW)
+        {
+            dc = get_nulldrv_dc( dev );
+
+            memset( &devmode, 0, sizeof(devmode) );
+            devmode.dmSize = sizeof(devmode);
+            display = dc->display[0] ? dc->display : NULL;
+            if (pEnumDisplaySettingsW( display, ENUM_CURRENT_SETTINGS, &devmode ))
+                return devmode.dmDisplayFrequency ? devmode.dmDisplayFrequency : 1;
+        }
+
+        return 1;
+    }
     case DESKTOPHORZRES:
         if (GetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && pGetSystemMetrics)
         {
diff --git a/dlls/gdi32/tests/dc.c b/dlls/gdi32/tests/dc.c
index 963b62f4e15..e3ac381964f 100644
--- a/dlls/gdi32/tests/dc.c
+++ b/dlls/gdi32/tests/dc.c
@@ -1708,7 +1708,6 @@ static void test_multi_monitor_dc(void)
     ok(value == dm.dmPelsHeight, "Expected %d, got %d.\n", dm.dmPelsHeight, value);
 
     value = GetDeviceCaps(hdc, VREFRESH);
-    todo_wine_if(value != dm.dmDisplayFrequency && value == 1)
     ok(value == dm.dmDisplayFrequency, "Expected %d, got %d.\n", dm.dmDisplayFrequency, value);
 
     /* Test GetDeviceCaps() values after mode changes */
@@ -1744,7 +1743,6 @@ static void test_multi_monitor_dc(void)
         ok(value == dm2.dmPelsHeight, "Expected %d, got %d.\n", dm2.dmPelsHeight, value);
 
         value = GetDeviceCaps(hdc, VREFRESH);
-        todo_wine_if(value != dm2.dmDisplayFrequency && value == 1)
         ok(value == dm2.dmDisplayFrequency, "Expected %d, got %d.\n", dm2.dmDisplayFrequency, value);
 
         res = ChangeDisplaySettingsExA(NULL, NULL, NULL, 0, NULL);
@@ -1785,7 +1783,6 @@ static void test_multi_monitor_dc(void)
         ok(value == dm.dmPelsHeight, "Expected %d, got %d.\n", dm.dmPelsHeight, value);
 
         value = GetDeviceCaps(hdc, VREFRESH);
-        todo_wine_if(value != dm.dmDisplayFrequency && value == 1)
         ok(value == dm.dmDisplayFrequency, "Expected %d, got %d.\n", dm.dmDisplayFrequency, value);
 
         /* Test GetDeviceCaps() values after mode changes */
@@ -1827,7 +1824,6 @@ static void test_multi_monitor_dc(void)
         ok(value == dm2.dmPelsHeight, "Expected %d, got %d.\n", dm2.dmPelsHeight, value);
 
         value = GetDeviceCaps(hdc, VREFRESH);
-        todo_wine_if(value != dm2.dmDisplayFrequency && value == 1)
         ok(value == dm2.dmDisplayFrequency, "Expected %d, got %d.\n", dm2.dmDisplayFrequency, value);
 
         /* Test GetDeviceCaps() values after monitor detach */
-- 
2.27.0



More information about the wine-devel mailing list