Last active
August 29, 2015 14:16
-
-
Save compholio/749bbec6ff1b4d096bc1 to your computer and use it in GitHub Desktop.
winex11: Return the actual refresh rate for NVIDIA cards with Dynamic TwinView enabled.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 5b9a41a5cfd0297b5fc1a226d37693a9dec34625 Mon Sep 17 00:00:00 2001 | |
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com> | |
Date: Tue, 3 Mar 2015 10:33:38 -0700 | |
Subject: winex11: Return the actual refresh rate for NVIDIA cards with Dynamic | |
TwinView enabled. | |
--- | |
dlls/winex11.drv/xrandr.c | 53 ++++++++++++++++++++++++++++++++++------------- | |
1 file changed, 39 insertions(+), 14 deletions(-) | |
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c | |
index e7fbf91..e85fbc5 100644 | |
--- a/dlls/winex11.drv/xrandr.c | |
+++ b/dlls/winex11.drv/xrandr.c | |
@@ -68,8 +68,12 @@ static int primary_crtc; | |
#undef MAKE_FUNCPTR | |
+struct xrandr10_mode { | |
+ SizeID id; | |
+ short rate; | |
+}; | |
static struct x11drv_mode_info *dd_modes; | |
-static SizeID *xrandr10_modes; | |
+static struct xrandr10_mode *xrandr10_modes; | |
static unsigned int xrandr_mode_count; | |
static int xrandr_current_mode = -1; | |
@@ -139,7 +143,7 @@ static int xrandr10_get_current_mode(void) | |
for (i = 0; i < xrandr_mode_count; ++i) | |
{ | |
- if (xrandr10_modes[i] == size && dd_modes[i].refresh_rate == rate) | |
+ if (xrandr10_modes[i].id == size && xrandr10_modes[i].rate == rate) | |
{ | |
res = i; | |
break; | |
@@ -174,8 +178,8 @@ static LONG xrandr10_set_current_mode( int mode ) | |
dd_modes[mode].height, | |
dd_modes[mode].refresh_rate); | |
- size = xrandr10_modes[mode]; | |
- rate = dd_modes[mode].refresh_rate; | |
+ size = xrandr10_modes[mode].id; | |
+ rate = xrandr10_modes[mode].rate; | |
if (rate) | |
stat = pXRRSetScreenConfigAndRate( gdi_display, sc, root, size, rot, rate, CurrentTime ); | |
@@ -195,10 +199,10 @@ static LONG xrandr10_set_current_mode( int mode ) | |
return DISP_CHANGE_FAILED; | |
} | |
-static void xrandr10_nvidia_rate(void) | |
+static void xrandr10_nvidia_rate(short *override_rate) | |
{ | |
#ifdef HAVE_NVCTRL | |
- int major, minor, twinview; | |
+ int major, minor, twinview, mask, devices; | |
if (!XNVCTRLIsNvScreen( gdi_display, DefaultScreen(gdi_display) )) return; | |
if (!XNVCTRLQueryVersion( gdi_display, &major, &minor )) return; | |
@@ -206,6 +210,23 @@ static void xrandr10_nvidia_rate(void) | |
NV_CTRL_DYNAMIC_TWINVIEW, &twinview )) return; | |
if (!twinview) return; | |
+ if (!XNVCTRLQueryAttribute( gdi_display, DefaultScreen(gdi_display), 0, | |
+ NV_CTRL_CONNECTED_DISPLAYS, &devices)) goto failed; | |
+ for (mask = 1; mask < (1 << 24); mask <<= 1) | |
+ { | |
+ int refresh_rate; | |
+ | |
+ if (!(devices & mask)) continue; | |
+ | |
+ if (!XNVCTRLQueryAttribute( gdi_display, DefaultScreen(gdi_display), mask, | |
+ NV_CTRL_REFRESH_RATE, &refresh_rate)) goto failed; | |
+ *override_rate = (short) round(refresh_rate / 100.0f); | |
+ /* The first device gives us the true refresh rate of the primary display, use this to | |
+ * override the false refresh rate the driver reports to XRandR. */ | |
+ return; | |
+ } | |
+ | |
+failed: | |
ERR_(winediag)("NVIDIA Dynamic TwinView detected, XRandR will report inaccurate refresh rates. " | |
"Please consider disabling the \"DynamicTwinView\" option in your X config.\n"); | |
#endif | |
@@ -213,6 +234,7 @@ static void xrandr10_nvidia_rate(void) | |
static void xrandr10_init_modes(void) | |
{ | |
+ short override_rate = 0; | |
XRRScreenSize *sizes; | |
int sizes_count; | |
int i, j, nmodes = 0; | |
@@ -221,7 +243,7 @@ static void xrandr10_init_modes(void) | |
if (sizes_count <= 0) return; | |
/* Output a warning about nVidia Dynamic TwinView (if applicable) */ | |
- xrandr10_nvidia_rate(); | |
+ xrandr10_nvidia_rate(&override_rate); | |
TRACE("XRandR: found %d sizes.\n", sizes_count); | |
for (i = 0; i < sizes_count; ++i) | |
@@ -230,15 +252,15 @@ static void xrandr10_init_modes(void) | |
short *rates; | |
rates = pXRRRates( gdi_display, DefaultScreen(gdi_display), i, &rates_count ); | |
+ rates_count = (rates_count && override_rate ? 1 : rates_count); | |
TRACE("- at %d: %dx%d (%d rates):", i, sizes[i].width, sizes[i].height, rates_count); | |
if (rates_count) | |
{ | |
nmodes += rates_count; | |
for (j = 0; j < rates_count; ++j) | |
{ | |
- if (j > 0) | |
- TRACE(","); | |
- TRACE(" %d", rates[j]); | |
+ short rate = (override_rate ? override_rate : rates[j]); | |
+ TRACE("%s %d", (j > 0 ? "," : ""), rate); | |
} | |
} | |
else | |
@@ -269,19 +291,22 @@ static void xrandr10_init_modes(void) | |
short *rates; | |
rates = pXRRRates( gdi_display, DefaultScreen(gdi_display), i, &rates_count ); | |
- | |
+ rates_count = (rates_count && override_rate ? 1 : rates_count); | |
if (rates_count) | |
{ | |
for (j = 0; j < rates_count; ++j) | |
{ | |
- X11DRV_Settings_AddOneMode( sizes[i].width, sizes[i].height, 0, rates[j] ); | |
- xrandr10_modes[xrandr_mode_count++] = i; | |
+ short rate = (override_rate ? override_rate : rates[j]); | |
+ X11DRV_Settings_AddOneMode( sizes[i].width, sizes[i].height, 0, rate ); | |
+ xrandr10_modes[xrandr_mode_count].id = i; | |
+ xrandr10_modes[xrandr_mode_count++].rate = rates[j]; | |
} | |
} | |
else | |
{ | |
X11DRV_Settings_AddOneMode( sizes[i].width, sizes[i].height, 0, 0 ); | |
- xrandr10_modes[xrandr_mode_count++] = i; | |
+ xrandr10_modes[xrandr_mode_count].id = i; | |
+ xrandr10_modes[xrandr_mode_count++].rate = 0; | |
} | |
} | |
-- | |
1.9.1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment