With this series it's now possible to run and pass `user32:monitor` and `user32:sysparams` tests with nulldrv, and so most `user32` tests (except for a few desktop cursor position tests). This still requires some prefix configuration to enable the nulldrv driver, or a change like https://gitlab.winehq.org/rbernon/wine/-/commit/753368ad0ec52f03f8d6e78ca794... to enable it when `DISPLAY` environment variable is unset.
This then shows that some of the user32 tests are failing with winex11 but passing with nulldrv, as in https://gitlab.winehq.org/rbernon/wine/-/commit/6d5f4109a514a0dc266899fcacfa....
-- v8: win32u: Read mode from the registry if GetCurrentDisplaySettings fails. win32u: Write display settings to the registry in apply_display_settings. win32u: Lock display devices while applying display settings. win32u: Use an internal WINE_DM_PRIMARY_DEVICE flag on primary adapter modes. win32u: Force update display cache after NtUserChangeDisplaySettingsEx. win32u: Add a BOOL force parameter to update_display_cache.
From: Rémi Bernon rbernon@codeweavers.com
And call it recursively with force = TRUE instead of calling graphics driver pUpdateDisplayDevices separately. --- dlls/win32u/sysparams.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 1c81dda9dd3..f6ffeaef065 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1552,7 +1552,7 @@ static BOOL update_display_cache_from_registry(void) return ret; }
-static BOOL update_display_cache(void) +static BOOL update_display_cache( BOOL force ) { HWINSTA winstation = NtUserGetProcessWindowStation(); struct device_manager_ctx ctx = {0}; @@ -1569,17 +1569,7 @@ static BOOL update_display_cache(void) return TRUE; }
- user_driver->pUpdateDisplayDevices( &device_manager, FALSE, &ctx ); - release_display_manager_ctx( &ctx ); - - if (update_display_cache_from_registry()) return TRUE; - if (ctx.gpu_count) - { - ERR( "driver reported devices, but we failed to read them\n" ); - return FALSE; - } - - if (!user_driver->pUpdateDisplayDevices( &device_manager, TRUE, &ctx )) + if (!user_driver->pUpdateDisplayDevices( &device_manager, force, &ctx ) && force) { static const DEVMODEW modes[] = { @@ -1618,15 +1608,27 @@ static BOOL update_display_cache(void)
if (!update_display_cache_from_registry()) { - ERR( "failed to read display config\n" ); - return FALSE; + if (force) + { + ERR( "Failed to read display config.\n" ); + return FALSE; + } + + if (ctx.gpu_count) + { + ERR( "Driver reported devices, but we failed to read them.\n" ); + return FALSE; + } + + return update_display_cache( TRUE ); } + return TRUE; }
static BOOL lock_display_devices(void) { - if (!update_display_cache()) return FALSE; + if (!update_display_cache( FALSE )) return FALSE; pthread_mutex_lock( &display_lock ); return TRUE; }
From: Rémi Bernon rbernon@codeweavers.com
This makes sure the driver does not need to call back to win32u when changing display settings, and allows us to lock display devices in apply_display_settings in next patch. --- dlls/win32u/sysparams.c | 3 +++ dlls/winemac.drv/display.c | 4 +--- dlls/winex11.drv/display.c | 2 -- 3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index f6ffeaef065..900c8a92871 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2483,6 +2483,9 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod free( displays ); if (ret) return ret;
+ if (!update_display_cache( TRUE )) + WARN( "Failed to update display cache after mode change.\n" ); + if ((adapter = find_adapter( NULL ))) { DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index e8d26dfd241..9012f54ad3d 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -830,9 +830,7 @@ LONG macdrv_ChangeDisplaySettings(LPDEVMODEW displays, HWND hwnd, DWORD flags, L bpp, mode->dmDisplayFrequency); ret = DISP_CHANGE_BADMODE; } - else if (macdrv_set_display_mode(&macdrv_displays[0], best_display_mode)) - macdrv_init_display_devices(TRUE); - else + else if (!macdrv_set_display_mode(&macdrv_displays[0], best_display_mode)) { WARN("Failed to set display mode\n"); ret = DISP_CHANGE_FAILED; diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 572b81aa491..2a4a34e2c02 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -418,8 +418,6 @@ LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, HWND hwnd, DWORD flags, ret = apply_display_settings( displays, ids, FALSE ); if (ret == DISP_CHANGE_SUCCESSFUL) ret = apply_display_settings( displays, ids, TRUE ); - if (ret == DISP_CHANGE_SUCCESSFUL) - X11DRV_DisplayDevices_Init(TRUE);
done: free( ids );
From: Rémi Bernon rbernon@codeweavers.com
Avoiding NtUserEnumDisplayDevices calls from GetCurrentDisplaySettings or ChangeDisplaySettings, as it requires entering the display device lock again. --- dlls/win32u/sysparams.c | 22 +++++++++++++++++----- dlls/winemac.drv/display.c | 24 +----------------------- dlls/winex11.drv/desktop.c | 8 ++------ dlls/winex11.drv/display.c | 31 ++++--------------------------- dlls/winex11.drv/x11drv.h | 6 +++--- dlls/winex11.drv/xrandr.c | 13 ++++--------- dlls/winex11.drv/xvidmode.c | 9 ++------- include/wine/gdi_driver.h | 3 ++- 8 files changed, 35 insertions(+), 81 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 900c8a92871..1bbbc7cdc32 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -542,6 +542,17 @@ static BOOL adapter_get_registry_settings( const struct adapter *adapter, DEVMOD return ret; }
+static BOOL adapter_get_current_settings( const struct adapter *adapter, DEVMODEW *mode ) +{ + BOOL ret; + + if (adapter->dev.state_flags & DISPLAY_DEVICE_PRIMARY_DEVICE) mode->dmDisplayFlags |= WINE_DM_PRIMARY_DEVICE; + ret = user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, mode ); + mode->dmDisplayFlags &= ~WINE_DM_PRIMARY_DEVICE; + + return ret; +} + static BOOL adapter_set_registry_settings( const struct adapter *adapter, const DEVMODEW *mode ) { HANDLE mutex; @@ -2214,7 +2225,7 @@ static BOOL adapter_get_full_mode( const struct adapter *adapter, const DEVMODEW if (!is_detached_mode( full_mode ) && (!full_mode->dmPelsWidth || !full_mode->dmPelsHeight || !(full_mode->dmFields & DM_POSITION))) { DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; - if (!user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, ¤t_mode )) return FALSE; + if (!adapter_get_current_settings( adapter, ¤t_mode )) return FALSE; if (!full_mode->dmPelsWidth) full_mode->dmPelsWidth = current_mode.dmPelsWidth; if (!full_mode->dmPelsHeight) full_mode->dmPelsHeight = current_mode.dmPelsHeight; if (!(full_mode->dmFields & DM_POSITION)) @@ -2255,10 +2266,11 @@ static DEVMODEW *get_display_settings( const WCHAR *devname, const DEVMODEW *dev else { if (!devname) ret = adapter_get_registry_settings( adapter, mode ); - else ret = user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, mode ); + else ret = adapter_get_current_settings( adapter, mode ); if (!ret) goto done; }
+ if (adapter->dev.state_flags & DISPLAY_DEVICE_PRIMARY_DEVICE) mode->dmDisplayFlags |= WINE_DM_PRIMARY_DEVICE; lstrcpyW( mode->dmDeviceName, adapter->dev.device_name ); mode = NEXT_DEVMODEW(mode); } @@ -2489,7 +2501,7 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod if ((adapter = find_adapter( NULL ))) { DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; - user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, ¤t_mode ); + if (!adapter_get_current_settings( adapter, ¤t_mode )) WARN( "Failed to get primary adapter current display settings.\n" ); adapter_release( adapter );
send_message( NtUserGetDesktopWindow(), WM_DISPLAYCHANGE, current_mode.dmBitsPerPel, @@ -2534,7 +2546,7 @@ static BOOL adapter_enum_display_settings( const struct adapter *adapter, DWORD DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; const DEVMODEW *adapter_mode;
- if (!(flags & EDS_ROTATEDMODE) && !user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, ¤t_mode )) + if (!(flags & EDS_ROTATEDMODE) && !adapter_get_current_settings( adapter, ¤t_mode )) { WARN( "Failed to query current display mode for EDS_ROTATEDMODE flag.\n" ); return FALSE; @@ -2582,7 +2594,7 @@ BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD index, DEVM devmode->dmDriverExtra = 0;
if (index == ENUM_REGISTRY_SETTINGS) ret = adapter_get_registry_settings( adapter, devmode ); - else if (index == ENUM_CURRENT_SETTINGS) ret = user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, devmode ); + else if (index == ENUM_CURRENT_SETTINGS) ret = adapter_get_current_settings( adapter, devmode ); else ret = adapter_enum_display_settings( adapter, index, devmode, flags ); adapter_release( adapter );
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 9012f54ad3d..bb1535f0d9c 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -685,24 +685,6 @@ void check_retina_status(void) } }
-static BOOL get_primary_adapter(WCHAR *name) -{ - DISPLAY_DEVICEW dd; - DWORD i; - - dd.cb = sizeof(dd); - for (i = 0; !NtUserEnumDisplayDevices(NULL, i, &dd, 0); ++i) - { - if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) - { - lstrcpyW(name, dd.DeviceName); - return TRUE; - } - } - - return FALSE; -} - static BOOL is_detached_mode(const DEVMODEW *mode) { return mode->dmFields & DM_POSITION && @@ -771,7 +753,6 @@ static CGDisplayModeRef find_best_display_mode(DEVMODEW *devmode, CFArrayRef dis */ LONG macdrv_ChangeDisplaySettings(LPDEVMODEW displays, HWND hwnd, DWORD flags, LPVOID lpvoid) { - WCHAR primary_adapter[CCHDEVICENAME]; LONG ret = DISP_CHANGE_SUCCESSFUL; DEVMODEW *mode; int bpp; @@ -785,9 +766,6 @@ LONG macdrv_ChangeDisplaySettings(LPDEVMODEW displays, HWND hwnd, DWORD flags, L
init_original_display_mode();
- if (!get_primary_adapter(primary_adapter)) - return DISP_CHANGE_FAILED; - if (macdrv_get_displays(&macdrv_displays, &num_displays)) return DISP_CHANGE_FAILED;
@@ -804,7 +782,7 @@ LONG macdrv_ChangeDisplaySettings(LPDEVMODEW displays, HWND hwnd, DWORD flags, L
for (mode = displays; mode->dmSize && !ret; mode = NEXT_DEVMODEW(mode)) { - if (wcsicmp(primary_adapter, mode->dmDeviceName)) + if (!(mode->dmDisplayFlags & WINE_DM_PRIMARY_DEVICE)) { FIXME("Changing non-primary adapter settings is currently unsupported.\n"); continue; diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index c6a08291f6a..a9b20713ca1 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -123,13 +123,9 @@ BOOL is_virtual_desktop(void) }
/* Virtual desktop display settings handler */ -static BOOL X11DRV_desktop_get_id( const WCHAR *device_name, ULONG_PTR *id ) +static BOOL X11DRV_desktop_get_id( const DEVMODEW *display, ULONG_PTR *id ) { - WCHAR primary_adapter[CCHDEVICENAME]; - - if (!get_primary_adapter( primary_adapter ) || wcsicmp( primary_adapter, device_name )) - return FALSE; - + if (!(display->u2.dmDisplayFlags & WINE_DM_PRIMARY_DEVICE)) return FALSE; *id = 0; return TRUE; } diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 2a4a34e2c02..24c12d253b2 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -66,14 +66,9 @@ void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *new_handle * Default handlers if resolution switching is not enabled * */ -static BOOL nores_get_id(const WCHAR *device_name, ULONG_PTR *id) +static BOOL nores_get_id(const DEVMODEW *display, ULONG_PTR *id) { - WCHAR primary_adapter[CCHDEVICENAME]; - - if (!get_primary_adapter( primary_adapter )) - return FALSE; - - *id = !wcsicmp( device_name, primary_adapter ) ? 1 : 0; + *id = (display->dmDisplayFlags & WINE_DM_PRIMARY_DEVICE) ? 1 : 0; return TRUE; }
@@ -196,24 +191,6 @@ void init_registry_display_settings(void) } }
-BOOL get_primary_adapter(WCHAR *name) -{ - DISPLAY_DEVICEW dd; - DWORD i; - - dd.cb = sizeof(dd); - for (i = 0; !NtUserEnumDisplayDevices( NULL, i, &dd, 0 ); ++i) - { - if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) - { - lstrcpyW(name, dd.DeviceName); - return TRUE; - } - } - - return FALSE; -} - static void set_display_depth(ULONG_PTR display_id, DWORD depth) { struct x11drv_display_depth *display_depth; @@ -271,7 +248,7 @@ BOOL X11DRV_GetCurrentDisplaySettings( LPCWSTR name, LPDEVMODEW devmode ) DEVMODEW mode; ULONG_PTR id;
- if (!settings_handler.get_id( name, &id ) || !settings_handler.get_current_mode( id, &mode )) + if (!settings_handler.get_id( devmode, &id ) || !settings_handler.get_current_mode( id, &mode )) { ERR("Failed to get %s current display settings.\n", wine_dbgstr_w(name)); return FALSE; @@ -409,7 +386,7 @@ LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, HWND hwnd, DWORD flags, if (!(ids = calloc( count, sizeof(*ids) ))) return DISP_CHANGE_FAILED; for (count = 0, mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode), count++) { - if (!settings_handler.get_id( mode->dmDeviceName, ids + count )) goto done; + if (!settings_handler.get_id( mode, ids + count )) goto done; mode->dmPosition.x -= left_most; mode->dmPosition.y -= top_most; } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index f8f8fe3d4d1..523b474d349 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -706,11 +706,12 @@ struct x11drv_settings_handler /* Higher priority can override handlers with a lower priority */ UINT priority;
- /* get_id() will be called to map a device name, e.g., \.\DISPLAY1 to a driver specific id. + /* get_id() will be called to map a display settings to a driver specific id, + * from its device name, e.g., \.\DISPLAY1 and WINE_DM_PRIMARY_DEVICE dmDisplayFlag. * Following functions use this id to identify the device. * * Return FALSE if the device cannot be found and TRUE on success */ - BOOL (*get_id)(const WCHAR *device_name, ULONG_PTR *id); + BOOL (*get_id)(const DEVMODEW *display, ULONG_PTR *id);
/* get_modes() will be called to get a list of supported modes of the device of id in modes * with respect to flags, which could be 0, EDS_RAWMODE or EDS_ROTATEDMODE. If the implementation @@ -751,7 +752,6 @@ extern BOOL is_virtual_desktop(void) DECLSPEC_HIDDEN; extern BOOL is_desktop_fullscreen(void) DECLSPEC_HIDDEN; extern BOOL is_detached_mode(const DEVMODEW *) DECLSPEC_HIDDEN; extern BOOL create_desktop_win_data( Window win ) DECLSPEC_HIDDEN; -extern BOOL get_primary_adapter(WCHAR *) DECLSPEC_HIDDEN; void X11DRV_Settings_Init(void) DECLSPEC_HIDDEN;
void X11DRV_XF86VM_Init(void) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index c7f922b1aae..a0f7329e4ad 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -144,17 +144,12 @@ static int XRandRErrorHandler(Display *dpy, XErrorEvent *event, void *arg) }
/* XRandR 1.0 display settings handler */ -static BOOL xrandr10_get_id( const WCHAR *device_name, ULONG_PTR *id ) +static BOOL xrandr10_get_id( const DEVMODEW *display, ULONG_PTR *id ) { - WCHAR primary_adapter[CCHDEVICENAME]; - - if (!get_primary_adapter( primary_adapter )) - return FALSE; - /* 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 = !wcsicmp( device_name, primary_adapter ) ? 1 : 0; + *id = (display->u2.dmDisplayFlags & WINE_DM_PRIMARY_DEVICE) ? 1 : 0; return TRUE; }
@@ -1224,7 +1219,7 @@ static void xrandr14_register_event_handlers(void) }
/* XRandR 1.4 display settings handler */ -static BOOL xrandr14_get_id( const WCHAR *device_name, ULONG_PTR *id ) +static BOOL xrandr14_get_id( const DEVMODEW *display, ULONG_PTR *id ) { struct current_mode *tmp_modes, *new_current_modes = NULL; INT gpu_count, adapter_count, new_current_mode_count = 0; @@ -1234,7 +1229,7 @@ static BOOL xrandr14_get_id( const WCHAR *device_name, ULONG_PTR *id ) WCHAR *end;
/* Parse \.\DISPLAY%d */ - display_idx = wcstol( device_name + 11, &end, 10 ) - 1; + display_idx = wcstol( display->dmDeviceName + 11, &end, 10 ) - 1; if (*end) return FALSE;
diff --git a/dlls/winex11.drv/xvidmode.c b/dlls/winex11.drv/xvidmode.c index 95342a84223..b804b49d0d6 100644 --- a/dlls/winex11.drv/xvidmode.c +++ b/dlls/winex11.drv/xvidmode.c @@ -85,17 +85,12 @@ static int XVidModeErrorHandler(Display *dpy, XErrorEvent *event, void *arg) }
/* XF86VidMode display settings handler */ -static BOOL xf86vm_get_id(const WCHAR *device_name, ULONG_PTR *id) +static BOOL xf86vm_get_id(const DEVMODEW *display, ULONG_PTR *id) { - WCHAR primary_adapter[CCHDEVICENAME]; - - if (!get_primary_adapter( primary_adapter )) - return FALSE; - /* XVidMode 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 = !wcsicmp( device_name, primary_adapter ) ? 1 : 0; + *id = (display->u2.dmDisplayFlags & WINE_DM_PRIMARY_DEVICE) ? 1 : 0; return TRUE; }
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 596d27156af..5cfe89e6440 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -269,7 +269,8 @@ struct gdi_device_manager void (*add_mode)( const DEVMODEW *mode, void *param ); };
-#define WINE_DM_UNSUPPORTED 0x80000000 +#define WINE_DM_UNSUPPORTED 0x80000000 /* maybe set internally on added / enumerated modes */ +#define WINE_DM_PRIMARY_DEVICE 0x40000000 /* maybe set internally for GetCurrentDisplaySettings / ChangeDisplaySettings */
struct tagUPDATELAYEREDWINDOWINFO;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 1bbbc7cdc32..3e0264a2161 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2252,10 +2252,8 @@ static DEVMODEW *get_display_settings( const WCHAR *devname, const DEVMODEW *dev struct adapter *adapter; BOOL ret;
- if (!lock_display_devices()) return NULL; - /* allocate an extra mode for easier iteration */ - if (!(displays = calloc( list_count( &adapters ) + 1, sizeof(DEVMODEW) ))) goto done; + if (!(displays = calloc( list_count( &adapters ) + 1, sizeof(DEVMODEW) ))) return NULL; mode = displays;
LIST_FOR_EACH_ENTRY( adapter, &adapters, struct adapter, entry ) @@ -2267,7 +2265,11 @@ static DEVMODEW *get_display_settings( const WCHAR *devname, const DEVMODEW *dev { if (!devname) ret = adapter_get_registry_settings( adapter, mode ); else ret = adapter_get_current_settings( adapter, mode ); - if (!ret) goto done; + if (!ret) + { + free( displays ); + return NULL; + } }
if (adapter->dev.state_flags & DISPLAY_DEVICE_PRIMARY_DEVICE) mode->dmDisplayFlags |= WINE_DM_PRIMARY_DEVICE; @@ -2275,13 +2277,7 @@ static DEVMODEW *get_display_settings( const WCHAR *devname, const DEVMODEW *dev mode = NEXT_DEVMODEW(mode); }
- unlock_display_devices(); return displays; - -done: - unlock_display_devices(); - free( displays ); - return NULL; }
static INT offset_length( POINT offset ) @@ -2478,11 +2474,16 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod DEVMODEW *displays; LONG ret;
- displays = get_display_settings( devname, devmode ); - if (!displays) return DISP_CHANGE_FAILED; + if (!lock_display_devices()) return DISP_CHANGE_FAILED; + if (!(displays = get_display_settings( devname, devmode ))) + { + unlock_display_devices(); + return DISP_CHANGE_FAILED; + }
if (all_detached_settings( displays )) { + unlock_display_devices(); WARN( "Detaching all modes is not permitted.\n" ); free( displays ); return DISP_CHANGE_SUCCESSFUL; @@ -2491,6 +2492,7 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod place_all_displays( displays );
ret = user_driver->pChangeDisplaySettings( displays, hwnd, flags, lparam ); + unlock_display_devices();
free( displays ); if (ret) return ret;
From: Rémi Bernon rbernon@codeweavers.com
As a fallback if ChangeDisplaySettings returns E_NOTIMPL. --- dlls/win32u/driver.c | 2 +- dlls/win32u/sysparams.c | 49 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index ee4a6534b50..64e88ab19de 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -756,7 +756,7 @@ static void nulldrv_UpdateClipboard(void) static LONG nulldrv_ChangeDisplaySettings( LPDEVMODEW displays, HWND hwnd, DWORD flags, LPVOID lparam ) { - return DISP_CHANGE_FAILED; + return E_NOTIMPL; }
static BOOL nulldrv_GetCurrentDisplaySettings( LPCWSTR name, LPDEVMODEW mode ) diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 3e0264a2161..41fd2780da3 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -573,6 +573,26 @@ static BOOL adapter_set_registry_settings( const struct adapter *adapter, const return ret; }
+static BOOL adapter_set_current_settings( const struct adapter *adapter, const DEVMODEW *mode ) +{ + HANDLE mutex; + HKEY hkey; + BOOL ret; + + mutex = get_display_device_init_mutex(); + + if (!config_key && !(config_key = reg_open_key( NULL, config_keyW, sizeof(config_keyW) ))) ret = FALSE; + if (!(hkey = reg_open_key( config_key, adapter->config_key, lstrlenW( adapter->config_key ) * sizeof(WCHAR) ))) ret = FALSE; + else + { + ret = write_adapter_mode( hkey, ENUM_CURRENT_SETTINGS, mode ); + NtClose( hkey ); + } + + release_display_device_init_mutex( mutex ); + return ret; +} + static int mode_compare(const void *p1, const void *p2) { BOOL a_interlaced, b_interlaced, a_stretched, b_stretched; @@ -1605,13 +1625,24 @@ static BOOL update_display_cache( BOOL force ) struct gdi_monitor monitor = { .state_flags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED, - .rc_monitor = {.right = modes[2].dmPelsWidth, .bottom = modes[2].dmPelsHeight}, - .rc_work = {.right = modes[2].dmPelsWidth, .bottom = modes[2].dmPelsHeight}, }; + DEVMODEW mode = {{0}}; UINT i;
add_gpu( &gpu, &ctx ); add_adapter( &adapter, &ctx ); + + if (!read_adapter_mode( ctx.adapter_key, ENUM_CURRENT_SETTINGS, &mode )) + { + mode = modes[2]; + mode.dmFields |= DM_POSITION; + write_adapter_mode( ctx.adapter_key, ENUM_CURRENT_SETTINGS, &mode ); + } + monitor.rc_monitor.right = mode.dmPelsWidth; + monitor.rc_monitor.bottom = mode.dmPelsHeight; + monitor.rc_work.right = mode.dmPelsWidth; + monitor.rc_work.bottom = mode.dmPelsHeight; + add_monitor( &monitor, &ctx ); for (i = 0; i < ARRAY_SIZE(modes); ++i) add_mode( modes + i, &ctx ); } @@ -2470,8 +2501,8 @@ static BOOL all_detached_settings( const DEVMODEW *displays ) static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmode, HWND hwnd, DWORD flags, void *lparam ) { + DEVMODEW *mode, *displays; struct adapter *adapter; - DEVMODEW *displays; LONG ret;
if (!lock_display_devices()) return DISP_CHANGE_FAILED; @@ -2491,7 +2522,17 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod
place_all_displays( displays );
- ret = user_driver->pChangeDisplaySettings( displays, hwnd, flags, lparam ); + if ((ret = user_driver->pChangeDisplaySettings( displays, hwnd, flags, lparam )) == E_NOTIMPL) + { + mode = displays; + LIST_FOR_EACH_ENTRY( adapter, &adapters, struct adapter, entry ) + { + if (!adapter_set_current_settings( adapter, mode )) + WARN( "Failed to write adapter %s current mode.\n", debugstr_w(adapter->dev.device_name) ); + mode = NEXT_DEVMODEW(mode); + } + ret = DISP_CHANGE_SUCCESSFUL; + } unlock_display_devices();
free( displays );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 41fd2780da3..107d822d6fb 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -544,12 +544,26 @@ static BOOL adapter_get_registry_settings( const struct adapter *adapter, DEVMOD
static BOOL adapter_get_current_settings( const struct adapter *adapter, DEVMODEW *mode ) { + HANDLE mutex; + HKEY hkey; BOOL ret;
if (adapter->dev.state_flags & DISPLAY_DEVICE_PRIMARY_DEVICE) mode->dmDisplayFlags |= WINE_DM_PRIMARY_DEVICE; ret = user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, mode ); mode->dmDisplayFlags &= ~WINE_DM_PRIMARY_DEVICE; + if (ret) return ret;
+ mutex = get_display_device_init_mutex(); + + if (!config_key && !(config_key = reg_open_key( NULL, config_keyW, sizeof(config_keyW) ))) ret = FALSE; + else if (!(hkey = reg_open_key( config_key, adapter->config_key, lstrlenW( adapter->config_key ) * sizeof(WCHAR) ))) ret = FALSE; + else + { + ret = read_adapter_mode( hkey, ENUM_CURRENT_SETTINGS, mode ); + NtClose( hkey ); + } + + release_display_device_init_mutex( mutex ); return ret; }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=124941
Your paranoid android.
=== debian11 (32 bit report) ===
amstream: amstream.c:7964: Test failed: Got hr 0x88760091. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00401daf).
d3d8: device.c:10863: Test failed: Failed to get display mode. device.c:10865: Test failed: Failed to get display mode. stateblock.c:186: Test failed: CreateAdditionalSwapChain returned 0x8876086c. stateblock.c:186: Test failed: CreateAdditionalSwapChain returned 0x8876086c.
d3d9: d3d9ex.c:4985: Test failed: Failed to get display mode. d3d9ex.c:4987: Test failed: Failed to get display mode. d3d9ex.c:490: Test failed: ScanLineOrdering returned 0. d3d9ex.c:512: Test failed: ScanLineOrdering returned 0. d3d9ex.c:560: Test failed: Failed to retrieve current display mode, retval 0. device.c:14819: Test failed: Failed to get display mode. device.c:14821: Test failed: Failed to get display mode.
d3drm: d3drm.c:3154: Test failed: Cannot get IDirect3DRMDevice interface, hr 0x88760091 Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402ea0).
ddrawex: surface.c:86: Test failed: Unexpected hr 0x88760091. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00401689).
ddraw: ddraw1.c:15397: Test failed: Failed to get display mode. ddraw1.c:15399: Test failed: Failed to get display mode. ddraw1.c:979: Test failed: Device window not found. ddraw1.c:996: Test failed: Device window not found. ddraw1.c:1076: Test failed: Failed to get clip list size, hr 0x80004005. ddraw1.c:1079: Test failed: Failed to get clip list, hr 0x80004005. ddraw1.c:1080: Test failed: Got unexpected structure size 0. ddraw1.c:1081: Test failed: Got unexpected type 0. ddraw1.c:1082: Test failed: Got unexpected count 0. ddraw1.c:1083: Test failed: Got unexpected bounding rect (0,0)-(0,0), expected (14,33)-(646,486). Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x714984ba). ddraw2.c:16349: Test failed: Failed to get display mode. ddraw2.c:16351: Test failed: Failed to get display mode. ddraw2.c:822: Test failed: Device window not found. ddraw2.c:839: Test failed: Device window not found. ddraw2.c:919: Test failed: Failed to get clip list size, hr 0x80004005. ddraw2.c:922: Test failed: Failed to get clip list, hr 0x80004005. ddraw2.c:923: Test failed: Got unexpected structure size 0. ddraw2.c:924: Test failed: Got unexpected type 0. ddraw2.c:925: Test failed: Got unexpected count 0. ddraw2.c:926: Test failed: Got unexpected bounding rect (0,0)-(0,0), expected (14,33)-(646,486). Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x714984ba). ddraw4.c:19412: Test failed: Failed to get display mode. ddraw4.c:19414: Test failed: Failed to get display mode. ddraw4.c:483: Test failed: Failed to create surface, hr 0x88760091. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x0049aba2). ddraw7.c:19525: Test failed: Failed to get display mode. ddraw7.c:19527: Test failed: Failed to get display mode. ddraw7.c:511: Test failed: Failed to create surface, hr 0x88760091. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x004f5f4a).
dxgi: dxgi.c:7637: Test failed: Failed to get display mode. dxgi.c:5634: Test failed: Adapter 0 output 1: EnumDisplaySettingsW failed for L"\\.\DISPLAY2", error 0x578.
evr: evr.c:3352: Test failed: Failed to create default presenter, hr 0x8876086c. Skipping tests.
gdi32: dc.c:266: Test failed: EnumDisplaySettingsExA error 0 dc.c:618: Test failed: EnumDisplaySettingsEx failed
mfplat: mfplat.c:5193: Test failed: D3D11CreateDevice failed: 0x80070057. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x0040189f).
mf: mf.c:3405: Test failed: Unexpected hr 0x8876086c. Unhandled exception: page fault on read access to 0xffffffff in 32-bit code (0x0040cc8d).
quartz: vmr7.c:1501: Test failed: Got hr 0x8876086c. vmr7.c:1503: Test failed: Got hr 0x1. vmr7.c:1505: Test failed: Got hr 0x1. vmr7.c:1511: Test failed: Got hr 0x8876086c for subtype {e436eb7b-524f-11ce-9f53-0020af0ba770}. vmr7.c:1514: Test failed: Got hr 0x1. vmr7.c:1516: Test failed: Got hr 0x1. vmr7.c:1511: Test failed: Got hr 0x8876086c for subtype {e436eb7d-524f-11ce-9f53-0020af0ba770}. vmr7.c:1514: Test failed: Got hr 0x1. vmr7.c:1516: Test failed: Got hr 0x1. vmr7.c:1511: Test failed: Got hr 0x8876086c for subtype {e436eb7e-524f-11ce-9f53-0020af0ba770}. vmr7.c:1514: Test failed: Got hr 0x1. vmr7.c:1516: Test failed: Got hr 0x1. vmr7.c:1511: Test failed: Got hr 0x8876086c for subtype {e436eb8b-524f-11ce-9f53-0020af0ba770}. vmr7.c:1514: Test failed: Got hr 0x1. vmr7.c:1516: Test failed: Got hr 0x1. vmr7.c:1550: Test failed: Got hr 0x8876086c. vmr7.c:1553: Test failed: Got hr 0x80040209. vmr7.c:1554: Test failed: Got peer 00000000. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00487ceb). vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7c-524f-11ce-9f53-0020af0ba770} and bpp 15. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7c-524f-11ce-9f53-0020af0ba770} and bpp 16. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7c-524f-11ce-9f53-0020af0ba770} and bpp 24. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7c-524f-11ce-9f53-0020af0ba770} and bpp 32. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7b-524f-11ce-9f53-0020af0ba770} and bpp 15. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7b-524f-11ce-9f53-0020af0ba770} and bpp 16. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7b-524f-11ce-9f53-0020af0ba770} and bpp 24. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7b-524f-11ce-9f53-0020af0ba770} and bpp 32. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7d-524f-11ce-9f53-0020af0ba770} and bpp 15. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7d-524f-11ce-9f53-0020af0ba770} and bpp 16. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7d-524f-11ce-9f53-0020af0ba770} and bpp 24. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7d-524f-11ce-9f53-0020af0ba770} and bpp 32. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7e-524f-11ce-9f53-0020af0ba770} and bpp 15. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7e-524f-11ce-9f53-0020af0ba770} and bpp 16. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7e-524f-11ce-9f53-0020af0ba770} and bpp 24. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1702: Test failed: Got hr 0x8004022a for subtype {e436eb7e-524f-11ce-9f53-0020af0ba770} and bpp 32. vmr9.c:1706: Test failed: Got hr 0x1. vmr9.c:1708: Test failed: Got hr 0x1. vmr9.c:1741: Test failed: Got hr 0x8004022a. vmr9.c:1744: Test failed: Got hr 0x80040209. vmr9.c:1745: Test failed: Got peer 00000000. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x004a32f0).
user32: monitor.c:344: Test failed: EnumDisplaySettingsA failed, error 0 monitor.c:359: Test failed: EnumDisplaySettingsA failed, error 0 monitor.c:364: Test failed: EnumDisplaySettingsW failed, error 0 monitor.c:369: Test failed: ChangeDisplaySettingsA returned unexpected -2 monitor.c:374: Test failed: ChangeDisplaySettingsW returned unexpected -2 monitor.c:380: Test failed: ChangeDisplaySettingsExA returned unexpected -2 monitor.c:385: Test failed: ChangeDisplaySettingsExW returned unexpected -2 monitor.c:393: Test failed: EnumDisplaySettingsA failed, error 0 monitor.c:407: Test failed: EnumDisplaySettingsW failed, error 0 monitor.c:419: Test failed: ChangeDisplaySettingsW returned unexpected -2 monitor.c:423: Test failed: ChangeDisplaySettingsExW returned unexpected -2 sysparams.c:3159: Test failed: EnumDisplaySettingsA failed, error 0xdeadbeef sysparams.c:3161: Test failed: EnumDisplaySettingsA failed, error 0xdeadbeef sysparams.c:3168: Test failed: EnumDisplaySettingsA failed, error 0xdeadbeef sysparams.c:3169: Test failed: Expect dmSize 124, got 0 sysparams.c:3171: Test failed: Expect dmFields to contain 0x7c00a0, got 0 sysparams.c:3177: Test failed: EnumDisplaySettingsA failed, error 0xdeadbeef sysparams.c:3178: Test failed: Expect dmSize 124, got 156 sysparams.c:3180: Test failed: Expect dmFields to contain 0x7c00a0, got 0 sysparams.c:3185: Test failed: EnumDisplaySettingsW failed, error 0xdeadbeef sysparams.c:3188: Test failed: Expect dmFields to contain 0x7c00a0, got 0 sysparams.c:3194: Test failed: EnumDisplaySettingsW failed, error 0xdeadbeef sysparams.c:3197: Test failed: Expect dmFields to contain 0x7c00a0, got 0 sysparams.c:3216: Test failed: EnumDisplaySettingsExA failed, error 0xdeadbeef sysparams.c:3217: Test succeeded inside todo block: Expect dmSize unchanged, got 40 sysparams.c:3218: Test succeeded inside todo block: Expect dmFields unchanged, got 0 sysparams.c:3223: Test failed: EnumDisplaySettingsExA failed, error 0xdeadbeef sysparams.c:3224: Test succeeded inside todo block: Expect dmSize unchanged, got 41 sysparams.c:3228: Test succeeded inside todo block: Expect dmPelsWidth unwritten sysparams.c:3233: Test failed: EnumDisplaySettingsExW failed, error 0xdeadbeef sysparams.c:3235: Test succeeded inside todo block: Expect dmFields unchanged, got 0 sysparams.c:3240: Test failed: EnumDisplaySettingsExW failed, error 0xdeadbeef sysparams.c:3245: Test succeeded inside todo block: Expect dmPelsWidth unwritten sysparams.c:3254: Test failed: EnumDisplaySettingsExA failed, error 0x578 sysparams.c:3255: Test failed: Expect dmFields to contain 0x7c00a0, got 0 sysparams.c:3257: Test failed: Expect dmBitsPerPel 32, got 0 sysparams.c:3262: Test failed: Screen bpp is 0, NUMCOLORS returned -1 sysparams.c:3105: Test failed: EnumDisplaySettingsA failed, error 0x578 sysparams.c:3107: Test failed: Unexpected dmFields 0. sysparams.c:3112: Test failed: Expect dmPelsWidth 1024, got 0 sysparams.c:3114: Test failed: Expect dmPelsHeight 737, got 0 sysparams.c:3105: Test failed: EnumDisplaySettingsA failed, error 0x578 sysparams.c:3107: Test failed: Unexpected dmFields 0. sysparams.c:3109: Test failed: Expect dmPosition.x 1024, got 0 sysparams.c:3112: Test failed: Expect dmPelsWidth 1024, got 0 sysparams.c:3114: Test failed: Expect dmPelsHeight 737, got 0 sysparams.c:3303: Test failed: Expect dmFields to contain 0x7c0080, got 0x180020 sysparams.c:2460: Test failed: EnumDisplaySettingsW failed, error 0 sysparams.c:2462: Test failed: got dmFields 0 sysparams.c:2463: Test failed: got dmBitsPerPel 0 sysparams.c:2472: Test failed: ChangeDisplaySettingsExW returned -2 sysparams.c:2474: Test failed: WaitForSingleObject returned 0x102 sysparams.c:2475: Test failed: got WM_DISPLAYCHANGE bpp 4294967295 sysparams.c:2520: Test failed: ChangeDisplaySettingsExW returned -2 sysparams.c:2523: Test succeeded inside todo block: WaitForSingleObject returned 0x102 sysparams.c:2525: Test succeeded inside todo block: got WM_DISPLAYCHANGE bpp 4294967295
wmvcore: wmvcore.c:2997: Test failed: Wait timed out.
Report validation errors: amstream:amstream prints too much data (38647 bytes) d3d8:device has no test summary line (early exit of the main process?) d3d8:device has unaccounted for failure messages d3d8:device returned success despite having failures d3d9:d3d9ex has no test summary line (early exit of the main process?) d3d9:d3d9ex has unaccounted for failure messages d3d9:d3d9ex has unaccounted for todo messages d3d9:d3d9ex has unaccounted for skip messages d3d9:d3d9ex returned success despite having failures d3d9:device has no test summary line (early exit of the main process?) d3d9:device has unaccounted for failure messages d3d9:device has unaccounted for todo messages d3d9:device returned success despite having failures ddraw:ddrawmodes has no test summary line (early exit of the main process?) ddraw:visual has no test summary line (early exit of the main process?) dxgi:dxgi has no test summary line (early exit of the main process?) dxgi:dxgi has unaccounted for failure messages dxgi:dxgi has unaccounted for skip messages dxgi:dxgi returned success despite having failures user32:monitor has no test summary line (early exit of the main process?) user32:monitor has unaccounted for failure messages user32:monitor returned success despite having failures
=== debian11 (build log) ===
Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24534. Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24534. Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24534.