From: Alexandros Frantzis alexandros.frantzis@collabora.com
Passthrough implementations with two additions:
1. Checking for invalidated VkSurfaceKHR. 2. Try to emulate vkGetPhysicalDeviceSurfaceFormats2KHR with vkGetPhysicalDeviceSurfaceFormatsKHR if needed. --- dlls/winewayland.drv/vulkan.c | 89 +++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index c729db4d1d3..0a827c69cce 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -60,6 +60,8 @@ static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *); static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *); static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, VkSurfaceCapabilities2KHR *); static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *); +static VkResult (*pvkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, uint32_t *, VkSurfaceFormat2KHR *); +static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *);
static void *vulkan_handle; static const struct vulkan_funcs vulkan_funcs; @@ -99,6 +101,20 @@ static void wine_vk_surface_destroy(struct wine_vk_surface *wine_vk_surface) free(wine_vk_surface); }
+static BOOL wine_vk_surface_is_valid(struct wine_vk_surface *wine_vk_surface) +{ + HWND hwnd = wine_vk_surface_get_hwnd(wine_vk_surface); + struct wayland_surface *wayland_surface; + + if ((wayland_surface = wayland_surface_lock_hwnd(hwnd))) + { + pthread_mutex_unlock(&wayland_surface->mutex); + return TRUE; + } + + return FALSE; +} + /* Helper function for converting between win32 and Wayland compatible VkInstanceCreateInfo. * Caller is responsible for allocation and cleanup of 'dst'. */ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src, @@ -436,6 +452,75 @@ static VkResult wayland_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevi return res; }
+static VkResult wayland_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice phys_dev, + const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, + uint32_t *count, + VkSurfaceFormat2KHR *formats) +{ + struct wine_vk_surface *wine_vk_surface = wine_vk_surface_from_handle(surface_info->surface); + VkPhysicalDeviceSurfaceInfo2KHR surface_info_host; + VkSurfaceFormatKHR *formats_host; + uint32_t i; + VkResult result; + + TRACE("%p, %p, %p, %p\n", phys_dev, surface_info, count, formats); + + if (!wine_vk_surface_is_valid(wine_vk_surface)) + return VK_ERROR_SURFACE_LOST_KHR; + + surface_info_host = *surface_info; + surface_info_host.surface = wine_vk_surface->native; + + if (pvkGetPhysicalDeviceSurfaceFormats2KHR) + { + return pvkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev, surface_info, + count, formats); + } + + /* Until the loader version exporting this function is common, emulate it + * using the older non-2 version. */ + if (surface_info->pNext) + { + FIXME("Emulating vkGetPhysicalDeviceSurfaceFormats2KHR with " + "vkGetPhysicalDeviceSurfaceFormatsKHR, pNext is ignored.\n"); + } + + if (!formats) + { + return pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, surface_info_host.surface, + count, NULL); + } + + formats_host = calloc(*count, sizeof(*formats_host)); + if (!formats_host) return VK_ERROR_OUT_OF_HOST_MEMORY; + result = pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, surface_info_host.surface, + count, formats_host); + if (result == VK_SUCCESS || result == VK_INCOMPLETE) + { + for (i = 0; i < *count; i++) + formats[i].surfaceFormat = formats_host[i]; + } + + free(formats_host); + return result; +} + +static VkResult wayland_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev, + VkSurfaceKHR surface, + uint32_t *count, + VkSurfaceFormatKHR *formats) +{ + struct wine_vk_surface *wine_vk_surface = wine_vk_surface_from_handle(surface); + + TRACE("%p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), count, formats); + + if (!wine_vk_surface_is_valid(wine_vk_surface)) + return VK_ERROR_SURFACE_LOST_KHR; + + return pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, wine_vk_surface->native, + count, formats); +} + static VkSurfaceKHR wayland_wine_get_native_surface(VkSurfaceKHR surface) { return wine_vk_surface_from_handle(surface)->native; @@ -460,6 +545,8 @@ static void wine_vk_init(void) LOAD_FUNCPTR(vkGetInstanceProcAddr); LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilities2KHR); LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); + LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceFormats2KHR); + LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormatsKHR); #undef LOAD_FUNCPTR #undef LOAD_OPTIONAL_FUNCPTR
@@ -481,6 +568,8 @@ static const struct vulkan_funcs vulkan_funcs = .p_vkGetInstanceProcAddr = wayland_vkGetInstanceProcAddr, .p_vkGetPhysicalDeviceSurfaceCapabilities2KHR = wayland_vkGetPhysicalDeviceSurfaceCapabilities2KHR, .p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = wayland_vkGetPhysicalDeviceSurfaceCapabilitiesKHR, + .p_vkGetPhysicalDeviceSurfaceFormats2KHR = wayland_vkGetPhysicalDeviceSurfaceFormats2KHR, + .p_vkGetPhysicalDeviceSurfaceFormatsKHR = wayland_vkGetPhysicalDeviceSurfaceFormatsKHR, .p_wine_get_native_surface = wayland_wine_get_native_surface, };