[PATCH] winex11.drv: Use XRRSetScreenSize with XRRSetCrtcConfig
Gabriel Corona
gabriel.corona at enst-bretagne.fr
Fri Jul 15 17:48:43 CDT 2016
Fixes https://bugs.winehq.org/show_bug.cgi?id=33290
The nvidia driver is not so happy about using XRRSetCrtcConfig alone
and generates a panning configuration. We set the screen size
accordingly. Moreover we disable the CRT during the transition.
Tested on Debian.
Signed-off-by: Gabriel Corona <gabriel.corona at enst-bretagne.fr>
---
dlls/winex11.drv/xrandr.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c
index 2fee851..d467832 100644
--- a/dlls/winex11.drv/xrandr.c
+++ b/dlls/winex11.drv/xrandr.c
@@ -48,6 +48,7 @@ MAKE_FUNCPTR(XRRQueryVersion)
MAKE_FUNCPTR(XRRRates)
MAKE_FUNCPTR(XRRSetScreenConfig)
MAKE_FUNCPTR(XRRSetScreenConfigAndRate)
+MAKE_FUNCPTR(XRRSetScreenSize)
MAKE_FUNCPTR(XRRSizes)
#ifdef HAVE_XRRGETSCREENRESOURCES
@@ -91,6 +92,7 @@ static int load_xrandr(void)
LOAD_FUNCPTR(XRRRates)
LOAD_FUNCPTR(XRRSetScreenConfig)
LOAD_FUNCPTR(XRRSetScreenConfigAndRate)
+ LOAD_FUNCPTR(XRRSetScreenSize)
LOAD_FUNCPTR(XRRSizes)
r = 1;
@@ -323,10 +325,14 @@ static int xrandr12_get_current_mode(void)
static LONG xrandr12_set_current_mode( int mode )
{
Status status = RRSetConfigFailed;
+ int screen;
XRRScreenResources *resources;
XRRCrtcInfo *crtc_info;
+ XRRModeInfo* mode_info;
+ int i;
mode = mode % xrandr_mode_count;
+ screen = DefaultScreen( gdi_display );
if (!(resources = pXRRGetScreenResourcesCurrent( gdi_display, root_window )))
{
@@ -345,9 +351,76 @@ static LONG xrandr12_set_current_mode( int mode )
TRACE("CRTC %d: mode %#lx, %ux%u+%d+%d.\n", primary_crtc, crtc_info->mode,
crtc_info->width, crtc_info->height, crtc_info->x, crtc_info->y);
+ // Find the mode_indo:
+ mode_info = NULL;
+ for (i = 0; i < resources->nmode; ++i)
+ {
+ if (xrandr12_modes[mode] == resources->modes[i].id) {
+ mode_info = &resources->modes[i];
+ break;
+ }
+ }
+ if (mode_info == NULL)
+ {
+ pXRRFreeScreenResources( resources );
+ ERR("Invalid mode.\n");
+ return DISP_CHANGE_FAILED;
+ }
+
+ // As per randrproto.txt:
+ // > The entire area of the CRTC must fit within the screen size,
+ // > else a Match error results. As an example, rotating the
+ // > screen so that a single CRTC fills the entire screen before
+ // > and after may necessitate disabling the CRTC, resizing the
+ // > screen, then re-enabling the CRTC at the new configuration to
+ // > avoid an invalid intermediate configuration.
+
+ // Don't let other clients see that we disable the CRT:
+ XGrabServer( gdi_display );
+
+ // Disable the CRT:
+ status = pXRRSetCrtcConfig( gdi_display, resources, resources->crtcs[primary_crtc],
+ CurrentTime, crtc_info->x, crtc_info->y, None,
+ crtc_info->rotation, NULL, 0 );
+ if (status != RRSetConfigSuccess)
+ {
+ WARN("Could not disable the CRT before changing resolution\n");
+ }
+
+ // Configure the screen size accordingly:
+ pXRRSetScreenSize( gdi_display, root_window, mode_info->width, mode_info->height,
+ DisplayWidthMM( gdi_display, screen ),
+ DisplayHeightMM( gdi_display, screen ));
+
+ // Set the CRT mode:
status = pXRRSetCrtcConfig( gdi_display, resources, resources->crtcs[primary_crtc],
CurrentTime, crtc_info->x, crtc_info->y, xrandr12_modes[mode],
crtc_info->rotation, crtc_info->outputs, crtc_info->noutput );
+ if (status != RRSetConfigSuccess )
+ {
+ // Try to revert to the previous mode
+ mode_info = NULL;
+ for (i = 0; i < resources->nmode; ++i)
+ {
+ if (xrandr12_modes[xrandr_current_mode] == resources->modes[i].id)
+ {
+ mode_info = &resources->modes[i];
+ break;
+ }
+ }
+ if (mode_info != NULL)
+ {
+ pXRRSetScreenSize( gdi_display, root_window, mode_info->width, mode_info->height,
+ DisplayWidthMM( gdi_display, screen ),
+ DisplayHeightMM( gdi_display, screen ));
+ pXRRSetCrtcConfig( gdi_display, resources, resources->crtcs[primary_crtc],
+ CurrentTime, crtc_info->x, crtc_info->y,
+ xrandr12_modes[xrandr_current_mode],
+ crtc_info->rotation, crtc_info->outputs, crtc_info->noutput );
+ }
+ }
+
+ XUngrabServer( gdi_display );
pXRRFreeCrtcInfo( crtc_info );
pXRRFreeScreenResources( resources );
--
2.8.1
More information about the wine-patches
mailing list