[PATCH 6/6] winex11.drv: Add a cache for querying XRandR 1.4 current modes.
Zhiyi Zhang
zzhang at codeweavers.com
Tue May 18 04:14:29 CDT 2021
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51047
Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
dlls/winex11.drv/xrandr.c | 124 ++++++++++++++++++++++++++++++++------
1 file changed, 106 insertions(+), 18 deletions(-)
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c
index fa748c2af04..c3af35d8ec3 100644
--- a/dlls/winex11.drv/xrandr.c
+++ b/dlls/winex11.drv/xrandr.c
@@ -324,6 +324,32 @@ static LONG xrandr10_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
#ifdef HAVE_XRRGETPROVIDERRESOURCES
+static struct current_mode
+{
+ ULONG_PTR id;
+ BOOL loaded;
+ DEVMODEW mode;
+} *current_modes;
+static int current_mode_count;
+
+static CRITICAL_SECTION current_modes_section;
+static CRITICAL_SECTION_DEBUG current_modes_critsect_debug =
+{
+ 0, 0, ¤t_modes_section,
+ {¤t_modes_critsect_debug.ProcessLocksList, ¤t_modes_critsect_debug.ProcessLocksList},
+ 0, 0, {(DWORD_PTR)(__FILE__ ": current_modes_section")}
+};
+static CRITICAL_SECTION current_modes_section = {¤t_modes_critsect_debug, -1, 0, 0, 0, 0};
+
+static void xrandr14_invalidate_current_mode_cache(void)
+{
+ EnterCriticalSection( ¤t_modes_section );
+ heap_free( current_modes);
+ current_modes = NULL;
+ current_mode_count = 0;
+ LeaveCriticalSection( ¤t_modes_section );
+}
+
static XRRScreenResources *xrandr_get_screen_resources(void)
{
XRRScreenResources *resources = pXRRGetScreenResourcesCurrent( gdi_display, root_window );
@@ -1115,6 +1141,7 @@ static void xrandr14_free_monitors( struct x11drv_monitor *monitors )
static BOOL xrandr14_device_change_handler( HWND hwnd, XEvent *event )
{
+ xrandr14_invalidate_current_mode_cache();
if (hwnd == GetDesktopWindow() && GetWindowThreadProcessId( hwnd, NULL ) == GetCurrentThreadId())
{
/* Don't send a WM_DISPLAYCHANGE message here because this event may be a result from
@@ -1148,7 +1175,8 @@ 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 )
{
- INT gpu_count, adapter_count, display_count = 0;
+ struct current_mode *tmp_modes, *new_current_modes = NULL;
+ INT gpu_count, adapter_count, new_current_mode_count = 0;
INT gpu_idx, adapter_idx, display_idx;
struct x11drv_adapter *adapters;
struct x11drv_gpu *gpus;
@@ -1159,31 +1187,60 @@ static BOOL xrandr14_get_id( const WCHAR *device_name, ULONG_PTR *id )
if (*end)
return FALSE;
- if (!xrandr14_get_gpus2( &gpus, &gpu_count, FALSE ))
- return FALSE;
-
- for (gpu_idx = 0; gpu_idx < gpu_count; ++gpu_idx)
+ /* Update cache */
+ EnterCriticalSection( ¤t_modes_section );
+ if (!current_modes)
{
- if (!xrandr14_get_adapters( gpus[gpu_idx].id, &adapters, &adapter_count ))
+ if (!xrandr14_get_gpus2( &gpus, &gpu_count, FALSE ))
{
- xrandr14_free_gpus( gpus );
+ LeaveCriticalSection( ¤t_modes_section );
return FALSE;
}
- adapter_idx = display_idx - display_count;
- if (adapter_idx < adapter_count)
+ for (gpu_idx = 0; gpu_idx < gpu_count; ++gpu_idx)
{
- *id = adapters[adapter_idx].id;
- xrandr14_free_adapters( adapters );
- xrandr14_free_gpus( gpus );
- return TRUE;
- }
+ if (!xrandr14_get_adapters( gpus[gpu_idx].id, &adapters, &adapter_count ))
+ break;
- display_count += adapter_count;
- xrandr14_free_adapters( adapters );
+ if (!new_current_modes)
+ tmp_modes = heap_alloc( adapter_count * sizeof(*tmp_modes) );
+ else
+ tmp_modes = heap_realloc( new_current_modes, (new_current_mode_count + adapter_count) * sizeof(*tmp_modes) );
+
+ if (!tmp_modes)
+ {
+ xrandr14_free_adapters( adapters );
+ break;
+ }
+ new_current_modes = tmp_modes;
+
+ for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx)
+ {
+ new_current_modes[new_current_mode_count + adapter_idx].id = adapters[adapter_idx].id;
+ new_current_modes[new_current_mode_count + adapter_idx].loaded = FALSE;
+ }
+ new_current_mode_count += adapter_count;
+ xrandr14_free_adapters( adapters );
+ }
+ xrandr14_free_gpus( gpus );
+
+ if (new_current_modes)
+ {
+ heap_free( current_modes );
+ current_modes = new_current_modes;
+ current_mode_count = new_current_mode_count;
+ }
}
- xrandr14_free_gpus( gpus );
- return FALSE;
+
+ if (display_idx >= current_mode_count)
+ {
+ LeaveCriticalSection( ¤t_modes_section );
+ return FALSE;
+ }
+
+ *id = current_modes[display_idx].id;
+ LeaveCriticalSection( ¤t_modes_section );
+ return TRUE;
}
static void add_xrandr14_mode( DEVMODEW *mode, XRRModeInfo *info, DWORD depth, DWORD frequency,
@@ -1342,6 +1399,21 @@ static BOOL xrandr14_get_current_mode( ULONG_PTR id, DEVMODEW *mode )
RECT primary;
INT mode_idx;
+ EnterCriticalSection( ¤t_modes_section );
+ for (mode_idx = 0; mode_idx < current_mode_count; ++mode_idx)
+ {
+ if (current_modes[mode_idx].id != id)
+ continue;
+
+ if (!current_modes[mode_idx].loaded)
+ break;
+
+ memcpy( mode, ¤t_modes[mode_idx].mode, sizeof(*mode) );
+ LeaveCriticalSection( ¤t_modes_section );
+ return TRUE;
+ }
+ LeaveCriticalSection( ¤t_modes_section );
+
screen_resources = xrandr_get_screen_resources();
if (!screen_resources)
goto done;
@@ -1400,6 +1472,21 @@ static BOOL xrandr14_get_current_mode( ULONG_PTR id, DEVMODEW *mode )
mode->u1.s2.dmPosition.x = crtc_info->x - primary.left;
mode->u1.s2.dmPosition.y = crtc_info->y - primary.top;
ret = TRUE;
+
+ EnterCriticalSection( ¤t_modes_section );
+ for (mode_idx = 0; mode_idx < current_mode_count; ++mode_idx)
+ {
+ if (current_modes[mode_idx].id != id)
+ continue;
+
+ memcpy( ¤t_modes[mode_idx].mode, mode, sizeof(*mode) );
+ current_modes[mode_idx].mode.dmSize = sizeof(*mode);
+ current_modes[mode_idx].mode.dmDriverExtra = 0;
+ current_modes[mode_idx].loaded = TRUE;
+ break;
+ }
+ LeaveCriticalSection( ¤t_modes_section );
+
done:
if (crtc_info)
pXRRFreeCrtcInfo( crtc_info );
@@ -1517,6 +1604,7 @@ done:
if (output_info)
pXRRFreeOutputInfo( output_info );
pXRRFreeScreenResources( screen_resources );
+ xrandr14_invalidate_current_mode_cache();
return ret;
}
--
2.30.2
More information about the wine-devel
mailing list