From ba571c3657ccbd331ee740af6e69ac52f75b6581 Mon Sep 17 00:00:00 2001 From: Leandro Ribeiro Date: Tue, 4 Oct 2022 17:55:50 -0300 Subject: [PATCH] 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 Signed-off-by: Leandro Ribeiro Part-of: --- src/vulkan/wsi/wsi_common_wayland.c | 40 ++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c index 9677b74c7e3..ee494e69549 100644 --- a/src/vulkan/wsi/wsi_common_wayland.c +++ b/src/vulkan/wsi/wsi_common_wayland.c @@ -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) {