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
31 #ifdef HAVE_X11_EXTENSIONS_XRANDR_H
32 #include <X11/extensions/Xrandr.h>
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(xrandr
);
39 #ifdef HAVE_XRRGETPROVIDERRESOURCES
40 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
43 #ifdef SONAME_LIBXRANDR
45 #define VK_NO_PROTOTYPES
48 #include "wine/vulkan.h"
49 #include "wine/vulkan_driver.h"
51 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR
)
53 static void *xrandr_handle
;
55 static VkInstance vk_instance
; /* Vulkan instance for XRandR functions */
56 static VkResult (*p_vkGetRandROutputDisplayEXT
)( VkPhysicalDevice
, Display
*, RROutput
, VkDisplayKHR
* );
57 static PFN_vkGetPhysicalDeviceProperties2KHR p_vkGetPhysicalDeviceProperties2KHR
;
58 static PFN_vkEnumeratePhysicalDevices p_vkEnumeratePhysicalDevices
;
60 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
61 MAKE_FUNCPTR(XRRConfigCurrentConfiguration
)
62 MAKE_FUNCPTR(XRRConfigCurrentRate
)
63 MAKE_FUNCPTR(XRRFreeScreenConfigInfo
)
64 MAKE_FUNCPTR(XRRGetScreenInfo
)
65 MAKE_FUNCPTR(XRRQueryExtension
)
66 MAKE_FUNCPTR(XRRQueryVersion
)
67 MAKE_FUNCPTR(XRRRates
)
68 MAKE_FUNCPTR(XRRSetScreenConfig
)
69 MAKE_FUNCPTR(XRRSetScreenConfigAndRate
)
70 MAKE_FUNCPTR(XRRSizes
)
72 #ifdef HAVE_XRRGETPROVIDERRESOURCES
73 MAKE_FUNCPTR(XRRFreeCrtcInfo
)
74 MAKE_FUNCPTR(XRRFreeOutputInfo
)
75 MAKE_FUNCPTR(XRRFreeScreenResources
)
76 MAKE_FUNCPTR(XRRGetCrtcInfo
)
77 MAKE_FUNCPTR(XRRGetOutputInfo
)
78 MAKE_FUNCPTR(XRRGetOutputProperty
)
79 MAKE_FUNCPTR(XRRGetScreenResources
)
80 MAKE_FUNCPTR(XRRGetScreenResourcesCurrent
)
81 MAKE_FUNCPTR(XRRGetScreenSizeRange
)
82 MAKE_FUNCPTR(XRRSetCrtcConfig
)
83 MAKE_FUNCPTR(XRRSetScreenSize
)
84 MAKE_FUNCPTR(XRRSelectInput
)
85 MAKE_FUNCPTR(XRRGetOutputPrimary
)
86 MAKE_FUNCPTR(XRRGetProviderResources
)
87 MAKE_FUNCPTR(XRRFreeProviderResources
)
88 MAKE_FUNCPTR(XRRGetProviderInfo
)
89 MAKE_FUNCPTR(XRRFreeProviderInfo
)
94 static int load_xrandr(void)
98 if (dlopen(SONAME_LIBXRENDER
, RTLD_NOW
|RTLD_GLOBAL
) &&
99 (xrandr_handle
= dlopen(SONAME_LIBXRANDR
, RTLD_NOW
)))
102 #define LOAD_FUNCPTR(f) \
103 if((p##f = dlsym(xrandr_handle, #f)) == NULL) goto sym_not_found
105 LOAD_FUNCPTR(XRRConfigCurrentConfiguration
);
106 LOAD_FUNCPTR(XRRConfigCurrentRate
);
107 LOAD_FUNCPTR(XRRFreeScreenConfigInfo
);
108 LOAD_FUNCPTR(XRRGetScreenInfo
);
109 LOAD_FUNCPTR(XRRQueryExtension
);
110 LOAD_FUNCPTR(XRRQueryVersion
);
111 LOAD_FUNCPTR(XRRRates
);
112 LOAD_FUNCPTR(XRRSetScreenConfig
);
113 LOAD_FUNCPTR(XRRSetScreenConfigAndRate
);
114 LOAD_FUNCPTR(XRRSizes
);
117 #ifdef HAVE_XRRGETPROVIDERRESOURCES
118 LOAD_FUNCPTR(XRRFreeCrtcInfo
);
119 LOAD_FUNCPTR(XRRFreeOutputInfo
);
120 LOAD_FUNCPTR(XRRFreeScreenResources
);
121 LOAD_FUNCPTR(XRRGetCrtcInfo
);
122 LOAD_FUNCPTR(XRRGetOutputInfo
);
123 LOAD_FUNCPTR(XRRGetOutputProperty
);
124 LOAD_FUNCPTR(XRRGetScreenResources
);
125 LOAD_FUNCPTR(XRRGetScreenResourcesCurrent
);
126 LOAD_FUNCPTR(XRRGetScreenSizeRange
);
127 LOAD_FUNCPTR(XRRSetCrtcConfig
);
128 LOAD_FUNCPTR(XRRSetScreenSize
);
129 LOAD_FUNCPTR(XRRSelectInput
);
130 LOAD_FUNCPTR(XRRGetOutputPrimary
);
131 LOAD_FUNCPTR(XRRGetProviderResources
);
132 LOAD_FUNCPTR(XRRFreeProviderResources
);
133 LOAD_FUNCPTR(XRRGetProviderInfo
);
134 LOAD_FUNCPTR(XRRFreeProviderInfo
);
141 if (!r
) TRACE("Unable to load function ptrs from XRandR library\n");
146 #ifdef SONAME_LIBVULKAN
148 static void *vulkan_handle
;
149 static void *(*p_vkGetInstanceProcAddr
)(VkInstance
, const char *);
151 static void vulkan_init_once(void)
153 static const char *extensions
[] =
155 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
,
156 VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME
,
157 "VK_EXT_acquire_xlib_display",
158 "VK_EXT_direct_mode_display",
160 VK_KHR_SURFACE_EXTENSION_NAME
,
162 VkInstanceCreateInfo create_info
=
164 .sType
= VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
,
165 .ppEnabledExtensionNames
= extensions
,
166 .enabledExtensionCount
= ARRAY_SIZE(extensions
),
169 PFN_vkDestroyInstance p_vkDestroyInstance
;
170 PFN_vkCreateInstance p_vkCreateInstance
;
173 if (!(vulkan_handle
= dlopen( SONAME_LIBVULKAN
, RTLD_NOW
)))
175 ERR( "Failed to load %s\n", SONAME_LIBVULKAN
);
179 #define LOAD_FUNCPTR( f ) \
180 if (!(p_##f = dlsym( vulkan_handle, #f ))) \
182 ERR( "Failed to find " #f "\n" ); \
183 dlclose( vulkan_handle ); \
187 LOAD_FUNCPTR( vkGetInstanceProcAddr
);
190 p_vkCreateInstance
= p_vkGetInstanceProcAddr( NULL
, "vkCreateInstance" );
191 if ((vr
= p_vkCreateInstance( &create_info
, NULL
, &vk_instance
)))
193 WARN( "Failed to create a Vulkan instance, vr %d.\n", vr
);
197 p_vkDestroyInstance
= p_vkGetInstanceProcAddr( vk_instance
, "vkDestroyInstance" );
198 #define LOAD_VK_FUNC(f) \
199 if (!(p_##f = (void *)p_vkGetInstanceProcAddr( vk_instance, #f ))) \
201 WARN("Failed to load " #f ".\n"); \
202 p_vkDestroyInstance( vk_instance, NULL ); \
203 vk_instance = NULL; \
207 LOAD_VK_FUNC( vkEnumeratePhysicalDevices
)
208 LOAD_VK_FUNC( vkGetPhysicalDeviceProperties2KHR
)
209 LOAD_VK_FUNC( vkGetRandROutputDisplayEXT
)
213 #else /* SONAME_LIBVULKAN */
215 static void vulkan_init_once(void)
217 ERR( "Wine was built without Vulkan support.\n" );
220 #endif /* SONAME_LIBVULKAN */
222 static BOOL
vulkan_init(void)
224 static pthread_once_t init_once
= PTHREAD_ONCE_INIT
;
225 pthread_once( &init_once
, vulkan_init_once
);
226 return !!vk_instance
;
229 static int XRandRErrorHandler(Display
*dpy
, XErrorEvent
*event
, void *arg
)
234 /* XRandR 1.0 display settings handler */
235 static BOOL
xrandr10_get_id( const WCHAR
*device_name
, BOOL is_primary
, x11drv_settings_id
*id
)
237 /* RandR 1.0 only supports changing the primary adapter settings.
238 * For non-primary adapters, an id is still provided but getting
239 * and changing non-primary adapters' settings will be ignored. */
240 id
->id
= is_primary
? 1 : 0;
244 static void add_xrandr10_mode( DEVMODEW
*mode
, DWORD depth
, DWORD width
, DWORD height
,
245 DWORD frequency
, SizeID size_id
, BOOL full
)
247 mode
->dmSize
= sizeof(*mode
);
248 mode
->dmDriverExtra
= full
? sizeof(SizeID
) : 0;
249 mode
->dmFields
= DM_DISPLAYORIENTATION
| DM_BITSPERPEL
| DM_PELSWIDTH
|
250 DM_PELSHEIGHT
| DM_DISPLAYFLAGS
;
253 mode
->dmFields
|= DM_DISPLAYFREQUENCY
;
254 mode
->dmDisplayFrequency
= frequency
;
256 mode
->dmDisplayOrientation
= DMDO_DEFAULT
;
257 mode
->dmBitsPerPel
= depth
;
258 mode
->dmPelsWidth
= width
;
259 mode
->dmPelsHeight
= height
;
260 mode
->dmDisplayFlags
= 0;
261 if (full
) memcpy( mode
+ 1, &size_id
, sizeof(size_id
) );
264 static BOOL
xrandr10_get_modes( x11drv_settings_id id
, DWORD flags
, DEVMODEW
**new_modes
, UINT
*new_mode_count
, BOOL full
)
266 INT size_idx
, depth_idx
, rate_idx
, mode_idx
= 0;
267 INT size_count
, rate_count
, mode_count
= 0;
268 DEVMODEW
*modes
, *mode
;
269 XRRScreenSize
*sizes
;
272 sizes
= pXRRSizes( gdi_display
, DefaultScreen( gdi_display
), &size_count
);
276 for (size_idx
= 0; size_idx
< size_count
; ++size_idx
)
278 rates
= pXRRRates( gdi_display
, DefaultScreen( gdi_display
), size_idx
, &rate_count
);
280 mode_count
+= rate_count
;
285 /* Allocate space for reported modes in three depths, and put an SizeID at the end of DEVMODEW as
286 * driver private data */
287 modes
= calloc( mode_count
* DEPTH_COUNT
, sizeof(*modes
) + sizeof(SizeID
) );
290 RtlSetLastWin32Error( ERROR_NOT_ENOUGH_MEMORY
);
294 for (size_idx
= 0, mode
= modes
; size_idx
< size_count
; ++size_idx
)
296 for (depth_idx
= 0; depth_idx
< DEPTH_COUNT
; ++depth_idx
)
298 rates
= pXRRRates( gdi_display
, DefaultScreen( gdi_display
), size_idx
, &rate_count
);
301 add_xrandr10_mode( mode
, depths
[depth_idx
], sizes
[size_idx
].width
,
302 sizes
[size_idx
].height
, 0, size_idx
, full
);
303 mode
= NEXT_DEVMODEW( mode
);
308 for (rate_idx
= 0; rate_idx
< rate_count
; ++rate_idx
)
310 add_xrandr10_mode( mode
, depths
[depth_idx
], sizes
[size_idx
].width
,
311 sizes
[size_idx
].height
, rates
[rate_idx
], size_idx
, full
);
312 mode
= NEXT_DEVMODEW( mode
);
319 *new_mode_count
= mode_idx
;
323 static void xrandr10_free_modes( DEVMODEW
*modes
)
328 static BOOL
xrandr10_get_current_mode( x11drv_settings_id id
, DEVMODEW
*mode
)
330 XRRScreenConfiguration
*screen_config
;
331 XRRScreenSize
*sizes
;
337 mode
->dmFields
= DM_DISPLAYORIENTATION
| DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
|
338 DM_DISPLAYFLAGS
| DM_DISPLAYFREQUENCY
| DM_POSITION
;
339 mode
->dmDisplayOrientation
= DMDO_DEFAULT
;
340 mode
->dmDisplayFlags
= 0;
341 mode
->dmPosition
.x
= 0;
342 mode
->dmPosition
.y
= 0;
346 FIXME("Non-primary adapters are unsupported.\n");
347 mode
->dmBitsPerPel
= 0;
348 mode
->dmPelsWidth
= 0;
349 mode
->dmPelsHeight
= 0;
350 mode
->dmDisplayFrequency
= 0;
354 sizes
= pXRRSizes( gdi_display
, DefaultScreen( gdi_display
), &size_count
);
358 screen_config
= pXRRGetScreenInfo( gdi_display
, DefaultRootWindow( gdi_display
) );
359 size_id
= pXRRConfigCurrentConfiguration( screen_config
, &rotation
);
360 rate
= pXRRConfigCurrentRate( screen_config
);
361 pXRRFreeScreenConfigInfo( screen_config
);
363 mode
->dmBitsPerPel
= screen_bpp
;
364 mode
->dmPelsWidth
= sizes
[size_id
].width
;
365 mode
->dmPelsHeight
= sizes
[size_id
].height
;
366 mode
->dmDisplayFrequency
= rate
;
370 static LONG
xrandr10_set_current_mode( x11drv_settings_id id
, const DEVMODEW
*mode
)
372 XRRScreenConfiguration
*screen_config
;
380 FIXME("Non-primary adapters are unsupported.\n");
381 return DISP_CHANGE_SUCCESSFUL
;
384 if (is_detached_mode(mode
))
386 FIXME("Detaching adapters is unsupported.\n");
387 return DISP_CHANGE_SUCCESSFUL
;
390 if (mode
->dmFields
& DM_BITSPERPEL
&& mode
->dmBitsPerPel
!= screen_bpp
)
391 WARN("Cannot change screen bit depth from %dbits to %dbits!\n",
392 screen_bpp
, (int)mode
->dmBitsPerPel
);
394 root
= DefaultRootWindow( gdi_display
);
395 screen_config
= pXRRGetScreenInfo( gdi_display
, root
);
396 pXRRConfigCurrentConfiguration( screen_config
, &rotation
);
398 assert( mode
->dmDriverExtra
== sizeof(SizeID
) );
399 memcpy( &size_id
, (BYTE
*)mode
+ sizeof(*mode
), sizeof(size_id
) );
401 if (mode
->dmFields
& DM_DISPLAYFREQUENCY
&& mode
->dmDisplayFrequency
)
402 stat
= pXRRSetScreenConfigAndRate( gdi_display
, screen_config
, root
, size_id
, rotation
,
403 mode
->dmDisplayFrequency
, CurrentTime
);
405 stat
= pXRRSetScreenConfig( gdi_display
, screen_config
, root
, size_id
, rotation
, CurrentTime
);
406 pXRRFreeScreenConfigInfo( screen_config
);
408 if (stat
!= RRSetConfigSuccess
)
409 return DISP_CHANGE_FAILED
;
411 XFlush( gdi_display
);
412 return DISP_CHANGE_SUCCESSFUL
;
415 #ifdef HAVE_XRRGETPROVIDERRESOURCES
417 static struct current_mode
423 static int current_mode_count
;
425 static pthread_mutex_t xrandr_mutex
= PTHREAD_MUTEX_INITIALIZER
;
427 static void xrandr14_invalidate_current_mode_cache(void)
429 pthread_mutex_lock( &xrandr_mutex
);
430 free( current_modes
);
431 current_modes
= NULL
;
432 current_mode_count
= 0;
433 pthread_mutex_unlock( &xrandr_mutex
);
436 static XRRScreenResources
*xrandr_get_screen_resources(void)
438 XRRScreenResources
*resources
= pXRRGetScreenResourcesCurrent( gdi_display
, root_window
);
439 if (resources
&& !resources
->ncrtc
)
441 pXRRFreeScreenResources( resources
);
442 resources
= pXRRGetScreenResources( gdi_display
, root_window
);
446 ERR("Failed to get screen resources.\n");
450 /* Some (304.64, possibly earlier) versions of the NVIDIA driver only
451 * report a DFP's native mode through RandR 1.2 / 1.3. Standard DMT modes
452 * are only listed through RandR 1.0 / 1.1. This is completely useless,
453 * but NVIDIA considers this a feature, so it's unlikely to change. The
454 * best we can do is to fall back to RandR 1.0 and encourage users to
455 * consider more cooperative driver vendors when we detect such a
457 static BOOL
is_broken_driver(void)
459 XRRScreenResources
*screen_resources
;
460 XRROutputInfo
*output_info
;
461 XRRModeInfo
*first_mode
;
462 INT major
, event
, error
;
463 INT output_idx
, i
, j
;
466 screen_resources
= xrandr_get_screen_resources();
467 if (!screen_resources
)
470 /* Check if any output only has one native mode */
471 for (output_idx
= 0; output_idx
< screen_resources
->noutput
; ++output_idx
)
473 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
,
474 screen_resources
->outputs
[output_idx
] );
478 if (output_info
->connection
!= RR_Connected
)
480 pXRRFreeOutputInfo( output_info
);
485 only_one_mode
= TRUE
;
486 for (i
= 0; i
< output_info
->nmode
; ++i
)
488 for (j
= 0; j
< screen_resources
->nmode
; ++j
)
490 if (output_info
->modes
[i
] != screen_resources
->modes
[j
].id
)
495 first_mode
= &screen_resources
->modes
[j
];
499 if (first_mode
->width
!= screen_resources
->modes
[j
].width
||
500 first_mode
->height
!= screen_resources
->modes
[j
].height
)
501 only_one_mode
= FALSE
;
509 pXRRFreeOutputInfo( output_info
);
514 /* Check if it is NVIDIA proprietary driver */
515 if (XQueryExtension( gdi_display
, "NV-CONTROL", &major
, &event
, &error
))
517 ERR_(winediag
)("Broken NVIDIA RandR detected, falling back to RandR 1.0. "
518 "Please consider using the Nouveau driver instead.\n");
519 pXRRFreeScreenResources( screen_resources
);
523 pXRRFreeScreenResources( screen_resources
);
527 static void get_screen_size( XRRScreenResources
*resources
, unsigned int *width
, unsigned int *height
)
529 int min_width
= 0, min_height
= 0, max_width
, max_height
;
530 XRRCrtcInfo
*crtc_info
;
533 pXRRGetScreenSizeRange( gdi_display
, root_window
, &min_width
, &min_height
, &max_width
, &max_height
);
535 *height
= min_height
;
537 for (i
= 0; i
< resources
->ncrtc
; ++i
)
539 if (!(crtc_info
= pXRRGetCrtcInfo( gdi_display
, resources
, resources
->crtcs
[i
] )))
542 if (crtc_info
->mode
!= None
)
544 *width
= max(*width
, crtc_info
->x
+ crtc_info
->width
);
545 *height
= max(*height
, crtc_info
->y
+ crtc_info
->height
);
548 pXRRFreeCrtcInfo( crtc_info
);
552 static unsigned int get_edid( RROutput output
, unsigned char **prop
)
554 int result
, actual_format
;
555 unsigned long bytes_after
, len
;
558 result
= pXRRGetOutputProperty( gdi_display
, output
, x11drv_atom(EDID
), 0, 128, FALSE
, FALSE
,
559 AnyPropertyType
, &actual_type
, &actual_format
, &len
,
560 &bytes_after
, prop
);
562 if (result
!= Success
)
564 WARN("Could not retrieve EDID property for output %#lx.\n", output
);
571 static void set_screen_size( int width
, int height
)
573 int screen
= default_visual
.screen
;
574 int mm_width
, mm_height
;
576 mm_width
= width
* DisplayWidthMM( gdi_display
, screen
) / DisplayWidth( gdi_display
, screen
);
577 mm_height
= height
* DisplayHeightMM( gdi_display
, screen
) / DisplayHeight( gdi_display
, screen
);
578 pXRRSetScreenSize( gdi_display
, root_window
, width
, height
, mm_width
, mm_height
);
581 static unsigned int get_frequency( const XRRModeInfo
*mode
)
583 unsigned int dots
= mode
->hTotal
* mode
->vTotal
;
588 if (mode
->modeFlags
& RR_DoubleScan
)
590 if (mode
->modeFlags
& RR_Interlace
)
593 return (mode
->dotClock
+ dots
/ 2) / dots
;
596 static DWORD
get_orientation( Rotation rotation
)
598 if (rotation
& RR_Rotate_270
) return DMDO_270
;
599 if (rotation
& RR_Rotate_180
) return DMDO_180
;
600 if (rotation
& RR_Rotate_90
) return DMDO_90
;
604 static DWORD
get_orientation_count( Rotation rotations
)
608 if (rotations
& RR_Rotate_0
) ++count
;
609 if (rotations
& RR_Rotate_90
) ++count
;
610 if (rotations
& RR_Rotate_180
) ++count
;
611 if (rotations
& RR_Rotate_270
) ++count
;
615 static Rotation
get_rotation( DWORD orientation
)
617 return (Rotation
)(1 << orientation
);
620 static RRCrtc
get_output_free_crtc( XRRScreenResources
*resources
, XRROutputInfo
*output_info
)
622 XRRCrtcInfo
*crtc_info
;
626 for (crtc_idx
= 0; crtc_idx
< output_info
->ncrtc
; ++crtc_idx
)
628 crtc_info
= pXRRGetCrtcInfo( gdi_display
, resources
, output_info
->crtcs
[crtc_idx
] );
632 if (!crtc_info
->noutput
)
634 crtc
= output_info
->crtcs
[crtc_idx
];
635 pXRRFreeCrtcInfo( crtc_info
);
639 pXRRFreeCrtcInfo( crtc_info
);
645 static RECT
get_primary_rect( XRRScreenResources
*resources
)
647 XRROutputInfo
*output_info
= NULL
;
648 XRRCrtcInfo
*crtc_info
= NULL
;
649 RROutput primary_output
;
650 RECT primary_rect
= {0};
651 RECT first_rect
= {0};
654 primary_output
= pXRRGetOutputPrimary( gdi_display
, root_window
);
658 output_info
= pXRRGetOutputInfo( gdi_display
, resources
, primary_output
);
659 if (!output_info
|| output_info
->connection
!= RR_Connected
|| !output_info
->crtc
)
662 crtc_info
= pXRRGetCrtcInfo( gdi_display
, resources
, output_info
->crtc
);
663 if (!crtc_info
|| !crtc_info
->mode
)
666 SetRect( &primary_rect
, crtc_info
->x
, crtc_info
->y
, crtc_info
->x
+ crtc_info
->width
, crtc_info
->y
+ crtc_info
->height
);
667 pXRRFreeCrtcInfo( crtc_info
);
668 pXRRFreeOutputInfo( output_info
);
671 /* Fallback when XRandR primary output is a disconnected output.
672 * Try to find a crtc with (x, y) being (0, 0). If it's found then get the primary rect from that crtc,
673 * otherwise use the first active crtc to get the primary rect */
676 pXRRFreeCrtcInfo( crtc_info
);
678 pXRRFreeOutputInfo( output_info
);
680 WARN("Primary is set to a disconnected XRandR output.\n");
681 for (i
= 0; i
< resources
->ncrtc
; ++i
)
683 crtc_info
= pXRRGetCrtcInfo( gdi_display
, resources
, resources
->crtcs
[i
] );
687 if (!crtc_info
->mode
)
689 pXRRFreeCrtcInfo( crtc_info
);
693 if (!crtc_info
->x
&& !crtc_info
->y
)
695 SetRect( &primary_rect
, 0, 0, crtc_info
->width
, crtc_info
->height
);
696 pXRRFreeCrtcInfo( crtc_info
);
700 if (IsRectEmpty( &first_rect
))
701 SetRect( &first_rect
, crtc_info
->x
, crtc_info
->y
,
702 crtc_info
->x
+ crtc_info
->width
, crtc_info
->y
+ crtc_info
->height
);
704 pXRRFreeCrtcInfo( crtc_info
);
707 return IsRectEmpty( &primary_rect
) ? first_rect
: primary_rect
;
710 static BOOL
is_crtc_primary( RECT primary
, const XRRCrtcInfo
*crtc
)
714 crtc
->x
== primary
.left
&&
715 crtc
->y
== primary
.top
&&
716 crtc
->x
+ crtc
->width
== primary
.right
&&
717 crtc
->y
+ crtc
->height
== primary
.bottom
;
720 static BOOL
get_gpu_properties_from_vulkan( struct x11drv_gpu
*gpu
, const XRRProviderInfo
*provider_info
,
721 struct x11drv_gpu
*prev_gpus
, int prev_gpu_count
)
723 uint32_t device_count
, device_idx
, output_idx
, i
;
724 VkPhysicalDevice
*vk_physical_devices
= NULL
;
725 VkPhysicalDeviceProperties2 properties2
;
726 VkPhysicalDeviceIDProperties id
;
727 VkDisplayKHR vk_display
;
731 if (!vulkan_init()) goto done
;
733 vr
= p_vkEnumeratePhysicalDevices( vk_instance
, &device_count
, NULL
);
734 if (vr
!= VK_SUCCESS
|| !device_count
)
736 WARN("No Vulkan device found, vr %d, device_count %d.\n", vr
, device_count
);
740 if (!(vk_physical_devices
= calloc( device_count
, sizeof(*vk_physical_devices
) )))
743 vr
= p_vkEnumeratePhysicalDevices( vk_instance
, &device_count
, vk_physical_devices
);
744 if (vr
!= VK_SUCCESS
)
746 WARN("vkEnumeratePhysicalDevices failed, vr %d.\n", vr
);
750 TRACE("provider name %s.\n", debugstr_a(provider_info
->name
));
752 for (device_idx
= 0; device_idx
< device_count
; ++device_idx
)
754 for (output_idx
= 0; output_idx
< provider_info
->noutputs
; ++output_idx
)
756 vr
= p_vkGetRandROutputDisplayEXT( vk_physical_devices
[device_idx
], gdi_display
,
757 provider_info
->outputs
[output_idx
], &vk_display
);
758 if (vr
!= VK_SUCCESS
|| vk_display
== VK_NULL_HANDLE
)
761 memset( &id
, 0, sizeof(id
) );
762 id
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES
;
763 properties2
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
;
764 properties2
.pNext
= &id
;
766 p_vkGetPhysicalDeviceProperties2KHR( vk_physical_devices
[device_idx
], &properties2
);
767 for (i
= 0; i
< prev_gpu_count
; ++i
)
769 if (!memcmp( &prev_gpus
[i
].vulkan_uuid
, &id
.deviceUUID
, sizeof(id
.deviceUUID
) ))
771 WARN( "device UUID %#x:%#x already assigned to GPU %u.\n", *((uint32_t *)id
.deviceUUID
+ 1),
772 *(uint32_t *)id
.deviceUUID
, i
);
776 if (i
< prev_gpu_count
) continue;
778 memcpy( &gpu
->vulkan_uuid
, id
.deviceUUID
, sizeof(id
.deviceUUID
) );
780 /* Ignore Khronos vendor IDs */
781 if (properties2
.properties
.vendorID
< 0x10000)
783 gpu
->pci_id
.vendor
= properties2
.properties
.vendorID
;
784 gpu
->pci_id
.device
= properties2
.properties
.deviceID
;
786 gpu
->name
= strdup( properties2
.properties
.deviceName
);
794 free( vk_physical_devices
);
798 /* Get a list of GPUs reported by XRandR 1.4. Set get_properties to FALSE if GPU properties are
799 * not needed to avoid unnecessary querying */
800 static BOOL
xrandr14_get_gpus( struct x11drv_gpu
**new_gpus
, int *count
, BOOL get_properties
)
802 struct x11drv_gpu
*gpus
= NULL
;
803 XRRScreenResources
*screen_resources
= NULL
;
804 XRRProviderResources
*provider_resources
= NULL
;
805 XRRProviderInfo
*provider_info
= NULL
;
806 XRRCrtcInfo
*crtc_info
= NULL
;
807 INT primary_provider
= -1;
812 screen_resources
= xrandr_get_screen_resources();
813 if (!screen_resources
)
816 provider_resources
= pXRRGetProviderResources( gdi_display
, root_window
);
817 if (!provider_resources
)
820 gpus
= calloc( provider_resources
->nproviders
? provider_resources
->nproviders
: 1, sizeof(*gpus
) );
824 /* Some XRandR implementations don't support providers.
825 * In this case, report a fake one to try searching adapters in screen resources */
826 if (!provider_resources
->nproviders
)
828 WARN("XRandR implementation doesn't report any providers, faking one.\n");
829 gpus
[0].name
= strdup( "Wine GPU" );
836 primary_rect
= get_primary_rect( screen_resources
);
837 for (i
= 0; i
< provider_resources
->nproviders
; ++i
)
839 provider_info
= pXRRGetProviderInfo( gdi_display
, screen_resources
, provider_resources
->providers
[i
] );
843 /* Find primary provider */
844 for (j
= 0; primary_provider
== -1 && j
< provider_info
->ncrtcs
; ++j
)
846 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, provider_info
->crtcs
[j
] );
850 if (is_crtc_primary( primary_rect
, crtc_info
))
852 primary_provider
= i
;
853 pXRRFreeCrtcInfo( crtc_info
);
857 pXRRFreeCrtcInfo( crtc_info
);
860 gpus
[i
].id
= provider_resources
->providers
[i
];
863 if (!get_gpu_properties_from_vulkan( &gpus
[i
], provider_info
, gpus
, i
))
864 gpus
[i
].name
= strdup( provider_info
->name
);
865 /* FIXME: Add an alternate method of getting PCI IDs, for systems that don't support Vulkan */
867 pXRRFreeProviderInfo( provider_info
);
870 /* Make primary GPU the first */
871 if (primary_provider
> 0)
873 struct x11drv_gpu tmp
= gpus
[0];
874 gpus
[0] = gpus
[primary_provider
];
875 gpus
[primary_provider
] = tmp
;
879 *count
= provider_resources
->nproviders
;
882 if (provider_resources
)
883 pXRRFreeProviderResources( provider_resources
);
884 if (screen_resources
)
885 pXRRFreeScreenResources( screen_resources
);
889 ERR("Failed to get gpus\n");
894 static void xrandr14_free_gpus( struct x11drv_gpu
*gpus
, int count
)
896 while (count
--) free( gpus
[count
].name
);
900 static BOOL
xrandr14_get_adapters( ULONG_PTR gpu_id
, struct x11drv_adapter
**new_adapters
, int *count
)
902 struct x11drv_adapter
*adapters
= NULL
;
903 XRRScreenResources
*screen_resources
= NULL
;
904 XRRProviderInfo
*provider_info
= NULL
;
905 XRRCrtcInfo
*enum_crtc_info
, *crtc_info
= NULL
;
906 XRROutputInfo
*enum_output_info
, *output_info
= NULL
;
908 INT crtc_count
, output_count
;
909 INT primary_adapter
= 0;
910 INT adapter_count
= 0;
911 BOOL mirrored
, detached
;
916 screen_resources
= xrandr_get_screen_resources();
917 if (!screen_resources
)
922 provider_info
= pXRRGetProviderInfo( gdi_display
, screen_resources
, gpu_id
);
926 crtc_count
= provider_info
->ncrtcs
;
927 output_count
= provider_info
->noutputs
;
928 outputs
= provider_info
->outputs
;
930 /* Fake provider id, search adapters in screen resources */
933 crtc_count
= screen_resources
->ncrtc
;
934 output_count
= screen_resources
->noutput
;
935 outputs
= screen_resources
->outputs
;
938 /* Actual adapter count could be less */
939 adapters
= calloc( crtc_count
, sizeof(*adapters
) );
943 primary_rect
= get_primary_rect( screen_resources
);
944 for (i
= 0; i
< output_count
; ++i
)
946 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, outputs
[i
] );
950 /* Only connected output are considered as monitors */
951 if (output_info
->connection
!= RR_Connected
)
953 pXRRFreeOutputInfo( output_info
);
958 /* Connected output doesn't mean the output is attached to a crtc */
960 if (output_info
->crtc
)
962 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, output_info
->crtc
);
967 if (!output_info
->crtc
|| !crtc_info
->mode
)
970 /* Ignore mirroring output replicas because mirrored monitors are under the same adapter */
974 for (j
= 0; j
< screen_resources
->noutput
; ++j
)
976 enum_output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, screen_resources
->outputs
[j
] );
977 if (!enum_output_info
)
980 if (enum_output_info
->connection
!= RR_Connected
|| !enum_output_info
->crtc
)
982 pXRRFreeOutputInfo( enum_output_info
);
986 enum_crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, enum_output_info
->crtc
);
987 pXRRFreeOutputInfo( enum_output_info
);
991 /* Some outputs may have the same coordinates, aka mirrored. Choose the output with
992 * the lowest value as primary and the rest will then be replicas in a mirroring set */
993 if (crtc_info
->x
== enum_crtc_info
->x
&&
994 crtc_info
->y
== enum_crtc_info
->y
&&
995 crtc_info
->width
== enum_crtc_info
->width
&&
996 crtc_info
->height
== enum_crtc_info
->height
&&
997 outputs
[i
] > screen_resources
->outputs
[j
])
1000 pXRRFreeCrtcInfo( enum_crtc_info
);
1004 pXRRFreeCrtcInfo( enum_crtc_info
);
1008 if (!mirrored
|| detached
)
1010 /* Use RROutput as adapter id. The reason of not using RRCrtc is that we need to detect inactive but
1011 * attached monitors */
1012 adapters
[adapter_count
].id
= outputs
[i
];
1014 adapters
[adapter_count
].state_flags
|= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
;
1015 if (is_crtc_primary( primary_rect
, crtc_info
))
1017 adapters
[adapter_count
].state_flags
|= DISPLAY_DEVICE_PRIMARY_DEVICE
;
1018 primary_adapter
= adapter_count
;
1024 pXRRFreeOutputInfo( output_info
);
1028 pXRRFreeCrtcInfo( crtc_info
);
1033 /* Make primary adapter the first */
1034 if (primary_adapter
)
1036 struct x11drv_adapter tmp
= adapters
[0];
1037 adapters
[0] = adapters
[primary_adapter
];
1038 adapters
[primary_adapter
] = tmp
;
1041 *new_adapters
= adapters
;
1042 *count
= adapter_count
;
1045 if (screen_resources
)
1046 pXRRFreeScreenResources( screen_resources
);
1048 pXRRFreeProviderInfo( provider_info
);
1050 pXRRFreeOutputInfo( output_info
);
1052 pXRRFreeCrtcInfo( crtc_info
);
1056 ERR("Failed to get adapters\n");
1061 static void xrandr14_free_adapters( struct x11drv_adapter
*adapters
)
1066 static BOOL
xrandr14_get_monitors( ULONG_PTR adapter_id
, struct gdi_monitor
**new_monitors
, int *count
)
1068 struct gdi_monitor
*realloc_monitors
, *monitors
= NULL
;
1069 XRRScreenResources
*screen_resources
= NULL
;
1070 XRROutputInfo
*output_info
= NULL
, *enum_output_info
= NULL
;
1071 XRRCrtcInfo
*crtc_info
= NULL
, *enum_crtc_info
;
1072 INT primary_index
= 0, monitor_count
= 0, capacity
;
1077 screen_resources
= xrandr_get_screen_resources();
1078 if (!screen_resources
)
1081 /* First start with a 2 monitors, should be enough for most cases */
1083 monitors
= calloc( capacity
, sizeof(*monitors
) );
1087 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, adapter_id
);
1091 if (output_info
->crtc
)
1093 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, output_info
->crtc
);
1098 /* Inactive but attached monitor, no need to check for mirrored/replica monitors */
1099 if (!output_info
->crtc
|| !crtc_info
->mode
)
1101 monitors
[monitor_count
].edid_len
= get_edid( adapter_id
, &monitors
[monitor_count
].edid
);
1104 /* Active monitors, need to find other monitors with the same coordinates as mirrored */
1107 primary_rect
= get_primary_rect( screen_resources
);
1109 for (i
= 0; i
< screen_resources
->noutput
; ++i
)
1111 enum_output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, screen_resources
->outputs
[i
] );
1112 if (!enum_output_info
)
1115 /* Detached outputs don't count */
1116 if (enum_output_info
->connection
!= RR_Connected
)
1118 pXRRFreeOutputInfo( enum_output_info
);
1119 enum_output_info
= NULL
;
1123 /* Allocate more space if needed */
1124 if (monitor_count
>= capacity
)
1127 realloc_monitors
= realloc( monitors
, capacity
* sizeof(*monitors
) );
1128 if (!realloc_monitors
)
1130 monitors
= realloc_monitors
;
1133 if (enum_output_info
->crtc
)
1135 enum_crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, enum_output_info
->crtc
);
1136 if (!enum_crtc_info
)
1139 if (enum_crtc_info
->x
== crtc_info
->x
&&
1140 enum_crtc_info
->y
== crtc_info
->y
&&
1141 enum_crtc_info
->width
== crtc_info
->width
&&
1142 enum_crtc_info
->height
== crtc_info
->height
)
1144 SetRect( &monitors
[monitor_count
].rc_monitor
, crtc_info
->x
, crtc_info
->y
,
1145 crtc_info
->x
+ crtc_info
->width
, crtc_info
->y
+ crtc_info
->height
);
1146 monitors
[monitor_count
].rc_work
= get_work_area( &monitors
[monitor_count
].rc_monitor
);
1148 if (is_crtc_primary( primary_rect
, crtc_info
))
1149 primary_index
= monitor_count
;
1151 monitors
[monitor_count
].edid_len
= get_edid( screen_resources
->outputs
[i
],
1152 &monitors
[monitor_count
].edid
);
1156 pXRRFreeCrtcInfo( enum_crtc_info
);
1159 pXRRFreeOutputInfo( enum_output_info
);
1160 enum_output_info
= NULL
;
1163 /* Make sure the first monitor is the primary */
1166 struct gdi_monitor tmp
= monitors
[0];
1167 monitors
[0] = monitors
[primary_index
];
1168 monitors
[primary_index
] = tmp
;
1171 /* Make sure the primary monitor origin is at (0, 0) */
1172 for (i
= 0; i
< monitor_count
; i
++)
1174 OffsetRect( &monitors
[i
].rc_monitor
, -primary_rect
.left
, -primary_rect
.top
);
1175 OffsetRect( &monitors
[i
].rc_work
, -primary_rect
.left
, -primary_rect
.top
);
1179 *new_monitors
= monitors
;
1180 *count
= monitor_count
;
1183 if (screen_resources
)
1184 pXRRFreeScreenResources( screen_resources
);
1186 pXRRFreeOutputInfo( output_info
);
1188 pXRRFreeCrtcInfo( crtc_info
);
1189 if (enum_output_info
)
1190 pXRRFreeOutputInfo( enum_output_info
);
1193 for (i
= 0; i
< monitor_count
; i
++)
1195 if (monitors
[i
].edid
)
1196 XFree( monitors
[i
].edid
);
1199 ERR("Failed to get monitors\n");
1204 static void xrandr14_free_monitors( struct gdi_monitor
*monitors
, int count
)
1208 for (i
= 0; i
< count
; i
++)
1210 if (monitors
[i
].edid
)
1211 XFree( monitors
[i
].edid
);
1216 static BOOL
xrandr14_device_change_handler( HWND hwnd
, XEvent
*event
)
1220 xrandr14_invalidate_current_mode_cache();
1221 if (hwnd
== NtUserGetDesktopWindow() && NtUserGetWindowThread( hwnd
, NULL
) == GetCurrentThreadId())
1222 NtUserCallNoParam( NtUserCallNoParam_DisplayModeChanged
);
1223 /* Update xinerama monitors for xinerama_get_fullscreen_monitors() */
1224 rect
= get_host_primary_monitor_rect();
1225 xinerama_init( rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
1229 static void xrandr14_register_event_handlers(void)
1231 Display
*display
= thread_init_display();
1232 int event_base
, error_base
;
1234 if (!pXRRQueryExtension( display
, &event_base
, &error_base
))
1237 pXRRSelectInput( display
, root_window
,
1238 RRCrtcChangeNotifyMask
| RROutputChangeNotifyMask
| RRProviderChangeNotifyMask
);
1239 X11DRV_register_event_handler( event_base
+ RRNotify_CrtcChange
, xrandr14_device_change_handler
,
1240 "XRandR CrtcChange" );
1241 X11DRV_register_event_handler( event_base
+ RRNotify_OutputChange
, xrandr14_device_change_handler
,
1242 "XRandR OutputChange" );
1243 X11DRV_register_event_handler( event_base
+ RRNotify_ProviderChange
, xrandr14_device_change_handler
,
1244 "XRandR ProviderChange" );
1247 static Bool
filter_rrnotify_event( Display
*display
, XEvent
*event
, char *arg
)
1249 ULONG_PTR event_base
= (ULONG_PTR
)arg
;
1251 if (event
->type
== event_base
+ RRNotify_CrtcChange
1252 || event
->type
== event_base
+ RRNotify_OutputChange
1253 || event
->type
== event_base
+ RRNotify_ProviderChange
)
1259 static void process_rrnotify_events(void)
1261 struct x11drv_thread_data
*data
= x11drv_thread_data();
1262 int event_base
, error_base
;
1265 if (data
->current_event
) return; /* don't process nested events */
1267 if (!pXRRQueryExtension( data
->display
, &event_base
, &error_base
))
1270 process_events( data
->display
, filter_rrnotify_event
, event_base
);
1273 /* XRandR 1.4 display settings handler */
1274 static BOOL
xrandr14_get_id( const WCHAR
*device_name
, BOOL is_primary
, x11drv_settings_id
*id
)
1276 struct current_mode
*tmp_modes
, *new_current_modes
= NULL
;
1277 INT gpu_count
, adapter_count
, new_current_mode_count
= 0;
1278 INT gpu_idx
, adapter_idx
, display_idx
;
1279 struct x11drv_adapter
*adapters
;
1280 struct x11drv_gpu
*gpus
;
1283 /* Parse \\.\DISPLAY%d */
1284 display_idx
= wcstol( device_name
+ 11, &end
, 10 ) - 1;
1288 process_rrnotify_events();
1291 pthread_mutex_lock( &xrandr_mutex
);
1294 if (!xrandr14_get_gpus( &gpus
, &gpu_count
, FALSE
))
1296 pthread_mutex_unlock( &xrandr_mutex
);
1300 for (gpu_idx
= 0; gpu_idx
< gpu_count
; ++gpu_idx
)
1302 if (!xrandr14_get_adapters( gpus
[gpu_idx
].id
, &adapters
, &adapter_count
))
1305 tmp_modes
= realloc( new_current_modes
, (new_current_mode_count
+ adapter_count
) * sizeof(*tmp_modes
) );
1308 xrandr14_free_adapters( adapters
);
1311 new_current_modes
= tmp_modes
;
1313 for (adapter_idx
= 0; adapter_idx
< adapter_count
; ++adapter_idx
)
1315 new_current_modes
[new_current_mode_count
+ adapter_idx
].id
= adapters
[adapter_idx
].id
;
1316 new_current_modes
[new_current_mode_count
+ adapter_idx
].loaded
= FALSE
;
1318 new_current_mode_count
+= adapter_count
;
1319 xrandr14_free_adapters( adapters
);
1321 xrandr14_free_gpus( gpus
, gpu_count
);
1323 if (new_current_modes
)
1325 free( current_modes
);
1326 current_modes
= new_current_modes
;
1327 current_mode_count
= new_current_mode_count
;
1331 if (display_idx
>= current_mode_count
)
1333 pthread_mutex_unlock( &xrandr_mutex
);
1337 id
->id
= current_modes
[display_idx
].id
;
1338 pthread_mutex_unlock( &xrandr_mutex
);
1342 static void add_xrandr14_mode( DEVMODEW
*mode
, XRRModeInfo
*info
, DWORD depth
, DWORD frequency
,
1343 DWORD orientation
, BOOL full
)
1345 mode
->dmSize
= sizeof(*mode
);
1346 mode
->dmDriverExtra
= full
? sizeof(RRMode
) : 0;
1347 mode
->dmFields
= DM_DISPLAYORIENTATION
| DM_BITSPERPEL
| DM_PELSWIDTH
|
1348 DM_PELSHEIGHT
| DM_DISPLAYFLAGS
;
1351 mode
->dmFields
|= DM_DISPLAYFREQUENCY
;
1352 mode
->dmDisplayFrequency
= frequency
;
1354 if (orientation
== DMDO_DEFAULT
|| orientation
== DMDO_180
)
1356 mode
->dmPelsWidth
= info
->width
;
1357 mode
->dmPelsHeight
= info
->height
;
1361 mode
->dmPelsWidth
= info
->height
;
1362 mode
->dmPelsHeight
= info
->width
;
1364 mode
->dmDisplayOrientation
= orientation
;
1365 mode
->dmBitsPerPel
= depth
;
1366 mode
->dmDisplayFlags
= 0;
1367 if (full
) memcpy( mode
+ 1, &info
->id
, sizeof(info
->id
) );
1370 static BOOL
xrandr14_get_modes( x11drv_settings_id id
, DWORD flags
, DEVMODEW
**new_modes
, UINT
*mode_count
, BOOL full
)
1372 DWORD frequency
, orientation
, orientation_count
;
1373 XRRScreenResources
*screen_resources
;
1374 XRROutputInfo
*output_info
= NULL
;
1375 RROutput output
= (RROutput
)id
.id
;
1376 XRRCrtcInfo
*crtc_info
= NULL
;
1377 UINT depth_idx
, mode_idx
= 0;
1378 XRRModeInfo
*mode_info
;
1379 DEVMODEW
*mode
, *modes
;
1385 screen_resources
= xrandr_get_screen_resources();
1386 if (!screen_resources
)
1389 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, output
);
1393 if (output_info
->connection
!= RR_Connected
)
1401 crtc
= output_info
->crtc
;
1403 crtc
= get_output_free_crtc( screen_resources
, output_info
);
1405 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, crtc
);
1407 /* If the output is connected to a CRTC, use rotations reported by the CRTC */
1410 if (flags
& EDS_ROTATEDMODE
)
1412 rotations
= crtc_info
->rotations
;
1416 /* According to the RandR spec, RRGetCrtcInfo should set the active rotation to Rotate_0
1417 * when a CRTC is disabled. However, some RandR implementations report 0 in this case */
1418 rotations
= (crtc_info
->rotation
& 0xf) ? crtc_info
->rotation
: RR_Rotate_0
;
1421 /* Not connected to CRTC, assume all rotations are supported */
1424 if (flags
& EDS_ROTATEDMODE
)
1426 rotations
= RR_Rotate_0
| RR_Rotate_90
| RR_Rotate_180
| RR_Rotate_270
;
1430 rotations
= RR_Rotate_0
;
1433 orientation_count
= get_orientation_count( rotations
);
1435 /* Allocate space for display modes in different color depths and orientations.
1436 * Store a RRMode at the end of each DEVMODEW as private driver data */
1437 modes
= calloc( output_info
->nmode
* DEPTH_COUNT
* orientation_count
,
1438 sizeof(*modes
) + sizeof(RRMode
) );
1442 for (i
= 0, mode
= modes
; i
< output_info
->nmode
; ++i
)
1444 for (j
= 0; j
< screen_resources
->nmode
; ++j
)
1446 if (output_info
->modes
[i
] != screen_resources
->modes
[j
].id
)
1449 mode_info
= &screen_resources
->modes
[j
];
1450 frequency
= get_frequency( mode_info
);
1452 for (depth_idx
= 0; depth_idx
< DEPTH_COUNT
; ++depth_idx
)
1454 for (orientation
= DMDO_DEFAULT
; orientation
<= DMDO_270
; ++orientation
)
1456 if (!((1 << orientation
) & rotations
))
1459 add_xrandr14_mode( mode
, mode_info
, depths
[depth_idx
], frequency
, orientation
, full
);
1460 mode
= NEXT_DEVMODEW( mode
);
1471 *mode_count
= mode_idx
;
1474 pXRRFreeCrtcInfo( crtc_info
);
1476 pXRRFreeOutputInfo( output_info
);
1477 if (screen_resources
)
1478 pXRRFreeScreenResources( screen_resources
);
1482 static void xrandr14_free_modes( DEVMODEW
*modes
)
1487 static BOOL
xrandr14_get_current_mode( x11drv_settings_id id
, DEVMODEW
*mode
)
1489 struct current_mode
*mode_ptr
= NULL
;
1490 XRRScreenResources
*screen_resources
;
1491 XRROutputInfo
*output_info
= NULL
;
1492 RROutput output
= (RROutput
)id
.id
;
1493 XRRModeInfo
*mode_info
= NULL
;
1494 XRRCrtcInfo
*crtc_info
= NULL
;
1499 pthread_mutex_lock( &xrandr_mutex
);
1500 for (mode_idx
= 0; mode_idx
< current_mode_count
; ++mode_idx
)
1502 if (current_modes
[mode_idx
].id
!= id
.id
)
1505 if (!current_modes
[mode_idx
].loaded
)
1507 mode_ptr
= ¤t_modes
[mode_idx
];
1511 memcpy( mode
, ¤t_modes
[mode_idx
].mode
, sizeof(*mode
) );
1512 pthread_mutex_unlock( &xrandr_mutex
);
1516 screen_resources
= xrandr_get_screen_resources();
1517 if (!screen_resources
)
1520 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, output
);
1524 if (output_info
->crtc
)
1526 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, output_info
->crtc
);
1532 if (output_info
->connection
!= RR_Connected
|| !output_info
->crtc
|| !crtc_info
->mode
)
1534 mode
->dmFields
= DM_DISPLAYORIENTATION
| DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
|
1535 DM_DISPLAYFLAGS
| DM_DISPLAYFREQUENCY
| DM_POSITION
;
1536 mode
->dmDisplayOrientation
= DMDO_DEFAULT
;
1537 mode
->dmBitsPerPel
= 0;
1538 mode
->dmPelsWidth
= 0;
1539 mode
->dmPelsHeight
= 0;
1540 mode
->dmDisplayFlags
= 0;
1541 mode
->dmDisplayFrequency
= 0;
1542 mode
->dmPosition
.x
= 0;
1543 mode
->dmPosition
.y
= 0;
1549 for (mode_idx
= 0; mode_idx
< screen_resources
->nmode
; ++mode_idx
)
1551 if (crtc_info
->mode
== screen_resources
->modes
[mode_idx
].id
)
1553 mode_info
= &screen_resources
->modes
[mode_idx
];
1561 mode
->dmFields
= DM_DISPLAYORIENTATION
| DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
|
1562 DM_DISPLAYFLAGS
| DM_DISPLAYFREQUENCY
| DM_POSITION
;
1563 mode
->dmDisplayOrientation
= get_orientation( crtc_info
->rotation
);
1564 mode
->dmBitsPerPel
= screen_bpp
;
1565 mode
->dmPelsWidth
= crtc_info
->width
;
1566 mode
->dmPelsHeight
= crtc_info
->height
;
1567 mode
->dmDisplayFlags
= 0;
1568 mode
->dmDisplayFrequency
= get_frequency( mode_info
);
1569 /* Convert RandR coordinates to virtual screen coordinates */
1570 primary
= get_primary_rect( screen_resources
);
1571 mode
->dmPosition
.x
= crtc_info
->x
- primary
.left
;
1572 mode
->dmPosition
.y
= crtc_info
->y
- primary
.top
;
1576 if (ret
&& mode_ptr
)
1578 memcpy( &mode_ptr
->mode
, mode
, sizeof(*mode
) );
1579 mode_ptr
->mode
.dmSize
= sizeof(*mode
);
1580 mode_ptr
->mode
.dmDriverExtra
= 0;
1581 mode_ptr
->loaded
= TRUE
;
1583 pthread_mutex_unlock( &xrandr_mutex
);
1585 pXRRFreeCrtcInfo( crtc_info
);
1587 pXRRFreeOutputInfo( output_info
);
1588 if (screen_resources
)
1589 pXRRFreeScreenResources( screen_resources
);
1593 static LONG
xrandr14_set_current_mode( x11drv_settings_id id
, const DEVMODEW
*mode
)
1595 unsigned int screen_width
, screen_height
;
1596 RROutput output
= (RROutput
)id
.id
, *outputs
;
1597 XRRScreenResources
*screen_resources
;
1598 XRROutputInfo
*output_info
= NULL
;
1599 XRRCrtcInfo
*crtc_info
= NULL
;
1600 LONG ret
= DISP_CHANGE_FAILED
;
1607 if (mode
->dmFields
& DM_BITSPERPEL
&& mode
->dmBitsPerPel
!= screen_bpp
)
1608 WARN("Cannot change screen color depth from %ubits to %ubits!\n",
1609 screen_bpp
, (int)mode
->dmBitsPerPel
);
1611 screen_resources
= xrandr_get_screen_resources();
1612 if (!screen_resources
)
1615 XGrabServer( gdi_display
);
1617 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, output
);
1618 if (!output_info
|| output_info
->connection
!= RR_Connected
)
1621 if (is_detached_mode(mode
))
1623 /* Already detached */
1624 if (!output_info
->crtc
)
1626 ret
= DISP_CHANGE_SUCCESSFUL
;
1630 /* Execute detach operation */
1631 status
= pXRRSetCrtcConfig( gdi_display
, screen_resources
, output_info
->crtc
,
1632 CurrentTime
, 0, 0, None
, RR_Rotate_0
, NULL
, 0 );
1633 if (status
== RRSetConfigSuccess
)
1635 get_screen_size( screen_resources
, &screen_width
, &screen_height
);
1636 set_screen_size( screen_width
, screen_height
);
1637 ret
= DISP_CHANGE_SUCCESSFUL
;
1643 if (output_info
->crtc
)
1645 crtc
= output_info
->crtc
;
1647 /* Detached, need to find a free CRTC */
1650 if (!(crtc
= get_output_free_crtc( screen_resources
, output_info
)))
1654 crtc_info
= pXRRGetCrtcInfo( gdi_display
, screen_resources
, crtc
);
1658 assert( mode
->dmDriverExtra
== sizeof(RRMode
) );
1659 memcpy( &rrmode
, (BYTE
*)mode
+ sizeof(*mode
), sizeof(rrmode
) );
1661 if (crtc_info
->noutput
)
1663 outputs
= crtc_info
->outputs
;
1664 output_count
= crtc_info
->noutput
;
1671 rotation
= get_rotation( mode
->dmDisplayOrientation
);
1673 /* According to the RandR spec, the entire CRTC must fit inside the screen.
1674 * Since we use the union of all enabled CRTCs to determine the necessary
1675 * screen size, this might involve shrinking the screen, so we must disable
1676 * the CRTC in question first. */
1677 status
= pXRRSetCrtcConfig( gdi_display
, screen_resources
, crtc
, CurrentTime
, 0, 0, None
,
1678 RR_Rotate_0
, NULL
, 0 );
1679 if (status
!= RRSetConfigSuccess
)
1682 get_screen_size( screen_resources
, &screen_width
, &screen_height
);
1683 screen_width
= max( screen_width
, mode
->dmPosition
.x
+ mode
->dmPelsWidth
);
1684 screen_height
= max( screen_height
, mode
->dmPosition
.y
+ mode
->dmPelsHeight
);
1685 set_screen_size( screen_width
, screen_height
);
1687 status
= pXRRSetCrtcConfig( gdi_display
, screen_resources
, crtc
, CurrentTime
,
1688 mode
->dmPosition
.x
, mode
->dmPosition
.y
, rrmode
,
1689 rotation
, outputs
, output_count
);
1690 if (status
== RRSetConfigSuccess
)
1691 ret
= DISP_CHANGE_SUCCESSFUL
;
1694 XUngrabServer( gdi_display
);
1695 XFlush( gdi_display
);
1697 pXRRFreeCrtcInfo( crtc_info
);
1699 pXRRFreeOutputInfo( output_info
);
1700 pXRRFreeScreenResources( screen_resources
);
1701 xrandr14_invalidate_current_mode_cache();
1707 void X11DRV_XRandR_Init(void)
1709 struct x11drv_display_device_handler display_handler
;
1710 struct x11drv_settings_handler settings_handler
;
1711 int event_base
, error_base
, minor
, ret
;
1715 if (major
) return; /* already initialized? */
1716 if (!usexrandr
) return; /* disabled in config */
1717 if (!(ret
= load_xrandr())) return; /* can't load the Xrandr library */
1719 /* see if Xrandr is available */
1720 if (!pXRRQueryExtension( gdi_display
, &event_base
, &error_base
)) return;
1721 X11DRV_expect_error( gdi_display
, XRandRErrorHandler
, NULL
);
1722 ok
= pXRRQueryVersion( gdi_display
, &major
, &minor
);
1723 if (X11DRV_check_error() || !ok
) return;
1725 TRACE("Found XRandR %d.%d.\n", major
, minor
);
1727 settings_handler
.name
= "XRandR 1.0";
1728 settings_handler
.priority
= 200;
1729 settings_handler
.get_id
= xrandr10_get_id
;
1730 settings_handler
.get_modes
= xrandr10_get_modes
;
1731 settings_handler
.free_modes
= xrandr10_free_modes
;
1732 settings_handler
.get_current_mode
= xrandr10_get_current_mode
;
1733 settings_handler
.set_current_mode
= xrandr10_set_current_mode
;
1734 X11DRV_Settings_SetHandler( &settings_handler
);
1736 #ifdef HAVE_XRRGETPROVIDERRESOURCES
1737 if (ret
>= 4 && (major
> 1 || (major
== 1 && minor
>= 4)))
1739 XRRScreenResources
*screen_resources
;
1740 XRROutputInfo
*output_info
;
1741 BOOL found_output
= FALSE
;
1744 screen_resources
= xrandr_get_screen_resources();
1745 if (!screen_resources
)
1748 for (i
= 0; i
< screen_resources
->noutput
; ++i
)
1750 output_info
= pXRRGetOutputInfo( gdi_display
, screen_resources
, screen_resources
->outputs
[i
] );
1754 if (output_info
->connection
== RR_Connected
)
1756 pXRRFreeOutputInfo( output_info
);
1757 found_output
= TRUE
;
1761 pXRRFreeOutputInfo( output_info
);
1763 pXRRFreeScreenResources( screen_resources
);
1767 WARN("No connected outputs found.\n");
1771 display_handler
.name
= "XRandR 1.4";
1772 display_handler
.priority
= 200;
1773 display_handler
.get_gpus
= xrandr14_get_gpus
;
1774 display_handler
.get_adapters
= xrandr14_get_adapters
;
1775 display_handler
.get_monitors
= xrandr14_get_monitors
;
1776 display_handler
.free_gpus
= xrandr14_free_gpus
;
1777 display_handler
.free_adapters
= xrandr14_free_adapters
;
1778 display_handler
.free_monitors
= xrandr14_free_monitors
;
1779 display_handler
.register_event_handlers
= xrandr14_register_event_handlers
;
1780 X11DRV_DisplayDevices_SetHandler( &display_handler
);
1782 if (is_broken_driver())
1785 settings_handler
.name
= "XRandR 1.4";
1786 settings_handler
.priority
= 300;
1787 settings_handler
.get_id
= xrandr14_get_id
;
1788 settings_handler
.get_modes
= xrandr14_get_modes
;
1789 settings_handler
.free_modes
= xrandr14_free_modes
;
1790 settings_handler
.get_current_mode
= xrandr14_get_current_mode
;
1791 settings_handler
.set_current_mode
= xrandr14_set_current_mode
;
1792 X11DRV_Settings_SetHandler( &settings_handler
);
1797 #else /* SONAME_LIBXRANDR */
1799 void X11DRV_XRandR_Init(void)
1801 TRACE("XRandR support not compiled in.\n");
1804 #endif /* SONAME_LIBXRANDR */