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
31 #define WIN32_NO_STATUS
32 #include "waylanddrv.h"
33 #include "wine/debug.h"
35 #define VK_NO_PROTOTYPES
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
;
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
) &&
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
)
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
);
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
;
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
;
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
;
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
);
155 *vk_surface
= (uintptr_t)wine_vk_surface
;
157 TRACE("Created surface=0x%s\n", wine_dbgstr_longlong(*vk_surface
));
161 if (wine_vk_surface
) wine_vk_surface_destroy(wine_vk_surface
);
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
);
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
,
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 /**********************************************************************
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
);
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 */