2 * Wine X11drv Xrandr interface
4 * Copyright 2003 Alexander James Pasadyn
5 * Copyright 2012 Henri Verbeet for CodeWeavers
6 * Copyright 2019 Zhiyi Zhang for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(xrandr
);
32 #ifdef HAVE_XRRGETPROVIDERRESOURCES
33 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
36 #ifdef SONAME_LIBXRANDR
40 #include <X11/extensions/Xrandr.h>
43 #define VK_NO_PROTOTYPES
46 #include "wine/heap.h"
47 #include "wine/unicode.h"
48 #include "wine/vulkan.h"
49 #include "wine/vulkan_driver.h"
51 static void *xrandr_handle
;
53 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
54 MAKE_FUNCPTR(XRRConfigCurrentConfiguration
)
55 MAKE_FUNCPTR(XRRConfigCurrentRate
)
56 MAKE_FUNCPTR(XRRFreeScreenConfigInfo
)
57 MAKE_FUNCPTR(XRRGetScreenInfo
)
58 MAKE_FUNCPTR(XRRQueryExtension
)
59 MAKE_FUNCPTR(XRRQueryVersion
)
60 MAKE_FUNCPTR(XRRRates
)
61 MAKE_FUNCPTR(XRRSetScreenConfig
)
62 MAKE_FUNCPTR(XRRSetScreenConfigAndRate
)
63 MAKE_FUNCPTR(XRRSizes
)
65 #ifdef HAVE_XRRGETPROVIDERRESOURCES
66 MAKE_FUNCPTR(XRRFreeCrtcInfo
)
67 MAKE_FUNCPTR(XRRFreeOutputInfo
)
68 MAKE_FUNCPTR(XRRFreeScreenResources
)
69 MAKE_FUNCPTR(XRRGetCrtcInfo
)
70 MAKE_FUNCPTR(XRRGetOutputInfo
)
71 MAKE_FUNCPTR(XRRGetScreenResources
)
72 MAKE_FUNCPTR(XRRGetScreenResourcesCurrent
)
73 MAKE_FUNCPTR(XRRGetScreenSizeRange
)
74 MAKE_FUNCPTR(XRRSetCrtcConfig
)
75 MAKE_FUNCPTR(XRRSetScreenSize
)
76 MAKE_FUNCPTR(XRRSelectInput
)
77 MAKE_FUNCPTR(XRRGetOutputPrimary
)
78 MAKE_FUNCPTR(XRRGetProviderResources
)
79 MAKE_FUNCPTR(XRRFreeProviderResources
)
80 MAKE_FUNCPTR(XRRGetProviderInfo
)
81 MAKE_FUNCPTR(XRRFreeProviderInfo
)
86 static struct x11drv_mode_info
*dd_modes
;
87 static SizeID
*xrandr10_modes
;
88 static unsigned int xrandr_mode_count
;
89 static int xrandr_current_mode
= -1;
91 static int load_xrandr(void)
95 if (dlopen(SONAME_LIBXRENDER
, RTLD_NOW
|RTLD_GLOBAL
) &&
96 (xrandr_handle
= dlopen(SONAME_LIBXRANDR
, RTLD_NOW
)))
99 #define LOAD_FUNCPTR(f) \
100 if((p##f = dlsym(xrandr_handle, #f)) == NULL) goto sym_not_found
102 LOAD_FUNCPTR(XRRConfigCurrentConfiguration
);
103 LOAD_FUNCPTR(XRRConfigCurrentRate
);
104 LOAD_FUNCPTR(XRRFreeScreenConfigInfo
);
105 LOAD_FUNCPTR(XRRGetScreenInfo
);
106 LOAD_FUNCPTR(XRRQueryExtension
);
107 LOAD_FUNCPTR(XRRQueryVersion
);
108 LOAD_FUNCPTR(XRRRates
);
109 LOAD_FUNCPTR(XRRSetScreenConfig
);
110 LOAD_FUNCPTR(XRRSetScreenConfigAndRate
);
111 LOAD_FUNCPTR(XRRSizes
);
114 #ifdef HAVE_XRRGETPROVIDERRESOURCES
115 LOAD_FUNCPTR(XRRFreeCrtcInfo
);
116 LOAD_FUNCPTR(XRRFreeOutputInfo
);
117 LOAD_FUNCPTR(XRRFreeScreenResources
);
118 LOAD_FUNCPTR(XRRGetCrtcInfo
);
119 LOAD_FUNCPTR(XRRGetOutputInfo
);
120 LOAD_FUNCPTR(XRRGetScreenResources
);
121 LOAD_FUNCPTR(XRRGetScreenResourcesCurrent
);
122 LOAD_FUNCPTR(XRRGetScreenSizeRange
);
123 LOAD_FUNCPTR(XRRSetCrtcConfig
);
124 LOAD_FUNCPTR(XRRSetScreenSize
);
125 LOAD_FUNCPTR(XRRSelectInput
);
126 LOAD_FUNCPTR(XRRGetOutputPrimary
);
127 LOAD_FUNCPTR(XRRGetProviderResources
);
128 LOAD_FUNCPTR(XRRFreeProviderResources
);
129 LOAD_FUNCPTR(XRRGetProviderInfo
);
130 LOAD_FUNCPTR(XRRFreeProviderInfo
);
137 if (!r
) TRACE("Unable to load function ptrs from XRandR library\n");
142 static int XRandRErrorHandler(Display
*dpy
, XErrorEvent
*event
, void *arg
)
147 static int xrandr10_get_current_mode(void)
151 XRRScreenConfiguration
*sc
;
156 if (xrandr_current_mode
!= -1)
157 return xrandr_current_mode
;
159 sc
= pXRRGetScreenInfo (gdi_display
, DefaultRootWindow( gdi_display
));
160 size
= pXRRConfigCurrentConfiguration (sc
, &rot
);
161 rate
= pXRRConfigCurrentRate (sc
);
162 pXRRFreeScreenConfigInfo(sc
);
164 for (i
= 0; i
< xrandr_mode_count
; ++i
)
166 if (xrandr10_modes
[i
] == size
&& dd_modes
[i
].refresh_rate
== rate
)
174 ERR("In unknown mode, returning default\n");
178 xrandr_current_mode
= res
;
182 static LONG
xrandr10_set_current_mode( int mode
)
187 XRRScreenConfiguration
*sc
;
191 root
= DefaultRootWindow( gdi_display
);
192 sc
= pXRRGetScreenInfo (gdi_display
, root
);
193 pXRRConfigCurrentConfiguration (sc
, &rot
);
194 mode
= mode
% xrandr_mode_count
;
196 TRACE("Changing Resolution to %dx%d @%d Hz\n",
197 dd_modes
[mode
].width
,
198 dd_modes
[mode
].height
,
199 dd_modes
[mode
].refresh_rate
);
201 size
= xrandr10_modes
[mode
];
202 rate
= dd_modes
[mode
].refresh_rate
;
205 stat
= pXRRSetScreenConfigAndRate( gdi_display
, sc
, root
, size
, rot
, rate
, CurrentTime
);
207 stat
= pXRRSetScreenConfig( gdi_display
, sc
, root
, size
, rot
, CurrentTime
);
209 pXRRFreeScreenConfigInfo(sc
);
211 if (stat
== RRSetConfigSuccess
)
213 xrandr_current_mode
= mode
;
214 X11DRV_DisplayDevices_Update( TRUE
);
215 return DISP_CHANGE_SUCCESSFUL
;
218 ERR("Resolution change not successful -- perhaps display has changed?\n");
219 return DISP_CHANGE_FAILED
;
222 static void xrandr10_init_modes(void)
224 XRRScreenSize
*sizes
;
226 int i
, j
, nmodes
= 0;
228 sizes
= pXRRSizes( gdi_display
, DefaultScreen(gdi_display
), &sizes_count
);
229 if (sizes_count
<= 0) return;
231 TRACE("XRandR: found %d sizes.\n", sizes_count
);
232 for (i
= 0; i
< sizes_count
; ++i
)
237 rates
= pXRRRates( gdi_display
, DefaultScreen(gdi_display
), i
, &rates_count
);
238 TRACE("- at %d: %dx%d (%d rates):", i
, sizes
[i
].width
, sizes
[i
].height
, rates_count
);
241 nmodes
+= rates_count
;
242 for (j
= 0; j
< rates_count
; ++j
)
246 TRACE(" %d", rates
[j
]);
257 TRACE("XRandR modes: count=%d\n", nmodes
);
259 if (!(xrandr10_modes
= HeapAlloc( GetProcessHeap(), 0, sizeof(*xrandr10_modes
) * nmodes
)))
261 ERR("Failed to allocate xrandr mode info array.\n");
265 dd_modes
= X11DRV_Settings_SetHandlers( "XRandR 1.0",
266 xrandr10_get_current_mode
,
267 xrandr10_set_current_mode
,
270 xrandr_mode_count
= 0;
271 for (i
= 0; i
< sizes_count
; ++i
)
276 rates
= pXRRRates( gdi_display
, DefaultScreen(gdi_display
), i
, &rates_count
);
280 for (j
= 0; j
< rates_count
; ++j
)
282 X11DRV_Settings_AddOneMode( sizes
[i
].width
, sizes
[i
].height
, 0, rates
[j
] );
283 xrandr10_modes
[xrandr_mode_count
++] = i
;
288 X11DRV_Settings_AddOneMode( sizes
[i
].width
, sizes
[i
].height
, 0, 0 );
289 xrandr10_modes
[xrandr_mode_count
++] = i
;
293 X11DRV_Settings_AddDepthModes();
294 nmodes
= X11DRV_Settings_GetModeCount();
296 TRACE("Available DD modes: count=%d\n", nmodes
);
297 TRACE("Enabling XRandR\n");
300 #ifdef HAVE_XRRGETPROVIDERRESOURCES
302 static XRRScreenResources
*xrandr_get_screen_resources(void)
304 XRRScreenResources
*resources
= pXRRGetScreenResourcesCurrent( gdi_display
, root_window
);
305 if (resources
&& !resources
->ncrtc
)
307 pXRRFreeScreenResources( resources
);
308 resources
= pXRRGetScreenResources( gdi_display
, root_window
);
312 ERR("Failed to get screen resources.\n");
316 /* Some (304.64, possibly earlier) versions of the NVIDIA driver only
317 * report a DFP's native mode through RandR 1.2 / 1.3. Standard DMT modes
318 * are only listed through RandR 1.0 / 1.1. This is completely useless,
319 * but NVIDIA considers this a feature, so it's unlikely to change. The
320 * best we can do is to fall back to RandR 1.0 and encourage users to
321 * consider more cooperative driver vendors when we detect such a
323 static BOOL
is_broken_driver(void)
325 XRRScreenResources
*screen_resources
;
326 XRROutputInfo
*output_info
;
327 XRRModeInfo
*first_mode
;
328 INT major
, event
, error
;
329 INT output_idx
, i
, j
;
332 screen_resources
= xrandr_get_screen_resources();
333 if (!screen_resources
)
336 /* Check if any output only has one native mode */
337 for (output_idx
= 0; output_idx
< screen_resources
->noutput
; ++output_idx
)
339 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
,
340 screen_resources
->outputs
[output_idx
] );
344 if (output_info
->connection
!= RR_Connected
)
346 pXRRFreeOutputInfo( output_info
);
351 only_one_mode
= TRUE
;
352 for (i
= 0; i
< output_info
->nmode
; ++i
)
354 for (j
= 0; j
< screen_resources
->nmode
; ++j
)
356 if (output_info
->modes
[i
] != screen_resources
->modes
[j
].id
)
361 first_mode
= &screen_resources
->modes
[j
];
365 if (first_mode
->width
!= screen_resources
->modes
[j
].width
||
366 first_mode
->height
!= screen_resources
->modes
[j
].height
)
367 only_one_mode
= FALSE
;
375 pXRRFreeOutputInfo( output_info
);
380 /* Check if it is NVIDIA proprietary driver */
381 if (XQueryExtension( gdi_display
, "NV-CONTROL", &major
, &event
, &error
))
383 ERR_(winediag
)("Broken NVIDIA RandR detected, falling back to RandR 1.0. "
384 "Please consider using the Nouveau driver instead.\n");
385 pXRRFreeScreenResources( screen_resources
);
389 pXRRFreeScreenResources( screen_resources
);
393 static void get_screen_size( XRRScreenResources
*resources
, unsigned int *width
, unsigned int *height
)
395 int min_width
= 0, min_height
= 0, max_width
, max_height
;
396 XRRCrtcInfo
*crtc_info
;
399 pXRRGetScreenSizeRange( gdi_display
, root_window
, &min_width
, &min_height
, &max_width
, &max_height
);
401 *height
= min_height
;
403 for (i
= 0; i
< resources
->ncrtc
; ++i
)
405 if (!(crtc_info
= pXRRGetCrtcInfo( gdi_display
, resources
, resources
->crtcs
[i
] )))
408 if (crtc_info
->mode
!= None
)
410 *width
= max(*width
, crtc_info
->x
+ crtc_info
->width
);
411 *height
= max(*height
, crtc_info
->y
+ crtc_info
->height
);
414 pXRRFreeCrtcInfo( crtc_info
);
418 static void set_screen_size( int width
, int height
)
420 int screen
= default_visual
.screen
;
421 int mm_width
, mm_height
;
423 mm_width
= width
* DisplayWidthMM( gdi_display
, screen
) / DisplayWidth( gdi_display
, screen
);
424 mm_height
= height
* DisplayHeightMM( gdi_display
, screen
) / DisplayHeight( gdi_display
, screen
);
425 pXRRSetScreenSize( gdi_display
, root_window
, width
, height
, mm_width
, mm_height
);
428 static unsigned int get_frequency( const XRRModeInfo
*mode
)
430 unsigned int dots
= mode
->hTotal
* mode
->vTotal
;
435 if (mode
->modeFlags
& RR_DoubleScan
)
437 if (mode
->modeFlags
& RR_Interlace
)
440 return (mode
->dotClock
+ dots
/ 2) / dots
;
443 static RECT
get_primary_rect( XRRScreenResources
*resources
)
445 XRROutputInfo
*output_info
= NULL
;
446 XRRCrtcInfo
*crtc_info
= NULL
;
447 RROutput primary_output
;
448 RECT primary_rect
= {0};
449 RECT first_rect
= {0};
452 primary_output
= pXRRGetOutputPrimary( gdi_display
, root_window
);
456 output_info
= pXRRGetOutputInfo( gdi_display
, resources
, primary_output
);
457 if (!output_info
|| output_info
->connection
!= RR_Connected
|| !output_info
->crtc
)
460 crtc_info
= pXRRGetCrtcInfo( gdi_display
, resources
, output_info
->crtc
);
461 if (!crtc_info
|| !crtc_info
->mode
)
464 SetRect( &primary_rect
, crtc_info
->x
, crtc_info
->y
, crtc_info
->x
+ crtc_info
->width
, crtc_info
->y
+ crtc_info
->height
);
465 pXRRFreeCrtcInfo( crtc_info
);
466 pXRRFreeOutputInfo( output_info
);
469 /* Fallback when XRandR primary output is a disconnected output.
470 * Try to find a crtc with (x, y) being (0, 0). If it's found then get the primary rect from that crtc,
471 * otherwise use the first active crtc to get the primary rect */
474 pXRRFreeCrtcInfo( crtc_info
);
476 pXRRFreeOutputInfo( output_info
);
478 WARN("Primary is set to a disconnected XRandR output.\n");
479 for (i
= 0; i
< resources
->ncrtc
; ++i
)
481 crtc_info
= pXRRGetCrtcInfo( gdi_display
, resources
, resources
->crtcs
[i
] );
485 if (!crtc_info
->mode
)
487 pXRRFreeCrtcInfo( crtc_info
);
491 if (!crtc_info
->x
&& !crtc_info
->y
)
493 SetRect( &primary_rect
, 0, 0, crtc_info
->width
, crtc_info
->height
);
494 pXRRFreeCrtcInfo( crtc_info
);
498 if (IsRectEmpty( &first_rect
))
499 SetRect( &first_rect
, crtc_info
->x
, crtc_info
->y
,
500 crtc_info
->x
+ crtc_info
->width
, crtc_info
->y
+ crtc_info
->height
);
502 pXRRFreeCrtcInfo( crtc_info
);
505 return IsRectEmpty( &primary_rect
) ? first_rect
: primary_rect
;
508 static BOOL
is_crtc_primary( RECT primary
, const XRRCrtcInfo
*crtc
)
512 crtc
->x
== primary
.left
&&
513 crtc
->y
== primary
.top
&&
514 crtc
->x
+ crtc
->width
== primary
.right
&&
515 crtc
->y
+ crtc
->height
== primary
.bottom
;
518 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR
)
520 static BOOL
get_gpu_properties_from_vulkan( struct x11drv_gpu
*gpu
, const XRRProviderInfo
*provider_info
)
522 static const char *extensions
[] =
524 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
,
525 "VK_EXT_acquire_xlib_display",
526 "VK_EXT_direct_mode_display",
528 const struct vulkan_funcs
*vulkan_funcs
= get_vulkan_driver( WINE_VULKAN_DRIVER_VERSION
);
529 VkResult (*pvkGetRandROutputDisplayEXT
)( VkPhysicalDevice
, Display
*, RROutput
, VkDisplayKHR
* );
530 PFN_vkGetPhysicalDeviceProperties2 pvkGetPhysicalDeviceProperties2
;
531 PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices
;
532 uint32_t device_count
, device_idx
, output_idx
;
533 VkPhysicalDevice
*vk_physical_devices
= NULL
;
534 VkPhysicalDeviceProperties2 properties2
;
535 VkInstanceCreateInfo create_info
;
536 VkPhysicalDeviceIDProperties id
;
537 VkInstance vk_instance
= NULL
;
538 VkDisplayKHR vk_display
;
545 memset( &create_info
, 0, sizeof(create_info
) );
546 create_info
.sType
= VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
;
547 create_info
.enabledExtensionCount
= ARRAY_SIZE(extensions
);
548 create_info
.ppEnabledExtensionNames
= extensions
;
550 vr
= vulkan_funcs
->p_vkCreateInstance( &create_info
, NULL
, &vk_instance
);
551 if (vr
!= VK_SUCCESS
)
553 WARN("Failed to create a Vulkan instance, vr %d.\n", vr
);
557 #define LOAD_VK_FUNC(f) \
558 if (!(p##f = (void *)vulkan_funcs->p_vkGetInstanceProcAddr( vk_instance, #f ))) \
560 WARN("Failed to load " #f ".\n"); \
564 LOAD_VK_FUNC(vkEnumeratePhysicalDevices
)
565 LOAD_VK_FUNC(vkGetPhysicalDeviceProperties2
)
566 LOAD_VK_FUNC(vkGetRandROutputDisplayEXT
)
569 vr
= pvkEnumeratePhysicalDevices( vk_instance
, &device_count
, NULL
);
570 if (vr
!= VK_SUCCESS
|| !device_count
)
572 WARN("No Vulkan device found, vr %d, device_count %d.\n", vr
, device_count
);
576 if (!(vk_physical_devices
= heap_calloc( device_count
, sizeof(*vk_physical_devices
) )))
579 vr
= pvkEnumeratePhysicalDevices( vk_instance
, &device_count
, vk_physical_devices
);
580 if (vr
!= VK_SUCCESS
)
582 WARN("vkEnumeratePhysicalDevices failed, vr %d.\n", vr
);
586 for (device_idx
= 0; device_idx
< device_count
; ++device_idx
)
588 for (output_idx
= 0; output_idx
< provider_info
->noutputs
; ++output_idx
)
590 X11DRV_expect_error( gdi_display
, XRandRErrorHandler
, NULL
);
591 vr
= pvkGetRandROutputDisplayEXT( vk_physical_devices
[device_idx
], gdi_display
,
592 provider_info
->outputs
[output_idx
], &vk_display
);
593 XSync( gdi_display
, FALSE
);
594 if (X11DRV_check_error() || vr
!= VK_SUCCESS
|| vk_display
== VK_NULL_HANDLE
)
597 memset( &id
, 0, sizeof(id
) );
598 id
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES
;
599 properties2
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
;
600 properties2
.pNext
= &id
;
602 pvkGetPhysicalDeviceProperties2( vk_physical_devices
[device_idx
], &properties2
);
603 memcpy( &gpu
->vulkan_uuid
, id
.deviceUUID
, sizeof(id
.deviceUUID
) );
604 /* Ignore Khronos vendor IDs */
605 if (properties2
.properties
.vendorID
< 0x10000)
607 gpu
->vendor_id
= properties2
.properties
.vendorID
;
608 gpu
->device_id
= properties2
.properties
.deviceID
;
610 MultiByteToWideChar( CP_UTF8
, 0, properties2
.properties
.deviceName
, -1, gpu
->name
, ARRAY_SIZE(gpu
->name
) );
617 heap_free( vk_physical_devices
);
619 vulkan_funcs
->p_vkDestroyInstance( vk_instance
, NULL
);
623 /* Get a list of GPUs reported by XRandR 1.4. Set get_properties to FALSE if GPU properties are
624 * not needed to avoid unnecessary querying */
625 static BOOL
xrandr14_get_gpus2( struct x11drv_gpu
**new_gpus
, int *count
, BOOL get_properties
)
627 static const WCHAR wine_adapterW
[] = {'W','i','n','e',' ','A','d','a','p','t','e','r',0};
628 struct x11drv_gpu
*gpus
= NULL
;
629 XRRScreenResources
*screen_resources
= NULL
;
630 XRRProviderResources
*provider_resources
= NULL
;
631 XRRProviderInfo
*provider_info
= NULL
;
632 XRRCrtcInfo
*crtc_info
= NULL
;
633 INT primary_provider
= -1;
638 screen_resources
= xrandr_get_screen_resources();
639 if (!screen_resources
)
642 provider_resources
= pXRRGetProviderResources( gdi_display
, root_window
);
643 if (!provider_resources
)
646 gpus
= heap_calloc( provider_resources
->nproviders
? provider_resources
->nproviders
: 1, sizeof(*gpus
) );
650 /* Some XRandR implementations don't support providers.
651 * In this case, report a fake one to try searching adapters in screen resources */
652 if (!provider_resources
->nproviders
)
654 WARN("XRandR implementation doesn't report any providers, faking one.\n");
655 lstrcpyW( gpus
[0].name
, wine_adapterW
);
662 primary_rect
= get_primary_rect( screen_resources
);
663 for (i
= 0; i
< provider_resources
->nproviders
; ++i
)
665 provider_info
= pXRRGetProviderInfo( gdi_display
, screen_resources
, provider_resources
->providers
[i
] );
669 /* Find primary provider */
670 for (j
= 0; primary_provider
== -1 && j
< provider_info
->ncrtcs
; ++j
)
672 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, provider_info
->crtcs
[j
] );
676 if (is_crtc_primary( primary_rect
, crtc_info
))
678 primary_provider
= i
;
679 pXRRFreeCrtcInfo( crtc_info
);
683 pXRRFreeCrtcInfo( crtc_info
);
686 gpus
[i
].id
= provider_resources
->providers
[i
];
689 if (!get_gpu_properties_from_vulkan( &gpus
[i
], provider_info
))
690 MultiByteToWideChar( CP_UTF8
, 0, provider_info
->name
, -1, gpus
[i
].name
, ARRAY_SIZE(gpus
[i
].name
) );
691 /* FIXME: Add an alternate method of getting PCI IDs, for systems that don't support Vulkan */
693 pXRRFreeProviderInfo( provider_info
);
696 /* Make primary GPU the first */
697 if (primary_provider
> 0)
699 struct x11drv_gpu tmp
= gpus
[0];
700 gpus
[0] = gpus
[primary_provider
];
701 gpus
[primary_provider
] = tmp
;
705 *count
= provider_resources
->nproviders
;
708 if (provider_resources
)
709 pXRRFreeProviderResources( provider_resources
);
710 if (screen_resources
)
711 pXRRFreeScreenResources( screen_resources
);
715 ERR("Failed to get gpus\n");
720 static BOOL
xrandr14_get_gpus( struct x11drv_gpu
**new_gpus
, int *count
)
722 return xrandr14_get_gpus2( new_gpus
, count
, TRUE
);
725 static void xrandr14_free_gpus( struct x11drv_gpu
*gpus
)
730 static BOOL
xrandr14_get_adapters( ULONG_PTR gpu_id
, struct x11drv_adapter
**new_adapters
, int *count
)
732 struct x11drv_adapter
*adapters
= NULL
;
733 XRRScreenResources
*screen_resources
= NULL
;
734 XRRProviderInfo
*provider_info
= NULL
;
735 XRRCrtcInfo
*enum_crtc_info
, *crtc_info
= NULL
;
736 XRROutputInfo
*enum_output_info
, *output_info
= NULL
;
738 INT crtc_count
, output_count
;
739 INT primary_adapter
= 0;
740 INT adapter_count
= 0;
741 BOOL mirrored
, detached
;
746 screen_resources
= xrandr_get_screen_resources();
747 if (!screen_resources
)
752 provider_info
= pXRRGetProviderInfo( gdi_display
, screen_resources
, gpu_id
);
756 crtc_count
= provider_info
->ncrtcs
;
757 output_count
= provider_info
->noutputs
;
758 outputs
= provider_info
->outputs
;
760 /* Fake provider id, search adapters in screen resources */
763 crtc_count
= screen_resources
->ncrtc
;
764 output_count
= screen_resources
->noutput
;
765 outputs
= screen_resources
->outputs
;
768 /* Actual adapter count could be less */
769 adapters
= heap_calloc( crtc_count
, sizeof(*adapters
) );
773 primary_rect
= get_primary_rect( screen_resources
);
774 for (i
= 0; i
< output_count
; ++i
)
776 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, outputs
[i
] );
780 /* Only connected output are considered as monitors */
781 if (output_info
->connection
!= RR_Connected
)
783 pXRRFreeOutputInfo( output_info
);
788 /* Connected output doesn't mean the output is attached to a crtc */
790 if (output_info
->crtc
)
792 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, output_info
->crtc
);
797 if (!output_info
->crtc
|| !crtc_info
->mode
)
800 /* Ignore mirroring output replicas because mirrored monitors are under the same adapter */
804 for (j
= 0; j
< screen_resources
->noutput
; ++j
)
806 enum_output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, screen_resources
->outputs
[j
] );
807 if (!enum_output_info
)
810 if (enum_output_info
->connection
!= RR_Connected
|| !enum_output_info
->crtc
)
812 pXRRFreeOutputInfo( enum_output_info
);
816 enum_crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, enum_output_info
->crtc
);
817 pXRRFreeOutputInfo( enum_output_info
);
821 /* Some outputs may have the same coordinates, aka mirrored. Choose the output with
822 * the lowest value as primary and the rest will then be replicas in a mirroring set */
823 if (crtc_info
->x
== enum_crtc_info
->x
&&
824 crtc_info
->y
== enum_crtc_info
->y
&&
825 crtc_info
->width
== enum_crtc_info
->width
&&
826 crtc_info
->height
== enum_crtc_info
->height
&&
827 outputs
[i
] > screen_resources
->outputs
[j
])
830 pXRRFreeCrtcInfo( enum_crtc_info
);
834 pXRRFreeCrtcInfo( enum_crtc_info
);
838 if (!mirrored
|| detached
)
840 /* Use RROutput as adapter id. The reason of not using RRCrtc is that we need to detect inactive but
841 * attached monitors */
842 adapters
[adapter_count
].id
= outputs
[i
];
844 adapters
[adapter_count
].state_flags
|= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
;
845 if (is_crtc_primary( primary_rect
, crtc_info
))
847 adapters
[adapter_count
].state_flags
|= DISPLAY_DEVICE_PRIMARY_DEVICE
;
848 primary_adapter
= adapter_count
;
854 pXRRFreeOutputInfo( output_info
);
858 pXRRFreeCrtcInfo( crtc_info
);
863 /* Make primary adapter the first */
866 struct x11drv_adapter tmp
= adapters
[0];
867 adapters
[0] = adapters
[primary_adapter
];
868 adapters
[primary_adapter
] = tmp
;
871 *new_adapters
= adapters
;
872 *count
= adapter_count
;
875 if (screen_resources
)
876 pXRRFreeScreenResources( screen_resources
);
878 pXRRFreeProviderInfo( provider_info
);
880 pXRRFreeOutputInfo( output_info
);
882 pXRRFreeCrtcInfo( crtc_info
);
885 heap_free( adapters
);
886 ERR("Failed to get adapters\n");
891 static void xrandr14_free_adapters( struct x11drv_adapter
*adapters
)
893 heap_free( adapters
);
896 static BOOL
xrandr14_get_monitors( ULONG_PTR adapter_id
, struct x11drv_monitor
**new_monitors
, int *count
)
898 static const WCHAR generic_nonpnp_monitorW
[] = {
899 'G','e','n','e','r','i','c',' ',
900 'N','o','n','-','P','n','P',' ','M','o','n','i','t','o','r',0};
901 struct x11drv_monitor
*realloc_monitors
, *monitors
= NULL
;
902 XRRScreenResources
*screen_resources
= NULL
;
903 XRROutputInfo
*output_info
= NULL
, *enum_output_info
= NULL
;
904 XRRCrtcInfo
*crtc_info
= NULL
, *enum_crtc_info
;
905 INT primary_index
= 0, monitor_count
= 0, capacity
;
910 screen_resources
= xrandr_get_screen_resources();
911 if (!screen_resources
)
914 /* First start with a 2 monitors, should be enough for most cases */
916 monitors
= heap_calloc( capacity
, sizeof(*monitors
) );
920 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, adapter_id
);
924 if (output_info
->crtc
)
926 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, output_info
->crtc
);
931 /* Inactive but attached monitor, no need to check for mirrored/replica monitors */
932 if (!output_info
->crtc
|| !crtc_info
->mode
)
934 lstrcpyW( monitors
[monitor_count
].name
, generic_nonpnp_monitorW
);
935 monitors
[monitor_count
].state_flags
= DISPLAY_DEVICE_ATTACHED
;
938 /* Active monitors, need to find other monitors with the same coordinates as mirrored */
941 primary_rect
= get_primary_rect( screen_resources
);
943 for (i
= 0; i
< screen_resources
->noutput
; ++i
)
945 enum_output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, screen_resources
->outputs
[i
] );
946 if (!enum_output_info
)
949 /* Detached outputs don't count */
950 if (enum_output_info
->connection
!= RR_Connected
)
952 pXRRFreeOutputInfo( enum_output_info
);
953 enum_output_info
= NULL
;
957 /* Allocate more space if needed */
958 if (monitor_count
>= capacity
)
961 realloc_monitors
= heap_realloc( monitors
, capacity
* sizeof(*monitors
) );
962 if (!realloc_monitors
)
964 monitors
= realloc_monitors
;
967 if (enum_output_info
->crtc
)
969 enum_crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, enum_output_info
->crtc
);
973 if (enum_crtc_info
->x
== crtc_info
->x
&&
974 enum_crtc_info
->y
== crtc_info
->y
&&
975 enum_crtc_info
->width
== crtc_info
->width
&&
976 enum_crtc_info
->height
== crtc_info
->height
)
978 /* FIXME: Read output EDID property and parse the data to get the correct name */
979 lstrcpyW( monitors
[monitor_count
].name
, generic_nonpnp_monitorW
);
981 SetRect( &monitors
[monitor_count
].rc_monitor
, crtc_info
->x
, crtc_info
->y
,
982 crtc_info
->x
+ crtc_info
->width
, crtc_info
->y
+ crtc_info
->height
);
983 monitors
[monitor_count
].rc_work
= get_work_area( &monitors
[monitor_count
].rc_monitor
);
985 monitors
[monitor_count
].state_flags
= DISPLAY_DEVICE_ATTACHED
;
986 if (!IsRectEmpty( &monitors
[monitor_count
].rc_monitor
))
987 monitors
[monitor_count
].state_flags
|= DISPLAY_DEVICE_ACTIVE
;
989 if (is_crtc_primary( primary_rect
, crtc_info
))
990 primary_index
= monitor_count
;
994 pXRRFreeCrtcInfo( enum_crtc_info
);
997 pXRRFreeOutputInfo( enum_output_info
);
998 enum_output_info
= NULL
;
1001 /* Make sure the first monitor is the primary */
1004 struct x11drv_monitor tmp
= monitors
[0];
1005 monitors
[0] = monitors
[primary_index
];
1006 monitors
[primary_index
] = tmp
;
1009 /* Make sure the primary monitor origin is at (0, 0) */
1010 for (i
= 0; i
< monitor_count
; i
++)
1012 OffsetRect( &monitors
[i
].rc_monitor
, -primary_rect
.left
, -primary_rect
.top
);
1013 OffsetRect( &monitors
[i
].rc_work
, -primary_rect
.left
, -primary_rect
.top
);
1017 *new_monitors
= monitors
;
1018 *count
= monitor_count
;
1021 if (screen_resources
)
1022 pXRRFreeScreenResources( screen_resources
);
1024 pXRRFreeOutputInfo( output_info
);
1026 pXRRFreeCrtcInfo( crtc_info
);
1027 if (enum_output_info
)
1028 pXRRFreeOutputInfo( enum_output_info
);
1031 heap_free( monitors
);
1032 ERR("Failed to get monitors\n");
1037 static void xrandr14_free_monitors( struct x11drv_monitor
*monitors
)
1039 heap_free( monitors
);
1042 static BOOL
xrandr14_device_change_handler( HWND hwnd
, XEvent
*event
)
1044 if (hwnd
== GetDesktopWindow() && GetWindowThreadProcessId( hwnd
, NULL
) == GetCurrentThreadId())
1046 /* Don't send a WM_DISPLAYCHANGE message here because this event may be a result from
1047 * ChangeDisplaySettings(). Otherwise, ChangeDisplaySettings() would send multiple
1048 * WM_DISPLAYCHANGE messages instead of just one */
1049 X11DRV_DisplayDevices_Update( FALSE
);
1054 static void xrandr14_register_event_handlers(void)
1056 Display
*display
= thread_init_display();
1057 int event_base
, error_base
;
1059 if (!pXRRQueryExtension( display
, &event_base
, &error_base
))
1062 pXRRSelectInput( display
, root_window
,
1063 RRCrtcChangeNotifyMask
| RROutputChangeNotifyMask
| RRProviderChangeNotifyMask
);
1064 X11DRV_register_event_handler( event_base
+ RRNotify_CrtcChange
, xrandr14_device_change_handler
,
1065 "XRandR CrtcChange" );
1066 X11DRV_register_event_handler( event_base
+ RRNotify_OutputChange
, xrandr14_device_change_handler
,
1067 "XRandR OutputChange" );
1068 X11DRV_register_event_handler( event_base
+ RRNotify_ProviderChange
, xrandr14_device_change_handler
,
1069 "XRandR ProviderChange" );
1072 /* XRandR 1.4 display settings handler */
1073 static BOOL
xrandr14_get_id( const WCHAR
*device_name
, ULONG_PTR
*id
)
1075 INT gpu_count
, adapter_count
, display_count
= 0;
1076 INT gpu_idx
, adapter_idx
, display_idx
;
1077 struct x11drv_adapter
*adapters
;
1078 struct x11drv_gpu
*gpus
;
1081 /* Parse \\.\DISPLAY%d */
1082 display_idx
= strtolW( device_name
+ 11, &end
, 10 ) - 1;
1086 if (!xrandr14_get_gpus2( &gpus
, &gpu_count
, FALSE
))
1089 for (gpu_idx
= 0; gpu_idx
< gpu_count
; ++gpu_idx
)
1091 if (!xrandr14_get_adapters( gpus
[gpu_idx
].id
, &adapters
, &adapter_count
))
1093 xrandr14_free_gpus( gpus
);
1097 adapter_idx
= display_idx
- display_count
;
1098 if (adapter_idx
< adapter_count
)
1100 *id
= adapters
[adapter_idx
].id
;
1101 xrandr14_free_adapters( adapters
);
1102 xrandr14_free_gpus( gpus
);
1106 display_count
+= adapter_count
;
1107 xrandr14_free_adapters( adapters
);
1109 xrandr14_free_gpus( gpus
);
1113 static void add_xrandr14_mode( DEVMODEW
*mode
, XRRModeInfo
*info
, DWORD depth
, DWORD frequency
)
1115 mode
->dmSize
= sizeof(*mode
);
1116 mode
->dmDriverExtra
= sizeof(RRMode
);
1117 mode
->dmFields
= DM_DISPLAYORIENTATION
| DM_BITSPERPEL
| DM_PELSWIDTH
|
1118 DM_PELSHEIGHT
| DM_DISPLAYFLAGS
;
1121 mode
->dmFields
|= DM_DISPLAYFREQUENCY
;
1122 mode
->dmDisplayFrequency
= frequency
;
1124 mode
->u1
.s2
.dmDisplayOrientation
= DMDO_DEFAULT
;
1125 mode
->dmBitsPerPel
= depth
;
1126 mode
->dmPelsWidth
= info
->width
;
1127 mode
->dmPelsHeight
= info
->height
;
1128 mode
->u2
.dmDisplayFlags
= 0;
1129 memcpy( (BYTE
*)mode
+ sizeof(*mode
), &info
->id
, sizeof(info
->id
) );
1132 static BOOL
xrandr14_get_modes( ULONG_PTR id
, DWORD flags
, DEVMODEW
**new_modes
, UINT
*mode_count
)
1134 XRRScreenResources
*screen_resources
;
1135 XRROutputInfo
*output_info
= NULL
;
1136 RROutput output
= (RROutput
)id
;
1137 UINT depth_idx
, mode_idx
= 0;
1138 XRRModeInfo
*mode_info
;
1139 DEVMODEW
*mode
, *modes
;
1144 screen_resources
= xrandr_get_screen_resources();
1145 if (!screen_resources
)
1148 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, output
);
1152 if (output_info
->connection
!= RR_Connected
)
1160 /* Allocate space for display modes in different color depths.
1161 * Store a RRMode at the end of each DEVMODEW as private driver data */
1162 modes
= heap_calloc( output_info
->nmode
* DEPTH_COUNT
, sizeof(*modes
) + sizeof(RRMode
) );
1166 for (i
= 0; i
< output_info
->nmode
; ++i
)
1168 for (j
= 0; j
< screen_resources
->nmode
; ++j
)
1170 if (output_info
->modes
[i
] != screen_resources
->modes
[j
].id
)
1173 mode_info
= &screen_resources
->modes
[j
];
1174 frequency
= get_frequency( mode_info
);
1176 for (depth_idx
= 0; depth_idx
< DEPTH_COUNT
; ++depth_idx
)
1178 mode
= (DEVMODEW
*)((BYTE
*)modes
+ (sizeof(*modes
) + sizeof(RRMode
)) * mode_idx
);
1179 add_xrandr14_mode( mode
, mode_info
, depths
[depth_idx
], frequency
);
1189 *mode_count
= mode_idx
;
1192 pXRRFreeOutputInfo( output_info
);
1193 if (screen_resources
)
1194 pXRRFreeScreenResources( screen_resources
);
1198 static void xrandr14_free_modes( DEVMODEW
*modes
)
1203 static BOOL
xrandr14_get_current_mode( ULONG_PTR id
, DEVMODEW
*mode
)
1205 XRRScreenResources
*screen_resources
;
1206 XRROutputInfo
*output_info
= NULL
;
1207 RROutput output
= (RROutput
)id
;
1208 XRRModeInfo
*mode_info
= NULL
;
1209 XRRCrtcInfo
*crtc_info
= NULL
;
1214 screen_resources
= xrandr_get_screen_resources();
1215 if (!screen_resources
)
1218 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, output
);
1222 if (output_info
->crtc
)
1224 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, output_info
->crtc
);
1230 if (output_info
->connection
!= RR_Connected
|| !output_info
->crtc
|| !crtc_info
->mode
)
1232 mode
->dmFields
= DM_DISPLAYORIENTATION
| DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
|
1233 DM_DISPLAYFLAGS
| DM_DISPLAYFREQUENCY
| DM_POSITION
;
1234 mode
->u1
.s2
.dmDisplayOrientation
= DMDO_DEFAULT
;
1235 mode
->dmBitsPerPel
= 0;
1236 mode
->dmPelsWidth
= 0;
1237 mode
->dmPelsHeight
= 0;
1238 mode
->u2
.dmDisplayFlags
= 0;
1239 mode
->dmDisplayFrequency
= 0;
1240 mode
->u1
.s2
.dmPosition
.x
= 0;
1241 mode
->u1
.s2
.dmPosition
.y
= 0;
1247 for (mode_idx
= 0; mode_idx
< screen_resources
->nmode
; ++mode_idx
)
1249 if (crtc_info
->mode
== screen_resources
->modes
[mode_idx
].id
)
1251 mode_info
= &screen_resources
->modes
[mode_idx
];
1259 mode
->dmFields
= DM_DISPLAYORIENTATION
| DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
|
1260 DM_DISPLAYFLAGS
| DM_DISPLAYFREQUENCY
| DM_POSITION
;
1261 mode
->u1
.s2
.dmDisplayOrientation
= DMDO_DEFAULT
;
1262 mode
->dmBitsPerPel
= screen_bpp
;
1263 mode
->dmPelsWidth
= mode_info
->width
;
1264 mode
->dmPelsHeight
= mode_info
->height
;
1265 mode
->u2
.dmDisplayFlags
= 0;
1266 mode
->dmDisplayFrequency
= get_frequency( mode_info
);
1267 /* Convert RandR coordinates to virtual screen coordinates */
1268 primary
= get_primary_rect( screen_resources
);
1269 mode
->u1
.s2
.dmPosition
.x
= crtc_info
->x
- primary
.left
;
1270 mode
->u1
.s2
.dmPosition
.y
= crtc_info
->y
- primary
.top
;
1274 pXRRFreeCrtcInfo( crtc_info
);
1276 pXRRFreeOutputInfo( output_info
);
1277 if (screen_resources
)
1278 pXRRFreeScreenResources( screen_resources
);
1282 static LONG
xrandr14_set_current_mode( ULONG_PTR id
, DEVMODEW
*mode
)
1284 unsigned int screen_width
, screen_height
;
1285 RROutput output
= (RROutput
)id
, *outputs
;
1286 XRRScreenResources
*screen_resources
;
1287 XRROutputInfo
*output_info
= NULL
;
1288 XRRCrtcInfo
*crtc_info
= NULL
;
1289 LONG ret
= DISP_CHANGE_FAILED
;
1290 INT crtc_idx
, output_count
;
1296 if (mode
->dmFields
& DM_BITSPERPEL
&& mode
->dmBitsPerPel
!= screen_bpp
)
1297 WARN("Cannot change screen color depth from %ubits to %ubits!\n", screen_bpp
, mode
->dmBitsPerPel
);
1299 screen_resources
= xrandr_get_screen_resources();
1300 if (!screen_resources
)
1303 XGrabServer( gdi_display
);
1305 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, output
);
1306 if (!output_info
|| output_info
->connection
!= RR_Connected
)
1310 if (output_info
->crtc
)
1312 crtc
= output_info
->crtc
;
1314 /* Detached, need to find a free CRTC */
1317 for (crtc_idx
= 0; crtc_idx
< output_info
->ncrtc
; ++crtc_idx
)
1319 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, output_info
->crtcs
[crtc_idx
] );
1323 if (!crtc_info
->noutput
)
1325 crtc
= output_info
->crtcs
[crtc_idx
];
1326 pXRRFreeCrtcInfo( crtc_info
);
1331 pXRRFreeCrtcInfo( crtc_info
);
1335 /* Failed to find a free CRTC */
1336 if (crtc_idx
== output_info
->ncrtc
)
1340 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, crtc
);
1344 assert( mode
->dmDriverExtra
== sizeof(RRMode
) );
1345 memcpy( &rrmode
, (BYTE
*)mode
+ sizeof(*mode
), sizeof(rrmode
) );
1347 if (crtc_info
->noutput
)
1349 outputs
= crtc_info
->outputs
;
1350 output_count
= crtc_info
->noutput
;
1351 rotation
= crtc_info
->rotation
;
1357 rotation
= RR_Rotate_0
;
1360 /* According to the RandR spec, the entire CRTC must fit inside the screen.
1361 * Since we use the union of all enabled CRTCs to determine the necessary
1362 * screen size, this might involve shrinking the screen, so we must disable
1363 * the CRTC in question first. */
1364 status
= pXRRSetCrtcConfig( gdi_display
, screen_resources
, crtc
, CurrentTime
, 0, 0, None
,
1365 RR_Rotate_0
, NULL
, 0 );
1366 if (status
!= RRSetConfigSuccess
)
1369 get_screen_size( screen_resources
, &screen_width
, &screen_height
);
1370 screen_width
= max( screen_width
, crtc_info
->x
+ mode
->dmPelsWidth
);
1371 screen_height
= max( screen_height
, crtc_info
->y
+ mode
->dmPelsHeight
);
1372 set_screen_size( screen_width
, screen_height
);
1374 status
= pXRRSetCrtcConfig( gdi_display
, screen_resources
, crtc
, CurrentTime
,
1375 crtc_info
->x
, crtc_info
->y
, rrmode
, rotation
, outputs
, output_count
);
1376 if (status
== RRSetConfigSuccess
)
1377 ret
= DISP_CHANGE_SUCCESSFUL
;
1380 XUngrabServer( gdi_display
);
1381 XFlush( gdi_display
);
1383 pXRRFreeCrtcInfo( crtc_info
);
1385 pXRRFreeOutputInfo( output_info
);
1386 pXRRFreeScreenResources( screen_resources
);
1392 void X11DRV_XRandR_Init(void)
1394 struct x11drv_display_device_handler display_handler
;
1395 struct x11drv_settings_handler settings_handler
;
1396 int event_base
, error_base
, minor
, ret
;
1400 if (major
) return; /* already initialized? */
1401 if (!usexrandr
) return; /* disabled in config */
1402 if (is_virtual_desktop()) return;
1403 if (!(ret
= load_xrandr())) return; /* can't load the Xrandr library */
1405 /* see if Xrandr is available */
1406 if (!pXRRQueryExtension( gdi_display
, &event_base
, &error_base
)) return;
1407 X11DRV_expect_error( gdi_display
, XRandRErrorHandler
, NULL
);
1408 ok
= pXRRQueryVersion( gdi_display
, &major
, &minor
);
1409 if (X11DRV_check_error() || !ok
) return;
1411 TRACE("Found XRandR %d.%d.\n", major
, minor
);
1413 xrandr10_init_modes();
1415 #ifdef HAVE_XRRGETPROVIDERRESOURCES
1416 if (ret
>= 4 && (major
> 1 || (major
== 1 && minor
>= 4)))
1418 display_handler
.name
= "XRandR 1.4";
1419 display_handler
.priority
= 200;
1420 display_handler
.get_gpus
= xrandr14_get_gpus
;
1421 display_handler
.get_adapters
= xrandr14_get_adapters
;
1422 display_handler
.get_monitors
= xrandr14_get_monitors
;
1423 display_handler
.free_gpus
= xrandr14_free_gpus
;
1424 display_handler
.free_adapters
= xrandr14_free_adapters
;
1425 display_handler
.free_monitors
= xrandr14_free_monitors
;
1426 display_handler
.register_event_handlers
= xrandr14_register_event_handlers
;
1427 X11DRV_DisplayDevices_SetHandler( &display_handler
);
1429 if (is_broken_driver())
1432 settings_handler
.name
= "XRandR 1.4";
1433 settings_handler
.priority
= 300;
1434 settings_handler
.get_id
= xrandr14_get_id
;
1435 settings_handler
.get_modes
= xrandr14_get_modes
;
1436 settings_handler
.free_modes
= xrandr14_free_modes
;
1437 settings_handler
.get_current_mode
= xrandr14_get_current_mode
;
1438 settings_handler
.set_current_mode
= xrandr14_set_current_mode
;
1439 X11DRV_Settings_SetHandler( &settings_handler
);
1444 #else /* SONAME_LIBXRANDR */
1446 void X11DRV_XRandR_Init(void)
1448 TRACE("XRandR support not compiled in.\n");
1451 #endif /* SONAME_LIBXRANDR */