-- v3: winex11: Lock and flush display in X11DRV_ChangeDisplaySettings. winex11: Retrieve full modes before applying new display settings. winex11: Introduce a x11drv_mode structure for full modes. winex11: Always return full modes from settings handlers. winex11: Copy XF86VidModeModeInfo to the DEVMODEW driver data.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/display.c | 14 ++++------- dlls/winex11.drv/x11drv.h | 3 --- dlls/winex11.drv/xrandr.c | 12 ---------- dlls/winex11.drv/xvidmode.c | 47 ++++++++++++++----------------------- 4 files changed, 21 insertions(+), 55 deletions(-)
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index f817c599383..5151a68f431 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -90,11 +90,6 @@ static BOOL nores_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_ return TRUE; }
-static void nores_free_modes(DEVMODEW *modes) -{ - free(modes); -} - static BOOL nores_get_current_mode(x11drv_settings_id id, DEVMODEW *mode) { RECT primary = get_host_primary_monitor_rect(); @@ -140,7 +135,6 @@ void X11DRV_Settings_Init(void) nores_handler.priority = 1; nores_handler.get_id = nores_get_id; nores_handler.get_modes = nores_get_modes; - nores_handler.free_modes = nores_free_modes; nores_handler.get_current_mode = nores_get_current_mode; nores_handler.set_current_mode = nores_set_current_mode; X11DRV_Settings_SetHandler(&nores_handler); @@ -184,18 +178,18 @@ static DEVMODEW *get_full_mode(x11drv_settings_id id, DEVMODEW *dev_mode)
if (!found_mode || mode_idx == mode_count) { - settings_handler.free_modes(modes); + free( modes ); return NULL; }
if (!(full_mode = malloc(sizeof(*found_mode) + found_mode->dmDriverExtra))) { - settings_handler.free_modes(modes); + free( modes ); return NULL; }
memcpy(full_mode, found_mode, sizeof(*found_mode) + found_mode->dmDriverExtra); - settings_handler.free_modes(modes); + free( modes );
full_mode->dmFields |= DM_POSITION; full_mode->dmPosition = dev_mode->dmPosition; @@ -456,7 +450,7 @@ UINT X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage if (settings_handler.get_modes( settings_id, EDS_ROTATEDMODE, &modes, &mode_count, FALSE )) { device_manager->add_modes( ¤t_mode, mode_count, modes, param ); - settings_handler.free_modes( modes ); + free( modes ); } }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index a71607e9e97..6513dca9468 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -783,9 +783,6 @@ struct x11drv_settings_handler * Return FALSE on failure with parameters unchanged and error code set. Return TRUE on success */ BOOL (*get_modes)(x11drv_settings_id id, DWORD flags, DEVMODEW **modes, UINT *mode_count, BOOL full);
- /* free_modes() will be called to free the mode list returned from get_modes() */ - void (*free_modes)(DEVMODEW *modes); - /* get_current_mode() will be called to get the current display mode of the device of id * * Following fields in DEVMODE must be valid: diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index 979cbc8645f..87bddd07cf5 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -317,11 +317,6 @@ static BOOL xrandr10_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **n return TRUE; }
-static void xrandr10_free_modes( DEVMODEW *modes ) -{ - free( modes ); -} - static BOOL xrandr10_get_current_mode( x11drv_settings_id id, DEVMODEW *mode ) { XRRScreenConfiguration *screen_config; @@ -1475,11 +1470,6 @@ done: return ret; }
-static void xrandr14_free_modes( DEVMODEW *modes ) -{ - free( modes ); -} - static BOOL xrandr14_get_current_mode( x11drv_settings_id id, DEVMODEW *mode ) { struct current_mode *mode_ptr = NULL; @@ -1724,7 +1714,6 @@ void X11DRV_XRandR_Init(void) 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 ); @@ -1782,7 +1771,6 @@ void X11DRV_XRandR_Init(void) settings_handler.priority = 300; settings_handler.get_id = xrandr14_get_id; settings_handler.get_modes = xrandr14_get_modes; - settings_handler.free_modes = xrandr14_free_modes; settings_handler.get_current_mode = xrandr14_get_current_mode; settings_handler.set_current_mode = xrandr14_set_current_mode; X11DRV_Settings_SetHandler( &settings_handler ); diff --git a/dlls/winex11.drv/xvidmode.c b/dlls/winex11.drv/xvidmode.c index f2313d88090..c333fa4dc7e 100644 --- a/dlls/winex11.drv/xvidmode.c +++ b/dlls/winex11.drv/xvidmode.c @@ -94,7 +94,7 @@ static BOOL xf86vm_get_id(const WCHAR *device_name, BOOL is_primary, x11drv_sett static void add_xf86vm_mode( DEVMODEW *mode, DWORD depth, const XF86VidModeModeInfo *mode_info, BOOL full ) { mode->dmSize = sizeof(*mode); - mode->dmDriverExtra = full ? sizeof(mode_info) : 0; + mode->dmDriverExtra = full ? sizeof(*mode_info) : 0; mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS; if (mode_info->htotal && mode_info->vtotal) { @@ -106,7 +106,13 @@ static void add_xf86vm_mode( DEVMODEW *mode, DWORD depth, const XF86VidModeModeI mode->dmPelsWidth = mode_info->hdisplay; mode->dmPelsHeight = mode_info->vdisplay; mode->dmDisplayFlags = 0; - if (full) memcpy( mode + 1, &mode_info, sizeof(mode_info) ); + if (full) + { + XF86VidModeModeInfo extra = *mode_info; + extra.private = NULL; + extra.privsize = 0; + memcpy( mode + 1, &extra, sizeof(extra) ); + } }
static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count, BOOL full ) @@ -115,8 +121,6 @@ static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new XF86VidModeModeInfo **xf86vm_modes; UINT depth_idx, mode_idx = 0; DEVMODEW *modes, *mode; - SIZE_T size; - BYTE *ptr; Bool ret;
X11DRV_expect_error(gdi_display, XVidModeErrorHandler, NULL); @@ -124,21 +128,15 @@ static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new if (X11DRV_check_error() || !ret || !xf86vm_mode_count) return FALSE;
- /* Put a XF86VidModeModeInfo ** at the start to store the XF86VidMode modes pointer */ - size = sizeof(XF86VidModeModeInfo **); /* Display modes in different color depth, with a XF86VidModeModeInfo * at the end of each * DEVMODEW as driver private data */ - size += (xf86vm_mode_count * DEPTH_COUNT) * (sizeof(DEVMODEW) + sizeof(XF86VidModeModeInfo *)); - ptr = calloc(1, size); - if (!ptr) + if (!(modes = calloc( 1, (xf86vm_mode_count * DEPTH_COUNT) * (sizeof(DEVMODEW) + sizeof(XF86VidModeModeInfo)) ))) { RtlSetLastWin32Error( ERROR_NOT_ENOUGH_MEMORY ); + XFree( xf86vm_modes ); return FALSE; }
- memcpy(ptr, &xf86vm_modes, sizeof(xf86vm_modes)); - modes = (DEVMODEW *)(ptr + sizeof(xf86vm_modes)); - for (depth_idx = 0, mode = modes; depth_idx < DEPTH_COUNT; ++depth_idx) { for (xf86vm_mode_idx = 0; xf86vm_mode_idx < xf86vm_mode_count; ++xf86vm_mode_idx) @@ -151,20 +149,9 @@ static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new
*new_modes = modes; *mode_count = mode_idx; - return TRUE; -} - -static void xf86vm_free_modes(DEVMODEW *modes) -{ - XF86VidModeModeInfo **xf86vm_modes;
- if (modes) - { - BYTE *ptr = (BYTE *)modes - sizeof(xf86vm_modes); - memcpy(&xf86vm_modes, ptr, sizeof(xf86vm_modes)); - XFree(xf86vm_modes); - free(ptr); - } + XFree( xf86vm_modes ); + return TRUE; }
static BOOL xf86vm_get_current_mode(x11drv_settings_id id, DEVMODEW *mode) @@ -210,7 +197,7 @@ static BOOL xf86vm_get_current_mode(x11drv_settings_id id, DEVMODEW *mode)
static LONG xf86vm_set_current_mode(x11drv_settings_id id, const DEVMODEW *mode) { - XF86VidModeModeInfo *xf86vm_mode; + XF86VidModeModeInfo xf86vm_mode; Bool ret;
if (id.id != 1) @@ -229,10 +216,11 @@ static LONG xf86vm_set_current_mode(x11drv_settings_id id, const DEVMODEW *mode) WARN("Cannot change screen bit depth from %dbits to %dbits!\n", screen_bpp, mode->dmBitsPerPel);
- assert(mode->dmDriverExtra == sizeof(XF86VidModeModeInfo *)); - memcpy(&xf86vm_mode, (BYTE *)mode + sizeof(*mode), sizeof(xf86vm_mode)); + assert( mode->dmDriverExtra == sizeof(XF86VidModeModeInfo) ); + memcpy( &xf86vm_mode, (BYTE *)mode + sizeof(*mode), sizeof(xf86vm_mode) ); + X11DRV_expect_error(gdi_display, XVidModeErrorHandler, NULL); - ret = pXF86VidModeSwitchToMode(gdi_display, DefaultScreen(gdi_display), xf86vm_mode); + ret = pXF86VidModeSwitchToMode( gdi_display, DefaultScreen(gdi_display), &xf86vm_mode ); if (X11DRV_check_error() || !ret) return DISP_CHANGE_FAILED; #if 0 /* it is said that SetViewPort causes problems with some X servers */ @@ -307,7 +295,6 @@ void X11DRV_XF86VM_Init(void) xf86vm_handler.priority = 100; xf86vm_handler.get_id = xf86vm_get_id; xf86vm_handler.get_modes = xf86vm_get_modes; - xf86vm_handler.free_modes = xf86vm_free_modes; xf86vm_handler.get_current_mode = xf86vm_get_current_mode; xf86vm_handler.set_current_mode = xf86vm_set_current_mode; X11DRV_Settings_SetHandler(&xf86vm_handler);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/display.c | 20 +++++++++++++++++--- dlls/winex11.drv/x11drv.h | 2 +- dlls/winex11.drv/xrandr.c | 22 +++++++++++----------- dlls/winex11.drv/xvidmode.c | 21 ++++++++++----------- 4 files changed, 39 insertions(+), 26 deletions(-)
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 5151a68f431..f063dabcbb5 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -62,7 +62,7 @@ static BOOL nores_get_id(const WCHAR *device_name, BOOL is_primary, x11drv_setti return TRUE; }
-static BOOL nores_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count, BOOL full ) +static BOOL nores_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count ) { RECT primary = get_host_primary_monitor_rect(); DEVMODEW *modes; @@ -140,6 +140,19 @@ void X11DRV_Settings_Init(void) X11DRV_Settings_SetHandler(&nores_handler); }
+static void strip_driver_extra( DEVMODEW *modes, UINT count ) +{ + DEVMODEW *mode, *next; + UINT i; + + for (i = 0, mode = modes; i < count; i++, mode = next) + { + next = NEXT_DEVMODEW(mode); + mode->dmDriverExtra = 0; + memcpy( modes + i, mode, sizeof(*mode) ); + } +} + BOOL is_detached_mode(const DEVMODEW *mode) { return mode->dmFields & DM_POSITION && @@ -168,7 +181,7 @@ static DEVMODEW *get_full_mode(x11drv_settings_id id, DEVMODEW *dev_mode) if (is_detached_mode(dev_mode)) return dev_mode;
- if (!settings_handler.get_modes( id, EDS_ROTATEDMODE, &modes, &mode_count, TRUE )) return NULL; + if (!settings_handler.get_modes( id, EDS_ROTATEDMODE, &modes, &mode_count )) return NULL;
for (mode_idx = 0; mode_idx < mode_count; ++mode_idx) { @@ -447,8 +460,9 @@ UINT X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage if (!settings_handler.get_id( devname, is_primary, &settings_id )) break;
settings_handler.get_current_mode( settings_id, ¤t_mode ); - if (settings_handler.get_modes( settings_id, EDS_ROTATEDMODE, &modes, &mode_count, FALSE )) + if (settings_handler.get_modes( settings_id, EDS_ROTATEDMODE, &modes, &mode_count )) { + strip_driver_extra( modes, mode_count ); device_manager->add_modes( ¤t_mode, mode_count, modes, param ); free( modes ); } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 6513dca9468..a92ffb6428e 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -781,7 +781,7 @@ struct x11drv_settings_handler * dmDisplayFlags and dmDisplayFrequency * * Return FALSE on failure with parameters unchanged and error code set. Return TRUE on success */ - BOOL (*get_modes)(x11drv_settings_id id, DWORD flags, DEVMODEW **modes, UINT *mode_count, BOOL full); + BOOL (*get_modes)(x11drv_settings_id id, DWORD flags, DEVMODEW **modes, UINT *mode_count);
/* get_current_mode() will be called to get the current display mode of the device of id * diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index 87bddd07cf5..8b675ec355b 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -239,10 +239,10 @@ static BOOL xrandr10_get_id( const WCHAR *device_name, BOOL is_primary, x11drv_s }
static void add_xrandr10_mode( DEVMODEW *mode, DWORD depth, DWORD width, DWORD height, - DWORD frequency, SizeID size_id, BOOL full ) + DWORD frequency, SizeID size_id ) { mode->dmSize = sizeof(*mode); - mode->dmDriverExtra = full ? sizeof(SizeID) : 0; + mode->dmDriverExtra = sizeof(SizeID); mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS; if (frequency) @@ -255,10 +255,10 @@ static void add_xrandr10_mode( DEVMODEW *mode, DWORD depth, DWORD width, DWORD h mode->dmPelsWidth = width; mode->dmPelsHeight = height; mode->dmDisplayFlags = 0; - if (full) memcpy( mode + 1, &size_id, sizeof(size_id) ); + memcpy( mode + 1, &size_id, sizeof(size_id) ); }
-static BOOL xrandr10_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *new_mode_count, BOOL full ) +static BOOL xrandr10_get_modes( x11drv_settings_id 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; @@ -296,7 +296,7 @@ static BOOL xrandr10_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **n if (!rate_count) { add_xrandr10_mode( mode, depths[depth_idx], sizes[size_idx].width, - sizes[size_idx].height, 0, size_idx, full ); + sizes[size_idx].height, 0, size_idx ); mode = NEXT_DEVMODEW( mode ); mode_idx++; continue; @@ -305,7 +305,7 @@ static BOOL xrandr10_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **n for (rate_idx = 0; rate_idx < rate_count; ++rate_idx) { add_xrandr10_mode( mode, depths[depth_idx], sizes[size_idx].width, - sizes[size_idx].height, rates[rate_idx], size_idx, full ); + sizes[size_idx].height, rates[rate_idx], size_idx ); mode = NEXT_DEVMODEW( mode ); mode_idx++; } @@ -1331,10 +1331,10 @@ static BOOL xrandr14_get_id( const WCHAR *device_name, BOOL is_primary, x11drv_s }
static void add_xrandr14_mode( DEVMODEW *mode, XRRModeInfo *info, DWORD depth, DWORD frequency, - DWORD orientation, BOOL full ) + DWORD orientation ) { mode->dmSize = sizeof(*mode); - mode->dmDriverExtra = full ? sizeof(RRMode) : 0; + mode->dmDriverExtra = sizeof(RRMode); mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS; if (frequency) @@ -1355,10 +1355,10 @@ static void add_xrandr14_mode( DEVMODEW *mode, XRRModeInfo *info, DWORD depth, D mode->dmDisplayOrientation = orientation; mode->dmBitsPerPel = depth; mode->dmDisplayFlags = 0; - if (full) memcpy( mode + 1, &info->id, sizeof(info->id) ); + memcpy( mode + 1, &info->id, sizeof(info->id) ); }
-static BOOL xrandr14_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count, BOOL full ) +static BOOL xrandr14_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count ) { DWORD frequency, orientation, orientation_count; XRRScreenResources *screen_resources; @@ -1447,7 +1447,7 @@ static BOOL xrandr14_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **n if (!((1 << orientation) & rotations)) continue;
- add_xrandr14_mode( mode, mode_info, depths[depth_idx], frequency, orientation, full ); + add_xrandr14_mode( mode, mode_info, depths[depth_idx], frequency, orientation ); mode = NEXT_DEVMODEW( mode ); ++mode_idx; } diff --git a/dlls/winex11.drv/xvidmode.c b/dlls/winex11.drv/xvidmode.c index c333fa4dc7e..7af34689dda 100644 --- a/dlls/winex11.drv/xvidmode.c +++ b/dlls/winex11.drv/xvidmode.c @@ -91,10 +91,12 @@ static BOOL xf86vm_get_id(const WCHAR *device_name, BOOL is_primary, x11drv_sett return TRUE; }
-static void add_xf86vm_mode( DEVMODEW *mode, DWORD depth, const XF86VidModeModeInfo *mode_info, BOOL full ) +static void add_xf86vm_mode( DEVMODEW *mode, DWORD depth, const XF86VidModeModeInfo *mode_info ) { + XF86VidModeModeInfo extra = *mode_info; + mode->dmSize = sizeof(*mode); - mode->dmDriverExtra = full ? sizeof(*mode_info) : 0; + mode->dmDriverExtra = sizeof(*mode_info); mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS; if (mode_info->htotal && mode_info->vtotal) { @@ -106,16 +108,13 @@ static void add_xf86vm_mode( DEVMODEW *mode, DWORD depth, const XF86VidModeModeI mode->dmPelsWidth = mode_info->hdisplay; mode->dmPelsHeight = mode_info->vdisplay; mode->dmDisplayFlags = 0; - if (full) - { - XF86VidModeModeInfo extra = *mode_info; - extra.private = NULL; - extra.privsize = 0; - memcpy( mode + 1, &extra, sizeof(extra) ); - } + + extra.private = NULL; + extra.privsize = 0; + memcpy( mode + 1, &extra, sizeof(extra) ); }
-static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count, BOOL full ) +static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count ) { INT xf86vm_mode_idx, xf86vm_mode_count; XF86VidModeModeInfo **xf86vm_modes; @@ -141,7 +140,7 @@ static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new { for (xf86vm_mode_idx = 0; xf86vm_mode_idx < xf86vm_mode_count; ++xf86vm_mode_idx) { - add_xf86vm_mode( mode, depths[depth_idx], xf86vm_modes[xf86vm_mode_idx], full ); + add_xf86vm_mode( mode, depths[depth_idx], xf86vm_modes[xf86vm_mode_idx] ); mode = NEXT_DEVMODEW( mode ); mode_idx++; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/display.c | 39 ++++++------ dlls/winex11.drv/x11drv.h | 31 +++++++-- dlls/winex11.drv/xrandr.c | 121 +++++++++++++++--------------------- dlls/winex11.drv/xvidmode.c | 54 ++++++++-------- 4 files changed, 122 insertions(+), 123 deletions(-)
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index f063dabcbb5..8634d99ed8e 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -62,10 +62,10 @@ static BOOL nores_get_id(const WCHAR *device_name, BOOL is_primary, x11drv_setti return TRUE; }
-static BOOL nores_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count ) +static BOOL nores_get_modes( x11drv_settings_id id, DWORD flags, struct x11drv_mode **new_modes, UINT *mode_count ) { RECT primary = get_host_primary_monitor_rect(); - DEVMODEW *modes; + struct x11drv_mode *modes;
modes = calloc(1, sizeof(*modes)); if (!modes) @@ -74,16 +74,16 @@ static BOOL nores_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_ return FALSE; }
- modes[0].dmSize = sizeof(*modes); - modes[0].dmDriverExtra = 0; - modes[0].dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | - DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; - modes[0].dmDisplayOrientation = DMDO_DEFAULT; - modes[0].dmBitsPerPel = screen_bpp; - modes[0].dmPelsWidth = primary.right; - modes[0].dmPelsHeight = primary.bottom; - modes[0].dmDisplayFlags = 0; - modes[0].dmDisplayFrequency = 60; + modes[0].mode.dmSize = sizeof(*modes); + modes[0].mode.dmDriverExtra = 0; + modes[0].mode.dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | + DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; + modes[0].mode.dmDisplayOrientation = DMDO_DEFAULT; + modes[0].mode.dmBitsPerPel = screen_bpp; + modes[0].mode.dmPelsWidth = primary.right; + modes[0].mode.dmPelsHeight = primary.bottom; + modes[0].mode.dmDisplayFlags = 0; + modes[0].mode.dmDisplayFrequency = 60;
*new_modes = modes; *mode_count = 1; @@ -118,7 +118,7 @@ static BOOL nores_get_current_mode(x11drv_settings_id id, DEVMODEW *mode) return TRUE; }
-static LONG nores_set_current_mode(x11drv_settings_id id, const DEVMODEW *mode) +static LONG nores_set_current_mode( x11drv_settings_id id, const struct x11drv_mode *mode ) { WARN("NoRes settings handler, ignoring mode change request.\n"); return DISP_CHANGE_SUCCESSFUL; @@ -175,8 +175,9 @@ static BOOL is_same_devmode( const DEVMODEW *a, const DEVMODEW *b ) * Return NULL on failure. Caller should call free_full_mode() to free the returned mode. */ static DEVMODEW *get_full_mode(x11drv_settings_id id, DEVMODEW *dev_mode) { - DEVMODEW *modes, *full_mode, *found_mode = NULL; + DEVMODEW *full_mode, *found_mode = NULL; UINT mode_count, mode_idx; + struct x11drv_mode *modes;
if (is_detached_mode(dev_mode)) return dev_mode; @@ -185,7 +186,7 @@ static DEVMODEW *get_full_mode(x11drv_settings_id id, DEVMODEW *dev_mode)
for (mode_idx = 0; mode_idx < mode_count; ++mode_idx) { - found_mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*modes) + modes[0].dmDriverExtra) * mode_idx); + found_mode = &modes[mode_idx].mode; if (is_same_devmode( found_mode, dev_mode )) break; }
@@ -242,7 +243,7 @@ static LONG apply_display_settings( DEVMODEW *displays, x11drv_settings_id *ids, full_mode->dmPelsHeight, full_mode->dmDisplayFrequency, full_mode->dmBitsPerPel, full_mode->dmDisplayOrientation);
- ret = settings_handler.set_current_mode(*id, full_mode); + ret = settings_handler.set_current_mode(*id, (struct x11drv_mode *)full_mode); free_full_mode(full_mode); if (ret != DISP_CHANGE_SUCCESSFUL) return ret; @@ -416,7 +417,7 @@ UINT X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage struct gdi_monitor *monitors; struct x11drv_gpu *gpus; INT gpu, adapter, monitor; - DEVMODEW *modes; + struct x11drv_mode *modes; UINT mode_count;
TRACE( "via %s\n", debugstr_a(host_handler.name) ); @@ -462,8 +463,8 @@ UINT X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage settings_handler.get_current_mode( settings_id, ¤t_mode ); if (settings_handler.get_modes( settings_id, EDS_ROTATEDMODE, &modes, &mode_count )) { - strip_driver_extra( modes, mode_count ); - device_manager->add_modes( ¤t_mode, mode_count, modes, param ); + strip_driver_extra( &modes->mode, mode_count ); + device_manager->add_modes( ¤t_mode, mode_count, &modes->mode, param ); free( modes ); } } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index a92ffb6428e..c73c7ef5e41 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -38,6 +38,9 @@ #include <X11/extensions/XInput2.h> #endif
+#undef Status /* avoid conflict with wintrnl.h */ +typedef int Status; + #define BOOL X_BOOL #define BYTE X_BYTE #define INT8 X_INT8 @@ -46,6 +49,12 @@ #define INT64 X_INT64 #include <X11/Xmd.h> #include <X11/Xproto.h> +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H +#include <X11/extensions/xf86vmode.h> +#endif +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H +#include <X11/extensions/Xrandr.h> +#endif #undef BOOL #undef BYTE #undef INT8 @@ -54,9 +63,6 @@ #undef INT64 #undef LONG64
-#undef Status /* avoid conflict with wintrnl.h */ -typedef int Status; - /* avoid conflict with processthreadsapi.h */ #undef ControlMask
@@ -757,6 +763,21 @@ extern const unsigned int *depths; /* Use a distinct type for the settings id, to avoid mixups other types of ids */ typedef struct { ULONG_PTR id; } x11drv_settings_id;
+struct x11drv_mode +{ + DEVMODEW mode; + union + { +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + XF86VidModeModeInfo mode_info; +#endif +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H + SizeID size_id; + RRMode rr_mode; +#endif + }; +}; + /* Required functions for changing and enumerating display settings */ struct x11drv_settings_handler { @@ -781,7 +802,7 @@ struct x11drv_settings_handler * dmDisplayFlags and dmDisplayFrequency * * Return FALSE on failure with parameters unchanged and error code set. Return TRUE on success */ - BOOL (*get_modes)(x11drv_settings_id id, DWORD flags, DEVMODEW **modes, UINT *mode_count); + BOOL (*get_modes)(x11drv_settings_id id, DWORD flags, struct x11drv_mode **modes, UINT *mode_count);
/* get_current_mode() will be called to get the current display mode of the device of id * @@ -796,7 +817,7 @@ struct x11drv_settings_handler * mode must be a valid mode from get_modes() with optional fields, such as dmPosition set. * * Return DISP_CHANGE_*, same as ChangeDisplaySettingsExW() return values */ - LONG (*set_current_mode)(x11drv_settings_id id, const DEVMODEW *mode); + LONG (*set_current_mode)(x11drv_settings_id id, const struct x11drv_mode *mode); };
#define NEXT_DEVMODEW(mode) ((DEVMODEW *)((char *)((mode) + 1) + (mode)->dmDriverExtra)) diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index 8b675ec355b..058bde94701 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -238,31 +238,30 @@ static BOOL xrandr10_get_id( const WCHAR *device_name, BOOL is_primary, x11drv_s return TRUE; }
-static void add_xrandr10_mode( DEVMODEW *mode, DWORD depth, DWORD width, DWORD height, +static void add_xrandr10_mode( struct x11drv_mode *mode, DWORD depth, DWORD width, DWORD height, DWORD frequency, SizeID size_id ) { - mode->dmSize = sizeof(*mode); - mode->dmDriverExtra = sizeof(SizeID); - mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | + mode->mode.dmSize = sizeof(*mode); + mode->mode.dmDriverExtra = sizeof(*mode) - sizeof(mode->mode); + mode->mode.dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS; if (frequency) { - mode->dmFields |= DM_DISPLAYFREQUENCY; - mode->dmDisplayFrequency = frequency; + mode->mode.dmFields |= DM_DISPLAYFREQUENCY; + mode->mode.dmDisplayFrequency = frequency; } - mode->dmDisplayOrientation = DMDO_DEFAULT; - mode->dmBitsPerPel = depth; - mode->dmPelsWidth = width; - mode->dmPelsHeight = height; - mode->dmDisplayFlags = 0; - memcpy( mode + 1, &size_id, sizeof(size_id) ); + mode->mode.dmDisplayOrientation = DMDO_DEFAULT; + mode->mode.dmBitsPerPel = depth; + mode->mode.dmPelsWidth = width; + mode->mode.dmPelsHeight = height; + mode->mode.dmDisplayFlags = 0; + mode->size_id = size_id; }
-static BOOL xrandr10_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *new_mode_count ) +static BOOL xrandr10_get_modes( x11drv_settings_id id, DWORD flags, struct x11drv_mode **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; + INT size_idx, depth_idx, rate_idx, size_count, rate_count, mode_count = 0; + struct x11drv_mode *modes, *mode; XRRScreenSize *sizes; short *rates;
@@ -279,10 +278,7 @@ static BOOL xrandr10_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **n ++mode_count; }
- /* Allocate space for reported modes in three depths, and put an SizeID at the end of DEVMODEW as - * driver private data */ - modes = calloc( mode_count * DEPTH_COUNT, sizeof(*modes) + sizeof(SizeID) ); - if (!modes) + if (!(modes = calloc( mode_count * DEPTH_COUNT, sizeof(*modes) ))) { RtlSetLastWin32Error( ERROR_NOT_ENOUGH_MEMORY ); return FALSE; @@ -295,25 +291,21 @@ static BOOL xrandr10_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **n rates = pXRRRates( gdi_display, DefaultScreen( gdi_display ), size_idx, &rate_count ); if (!rate_count) { - add_xrandr10_mode( mode, depths[depth_idx], sizes[size_idx].width, + add_xrandr10_mode( mode++, depths[depth_idx], sizes[size_idx].width, sizes[size_idx].height, 0, size_idx ); - mode = NEXT_DEVMODEW( mode ); - mode_idx++; continue; }
for (rate_idx = 0; rate_idx < rate_count; ++rate_idx) { - add_xrandr10_mode( mode, depths[depth_idx], sizes[size_idx].width, + add_xrandr10_mode( mode++, depths[depth_idx], sizes[size_idx].width, sizes[size_idx].height, rates[rate_idx], size_idx ); - mode = NEXT_DEVMODEW( mode ); - mode_idx++; } } }
*new_modes = modes; - *new_mode_count = mode_idx; + *new_mode_count = mode - modes; return TRUE; }
@@ -359,14 +351,16 @@ static BOOL xrandr10_get_current_mode( x11drv_settings_id id, DEVMODEW *mode ) return TRUE; }
-static LONG xrandr10_set_current_mode( x11drv_settings_id id, const DEVMODEW *mode ) +static LONG xrandr10_set_current_mode( x11drv_settings_id id, const struct x11drv_mode *full_mode ) { + const DEVMODEW *mode = &full_mode->mode; XRRScreenConfiguration *screen_config; Rotation rotation; - SizeID size_id; Window root; Status stat;
+ assert( sizeof(*full_mode) == sizeof(full_mode->mode) + full_mode->mode.dmDriverExtra ); + if (id.id != 1) { FIXME("Non-primary adapters are unsupported.\n"); @@ -387,14 +381,11 @@ static LONG xrandr10_set_current_mode( x11drv_settings_id id, const DEVMODEW *mo screen_config = pXRRGetScreenInfo( gdi_display, root ); pXRRConfigCurrentConfiguration( screen_config, &rotation );
- assert( mode->dmDriverExtra == sizeof(SizeID) ); - memcpy( &size_id, (BYTE *)mode + sizeof(*mode), sizeof(size_id) ); - if (mode->dmFields & DM_DISPLAYFREQUENCY && mode->dmDisplayFrequency) - stat = pXRRSetScreenConfigAndRate( gdi_display, screen_config, root, size_id, rotation, + stat = pXRRSetScreenConfigAndRate( gdi_display, screen_config, root, full_mode->size_id, rotation, mode->dmDisplayFrequency, CurrentTime ); else - stat = pXRRSetScreenConfig( gdi_display, screen_config, root, size_id, rotation, CurrentTime ); + stat = pXRRSetScreenConfig( gdi_display, screen_config, root, full_mode->size_id, rotation, CurrentTime ); pXRRFreeScreenConfigInfo( screen_config );
if (stat != RRSetConfigSuccess) @@ -1330,46 +1321,46 @@ static BOOL xrandr14_get_id( const WCHAR *device_name, BOOL is_primary, x11drv_s return TRUE; }
-static void add_xrandr14_mode( DEVMODEW *mode, XRRModeInfo *info, DWORD depth, DWORD frequency, +static void add_xrandr14_mode( struct x11drv_mode *mode, XRRModeInfo *info, DWORD depth, DWORD frequency, DWORD orientation ) { - mode->dmSize = sizeof(*mode); - mode->dmDriverExtra = sizeof(RRMode); - mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | + mode->mode.dmSize = sizeof(*mode); + mode->mode.dmDriverExtra = sizeof(*mode) - sizeof(mode->mode); + mode->mode.dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS; if (frequency) { - mode->dmFields |= DM_DISPLAYFREQUENCY; - mode->dmDisplayFrequency = frequency; + mode->mode.dmFields |= DM_DISPLAYFREQUENCY; + mode->mode.dmDisplayFrequency = frequency; } if (orientation == DMDO_DEFAULT || orientation == DMDO_180) { - mode->dmPelsWidth = info->width; - mode->dmPelsHeight = info->height; + mode->mode.dmPelsWidth = info->width; + mode->mode.dmPelsHeight = info->height; } else { - mode->dmPelsWidth = info->height; - mode->dmPelsHeight = info->width; + mode->mode.dmPelsWidth = info->height; + mode->mode.dmPelsHeight = info->width; } - mode->dmDisplayOrientation = orientation; - mode->dmBitsPerPel = depth; - mode->dmDisplayFlags = 0; - memcpy( mode + 1, &info->id, sizeof(info->id) ); + mode->mode.dmDisplayOrientation = orientation; + mode->mode.dmBitsPerPel = depth; + mode->mode.dmDisplayFlags = 0; + mode->rr_mode = info->id; }
-static BOOL xrandr14_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count ) +static BOOL xrandr14_get_modes( x11drv_settings_id id, DWORD flags, struct x11drv_mode **new_modes, UINT *mode_count ) { DWORD frequency, orientation, orientation_count; XRRScreenResources *screen_resources; XRROutputInfo *output_info = NULL; RROutput output = (RROutput)id.id; + struct x11drv_mode *mode, *modes; XRRCrtcInfo *crtc_info = NULL; - UINT depth_idx, mode_idx = 0; XRRModeInfo *mode_info; - DEVMODEW *mode, *modes; Rotation rotations; BOOL ret = FALSE; + UINT depth_idx; RRCrtc crtc; INT i, j;
@@ -1423,12 +1414,7 @@ static BOOL xrandr14_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **n } orientation_count = get_orientation_count( rotations );
- /* Allocate space for display modes in different color depths and orientations. - * Store a RRMode at the end of each DEVMODEW as private driver data */ - modes = calloc( output_info->nmode * DEPTH_COUNT * orientation_count, - sizeof(*modes) + sizeof(RRMode) ); - if (!modes) - goto done; + if (!(modes = calloc( output_info->nmode * DEPTH_COUNT * orientation_count, sizeof(*modes) ))) goto done;
for (i = 0, mode = modes; i < output_info->nmode; ++i) { @@ -1444,12 +1430,8 @@ static BOOL xrandr14_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **n { for (orientation = DMDO_DEFAULT; orientation <= DMDO_270; ++orientation) { - if (!((1 << orientation) & rotations)) - continue; - - add_xrandr14_mode( mode, mode_info, depths[depth_idx], frequency, orientation ); - mode = NEXT_DEVMODEW( mode ); - ++mode_idx; + if (!((1 << orientation) & rotations)) continue; + add_xrandr14_mode( mode++, mode_info, depths[depth_idx], frequency, orientation ); } }
@@ -1459,7 +1441,7 @@ static BOOL xrandr14_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **n
ret = TRUE; *new_modes = modes; - *mode_count = mode_idx; + *mode_count = mode - modes; done: if (crtc_info) pXRRFreeCrtcInfo( crtc_info ); @@ -1576,8 +1558,9 @@ done: return ret; }
-static LONG xrandr14_set_current_mode( x11drv_settings_id id, const DEVMODEW *mode ) +static LONG xrandr14_set_current_mode( x11drv_settings_id id, const struct x11drv_mode *full_mode ) { + const DEVMODEW *mode = &full_mode->mode; unsigned int screen_width, screen_height; RROutput output = (RROutput)id.id, *outputs; XRRScreenResources *screen_resources; @@ -1588,7 +1571,8 @@ static LONG xrandr14_set_current_mode( x11drv_settings_id id, const DEVMODEW *mo INT output_count; RRCrtc crtc = 0; Status status; - RRMode rrmode; + + assert( sizeof(*full_mode) == sizeof(full_mode->mode) + full_mode->mode.dmDriverExtra );
if (mode->dmFields & DM_BITSPERPEL && mode->dmBitsPerPel != screen_bpp) WARN("Cannot change screen color depth from %ubits to %ubits!\n", @@ -1641,9 +1625,6 @@ static LONG xrandr14_set_current_mode( x11drv_settings_id id, const DEVMODEW *mo if (!crtc_info) goto done;
- assert( mode->dmDriverExtra == sizeof(RRMode) ); - memcpy( &rrmode, (BYTE *)mode + sizeof(*mode), sizeof(rrmode) ); - if (crtc_info->noutput) { outputs = crtc_info->outputs; @@ -1671,7 +1652,7 @@ static LONG xrandr14_set_current_mode( x11drv_settings_id id, const DEVMODEW *mo set_screen_size( screen_width, screen_height );
status = pXRRSetCrtcConfig( gdi_display, screen_resources, crtc, CurrentTime, - mode->dmPosition.x, mode->dmPosition.y, rrmode, + mode->dmPosition.x, mode->dmPosition.y, full_mode->rr_mode, rotation, outputs, output_count ); if (status == RRSetConfigSuccess) ret = DISP_CHANGE_SUCCESSFUL; diff --git a/dlls/winex11.drv/xvidmode.c b/dlls/winex11.drv/xvidmode.c index 7af34689dda..d39116c48ff 100644 --- a/dlls/winex11.drv/xvidmode.c +++ b/dlls/winex11.drv/xvidmode.c @@ -91,35 +91,32 @@ static BOOL xf86vm_get_id(const WCHAR *device_name, BOOL is_primary, x11drv_sett return TRUE; }
-static void add_xf86vm_mode( DEVMODEW *mode, DWORD depth, const XF86VidModeModeInfo *mode_info ) +static void add_xf86vm_mode( struct x11drv_mode *mode, DWORD depth, const XF86VidModeModeInfo *mode_info ) { - XF86VidModeModeInfo extra = *mode_info; - - mode->dmSize = sizeof(*mode); - mode->dmDriverExtra = sizeof(*mode_info); - mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS; + mode->mode.dmSize = sizeof(*mode); + mode->mode.dmDriverExtra = sizeof(*mode) - sizeof(mode->mode); + mode->mode.dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS; if (mode_info->htotal && mode_info->vtotal) { - mode->dmFields |= DM_DISPLAYFREQUENCY; - mode->dmDisplayFrequency = mode_info->dotclock * 1000 / (mode_info->htotal * mode_info->vtotal); + mode->mode.dmFields |= DM_DISPLAYFREQUENCY; + mode->mode.dmDisplayFrequency = mode_info->dotclock * 1000 / (mode_info->htotal * mode_info->vtotal); } - mode->dmDisplayOrientation = DMDO_DEFAULT; - mode->dmBitsPerPel = depth; - mode->dmPelsWidth = mode_info->hdisplay; - mode->dmPelsHeight = mode_info->vdisplay; - mode->dmDisplayFlags = 0; - - extra.private = NULL; - extra.privsize = 0; - memcpy( mode + 1, &extra, sizeof(extra) ); + mode->mode.dmDisplayOrientation = DMDO_DEFAULT; + mode->mode.dmBitsPerPel = depth; + mode->mode.dmPelsWidth = mode_info->hdisplay; + mode->mode.dmPelsHeight = mode_info->vdisplay; + mode->mode.dmDisplayFlags = 0; + mode->mode_info = *mode_info; + mode->mode_info.privsize = 0; + mode->mode_info.private = NULL; }
-static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count ) +static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, struct x11drv_mode **new_modes, UINT *mode_count ) { INT xf86vm_mode_idx, xf86vm_mode_count; XF86VidModeModeInfo **xf86vm_modes; - UINT depth_idx, mode_idx = 0; - DEVMODEW *modes, *mode; + struct x11drv_mode *modes, *mode; + UINT depth_idx; Bool ret;
X11DRV_expect_error(gdi_display, XVidModeErrorHandler, NULL); @@ -129,7 +126,7 @@ static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new
/* Display modes in different color depth, with a XF86VidModeModeInfo * at the end of each * DEVMODEW as driver private data */ - if (!(modes = calloc( 1, (xf86vm_mode_count * DEPTH_COUNT) * (sizeof(DEVMODEW) + sizeof(XF86VidModeModeInfo)) ))) + if (!(modes = calloc( xf86vm_mode_count * DEPTH_COUNT, sizeof(*modes) ))) { RtlSetLastWin32Error( ERROR_NOT_ENOUGH_MEMORY ); XFree( xf86vm_modes ); @@ -140,14 +137,12 @@ static BOOL xf86vm_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **new { for (xf86vm_mode_idx = 0; xf86vm_mode_idx < xf86vm_mode_count; ++xf86vm_mode_idx) { - add_xf86vm_mode( mode, depths[depth_idx], xf86vm_modes[xf86vm_mode_idx] ); - mode = NEXT_DEVMODEW( mode ); - mode_idx++; + add_xf86vm_mode( mode++, depths[depth_idx], xf86vm_modes[xf86vm_mode_idx] ); } }
*new_modes = modes; - *mode_count = mode_idx; + *mode_count = mode - modes;
XFree( xf86vm_modes ); return TRUE; @@ -194,11 +189,14 @@ static BOOL xf86vm_get_current_mode(x11drv_settings_id id, DEVMODEW *mode) return TRUE; }
-static LONG xf86vm_set_current_mode(x11drv_settings_id id, const DEVMODEW *mode) +static LONG xf86vm_set_current_mode( x11drv_settings_id id, const struct x11drv_mode *full_mode ) { + const DEVMODEW *mode = &full_mode->mode; XF86VidModeModeInfo xf86vm_mode; Bool ret;
+ assert( sizeof(*full_mode) == sizeof(full_mode->mode) + full_mode->mode.dmDriverExtra ); + if (id.id != 1) { FIXME("Non-primary adapters are unsupported.\n"); @@ -215,9 +213,7 @@ static LONG xf86vm_set_current_mode(x11drv_settings_id id, const DEVMODEW *mode) WARN("Cannot change screen bit depth from %dbits to %dbits!\n", screen_bpp, mode->dmBitsPerPel);
- assert( mode->dmDriverExtra == sizeof(XF86VidModeModeInfo) ); - memcpy( &xf86vm_mode, (BYTE *)mode + sizeof(*mode), sizeof(xf86vm_mode) ); - + xf86vm_mode = full_mode->mode_info; X11DRV_expect_error(gdi_display, XVidModeErrorHandler, NULL); ret = pXF86VidModeSwitchToMode( gdi_display, DefaultScreen(gdi_display), &xf86vm_mode ); if (X11DRV_check_error() || !ret)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/display.c | 121 ++++++++++++++----------------------- 1 file changed, 45 insertions(+), 76 deletions(-)
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 8634d99ed8e..68073f88955 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -43,6 +43,18 @@ static const unsigned int depths_24[] = {8, 16, 24}; static const unsigned int depths_32[] = {8, 16, 32}; const unsigned int *depths;
+static const char *debugstr_devmodew( const DEVMODEW *devmode ) +{ + char position[32] = {0}; + if (devmode->dmFields & DM_POSITION) snprintf( position, sizeof(position), " at %s", wine_dbgstr_point( (POINT *)&devmode->dmPosition ) ); + return wine_dbg_sprintf( "%ux%u %ubits %uHz rotated %u degrees %sstretched %sinterlaced%s", + devmode->dmPelsWidth, devmode->dmPelsHeight, devmode->dmBitsPerPel, + devmode->dmDisplayFrequency, devmode->dmDisplayOrientation * 90, + devmode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un", + devmode->dmDisplayFlags & DM_INTERLACED ? "" : "non-", + position ); +} + void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *new_handler) { if (new_handler->priority > settings_handler.priority) @@ -171,85 +183,26 @@ static BOOL is_same_devmode( const DEVMODEW *a, const DEVMODEW *b ) a->dmDisplayFrequency == b->dmDisplayFrequency; }
-/* Get the full display mode with all the necessary fields set. - * Return NULL on failure. Caller should call free_full_mode() to free the returned mode. */ -static DEVMODEW *get_full_mode(x11drv_settings_id id, DEVMODEW *dev_mode) +static DWORD x11drv_mode_from_devmode( x11drv_settings_id id, DEVMODEW *mode, struct x11drv_mode *full ) { - DEVMODEW *full_mode, *found_mode = NULL; - UINT mode_count, mode_idx; struct x11drv_mode *modes; + UINT count, i;
- if (is_detached_mode(dev_mode)) - return dev_mode; - - if (!settings_handler.get_modes( id, EDS_ROTATEDMODE, &modes, &mode_count )) return NULL; - - for (mode_idx = 0; mode_idx < mode_count; ++mode_idx) - { - found_mode = &modes[mode_idx].mode; - if (is_same_devmode( found_mode, dev_mode )) break; - } - - if (!found_mode || mode_idx == mode_count) - { - free( modes ); - return NULL; - } + full->mode = *mode; + if (is_detached_mode( mode )) return DISP_CHANGE_SUCCESSFUL;
- if (!(full_mode = malloc(sizeof(*found_mode) + found_mode->dmDriverExtra))) + if (!settings_handler.get_modes( id, EDS_ROTATEDMODE, &modes, &count )) return DISP_CHANGE_BADMODE; + for (i = 0; i < count; i++) if (is_same_devmode( &modes[i].mode, mode )) break; + if (i < count) { - free( modes ); - return NULL; + *full = modes[i]; + full->mode.dmFields |= DM_POSITION; + full->mode.dmPosition = mode->dmPosition; + memcpy( full->mode.dmDeviceName, mode->dmDeviceName, sizeof(mode->dmDeviceName) ); } - - memcpy(full_mode, found_mode, sizeof(*found_mode) + found_mode->dmDriverExtra); free( modes );
- full_mode->dmFields |= DM_POSITION; - full_mode->dmPosition = dev_mode->dmPosition; - return full_mode; -} - -static void free_full_mode(DEVMODEW *mode) -{ - if (!is_detached_mode(mode)) - free(mode); -} - -static LONG apply_display_settings( DEVMODEW *displays, x11drv_settings_id *ids, BOOL do_attach ) -{ - DEVMODEW *full_mode; - BOOL attached_mode; - LONG count, ret; - DEVMODEW *mode; - - for (count = 0, mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode), count++) - { - x11drv_settings_id *id = ids + count; - - attached_mode = !is_detached_mode(mode); - if ((attached_mode && !do_attach) || (!attached_mode && do_attach)) - continue; - - /* FIXME: get a full mode again because X11 driver extra data isn't portable */ - full_mode = get_full_mode(*id, mode); - if (!full_mode) - return DISP_CHANGE_BADMODE; - - TRACE("handler:%s changing %s to position:(%d,%d) resolution:%ux%u frequency:%uHz " - "depth:%ubits orientation:%#x.\n", settings_handler.name, - wine_dbgstr_w(mode->dmDeviceName), - full_mode->dmPosition.x, full_mode->dmPosition.y, full_mode->dmPelsWidth, - full_mode->dmPelsHeight, full_mode->dmDisplayFrequency, - full_mode->dmBitsPerPel, full_mode->dmDisplayOrientation); - - ret = settings_handler.set_current_mode(*id, (struct x11drv_mode *)full_mode); - free_full_mode(full_mode); - if (ret != DISP_CHANGE_SUCCESSFUL) - return ret; - } - - return DISP_CHANGE_SUCCESSFUL; + return i < count ? DISP_CHANGE_SUCCESSFUL : DISP_CHANGE_BADMODE; }
/*********************************************************************** @@ -259,7 +212,8 @@ static LONG apply_display_settings( DEVMODEW *displays, x11drv_settings_id *ids, LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, LPCWSTR primary_name, HWND hwnd, DWORD flags, LPVOID lpvoid ) { INT left_most = INT_MAX, top_most = INT_MAX; - LONG count, ret = DISP_CHANGE_BADPARAM; + LONG count, ret = DISP_CHANGE_FAILED; + struct x11drv_mode *modes; x11drv_settings_id *ids; DEVMODEW *mode;
@@ -273,19 +227,34 @@ LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, LPCWSTR primary_name, HW }
if (!(ids = calloc( count, sizeof(*ids) ))) return DISP_CHANGE_FAILED; + if (!(modes = calloc( count, sizeof(*modes) ))) goto done; + for (count = 0, mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode), count++) { - if (!settings_handler.get_id( mode->dmDeviceName, !wcsicmp( mode->dmDeviceName, primary_name ), ids + count )) goto done; + BOOL is_primary = !wcsicmp( mode->dmDeviceName, primary_name ); + if (!settings_handler.get_id( mode->dmDeviceName, is_primary, ids + count )) goto done; mode->dmPosition.x -= left_most; mode->dmPosition.y -= top_most; + if ((ret = x11drv_mode_from_devmode( ids[count], mode, modes + count ))) goto done; }
/* Detach displays first to free up CRTCs */ - ret = apply_display_settings( displays, ids, FALSE ); - if (ret == DISP_CHANGE_SUCCESSFUL) - ret = apply_display_settings( displays, ids, TRUE ); + TRACE( "Using %s\n", settings_handler.name ); + for (UINT i = 0; !ret && i < count; i++) + { + if (!is_detached_mode( &modes[i].mode )) continue; + TRACE( " setting %s mode %s\n", debugstr_w(modes[i].mode.dmDeviceName), debugstr_devmodew(&modes[i].mode) ); + ret = settings_handler.set_current_mode( ids[i], modes + i ); + } + for (UINT i = 0; !ret && i < count; i++) + { + if (is_detached_mode( &modes[i].mode )) continue; + TRACE( " setting %s mode %s\n", debugstr_w(modes[i].mode.dmDeviceName), debugstr_devmodew(&modes[i].mode) ); + ret = settings_handler.set_current_mode( ids[i], modes + i ); + }
done: + free( modes ); free( ids ); return ret; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/display.c | 5 +++++ dlls/winex11.drv/xrandr.c | 5 ----- dlls/winex11.drv/xvidmode.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 68073f88955..af984efe7f0 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -238,6 +238,8 @@ LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, LPCWSTR primary_name, HW if ((ret = x11drv_mode_from_devmode( ids[count], mode, modes + count ))) goto done; }
+ XGrabServer( gdi_display ); + /* Detach displays first to free up CRTCs */ TRACE( "Using %s\n", settings_handler.name ); for (UINT i = 0; !ret && i < count; i++) @@ -253,6 +255,9 @@ LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, LPCWSTR primary_name, HW ret = settings_handler.set_current_mode( ids[i], modes + i ); }
+ XUngrabServer( gdi_display ); + XFlush( gdi_display ); + done: free( modes ); free( ids ); diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index 058bde94701..1bc2c722416 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -391,7 +391,6 @@ static LONG xrandr10_set_current_mode( x11drv_settings_id id, const struct x11dr if (stat != RRSetConfigSuccess) return DISP_CHANGE_FAILED;
- XFlush( gdi_display ); return DISP_CHANGE_SUCCESSFUL; }
@@ -1582,8 +1581,6 @@ static LONG xrandr14_set_current_mode( x11drv_settings_id id, const struct x11dr if (!screen_resources) return ret;
- XGrabServer( gdi_display ); - output_info = pXRRGetOutputInfo( gdi_display, screen_resources, output ); if (!output_info || output_info->connection != RR_Connected) goto done; @@ -1658,8 +1655,6 @@ static LONG xrandr14_set_current_mode( x11drv_settings_id id, const struct x11dr ret = DISP_CHANGE_SUCCESSFUL;
done: - XUngrabServer( gdi_display ); - XFlush( gdi_display ); if (crtc_info) pXRRFreeCrtcInfo( crtc_info ); if (output_info) diff --git a/dlls/winex11.drv/xvidmode.c b/dlls/winex11.drv/xvidmode.c index d39116c48ff..23fd09a08f0 100644 --- a/dlls/winex11.drv/xvidmode.c +++ b/dlls/winex11.drv/xvidmode.c @@ -223,7 +223,7 @@ static LONG xf86vm_set_current_mode( x11drv_settings_id id, const struct x11drv_ #else XWarpPointer(gdi_display, None, DefaultRootWindow(gdi_display), 0, 0, 0, 0, 0, 0); #endif - XFlush(gdi_display); + return DISP_CHANGE_SUCCESSFUL; }
Hi Rémi, did you run the user32/monitor.c tests with the XF86VidMode display settings backend? I am getting the following errors here. They don't look new, so it might be because of something wrong with my drivers. I will try to test this MR on another machine. ``` X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 153 (XFree86-VidModeExtension) Minor opcode of failed request: 10 (XF86VidModeSwitchToMode) Value in failed request: 0x3e6 Serial number of failed request: 1332 Current serial number in output stream: 1333 ```
Yeah I did try and saw the same errors, but they seem to occur already without this MR and I didn't investigate further.
I just tried the tests on Debian 11 on VirtualBox, and the errors are gone. So it might indeed be an issue with the drivers. XF86VidMode is so old that probably no one cares about it anymore.
This merge request was approved by Zhiyi Zhang.