widl: Add support for function parameter flags to SLTG typelib generator.
[wine.git] / dlls / winewayland.drv / vulkan.c
blob6e95fb4b0f6193fef953a35920d0bfc2a14b9516
1 /* WAYLANDDRV Vulkan implementation
3 * Copyright 2017 Roderick Colenbrander
4 * Copyright 2021 Alexandros Frantzis
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
27 #include <dlfcn.h>
28 #include <stdlib.h>
30 #include "ntstatus.h"
31 #define WIN32_NO_STATUS
32 #include "waylanddrv.h"
33 #include "wine/debug.h"
35 #define VK_NO_PROTOTYPES
36 #define WINE_VK_HOST
38 #include "wine/vulkan.h"
39 #include "wine/vulkan_driver.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
43 #ifdef SONAME_LIBVULKAN
45 #define VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR 1000006000
47 typedef struct VkWaylandSurfaceCreateInfoKHR
49 VkStructureType sType;
50 const void *pNext;
51 VkWaylandSurfaceCreateFlagsKHR flags;
52 struct wl_display *display;
53 struct wl_surface *surface;
54 } VkWaylandSurfaceCreateInfoKHR;
56 static VkResult (*pvkCreateWaylandSurfaceKHR)(VkInstance, const VkWaylandSurfaceCreateInfoKHR *, const VkAllocationCallbacks *, VkSurfaceKHR *);
57 static void (*pvkDestroySurfaceKHR)(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks *);
58 static VkBool32 (*pvkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice, uint32_t, struct wl_display *);
60 static const struct vulkan_funcs vulkan_funcs;
62 struct wine_vk_surface
64 struct wayland_client_surface *client;
65 VkSurfaceKHR host_surface;
68 static struct wine_vk_surface *wine_vk_surface_from_handle(VkSurfaceKHR handle)
70 return (struct wine_vk_surface *)(uintptr_t)handle;
73 static HWND wine_vk_surface_get_hwnd(struct wine_vk_surface *wine_vk_surface)
75 return wl_surface_get_user_data(wine_vk_surface->client->wl_surface);
78 static void wine_vk_surface_destroy(struct wine_vk_surface *wine_vk_surface)
80 if (wine_vk_surface->client)
82 HWND hwnd = wine_vk_surface_get_hwnd(wine_vk_surface);
83 struct wayland_surface *wayland_surface = wayland_surface_lock_hwnd(hwnd);
85 if (wayland_client_surface_release(wine_vk_surface->client) &&
86 wayland_surface)
88 wayland_surface->client = NULL;
91 if (wayland_surface) pthread_mutex_unlock(&wayland_surface->mutex);
94 free(wine_vk_surface);
97 static VkResult wayland_vkCreateWin32SurfaceKHR(VkInstance instance,
98 const VkWin32SurfaceCreateInfoKHR *create_info,
99 const VkAllocationCallbacks *allocator,
100 VkSurfaceKHR *vk_surface)
102 VkResult res;
103 VkWaylandSurfaceCreateInfoKHR create_info_host;
104 struct wine_vk_surface *wine_vk_surface;
105 struct wayland_surface *wayland_surface;
107 TRACE("%p %p %p %p\n", instance, create_info, allocator, vk_surface);
109 if (allocator)
110 FIXME("Support for allocation callbacks not implemented yet\n");
112 wine_vk_surface = calloc(1, sizeof(*wine_vk_surface));
113 if (!wine_vk_surface)
115 ERR("Failed to allocate memory for wayland vulkan surface\n");
116 res = VK_ERROR_OUT_OF_HOST_MEMORY;
117 goto err;
120 wayland_surface = wayland_surface_lock_hwnd(create_info->hwnd);
121 if (!wayland_surface)
123 ERR("Failed to find wayland surface for hwnd=%p\n", create_info->hwnd);
124 /* VK_KHR_win32_surface only allows out of host and device memory as errors. */
125 res = VK_ERROR_OUT_OF_HOST_MEMORY;
126 goto err;
129 wine_vk_surface->client = wayland_surface_get_client(wayland_surface);
130 pthread_mutex_unlock(&wayland_surface->mutex);
132 if (!wine_vk_surface->client)
134 ERR("Failed to create client surface for hwnd=%p\n", create_info->hwnd);
135 /* VK_KHR_win32_surface only allows out of host and device memory as errors. */
136 res = VK_ERROR_OUT_OF_HOST_MEMORY;
137 goto err;
140 create_info_host.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
141 create_info_host.pNext = NULL;
142 create_info_host.flags = 0; /* reserved */
143 create_info_host.display = process_wayland.wl_display;
144 create_info_host.surface = wine_vk_surface->client->wl_surface;
146 res = pvkCreateWaylandSurfaceKHR(instance, &create_info_host,
147 NULL /* allocator */,
148 &wine_vk_surface->host_surface);
149 if (res != VK_SUCCESS)
151 ERR("Failed to create vulkan wayland surface, res=%d\n", res);
152 goto err;
155 *vk_surface = (uintptr_t)wine_vk_surface;
157 TRACE("Created surface=0x%s\n", wine_dbgstr_longlong(*vk_surface));
158 return VK_SUCCESS;
160 err:
161 if (wine_vk_surface) wine_vk_surface_destroy(wine_vk_surface);
162 return res;
165 static void wayland_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
166 const VkAllocationCallbacks *allocator)
168 struct wine_vk_surface *wine_vk_surface = wine_vk_surface_from_handle(surface);
170 TRACE("%p 0x%s %p\n", instance, wine_dbgstr_longlong(surface), allocator);
172 if (allocator)
173 FIXME("Support for allocation callbacks not implemented yet\n");
175 pvkDestroySurfaceKHR(instance, wine_vk_surface->host_surface, NULL /* allocator */);
176 wine_vk_surface_destroy(wine_vk_surface);
179 static VkBool32 wayland_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev,
180 uint32_t index)
182 TRACE("%p %u\n", phys_dev, index);
184 return pvkGetPhysicalDeviceWaylandPresentationSupportKHR(phys_dev, index,
185 process_wayland.wl_display);
188 static const char *wayland_get_host_surface_extension(void)
190 return "VK_KHR_wayland_surface";
193 static VkSurfaceKHR wayland_wine_get_host_surface(VkSurfaceKHR surface)
195 return wine_vk_surface_from_handle(surface)->host_surface;
198 static void wayland_vulkan_surface_presented(HWND hwnd, VkResult result)
200 struct wayland_surface *wayland_surface;
202 if ((wayland_surface = wayland_surface_lock_hwnd(hwnd)))
204 wayland_surface_ensure_contents(wayland_surface);
206 /* Handle any processed configure request, to ensure the related
207 * surface state is applied by the compositor. */
208 if (wayland_surface->processing.serial &&
209 wayland_surface->processing.processed &&
210 wayland_surface_reconfigure(wayland_surface))
212 wl_surface_commit(wayland_surface->wl_surface);
215 pthread_mutex_unlock(&wayland_surface->mutex);
219 static const struct vulkan_funcs vulkan_funcs =
221 .p_vkCreateWin32SurfaceKHR = wayland_vkCreateWin32SurfaceKHR,
222 .p_vkDestroySurfaceKHR = wayland_vkDestroySurfaceKHR,
223 .p_vkGetPhysicalDeviceWin32PresentationSupportKHR = wayland_vkGetPhysicalDeviceWin32PresentationSupportKHR,
224 .p_get_host_surface_extension = wayland_get_host_surface_extension,
225 .p_wine_get_host_surface = wayland_wine_get_host_surface,
226 .p_vulkan_surface_presented = wayland_vulkan_surface_presented,
229 /**********************************************************************
230 * WAYLAND_VulkanInit
232 UINT WAYLAND_VulkanInit(UINT version, void *vulkan_handle, struct vulkan_funcs *driver_funcs)
234 if (version != WINE_VULKAN_DRIVER_VERSION)
236 ERR("version mismatch, win32u wants %u but driver has %u\n", version, WINE_VULKAN_DRIVER_VERSION);
237 return STATUS_INVALID_PARAMETER;
240 #define LOAD_FUNCPTR(f) if (!(p##f = dlsym(vulkan_handle, #f))) return STATUS_PROCEDURE_NOT_FOUND;
241 LOAD_FUNCPTR(vkCreateWaylandSurfaceKHR);
242 LOAD_FUNCPTR(vkDestroySurfaceKHR);
243 LOAD_FUNCPTR(vkGetPhysicalDeviceWaylandPresentationSupportKHR);
244 #undef LOAD_FUNCPTR
246 *driver_funcs = vulkan_funcs;
247 return STATUS_SUCCESS;
250 #else /* No vulkan */
252 UINT WAYLAND_VulkanInit(UINT version, void *vulkan_handle, struct vulkan_funcs *driver_funcs)
254 ERR( "Wine was built without Vulkan support.\n" );
255 return STATUS_NOT_IMPLEMENTED;
258 #endif /* SONAME_LIBVULKAN */