vulkan/wsi/wayland: take ownership of wsi_wl_surface when creating chain

When we create a swapchain, take ownership of a struct wsi_wl_surface.
When the chain gets destroyed, the ownership is dropped.

We can safely do that because only a single swapchain can be associated
with the surface at a time, according to vkCreateSwapchainKHR spec:

  "If pCreateInfo->oldSwapchain is VK_NULL_HANDLE, and the native
   window referred to by pCreateInfo->surface is already associated
   with a Vulkan swapchain, VK_ERROR_NATIVE_WINDOW_IN_USE_KHR must
   be returned."

Reviewed-by: Simon Ser <contact@emersion.fr>
Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12226>
This commit is contained in:
Leandro Ribeiro
2022-10-04 17:55:50 -03:00
committed by Marge Bot
parent abc464f3a9
commit ba571c3657

View File

@@ -103,6 +103,8 @@ enum wsi_wl_buffer_type {
struct wsi_wl_surface {
VkIcdSurfaceWayland base;
struct wsi_wl_swapchain *chain;
};
struct wsi_wl_swapchain {
@@ -112,6 +114,8 @@ struct wsi_wl_swapchain {
struct wl_surface *surface;
struct wsi_wl_surface *wsi_wl_surface;
struct wl_callback *frame;
VkExtent2D extent;
@@ -1253,6 +1257,8 @@ wsi_wl_swapchain_chain_free(struct wsi_wl_swapchain *chain,
wl_callback_destroy(chain->frame);
if (chain->surface)
wl_proxy_wrapper_destroy(chain->surface);
if (chain->wsi_wl_surface)
chain->wsi_wl_surface->chain = NULL;
if (chain->display)
wsi_wl_display_unref(chain->display);
@@ -1283,6 +1289,8 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
struct wsi_swapchain **swapchain_out)
{
VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface;
struct wsi_wl_surface *wsi_wl_surface =
wl_container_of((VkIcdSurfaceWayland *)icd_surface, wsi_wl_surface, base);
struct wsi_wayland *wsi =
(struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND];
struct wsi_wl_swapchain *chain;
@@ -1306,6 +1314,31 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
return result;
}
size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]);
chain = vk_zalloc(pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (chain == NULL) {
wsi_wl_display_unref(display);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
/* We are taking ownership of the wsi_wl_surface, so remove ownership from
* oldSwapchain.
*
* If the surface is currently owned by a swapchain that is not
* oldSwapchain we should return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR. There's
* an open issue tracking that:
*
* https://gitlab.freedesktop.org/mesa/mesa/-/issues/7467
*/
if (pCreateInfo->oldSwapchain) {
VK_FROM_HANDLE(wsi_wl_swapchain, old_chain, pCreateInfo->oldSwapchain);
old_chain->wsi_wl_surface = NULL;
}
/* Take ownership of the wsi_wl_surface */
chain->wsi_wl_surface = wsi_wl_surface;
wsi_wl_surface->chain = chain;
enum wsi_wl_buffer_type buffer_type;
struct wsi_base_image_params *image_params = NULL;
struct wsi_cpu_image_params cpu_image_params;
@@ -1347,13 +1380,6 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
image_params = &drm_image_params.base;
}
size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]);
chain = vk_zalloc(pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (chain == NULL) {
wsi_wl_display_unref(display);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
result = wsi_swapchain_init(wsi_device, &chain->base, device,
pCreateInfo, image_params, pAllocator);
if (result != VK_SUCCESS) {