Module: wine Branch: master Commit: b6e9e8deda5d9ef3cccc81211fdd06a9fc41aeab URL: https://gitlab.winehq.org/wine/wine/-/commit/b6e9e8deda5d9ef3cccc81211fdd06a...
Author: Alexandros Frantzis alexandros.frantzis@collabora.com Date: Wed Sep 15 19:08:53 2021 +0300
winewayland.drv: Implement vkCreateWin32SurfaceKHR.
Create Win32 VkSurfaceKHR objects which are backed by native Wayland VkSurfaceKHR objects. For now we associate a dummy Wayland surface with the VkSurfaceKHR.
---
dlls/winewayland.drv/vulkan.c | 111 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index d22b8401422..15e5edf503b 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -40,7 +40,19 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
#ifdef SONAME_LIBVULKAN
+#define VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR 1000006000 + +typedef struct VkWaylandSurfaceCreateInfoKHR +{ + VkStructureType sType; + const void *pNext; + VkWaylandSurfaceCreateFlagsKHR flags; + struct wl_display *display; + struct wl_surface *surface; +} VkWaylandSurfaceCreateInfoKHR; + static VkResult (*pvkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *); +static VkResult (*pvkCreateWaylandSurfaceKHR)(VkInstance, const VkWaylandSurfaceCreateInfoKHR *, const VkAllocationCallbacks *, VkSurfaceKHR *); static void (*pvkDestroyInstance)(VkInstance, const VkAllocationCallbacks *); static VkResult (*pvkEnumerateInstanceExtensionProperties)(const char *, uint32_t *, VkExtensionProperties *); static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *); @@ -49,6 +61,23 @@ static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *); static void *vulkan_handle; static const struct vulkan_funcs vulkan_funcs;
+struct wine_vk_surface +{ + struct wl_surface *client; + VkSurfaceKHR native; +}; + +static struct wine_vk_surface *wine_vk_surface_from_handle(VkSurfaceKHR handle) +{ + return (struct wine_vk_surface *)(uintptr_t)handle; +} + +static void wine_vk_surface_destroy(struct wine_vk_surface *wine_vk_surface) +{ + if (wine_vk_surface->client) wl_surface_destroy(wine_vk_surface->client); + free(wine_vk_surface); +} + /* 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, @@ -92,6 +121,14 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo return VK_SUCCESS; }
+static const char *wine_vk_native_fn_name(const char *name) +{ + if (!strcmp(name, "vkCreateWin32SurfaceKHR")) + return "vkCreateWaylandSurfaceKHR"; + + return name; +} + static VkResult wayland_vkCreateInstance(const VkInstanceCreateInfo *create_info, const VkAllocationCallbacks *allocator, VkInstance *instance) @@ -120,6 +157,62 @@ static VkResult wayland_vkCreateInstance(const VkInstanceCreateInfo *create_info return res; }
+static VkResult wayland_vkCreateWin32SurfaceKHR(VkInstance instance, + const VkWin32SurfaceCreateInfoKHR *create_info, + const VkAllocationCallbacks *allocator, + VkSurfaceKHR *vk_surface) +{ + VkResult res; + VkWaylandSurfaceCreateInfoKHR create_info_host; + struct wine_vk_surface *wine_vk_surface; + + TRACE("%p %p %p %p\n", instance, create_info, allocator, vk_surface); + + if (allocator) + FIXME("Support for allocation callbacks not implemented yet\n"); + + wine_vk_surface = calloc(1, sizeof(*wine_vk_surface)); + if (!wine_vk_surface) + { + ERR("Failed to allocate memory for wayland vulkan surface\n"); + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto err; + } + + wine_vk_surface->client = wl_compositor_create_surface(process_wayland.wl_compositor); + if (!wine_vk_surface->client) + { + ERR("Failed to create client surface for hwnd=%p\n", create_info->hwnd); + /* VK_KHR_win32_surface only allows out of host and device memory as errors. */ + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto err; + } + + create_info_host.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR; + create_info_host.pNext = NULL; + create_info_host.flags = 0; /* reserved */ + create_info_host.display = process_wayland.wl_display; + create_info_host.surface = wine_vk_surface->client; + + res = pvkCreateWaylandSurfaceKHR(instance, &create_info_host, + NULL /* allocator */, + &wine_vk_surface->native); + if (res != VK_SUCCESS) + { + ERR("Failed to create vulkan wayland surface, res=%d\n", res); + goto err; + } + + *vk_surface = (uintptr_t)wine_vk_surface; + + TRACE("Created surface=0x%s\n", wine_dbgstr_longlong(*vk_surface)); + return VK_SUCCESS; + +err: + if (wine_vk_surface) wine_vk_surface_destroy(wine_vk_surface); + return res; +} + static void wayland_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *allocator) { @@ -179,6 +272,11 @@ static void *wayland_vkGetDeviceProcAddr(VkDevice device, const char *name)
TRACE("%p, %s\n", device, debugstr_a(name));
+ /* Do not return the driver function if the corresponding native function + * is not available. */ + if (!pvkGetDeviceProcAddr(device, wine_vk_native_fn_name(name))) + return NULL; + if ((proc_addr = get_vulkan_driver_device_proc_addr(&vulkan_funcs, name))) return proc_addr;
@@ -191,12 +289,22 @@ static void *wayland_vkGetInstanceProcAddr(VkInstance instance, const char *name
TRACE("%p, %s\n", instance, debugstr_a(name));
+ /* Do not return the driver function if the corresponding native function + * is not available. */ + if (!pvkGetInstanceProcAddr(instance, wine_vk_native_fn_name(name))) + return NULL; + if ((proc_addr = get_vulkan_driver_instance_proc_addr(&vulkan_funcs, instance, name))) return proc_addr;
return pvkGetInstanceProcAddr(instance, name); }
+static VkSurfaceKHR wayland_wine_get_native_surface(VkSurfaceKHR surface) +{ + return wine_vk_surface_from_handle(surface)->native; +} + static void wine_vk_init(void) { if (!(vulkan_handle = dlopen(SONAME_LIBVULKAN, RTLD_NOW))) @@ -207,6 +315,7 @@ static void wine_vk_init(void)
#define LOAD_FUNCPTR(f) if (!(p##f = dlsym(vulkan_handle, #f))) goto fail LOAD_FUNCPTR(vkCreateInstance); + LOAD_FUNCPTR(vkCreateWaylandSurfaceKHR); LOAD_FUNCPTR(vkDestroyInstance); LOAD_FUNCPTR(vkEnumerateInstanceExtensionProperties); LOAD_FUNCPTR(vkGetDeviceProcAddr); @@ -223,10 +332,12 @@ fail: static const struct vulkan_funcs vulkan_funcs = { .p_vkCreateInstance = wayland_vkCreateInstance, + .p_vkCreateWin32SurfaceKHR = wayland_vkCreateWin32SurfaceKHR, .p_vkDestroyInstance = wayland_vkDestroyInstance, .p_vkEnumerateInstanceExtensionProperties = wayland_vkEnumerateInstanceExtensionProperties, .p_vkGetDeviceProcAddr = wayland_vkGetDeviceProcAddr, .p_vkGetInstanceProcAddr = wayland_vkGetInstanceProcAddr, + .p_wine_get_native_surface = wayland_wine_get_native_surface, };
/**********************************************************************