From: Zhiyi Zhang Subject: [PATCH v2 2/6] winex11.drv: Support Xinerama display device handler. Message-Id: Date: Tue, 9 Apr 2019 21:16:39 +0800 Signed-off-by: Zhiyi Zhang --- dlls/winex11.drv/xinerama.c | 150 ++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c index 739b139736..d4ccc0373e 100644 --- a/dlls/winex11.drv/xinerama.c +++ b/dlls/winex11.drv/xinerama.c @@ -30,6 +30,8 @@ #include "wine/library.h" #include "x11drv.h" #include "wine/debug.h" +#include "wine/heap.h" +#include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(x11drv); @@ -199,8 +201,146 @@ RECT get_primary_monitor_rect(void) return get_primary()->rcMonitor; } +static BOOL xinerama_get_gpus( struct x11drv_gpu **new_gpus, int *count ) +{ + static const WCHAR wine_gpuW[] = {'W','i','n','e',' ','G','P','U',0}; + struct x11drv_gpu *gpus; + + /* Xinerama has no support for GPU, faking one */ + gpus = heap_calloc( 1, sizeof(*gpus) ); + if (!gpus) + return FALSE; + + strcpyW( gpus[0].name, wine_gpuW ); + + *new_gpus = gpus; + *count = 1; + + return TRUE; +} + +static void xinerama_free_gpus( struct x11drv_gpu *gpus ) +{ + heap_free( gpus ); +} + +static BOOL xinerama_get_adapters( ULONG_PTR gpu_id, struct x11drv_adapter **new_adapters, int *count ) +{ + struct x11drv_adapter *adapters = NULL; + INT index = 0; + INT i, j; + INT primary_index; + BOOL mirrored; + + if (gpu_id) + return FALSE; + + /* Being lazy, actual adapter count maybe less */ + adapters = heap_calloc( nb_monitors, sizeof(*adapters) ); + if (!adapters) + return FALSE; + + primary_index = primary_monitor; + if (primary_index >= nb_monitors) + primary_index = 0; + + for (i = 0; i < nb_monitors; i++) + { + mirrored = FALSE; + for (j = 0; j < i; j++) + { + if (EqualRect( &monitors[i].rcMonitor, &monitors[j].rcMonitor) && !IsRectEmpty( &monitors[j].rcMonitor )) + { + mirrored = TRUE; + break; + } + } + + /* Mirrored monitors share the same adapter */ + if (mirrored) + continue; + + /* Use monitor index as id */ + adapters[index].id = (ULONG_PTR)i; + + if (i == primary_index) + adapters[index].state_flags |= DISPLAY_DEVICE_PRIMARY_DEVICE; + + if (!IsRectEmpty( &monitors[i].rcMonitor )) + adapters[index].state_flags |= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP; + + index++; + } + + /* Primary adapter has to be first */ + if (primary_index) + { + struct x11drv_adapter tmp; + tmp = adapters[primary_index]; + adapters[primary_index] = adapters[0]; + adapters[0] = tmp; + } + + *new_adapters = adapters; + *count = index; + return TRUE; +} + +static void xinerama_free_adapters( struct x11drv_adapter *adapters ) +{ + heap_free( adapters ); +} + +static BOOL xinerama_get_monitors( ULONG_PTR adapter_id, struct x11drv_monitor **new_monitors, int *count ) +{ + static const WCHAR generic_nonpnp_monitorW[] = { + 'G','e','n','e','r','i','c',' ', + 'N','o','n','-','P','n','P',' ','M','o','n','i','t','o','r',0}; + struct x11drv_monitor *monitor; + INT first = (INT)adapter_id; + INT monitor_count = 0; + INT index = 0; + INT i; + + for (i = first; i < nb_monitors; i++) + { + if (i == first || EqualRect( &monitors[i].rcMonitor, &monitors[first].rcMonitor )) + monitor_count++; + } + + monitor = heap_calloc( monitor_count, sizeof(*monitor) ); + if (!monitor) + return FALSE; + + for (i = first; i < nb_monitors; i++) + { + if (i == first || EqualRect( &monitors[i].rcMonitor, &monitors[first].rcMonitor )) + { + strcpyW( monitor[index].name, generic_nonpnp_monitorW ); + monitor[index].rc_monitor = monitors[i].rcMonitor; + monitor[index].rc_work = monitors[i].rcWork; + /* Xinerama only reports monitors already attached */ + monitor[index].state_flags = DISPLAY_DEVICE_ATTACHED; + if (!IsRectEmpty( &monitors[i].rcMonitor )) + monitor[index].state_flags |= DISPLAY_DEVICE_ACTIVE; + + index++; + } + } + + *new_monitors = monitor; + *count = monitor_count; + return TRUE; +} + +static void xinerama_free_monitors( struct x11drv_monitor *monitors ) +{ + heap_free( monitors ); +} + void xinerama_init( unsigned int width, unsigned int height ) { + struct x11drv_display_device_handler handler; MONITORINFOEXW *primary; int i; RECT rect; @@ -234,6 +374,16 @@ void xinerama_init( unsigned int width, unsigned int height ) (monitors[i].dwFlags & MONITORINFOF_PRIMARY) ? " (primary)" : "" ); } + strcpy( handler.name, "Xinerama" ); + handler.priority = 100; + handler.pGetGpus = xinerama_get_gpus; + handler.pGetAdapters = xinerama_get_adapters; + handler.pGetMonitors = xinerama_get_monitors; + handler.pFreeGpus = xinerama_free_gpus; + handler.pFreeAdapters = xinerama_free_adapters; + handler.pFreeMonitors = xinerama_free_monitors; + X11DRV_DisplayDevices_SetHandler( &handler ); + TRACE( "virtual size: %s primary: %s\n", wine_dbgstr_rect(&virtual_screen_rect), wine_dbgstr_rect(&primary->rcMonitor) ); } -- 2.20.1