Skip to content

Instantly share code, notes, and snippets.

@compholio
Last active August 29, 2015 14:16
Show Gist options
  • Save compholio/749bbec6ff1b4d096bc1 to your computer and use it in GitHub Desktop.
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.
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