From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/display.c | 123 ++++++++++++++---------------------- dlls/winex11.drv/xrandr.c | 18 ++---- dlls/winex11.drv/xvidmode.c | 8 +-- 3 files changed, 56 insertions(+), 93 deletions(-)
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index e4a0bef2f08..6cf0afcbd23 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) @@ -118,7 +130,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; @@ -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 get_full_mode( 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, 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 = get_full_mode( 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; } diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index 6555d07f4ca..8b560d1d0f5 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -351,11 +351,12 @@ 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; + SizeID size_id = full_mode->xrandr10; Rotation rotation; - SizeID size_id; Window root; Status stat;
@@ -365,7 +366,7 @@ static LONG xrandr10_set_current_mode( x11drv_settings_id id, const DEVMODEW *mo return DISP_CHANGE_SUCCESSFUL; }
- if (is_detached_mode(mode)) + if (is_detached_mode( mode )) { FIXME("Detaching adapters is unsupported.\n"); return DISP_CHANGE_SUCCESSFUL; @@ -379,9 +380,6 @@ 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, mode->dmDisplayFrequency, CurrentTime ); @@ -1559,10 +1557,12 @@ 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; + RRMode rrmode = (RRMode)full_mode->xrandr14; XRRScreenResources *screen_resources; XRROutputInfo *output_info = NULL; XRRCrtcInfo *crtc_info = NULL; @@ -1571,7 +1571,6 @@ static LONG xrandr14_set_current_mode( x11drv_settings_id id, const DEVMODEW *mo INT output_count; RRCrtc crtc = 0; Status status; - RRMode rrmode;
if (mode->dmFields & DM_BITSPERPEL && mode->dmBitsPerPel != screen_bpp) WARN("Cannot change screen color depth from %ubits to %ubits!\n", @@ -1624,9 +1623,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; diff --git a/dlls/winex11.drv/xvidmode.c b/dlls/winex11.drv/xvidmode.c index a47fed8a2e1..40f0a4d867d 100644 --- a/dlls/winex11.drv/xvidmode.c +++ b/dlls/winex11.drv/xvidmode.c @@ -189,9 +189,10 @@ 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 ) { - XF86VidModeModeInfo xf86vm_mode; + XF86VidModeModeInfo xf86vm_mode = full_mode->xf86vm; + const DEVMODEW *mode = &full_mode->mode; Bool ret;
if (id.id != 1) @@ -210,9 +211,6 @@ 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) ); - X11DRV_expect_error(gdi_display, XVidModeErrorHandler, NULL); ret = pXF86VidModeSwitchToMode( gdi_display, DefaultScreen(gdi_display), &xf86vm_mode ); if (X11DRV_check_error() || !ret)