Using EnumDisplaySettings() directly to query display depth has a high overhead when using the XRandR 1.0 display device handler on some NVIDIA setups.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51420 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53382
From: Zhiyi Zhang zzhang@codeweavers.com
Using EnumDisplaySettings() directly to query display depth has a high overhead when using the XRandR 1.0 display device handler on some NVIDIA setups.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51420 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53382 --- dlls/win32u/driver.c | 19 +++++++++++++------ dlls/win32u/sysparams.c | 25 +++++++++++++++++++++++++ dlls/win32u/win32u_private.h | 1 + dlls/winemac.drv/display.c | 8 ++++++++ dlls/winemac.drv/gdi.c | 1 + dlls/winemac.drv/macdrv.h | 1 + dlls/winex11.drv/display.c | 10 ++++++++++ dlls/winex11.drv/init.c | 1 + dlls/winex11.drv/x11drv.h | 1 + include/wine/gdi_driver.h | 1 + 10 files changed, 62 insertions(+), 6 deletions(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 557d555d673..e2c9ba04efd 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -207,18 +207,13 @@ static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap ) case BITSPIXEL: { UNICODE_STRING display; - DEVMODEW devmode; DC *dc;
if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY) { dc = get_nulldrv_dc( dev ); - memset( &devmode, 0, sizeof(devmode) ); - devmode.dmSize = sizeof(devmode); RtlInitUnicodeString( &display, dc->display ); - if (NtUserEnumDisplaySettings( &display, ENUM_CURRENT_SETTINGS, &devmode, 0 ) && - (devmode.dmFields & DM_BITSPERPEL) && devmode.dmBitsPerPel) - return devmode.dmBitsPerPel; + return get_display_depth( &display ); } return 32; } @@ -764,6 +759,11 @@ static BOOL nulldrv_GetCurrentDisplaySettings( LPCWSTR name, BOOL is_primary, LP return FALSE; /* use default implementation */ }
+static INT nulldrv_GetDisplayDepth( LPCWSTR name, BOOL is_primary ) +{ + return 32; +} + static BOOL nulldrv_UpdateDisplayDevices( const struct gdi_device_manager *manager, BOOL force, void *param ) { return FALSE; @@ -1077,6 +1077,11 @@ static BOOL loaderdrv_GetCurrentDisplaySettings( LPCWSTR name, BOOL is_primary, return load_driver()->pGetCurrentDisplaySettings( name, is_primary, mode ); }
+static INT loaderdrv_GetDisplayDepth( LPCWSTR name, BOOL is_primary ) +{ + return load_driver()->pGetDisplayDepth( name, is_primary ); +} + static void loaderdrv_SetCursor( HCURSOR cursor ) { load_driver()->pSetCursor( cursor ); @@ -1179,6 +1184,7 @@ static const struct user_driver_funcs lazy_load_driver = /* display modes */ loaderdrv_ChangeDisplaySettings, loaderdrv_GetCurrentDisplaySettings, + loaderdrv_GetDisplayDepth, loaderdrv_UpdateDisplayDevices, /* windowing functions */ loaderdrv_CreateDesktopWindow, @@ -1254,6 +1260,7 @@ void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version SET_USER_FUNC(UpdateClipboard); SET_USER_FUNC(ChangeDisplaySettings); SET_USER_FUNC(GetCurrentDisplaySettings); + SET_USER_FUNC(GetDisplayDepth); SET_USER_FUNC(UpdateDisplayDevices); SET_USER_FUNC(CreateDesktopWindow); SET_USER_FUNC(CreateWindow); diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 13aaaa308c9..2269193b7ff 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2655,6 +2655,31 @@ static unsigned int active_monitor_count(void) return count; }
+INT get_display_depth( UNICODE_STRING *name ) +{ + struct display_device *device; + INT depth; + + if (!lock_display_devices()) + return 32; + + if (name && name->Length) + device = find_adapter_device_by_name( name ); + else + device = find_adapter_device_by_id( 0 ); /* use primary adapter */ + + if (!device) + { + unlock_display_devices(); + return 32; + } + + depth = user_driver->pGetDisplayDepth( device->device_name, + !!(device->state_flags & DISPLAY_DEVICE_PRIMARY_DEVICE) ); + unlock_display_devices(); + return depth; +} + /*********************************************************************** * NtUserEnumDisplayMonitors (win32u.@) */ diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index dfa83daba91..96b1b7647fe 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -334,6 +334,7 @@ extern BOOL enable_thunk_lock DECLSPEC_HIDDEN; extern HBRUSH get_55aa_brush(void) DECLSPEC_HIDDEN; extern DWORD get_dialog_base_units(void) DECLSPEC_HIDDEN; extern LONG get_char_dimensions( HDC hdc, TEXTMETRICW *metric, int *height ) DECLSPEC_HIDDEN; +extern INT get_display_depth( UNICODE_STRING *name ) DECLSPEC_HIDDEN; extern RECT get_display_rect( const WCHAR *display ) DECLSPEC_HIDDEN; extern UINT get_monitor_dpi( HMONITOR monitor ) DECLSPEC_HIDDEN; extern BOOL get_monitor_info( HMONITOR handle, MONITORINFO *info ) DECLSPEC_HIDDEN; diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 12e12d297d9..dab81cc8ffb 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -927,6 +927,14 @@ BOOL macdrv_GetCurrentDisplaySettings(LPCWSTR devname, BOOL is_primary, LPDEVMOD return TRUE; }
+/*********************************************************************** + * GetDisplayDepth (MACDRV.@) + * + */ +INT macdrv_GetDisplayDepth(LPCWSTR name, BOOL is_primary) +{ + return get_default_bpp(); +}
/*********************************************************************** * GetDeviceGammaRamp (MACDRV.@) diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c index 193a3f4bbd2..fd1da722061 100644 --- a/dlls/winemac.drv/gdi.c +++ b/dlls/winemac.drv/gdi.c @@ -276,6 +276,7 @@ static const struct user_driver_funcs macdrv_funcs = .pDestroyCursorIcon = macdrv_DestroyCursorIcon, .pDestroyWindow = macdrv_DestroyWindow, .pGetCurrentDisplaySettings = macdrv_GetCurrentDisplaySettings, + .pGetDisplayDepth = macdrv_GetDisplayDepth, .pUpdateDisplayDevices = macdrv_UpdateDisplayDevices, .pGetCursorPos = macdrv_GetCursorPos, .pGetKeyboardLayoutList = macdrv_GetKeyboardLayoutList, diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index f6f9e5b6c67..40f70e55094 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -124,6 +124,7 @@ extern BOOL macdrv_ActivateKeyboardLayout(HKL hkl, UINT flags) DECLSPEC_HIDDEN; extern void macdrv_Beep(void) DECLSPEC_HIDDEN; extern LONG macdrv_ChangeDisplaySettings(LPDEVMODEW displays, LPCWSTR primary_name, HWND hwnd, DWORD flags, LPVOID lpvoid) DECLSPEC_HIDDEN; extern BOOL macdrv_GetCurrentDisplaySettings(LPCWSTR name, BOOL is_primary, LPDEVMODEW devmode) DECLSPEC_HIDDEN; +extern INT macdrv_GetDisplayDepth(LPCWSTR name, BOOL is_primary) DECLSPEC_HIDDEN; extern LRESULT macdrv_ClipboardWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) DECLSPEC_HIDDEN; extern BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manager, BOOL force, void *param ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 5e8305432a0..34085c49543 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -239,6 +239,16 @@ static DWORD get_display_depth(ULONG_PTR display_id) return screen_bpp; }
+INT X11DRV_GetDisplayDepth(LPCWSTR name, BOOL is_primary) +{ + ULONG_PTR id; + + if (settings_handler.get_id( name, is_primary, &id )) + return get_display_depth( id ); + + return screen_bpp; +} + /*********************************************************************** * GetCurrentDisplaySettings (X11DRV.@) * diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 4ebe3a16367..7e343591413 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -405,6 +405,7 @@ static const struct user_driver_funcs x11drv_funcs = .pClipCursor = X11DRV_ClipCursor, .pChangeDisplaySettings = X11DRV_ChangeDisplaySettings, .pGetCurrentDisplaySettings = X11DRV_GetCurrentDisplaySettings, + .pGetDisplayDepth = X11DRV_GetDisplayDepth, .pUpdateDisplayDevices = X11DRV_UpdateDisplayDevices, .pCreateDesktopWindow = X11DRV_CreateDesktopWindow, .pCreateWindow = X11DRV_CreateWindow, diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index b394795a326..4997367ce9a 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -216,6 +216,7 @@ extern BOOL X11DRV_GetCursorPos( LPPOINT pos ) DECLSPEC_HIDDEN; extern BOOL X11DRV_ClipCursor( LPCRECT clip ) DECLSPEC_HIDDEN; extern LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, LPCWSTR primary_name, HWND hwnd, DWORD flags, LPVOID lpvoid ) DECLSPEC_HIDDEN; extern BOOL X11DRV_GetCurrentDisplaySettings( LPCWSTR name, BOOL is_primary, LPDEVMODEW devmode ) DECLSPEC_HIDDEN; +extern INT X11DRV_GetDisplayDepth( LPCWSTR name, BOOL is_primary ) DECLSPEC_HIDDEN; extern BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manager, BOOL force, void *param ) DECLSPEC_HIDDEN; extern BOOL X11DRV_CreateDesktopWindow( HWND hwnd ) DECLSPEC_HIDDEN; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index d074c09cceb..3db3d0d6af3 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -299,6 +299,7 @@ struct user_driver_funcs /* display modes */ LONG (*pChangeDisplaySettings)(LPDEVMODEW,LPCWSTR,HWND,DWORD,LPVOID); BOOL (*pGetCurrentDisplaySettings)(LPCWSTR,BOOL,LPDEVMODEW); + INT (*pGetDisplayDepth)(LPCWSTR,BOOL); BOOL (*pUpdateDisplayDevices)(const struct gdi_device_manager *,BOOL,void*); /* windowing functions */ BOOL (*pCreateDesktopWindow)(HWND);
While I guess this is ok, did we try caching the current display mode as suggested by @hverbeet in https://bugs.winehq.org/show_bug.cgi?id=51420#c44 ?
On Wed Jan 4 08:10:29 2023 +0000, Huw Davies wrote:
While I guess this is ok, did we try caching the current display mode as suggested by @hverbeet in https://bugs.winehq.org/show_bug.cgi?id=51420#c44 ?
Well, for RandR 1.4 the display mode is already cached. For RandR 1.0, there are no device change notifications. So for the NVIDIA devices falling back to RandR 1.0 we need to use RandR 1.0 display device handlers and meanwhile, RandR 1.4 device change notifications, which seems a bit messy. Using a separate GetDisplayDepth() helper avoids using RandR at all and has a much lower overhead. So it's not necessary to cache the current mode for RandR 1.0 in this case. It could be beneficial in other cases, but it's not in the scope of this bug fix.
This merge request was approved by Huw Davies.