winex11.drv: Migrate XRandR 1.0 display settings handler to a new interface.

Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zhiyi Zhang 2020-07-27 16:01:15 +08:00 committed by Alexandre Julliard
parent d13b61b738
commit 5491e939bc
1 changed files with 168 additions and 136 deletions

View File

@ -83,11 +83,6 @@ MAKE_FUNCPTR(XRRFreeProviderInfo)
#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;
@ -144,157 +139,187 @@ static int XRandRErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
return 1;
}
static int xrandr10_get_current_mode(void)
/* XRandR 1.0 display settings handler */
static BOOL xrandr10_get_id( const WCHAR *device_name, ULONG_PTR *id )
{
SizeID size;
Rotation rot;
XRRScreenConfiguration *sc;
short rate;
unsigned int i;
int res = -1;
WCHAR primary_adapter[CCHDEVICENAME];
if (xrandr_current_mode != -1)
return xrandr_current_mode;
if (!get_primary_adapter( primary_adapter ))
return FALSE;
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;
/* RandR 1.0 only supports changing the primary adapter settings.
* For non-primary adapters, an id is still provided but getting
* and changing non-primary adapters' settings will be ignored. */
*id = !lstrcmpiW( device_name, primary_adapter ) ? 1 : 0;
return TRUE;
}
static LONG xrandr10_set_current_mode( int mode )
static void add_xrandr10_mode( DEVMODEW *mode, DWORD depth, DWORD width, DWORD height,
DWORD frequency, SizeID size_id )
{
SizeID size;
Rotation rot;
Window root;
XRRScreenConfiguration *sc;
Status stat;
mode->dmSize = sizeof(*mode);
mode->dmDriverExtra = sizeof(SizeID);
mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH |
DM_PELSHEIGHT | DM_DISPLAYFLAGS;
if (frequency)
{
mode->dmFields |= DM_DISPLAYFREQUENCY;
mode->dmDisplayFrequency = frequency;
}
mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
mode->dmBitsPerPel = depth;
mode->dmPelsWidth = width;
mode->dmPelsHeight = height;
mode->u2.dmDisplayFlags = 0;
memcpy( (BYTE *)mode + sizeof(*mode), &size_id, sizeof(size_id) );
}
static BOOL xrandr10_get_modes( ULONG_PTR id, DWORD flags, DEVMODEW **new_modes, UINT *new_mode_count )
{
INT size_idx, depth_idx, rate_idx, mode_idx = 0;
INT size_count, rate_count, mode_count = 0;
DEVMODEW *modes, *mode;
XRRScreenSize *sizes;
short *rates;
sizes = pXRRSizes( gdi_display, DefaultScreen( gdi_display ), &size_count );
if (size_count <= 0)
return FALSE;
for (size_idx = 0; size_idx < size_count; ++size_idx)
{
rates = pXRRRates( gdi_display, DefaultScreen( gdi_display ), size_idx, &rate_count );
if (rate_count)
mode_count += rate_count;
else
++mode_count;
}
/* Allocate space for reported modes in three depths, and put an SizeID at the end of DEVMODEW as
* driver private data */
modes = heap_calloc( mode_count * DEPTH_COUNT, sizeof(*modes) + sizeof(SizeID) );
if (!modes)
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
for (size_idx = 0; size_idx < size_count; ++size_idx)
{
for (depth_idx = 0; depth_idx < DEPTH_COUNT; ++depth_idx)
{
rates = pXRRRates( gdi_display, DefaultScreen( gdi_display ), size_idx, &rate_count );
if (!rate_count)
{
mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*mode) + sizeof(SizeID)) * mode_idx++);
add_xrandr10_mode( mode, depths[depth_idx], sizes[size_idx].width,
sizes[size_idx].height, 0, size_idx );
continue;
}
for (rate_idx = 0; rate_idx < rate_count; ++rate_idx)
{
mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*mode) + sizeof(SizeID)) * mode_idx++);
add_xrandr10_mode( mode, depths[depth_idx], sizes[size_idx].width,
sizes[size_idx].height, rates[rate_idx], size_idx );
}
}
}
*new_modes = modes;
*new_mode_count = mode_idx;
return TRUE;
}
static void xrandr10_free_modes( DEVMODEW *modes )
{
heap_free( modes );
}
static BOOL xrandr10_get_current_mode( ULONG_PTR id, DEVMODEW *mode )
{
XRRScreenConfiguration *screen_config;
XRRScreenSize *sizes;
Rotation rotation;
SizeID size_id;
INT size_count;
short rate;
root = DefaultRootWindow( gdi_display );
sc = pXRRGetScreenInfo (gdi_display, root);
pXRRConfigCurrentConfiguration (sc, &rot);
mode = mode % xrandr_mode_count;
mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
mode->u2.dmDisplayFlags = 0;
mode->u1.s2.dmPosition.x = 0;
mode->u1.s2.dmPosition.y = 0;
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)
if (id != 1)
{
xrandr_current_mode = mode;
X11DRV_DisplayDevices_Update( TRUE );
FIXME("Non-primary adapters are unsupported.\n");
mode->dmBitsPerPel = 0;
mode->dmPelsWidth = 0;
mode->dmPelsHeight = 0;
mode->dmDisplayFrequency = 0;
return TRUE;
}
sizes = pXRRSizes( gdi_display, DefaultScreen( gdi_display ), &size_count );
if (size_count <= 0)
return FALSE;
screen_config = pXRRGetScreenInfo( gdi_display, DefaultRootWindow( gdi_display ) );
size_id = pXRRConfigCurrentConfiguration( screen_config, &rotation );
rate = pXRRConfigCurrentRate( screen_config );
pXRRFreeScreenConfigInfo( screen_config );
mode->dmBitsPerPel = screen_bpp;
mode->dmPelsWidth = sizes[size_id].width;
mode->dmPelsHeight = sizes[size_id].height;
mode->dmDisplayFrequency = rate;
return TRUE;
}
static LONG xrandr10_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
{
XRRScreenConfiguration *screen_config;
Rotation rotation;
SizeID size_id;
Window root;
Status stat;
if (id != 1)
{
FIXME("Non-primary adapters are unsupported.\n");
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)
if (is_detached_mode(mode))
{
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");
FIXME("Detaching adapters is unsupported.\n");
return DISP_CHANGE_SUCCESSFUL;
}
TRACE("XRandR modes: count=%d\n", nmodes);
if (mode->dmFields & DM_BITSPERPEL && mode->dmBitsPerPel != screen_bpp)
WARN("Cannot change screen bit depth from %dbits to %dbits!\n", screen_bpp, mode->dmBitsPerPel);
if (!(xrandr10_modes = HeapAlloc( GetProcessHeap(), 0, sizeof(*xrandr10_modes) * nmodes )))
{
ERR("Failed to allocate xrandr mode info array.\n");
return;
}
root = DefaultRootWindow( gdi_display );
screen_config = pXRRGetScreenInfo( gdi_display, root );
pXRRConfigCurrentConfiguration( screen_config, &rotation );
dd_modes = X11DRV_Settings_SetHandlers( "XRandR 1.0",
xrandr10_get_current_mode,
xrandr10_set_current_mode,
nmodes, 1 );
assert( mode->dmDriverExtra == sizeof(SizeID) );
memcpy( &size_id, (BYTE *)mode + sizeof(*mode), sizeof(size_id) );
xrandr_mode_count = 0;
for (i = 0; i < sizes_count; ++i)
{
int rates_count;
short *rates;
if (mode->dmFields & DM_DISPLAYFREQUENCY && mode->dmDisplayFrequency)
stat = pXRRSetScreenConfigAndRate( gdi_display, screen_config, root, size_id, rotation,
mode->dmDisplayFrequency, CurrentTime );
else
stat = pXRRSetScreenConfig( gdi_display, screen_config, root, size_id, rotation, CurrentTime );
pXRRFreeScreenConfigInfo( screen_config );
rates = pXRRRates( gdi_display, DefaultScreen(gdi_display), i, &rates_count );
if (stat != RRSetConfigSuccess)
return DISP_CHANGE_FAILED;
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");
XFlush( gdi_display );
return DISP_CHANGE_SUCCESSFUL;
}
#ifdef HAVE_XRRGETPROVIDERRESOURCES
@ -1432,7 +1457,14 @@ void X11DRV_XRandR_Init(void)
TRACE("Found XRandR %d.%d.\n", major, minor);
xrandr10_init_modes();
settings_handler.name = "XRandR 1.0";
settings_handler.priority = 200;
settings_handler.get_id = xrandr10_get_id;
settings_handler.get_modes = xrandr10_get_modes;
settings_handler.free_modes = xrandr10_free_modes;
settings_handler.get_current_mode = xrandr10_get_current_mode;
settings_handler.set_current_mode = xrandr10_set_current_mode;
X11DRV_Settings_SetHandler( &settings_handler );
#ifdef HAVE_XRRGETPROVIDERRESOURCES
if (ret >= 4 && (major > 1 || (major == 1 && minor >= 4)))