Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/vulkan-1/tests/vulkan.c | 2 +- dlls/winex11.drv/vulkan.c | 11 +++ dlls/winex11.drv/xrandr.c | 156 +++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 1 deletion(-)
diff --git a/dlls/vulkan-1/tests/vulkan.c b/dlls/vulkan-1/tests/vulkan.c index 4ebfe6815bf..4f80a36cd1b 100644 --- a/dlls/vulkan-1/tests/vulkan.c +++ b/dlls/vulkan-1/tests/vulkan.c @@ -212,7 +212,7 @@ static void test_enumerate_physical_device2(void) trace("Device '%s', device UUID: %s, driver UUID: %s, device LUID: %08x:%08x.\n", properties2.properties.deviceName, wine_dbgstr_guid((const GUID *)id.deviceUUID), wine_dbgstr_guid((const GUID *)id.driverUUID), luid->HighPart, luid->LowPart); - todo_wine ok(id.deviceLUIDValid == VK_TRUE, "Expected valid device LUID.\n"); + ok(id.deviceLUIDValid == VK_TRUE, "Expected valid device LUID.\n"); } }
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index 9ee79220f76..28c53a98d14 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -504,12 +504,21 @@ static VkResult X11DRV_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice return pvkGetPhysicalDevicePresentRectanglesKHR(phys_dev, x11_surface->surface, count, rects); }
+#if defined(SONAME_LIBXRANDR) && defined(HAVE_XRRGETPROVIDERRESOURCES) +extern void fill_vk_device_luid_property(VkPhysicalDevice physical_device, + VkPhysicalDeviceProperties2 *properties) DECLSPEC_HIDDEN; +#else +#define fill_vk_device_luid_property(a, b) +#endif + static void X11DRV_vkGetPhysicalDeviceProperties2(VkPhysicalDevice phys_dev, VkPhysicalDeviceProperties2 *properties) { TRACE("%p, %p\n", phys_dev, properties);
pvkGetPhysicalDeviceProperties2(phys_dev, properties); + + fill_vk_device_luid_property(phys_dev, properties); }
static void X11DRV_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice phys_dev, @@ -521,6 +530,8 @@ static void X11DRV_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice phys_dev, pvkGetPhysicalDeviceProperties2KHR(phys_dev, properties); else pvkGetPhysicalDeviceProperties2(phys_dev, properties); + + fill_vk_device_luid_property(phys_dev, properties); }
static VkResult X11DRV_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev, diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index ce7efc9deb4..161c053e659 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -35,8 +35,16 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag); #include <X11/extensions/Xrandr.h> #include "x11drv.h"
+#define VK_NO_PROTOTYPES +#define WINE_VK_HOST + +#include "winreg.h" +#include "devguid.h" +#include "setupapi.h" #include "wine/heap.h" #include "wine/unicode.h" +#include "wine/vulkan.h" +#include "wine/vulkan_driver.h"
static void *xrandr_handle;
@@ -680,6 +688,154 @@ static BOOL is_crtc_primary( RECT primary, const XRRCrtcInfo *crtc ) crtc->y + crtc->height == primary.bottom; }
+#ifdef SONAME_LIBVULKAN + +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR) +DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2); +DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_GPU_RANDR_PROVIDER_ID, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5c, 2); + +static BOOL get_provider_luid( RRProvider provider_id, LUID *luid ) +{ + static const WCHAR pci[] = {'P','C','I',0}; + SP_DEVINFO_DATA device_data; + DWORD type, device_idx = 0; + BOOL ret = FALSE; + HDEVINFO devinfo; + HANDLE mutex; + UINT64 id; + + mutex = get_display_device_init_mutex(); + devinfo = SetupDiGetClassDevsW( &GUID_DEVCLASS_DISPLAY, pci, NULL, 0 ); + device_data.cbSize = sizeof(device_data); + while (SetupDiEnumDeviceInfo( devinfo, device_idx++, &device_data) ) + { + if (!SetupDiGetDevicePropertyW( devinfo, &device_data, + &WINE_DEVPROPKEY_GPU_RANDR_PROVIDER_ID, &type, (BYTE *)&id, + sizeof(id), NULL, 0) ) + continue; + + if (id != provider_id) + continue; + + if (SetupDiGetDevicePropertyW( devinfo, &device_data, &DEVPROPKEY_GPU_LUID, &type, + (BYTE *)luid, sizeof(*luid), NULL, 0) ) + { + ret = TRUE; + break; + } + } + SetupDiDestroyDeviceInfoList( devinfo ); + release_display_device_init_mutex( mutex ); + + if (!ret) + WARN("Failed to get LUID for RandR provider %#lx.\n", provider_id); + return ret; +} + +static void set_luid_property( VkPhysicalDeviceProperties2 *properties, const LUID *luid ) +{ + VkPhysicalDeviceIDProperties *id; + VkBaseOutStructure *header; + + for (header = (VkBaseOutStructure *)properties; header; header = header->pNext) + { + if (header->sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES) + continue; + + id = (VkPhysicalDeviceIDProperties *)header; + memcpy( &id->deviceLUID, luid, sizeof(*luid) ); + id->deviceLUIDValid = VK_TRUE; + TRACE("Set LUID %08x:%08x for Vulkan physical device properties %p.\n", luid->HighPart, + luid->LowPart, properties); + return; + } +} + +void fill_vk_device_luid_property( VkPhysicalDevice physical_device, + VkPhysicalDeviceProperties2 *properties ) +{ + VkResult (*p_vkGetRandROutputDisplayEXT)( VkPhysicalDevice, Display *, RROutput, VkDisplayKHR * ); + const struct vulkan_funcs *vulkan_funcs = get_vulkan_driver( WINE_VULKAN_DRIVER_VERSION ); + static const char *extensions[] = { "VK_EXT_acquire_xlib_display" }; + XRRProviderResources *provider_resources = NULL; + XRRScreenResources *screen_resources = NULL; + XRRProviderInfo *provider_info = NULL; + unsigned int provider_idx, output_idx; + VkInstanceCreateInfo create_info; + VkDisplayKHR vk_display; + VkInstance vk_instance; + VkResult vr; + LUID luid; + + memset( &create_info, 0, sizeof(create_info) ); + create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + create_info.enabledExtensionCount = ARRAY_SIZE(extensions); + create_info.ppEnabledExtensionNames = extensions; + + vr = vulkan_funcs->p_vkCreateInstance( &create_info, NULL, &vk_instance ); + if (vr != VK_SUCCESS) + { + ERR("Failed to create a Vulkan instance, vr %d.\n", vr); + return; + } + + p_vkGetRandROutputDisplayEXT = (void *)vulkan_funcs->p_vkGetInstanceProcAddr( vk_instance, "vkGetRandROutputDisplayEXT" ); + if (!p_vkGetRandROutputDisplayEXT) + { + ERR("Failed to load vkGetRandROutputDisplayEXT.\n"); + goto done; + } + + screen_resources = xrandr_get_screen_resources(); + if (!screen_resources) + goto done; + + provider_resources = pXRRGetProviderResources( gdi_display, root_window ); + if (!provider_resources) + goto done; + + if (!provider_resources->nproviders && get_provider_luid( 1, &luid )) + { + set_luid_property( properties, &luid ); + goto done; + } + + for (provider_idx = 0; provider_idx < provider_resources->nproviders; ++provider_idx) + { + provider_info = pXRRGetProviderInfo( gdi_display, screen_resources, + provider_resources->providers[provider_idx] ); + if (!provider_info) + continue; + + for (output_idx = 0; output_idx < provider_info->noutputs; ++output_idx) + { + vr = p_vkGetRandROutputDisplayEXT( physical_device, gdi_display, + provider_info->outputs[output_idx], &vk_display); + if (vr != VK_SUCCESS || vk_display == VK_NULL_HANDLE) + continue; + + if (get_provider_luid( provider_resources->providers[provider_idx], &luid )) + { + set_luid_property( properties, &luid ); + goto done; + } + } + + pXRRFreeProviderInfo( provider_info ); + provider_info = NULL; + } + +done: + if (provider_info) + pXRRFreeProviderInfo( provider_info ); + if (provider_resources) + pXRRFreeProviderResources( provider_resources ); + if (screen_resources) + pXRRFreeScreenResources( screen_resources ); + vulkan_funcs->p_vkDestroyInstance( vk_instance, NULL ); +} +#endif /* SONAME_LIBVULKAN */ + static BOOL xrandr14_get_gpus( struct x11drv_gpu **new_gpus, int *count ) { static const WCHAR wine_adapterW[] = {'W','i','n','e',' ','A','d','a','p','t','e','r',0};