
Based on a patch by Gabriel Corona. According to the RandR spec for RRSetCrtcConfig: "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." This patch involves resizing the screen also when shrinking a CRTC, not just when expanding it past the current screen size. This is partially because we have no way to reliably determine the current display width (DisplayWidth() is never updated past opening the connection, and RandR exposes no way to retrieve the screen dimensions), and partially because it's probably what the user wants anyway (e.g. it's what the `xrandr` configuration app does when the screen size is not expliticly specified). This patch fixes TestBot failures on the Debian machines for ddraw, d3d8, and d3d9 device tests. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=33290 Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
603 lines
18 KiB
C
603 lines
18 KiB
C
/*
|
|
* Wine X11drv Xrandr interface
|
|
*
|
|
* Copyright 2003 Alexander James Pasadyn
|
|
* Copyright 2012 Henri Verbeet for CodeWeavers
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "wine/port.h"
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(xrandr);
|
|
#ifdef HAVE_XRRGETSCREENRESOURCES
|
|
WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
|
#endif
|
|
|
|
#ifdef SONAME_LIBXRANDR
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/extensions/Xrandr.h>
|
|
#include "x11drv.h"
|
|
|
|
#include "wine/library.h"
|
|
|
|
static void *xrandr_handle;
|
|
|
|
#define MAKE_FUNCPTR(f) static typeof(f) * p##f;
|
|
MAKE_FUNCPTR(XRRConfigCurrentConfiguration)
|
|
MAKE_FUNCPTR(XRRConfigCurrentRate)
|
|
MAKE_FUNCPTR(XRRFreeScreenConfigInfo)
|
|
MAKE_FUNCPTR(XRRGetScreenInfo)
|
|
MAKE_FUNCPTR(XRRQueryExtension)
|
|
MAKE_FUNCPTR(XRRQueryVersion)
|
|
MAKE_FUNCPTR(XRRRates)
|
|
MAKE_FUNCPTR(XRRSetScreenConfig)
|
|
MAKE_FUNCPTR(XRRSetScreenConfigAndRate)
|
|
MAKE_FUNCPTR(XRRSizes)
|
|
|
|
#ifdef HAVE_XRRGETSCREENRESOURCES
|
|
MAKE_FUNCPTR(XRRFreeCrtcInfo)
|
|
MAKE_FUNCPTR(XRRFreeOutputInfo)
|
|
MAKE_FUNCPTR(XRRFreeScreenResources)
|
|
MAKE_FUNCPTR(XRRGetCrtcInfo)
|
|
MAKE_FUNCPTR(XRRGetOutputInfo)
|
|
MAKE_FUNCPTR(XRRGetScreenResources)
|
|
MAKE_FUNCPTR(XRRSetCrtcConfig)
|
|
MAKE_FUNCPTR(XRRSetScreenSize)
|
|
static typeof(XRRGetScreenResources) *pXRRGetScreenResourcesCurrent;
|
|
static RRMode *xrandr12_modes;
|
|
static int primary_crtc;
|
|
#endif
|
|
|
|
#undef MAKE_FUNCPTR
|
|
|
|
static struct x11drv_mode_info *dd_modes;
|
|
static SizeID *xrandr10_modes;
|
|
static unsigned int xrandr_mode_count;
|
|
static int xrandr_current_mode = -1;
|
|
|
|
static int load_xrandr(void)
|
|
{
|
|
int r = 0;
|
|
|
|
if (wine_dlopen(SONAME_LIBXRENDER, RTLD_NOW|RTLD_GLOBAL, NULL, 0) &&
|
|
(xrandr_handle = wine_dlopen(SONAME_LIBXRANDR, RTLD_NOW, NULL, 0)))
|
|
{
|
|
|
|
#define LOAD_FUNCPTR(f) \
|
|
if((p##f = wine_dlsym(xrandr_handle, #f, NULL, 0)) == NULL) \
|
|
goto sym_not_found;
|
|
|
|
LOAD_FUNCPTR(XRRConfigCurrentConfiguration)
|
|
LOAD_FUNCPTR(XRRConfigCurrentRate)
|
|
LOAD_FUNCPTR(XRRFreeScreenConfigInfo)
|
|
LOAD_FUNCPTR(XRRGetScreenInfo)
|
|
LOAD_FUNCPTR(XRRQueryExtension)
|
|
LOAD_FUNCPTR(XRRQueryVersion)
|
|
LOAD_FUNCPTR(XRRRates)
|
|
LOAD_FUNCPTR(XRRSetScreenConfig)
|
|
LOAD_FUNCPTR(XRRSetScreenConfigAndRate)
|
|
LOAD_FUNCPTR(XRRSizes)
|
|
r = 1;
|
|
|
|
#ifdef HAVE_XRRGETSCREENRESOURCES
|
|
LOAD_FUNCPTR(XRRFreeCrtcInfo)
|
|
LOAD_FUNCPTR(XRRFreeOutputInfo)
|
|
LOAD_FUNCPTR(XRRFreeScreenResources)
|
|
LOAD_FUNCPTR(XRRGetCrtcInfo)
|
|
LOAD_FUNCPTR(XRRGetOutputInfo)
|
|
LOAD_FUNCPTR(XRRGetScreenResources)
|
|
LOAD_FUNCPTR(XRRSetCrtcConfig)
|
|
LOAD_FUNCPTR(XRRSetScreenSize)
|
|
r = 2;
|
|
#endif
|
|
#undef LOAD_FUNCPTR
|
|
|
|
sym_not_found:
|
|
if (!r) TRACE("Unable to load function ptrs from XRandR library\n");
|
|
}
|
|
return r;
|
|
}
|
|
|
|
static int XRandRErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static int xrandr10_get_current_mode(void)
|
|
{
|
|
SizeID size;
|
|
Rotation rot;
|
|
XRRScreenConfiguration *sc;
|
|
short rate;
|
|
unsigned int i;
|
|
int res = -1;
|
|
|
|
if (xrandr_current_mode != -1)
|
|
return xrandr_current_mode;
|
|
|
|
sc = pXRRGetScreenInfo (gdi_display, DefaultRootWindow( gdi_display ));
|
|
size = pXRRConfigCurrentConfiguration (sc, &rot);
|
|
rate = pXRRConfigCurrentRate (sc);
|
|
pXRRFreeScreenConfigInfo(sc);
|
|
|
|
for (i = 0; i < xrandr_mode_count; ++i)
|
|
{
|
|
if (xrandr10_modes[i] == size && dd_modes[i].refresh_rate == rate)
|
|
{
|
|
res = i;
|
|
break;
|
|
}
|
|
}
|
|
if (res == -1)
|
|
{
|
|
ERR("In unknown mode, returning default\n");
|
|
return 0;
|
|
}
|
|
|
|
xrandr_current_mode = res;
|
|
return res;
|
|
}
|
|
|
|
static LONG xrandr10_set_current_mode( int mode )
|
|
{
|
|
SizeID size;
|
|
Rotation rot;
|
|
Window root;
|
|
XRRScreenConfiguration *sc;
|
|
Status stat;
|
|
short rate;
|
|
|
|
root = DefaultRootWindow( gdi_display );
|
|
sc = pXRRGetScreenInfo (gdi_display, root);
|
|
pXRRConfigCurrentConfiguration (sc, &rot);
|
|
mode = mode % xrandr_mode_count;
|
|
|
|
TRACE("Changing Resolution to %dx%d @%d Hz\n",
|
|
dd_modes[mode].width,
|
|
dd_modes[mode].height,
|
|
dd_modes[mode].refresh_rate);
|
|
|
|
size = xrandr10_modes[mode];
|
|
rate = dd_modes[mode].refresh_rate;
|
|
|
|
if (rate)
|
|
stat = pXRRSetScreenConfigAndRate( gdi_display, sc, root, size, rot, rate, CurrentTime );
|
|
else
|
|
stat = pXRRSetScreenConfig( gdi_display, sc, root, size, rot, CurrentTime );
|
|
|
|
pXRRFreeScreenConfigInfo(sc);
|
|
|
|
if (stat == RRSetConfigSuccess)
|
|
{
|
|
xrandr_current_mode = mode;
|
|
X11DRV_resize_desktop( dd_modes[mode].width, dd_modes[mode].height );
|
|
return DISP_CHANGE_SUCCESSFUL;
|
|
}
|
|
|
|
ERR("Resolution change not successful -- perhaps display has changed?\n");
|
|
return DISP_CHANGE_FAILED;
|
|
}
|
|
|
|
static void xrandr10_init_modes(void)
|
|
{
|
|
XRRScreenSize *sizes;
|
|
int sizes_count;
|
|
int i, j, nmodes = 0;
|
|
|
|
sizes = pXRRSizes( gdi_display, DefaultScreen(gdi_display), &sizes_count );
|
|
if (sizes_count <= 0) return;
|
|
|
|
TRACE("XRandR: found %d sizes.\n", sizes_count);
|
|
for (i = 0; i < sizes_count; ++i)
|
|
{
|
|
int rates_count;
|
|
short *rates;
|
|
|
|
rates = pXRRRates( gdi_display, DefaultScreen(gdi_display), i, &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]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++nmodes;
|
|
TRACE(" <default>");
|
|
}
|
|
TRACE(" Hz\n");
|
|
}
|
|
|
|
TRACE("XRandR modes: count=%d\n", nmodes);
|
|
|
|
if (!(xrandr10_modes = HeapAlloc( GetProcessHeap(), 0, sizeof(*xrandr10_modes) * nmodes )))
|
|
{
|
|
ERR("Failed to allocate xrandr mode info array.\n");
|
|
return;
|
|
}
|
|
|
|
dd_modes = X11DRV_Settings_SetHandlers( "XRandR 1.0",
|
|
xrandr10_get_current_mode,
|
|
xrandr10_set_current_mode,
|
|
nmodes, 1 );
|
|
|
|
xrandr_mode_count = 0;
|
|
for (i = 0; i < sizes_count; ++i)
|
|
{
|
|
int rates_count;
|
|
short *rates;
|
|
|
|
rates = pXRRRates( gdi_display, DefaultScreen(gdi_display), i, &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;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
X11DRV_Settings_AddOneMode( sizes[i].width, sizes[i].height, 0, 0 );
|
|
xrandr10_modes[xrandr_mode_count++] = i;
|
|
}
|
|
}
|
|
|
|
X11DRV_Settings_AddDepthModes();
|
|
nmodes = X11DRV_Settings_GetModeCount();
|
|
|
|
TRACE("Available DD modes: count=%d\n", nmodes);
|
|
TRACE("Enabling XRandR\n");
|
|
}
|
|
|
|
#ifdef HAVE_XRRGETSCREENRESOURCES
|
|
|
|
static int xrandr12_get_current_mode(void)
|
|
{
|
|
XRRScreenResources *resources;
|
|
XRRCrtcInfo *crtc_info;
|
|
int i, ret = -1;
|
|
|
|
if (xrandr_current_mode != -1)
|
|
return xrandr_current_mode;
|
|
|
|
if (!(resources = pXRRGetScreenResourcesCurrent( gdi_display, root_window )))
|
|
{
|
|
ERR("Failed to get screen resources.\n");
|
|
return 0;
|
|
}
|
|
|
|
if (resources->ncrtc <= primary_crtc ||
|
|
!(crtc_info = pXRRGetCrtcInfo( gdi_display, resources, resources->crtcs[primary_crtc] )))
|
|
{
|
|
pXRRFreeScreenResources( resources );
|
|
ERR("Failed to get CRTC info.\n");
|
|
return 0;
|
|
}
|
|
|
|
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);
|
|
|
|
for (i = 0; i < xrandr_mode_count; ++i)
|
|
{
|
|
if (xrandr12_modes[i] == crtc_info->mode)
|
|
{
|
|
ret = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pXRRFreeCrtcInfo( crtc_info );
|
|
pXRRFreeScreenResources( resources );
|
|
|
|
if (ret == -1)
|
|
{
|
|
ERR("Unknown mode, returning default.\n");
|
|
return 0;
|
|
}
|
|
|
|
xrandr_current_mode = ret;
|
|
return ret;
|
|
}
|
|
|
|
static void get_screen_size( XRRScreenResources *resources, unsigned int *width, unsigned int *height )
|
|
{
|
|
XRRCrtcInfo *crtc_info;
|
|
int i;
|
|
*width = *height = 0;
|
|
|
|
for (i = 0; i < resources->ncrtc; ++i)
|
|
{
|
|
if (!(crtc_info = pXRRGetCrtcInfo( gdi_display, resources, resources->crtcs[i] )))
|
|
continue;
|
|
|
|
if (crtc_info->mode != None)
|
|
{
|
|
*width = max(*width, crtc_info->x + crtc_info->width);
|
|
*height = max(*height, crtc_info->y + crtc_info->height);
|
|
}
|
|
|
|
pXRRFreeCrtcInfo( crtc_info );
|
|
}
|
|
}
|
|
|
|
static LONG xrandr12_set_current_mode( int mode )
|
|
{
|
|
unsigned int screen_width, screen_height;
|
|
Status status = RRSetConfigFailed;
|
|
XRRScreenResources *resources;
|
|
XRRCrtcInfo *crtc_info;
|
|
|
|
mode = mode % xrandr_mode_count;
|
|
|
|
if (!(resources = pXRRGetScreenResourcesCurrent( gdi_display, root_window )))
|
|
{
|
|
ERR("Failed to get screen resources.\n");
|
|
return DISP_CHANGE_FAILED;
|
|
}
|
|
|
|
if (resources->ncrtc <= primary_crtc ||
|
|
!(crtc_info = pXRRGetCrtcInfo( gdi_display, resources, resources->crtcs[primary_crtc] )))
|
|
{
|
|
pXRRFreeScreenResources( resources );
|
|
ERR("Failed to get CRTC info.\n");
|
|
return DISP_CHANGE_FAILED;
|
|
}
|
|
|
|
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);
|
|
|
|
/* According to the RandR spec, the entire CRTC must fit inside the screen.
|
|
* Since we use the union of all enabled CRTCs to determine the necessary
|
|
* screen size, this might involve shrinking the screen, so we must disable
|
|
* the CRTC in question first. */
|
|
|
|
XGrabServer( gdi_display );
|
|
|
|
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)
|
|
{
|
|
XUngrabServer( gdi_display );
|
|
ERR("Failed to disable CRTC.\n");
|
|
pXRRFreeCrtcInfo( crtc_info );
|
|
pXRRFreeScreenResources( resources );
|
|
return DISP_CHANGE_FAILED;
|
|
}
|
|
|
|
get_screen_size( resources, &screen_width, &screen_height );
|
|
screen_width = max( screen_width, crtc_info->x + dd_modes[mode].width );
|
|
screen_height = max( screen_height, crtc_info->y + dd_modes[mode].height );
|
|
|
|
pXRRSetScreenSize( gdi_display, root_window, screen_width, screen_height,
|
|
screen_width * DisplayWidthMM( gdi_display, default_visual.screen )
|
|
/ DisplayWidth( gdi_display, default_visual.screen ),
|
|
screen_height * DisplayHeightMM( gdi_display, default_visual.screen )
|
|
/ DisplayHeight( gdi_display, default_visual.screen ));
|
|
|
|
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 );
|
|
|
|
XUngrabServer( gdi_display );
|
|
|
|
pXRRFreeCrtcInfo( crtc_info );
|
|
pXRRFreeScreenResources( resources );
|
|
|
|
if (status != RRSetConfigSuccess)
|
|
{
|
|
ERR("Resolution change not successful -- perhaps display has changed?\n");
|
|
return DISP_CHANGE_FAILED;
|
|
}
|
|
|
|
xrandr_current_mode = mode;
|
|
X11DRV_resize_desktop( dd_modes[mode].width, dd_modes[mode].height );
|
|
return DISP_CHANGE_SUCCESSFUL;
|
|
}
|
|
|
|
static XRRCrtcInfo *xrandr12_get_primary_crtc_info( XRRScreenResources *resources, int *crtc_idx )
|
|
{
|
|
XRRCrtcInfo *crtc_info;
|
|
int i;
|
|
|
|
for (i = 0; i < resources->ncrtc; ++i)
|
|
{
|
|
crtc_info = pXRRGetCrtcInfo( gdi_display, resources, resources->crtcs[i] );
|
|
if (!crtc_info || crtc_info->mode == None)
|
|
{
|
|
pXRRFreeCrtcInfo( crtc_info );
|
|
continue;
|
|
}
|
|
|
|
*crtc_idx = i;
|
|
return crtc_info;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int xrandr12_init_modes(void)
|
|
{
|
|
unsigned int only_one_resolution = 1, mode_count;
|
|
XRRScreenResources *resources;
|
|
XRROutputInfo *output_info;
|
|
XRRCrtcInfo *crtc_info;
|
|
int ret = -1;
|
|
int i, j;
|
|
|
|
if (!(resources = pXRRGetScreenResourcesCurrent( gdi_display, root_window )))
|
|
{
|
|
ERR("Failed to get screen resources.\n");
|
|
return ret;
|
|
}
|
|
|
|
if (!resources->ncrtc)
|
|
{
|
|
pXRRFreeScreenResources( resources );
|
|
if (!(resources = pXRRGetScreenResources( gdi_display, root_window )))
|
|
{
|
|
ERR("Failed to get screen resources.\n");
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
if (!(crtc_info = xrandr12_get_primary_crtc_info( resources, &primary_crtc )))
|
|
{
|
|
pXRRFreeScreenResources( resources );
|
|
ERR("Failed to get primary CRTC info.\n");
|
|
return ret;
|
|
}
|
|
|
|
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);
|
|
|
|
if (!crtc_info->noutput || !(output_info = pXRRGetOutputInfo( gdi_display, resources, crtc_info->outputs[0] )))
|
|
{
|
|
pXRRFreeCrtcInfo( crtc_info );
|
|
pXRRFreeScreenResources( resources );
|
|
ERR("Failed to get output info.\n");
|
|
return ret;
|
|
}
|
|
|
|
TRACE("OUTPUT 0: name %s.\n", debugstr_a(output_info->name));
|
|
|
|
if (!output_info->nmode)
|
|
{
|
|
WARN("Output has no modes.\n");
|
|
goto done;
|
|
}
|
|
|
|
if (!(xrandr12_modes = HeapAlloc( GetProcessHeap(), 0, sizeof(*xrandr12_modes) * output_info->nmode )))
|
|
{
|
|
ERR("Failed to allocate xrandr mode info array.\n");
|
|
goto done;
|
|
}
|
|
|
|
dd_modes = X11DRV_Settings_SetHandlers( "XRandR 1.2",
|
|
xrandr12_get_current_mode,
|
|
xrandr12_set_current_mode,
|
|
output_info->nmode, 1 );
|
|
|
|
xrandr_mode_count = 0;
|
|
for (i = 0; i < output_info->nmode; ++i)
|
|
{
|
|
for (j = 0; j < resources->nmode; ++j)
|
|
{
|
|
XRRModeInfo *mode = &resources->modes[j];
|
|
|
|
if (mode->id == output_info->modes[i])
|
|
{
|
|
unsigned int dots = mode->hTotal * mode->vTotal;
|
|
unsigned int refresh = dots ? (mode->dotClock + dots / 2) / dots : 0;
|
|
|
|
TRACE("Adding mode %#lx: %ux%u@%u.\n", mode->id, mode->width, mode->height, refresh);
|
|
X11DRV_Settings_AddOneMode( mode->width, mode->height, 0, refresh );
|
|
xrandr12_modes[xrandr_mode_count++] = mode->id;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
mode_count = X11DRV_Settings_GetModeCount();
|
|
for (i = 1; i < mode_count; ++i)
|
|
{
|
|
if (dd_modes[i].width != dd_modes[0].width || dd_modes[i].height != dd_modes[0].height)
|
|
{
|
|
only_one_resolution = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Recent (304.64, possibly earlier) versions of the nvidia driver only
|
|
* report a DFP's native mode through RandR 1.2 / 1.3. Standard DMT modes
|
|
* are only listed through RandR 1.0 / 1.1. This is completely useless,
|
|
* but NVIDIA considers this a feature, so it's unlikely to change. The
|
|
* best we can do is to fall back to RandR 1.0 and encourage users to
|
|
* consider more cooperative driver vendors when we detect such a
|
|
* configuration. */
|
|
if (only_one_resolution && XQueryExtension( gdi_display, "NV-CONTROL", &i, &j, &ret ))
|
|
{
|
|
ERR_(winediag)("Broken NVIDIA RandR detected, falling back to RandR 1.0. "
|
|
"Please consider using the Nouveau driver instead.\n");
|
|
ret = -1;
|
|
HeapFree( GetProcessHeap(), 0, xrandr12_modes );
|
|
goto done;
|
|
}
|
|
|
|
X11DRV_Settings_AddDepthModes();
|
|
ret = 0;
|
|
|
|
done:
|
|
pXRRFreeOutputInfo( output_info );
|
|
pXRRFreeCrtcInfo( crtc_info );
|
|
pXRRFreeScreenResources( resources );
|
|
return ret;
|
|
}
|
|
|
|
#endif /* HAVE_XRRGETSCREENRESOURCES */
|
|
|
|
void X11DRV_XRandR_Init(void)
|
|
{
|
|
int event_base, error_base, minor, ret;
|
|
static int major;
|
|
Bool ok;
|
|
|
|
if (major) return; /* already initialized? */
|
|
if (!usexrandr) return; /* disabled in config */
|
|
if (root_window != DefaultRootWindow( gdi_display )) return;
|
|
if (!(ret = load_xrandr())) return; /* can't load the Xrandr library */
|
|
|
|
/* see if Xrandr is available */
|
|
if (!pXRRQueryExtension( gdi_display, &event_base, &error_base )) return;
|
|
X11DRV_expect_error( gdi_display, XRandRErrorHandler, NULL );
|
|
ok = pXRRQueryVersion( gdi_display, &major, &minor );
|
|
if (X11DRV_check_error() || !ok) return;
|
|
|
|
TRACE("Found XRandR %d.%d.\n", major, minor);
|
|
|
|
#ifdef HAVE_XRRGETSCREENRESOURCES
|
|
if (ret >= 2 && (major > 1 || (major == 1 && minor >= 2)))
|
|
{
|
|
if (major > 1 || (major == 1 && minor >= 3))
|
|
pXRRGetScreenResourcesCurrent = wine_dlsym( xrandr_handle, "XRRGetScreenResourcesCurrent", NULL, 0 );
|
|
if (!pXRRGetScreenResourcesCurrent)
|
|
pXRRGetScreenResourcesCurrent = pXRRGetScreenResources;
|
|
}
|
|
|
|
if (!pXRRGetScreenResourcesCurrent || xrandr12_init_modes() < 0)
|
|
#endif
|
|
xrandr10_init_modes();
|
|
}
|
|
|
|
#else /* SONAME_LIBXRANDR */
|
|
|
|
void X11DRV_XRandR_Init(void)
|
|
{
|
|
TRACE("XRandR support not compiled in.\n");
|
|
}
|
|
|
|
#endif /* SONAME_LIBXRANDR */
|