From: Alexandros Frantzis alexandros.frantzis@collabora.com
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 | 95 ++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index b89e6cdcc45..6e2d430881a 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -41,11 +41,40 @@ 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 void *vulkan_handle;
+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, @@ -117,6 +146,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) { @@ -128,6 +213,11 @@ static void wayland_vkDestroyInstance(VkInstance instance, pvkDestroyInstance(instance, NULL /* allocator */); }
+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))) @@ -138,6 +228,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); #undef LOAD_FUNCPTR
@@ -151,7 +242,9 @@ fail: static const struct vulkan_funcs vulkan_funcs = { .p_vkCreateInstance = wayland_vkCreateInstance, - .p_vkDestroyInstance = wayland_vkDestroyInstance + .p_vkCreateWin32SurfaceKHR = wayland_vkCreateWin32SurfaceKHR, + .p_vkDestroyInstance = wayland_vkDestroyInstance, + .p_wine_get_native_surface = wayland_wine_get_native_surface };
/**********************************************************************