[Mesa-dev] [PATCH v2 4/6] vulkan/wsi/wayland: Use proxy wrappers for swapchain

Daniel Stone daniels at collabora.com
Fri May 5 16:47:27 UTC 2017


Though most swapchain operations used a queue, they were racy in that
the object was created with the queue only set later, meaning that its
event could potentially be dispatched from the default queue in between
these two steps.

Use proxy wrappers to avoid this race, also assigning wl_buffers created
for the swapchain to the event queue.

Signed-off-by: Daniel Stone <daniels at collabora.com>
Cc: mesa-stable at lists.freedesktop.org
---
 src/vulkan/wsi/wsi_common_wayland.c | 52 +++++++++++++++++++++++++------------
 1 file changed, 36 insertions(+), 16 deletions(-)

diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index c67ba089f9..cb72183efd 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -510,6 +510,7 @@ struct wsi_wl_swapchain {
    struct wl_event_queue *                      queue;
    struct wl_surface *                          surface;
    uint32_t                                     surface_version;
+   struct wl_drm *                              drm_wrapper;
 
    VkExtent2D                                   extent;
    VkFormat                                     vk_format;
@@ -632,7 +633,6 @@ wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain,
 
    if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) {
       struct wl_callback *frame = wl_surface_frame(chain->surface);
-      wl_proxy_set_queue((struct wl_proxy *)frame, chain->queue);
       wl_callback_add_listener(frame, &frame_listener, chain);
       chain->fifo_ready = false;
    }
@@ -684,7 +684,7 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain,
    if (result != VK_SUCCESS)
       return result;
 
-   image->buffer = wl_drm_create_prime_buffer(chain->display->drm,
+   image->buffer = wl_drm_create_prime_buffer(chain->drm_wrapper,
                                               fd, /* name */
                                               chain->extent.width,
                                               chain->extent.height,
@@ -697,7 +697,6 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain,
    if (!image->buffer)
       goto fail_image;
 
-   wl_proxy_set_queue((struct wl_proxy *)image->buffer, chain->queue);
    wl_buffer_add_listener(image->buffer, &buffer_listener, image);
 
    return VK_SUCCESS;
@@ -722,6 +721,13 @@ wsi_wl_swapchain_destroy(struct wsi_swapchain *wsi_chain,
                                                chain->images[i].memory);
    }
 
+   if (chain->surface)
+      wl_proxy_wrapper_destroy(chain->surface);
+   if (chain->drm_wrapper)
+      wl_proxy_wrapper_destroy(chain->drm_wrapper);
+   if (chain->queue)
+      wl_event_queue_destroy(chain->queue);
+
    vk_free(pAllocator, chain);
 
    return VK_SUCCESS;
@@ -751,6 +757,15 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
    if (chain == NULL)
       return VK_ERROR_OUT_OF_HOST_MEMORY;
 
+   /* Mark a bunch of stuff as NULL.  This way we can just call
+    * destroy_swapchain for cleanup.
+    */
+   for (uint32_t i = 0; i < num_images; i++)
+      chain->images[i].buffer = NULL;
+   chain->queue = NULL;
+   chain->surface = NULL;
+   chain->drm_wrapper = NULL;
+
    bool alpha = pCreateInfo->compositeAlpha ==
                       VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
 
@@ -763,23 +778,11 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
    chain->base.present_mode = pCreateInfo->presentMode;
    chain->base.image_count = num_images;
    chain->base.needs_linear_copy = false;
-   chain->surface = surface->surface;
-   chain->surface_version = wl_proxy_get_version((void *)surface->surface);
    chain->extent = pCreateInfo->imageExtent;
    chain->vk_format = pCreateInfo->imageFormat;
    chain->drm_format = wl_drm_format_for_vk_format(chain->vk_format, alpha);
 
-   chain->fifo_ready = true;
-
-   /* Mark a bunch of stuff as NULL.  This way we can just call
-    * destroy_swapchain for cleanup.
-    */
-   for (uint32_t i = 0; i < chain->base.image_count; i++)
-      chain->images[i].buffer = NULL;
-   chain->queue = NULL;
-
-   chain->display = wsi_wl_get_display(wsi_device,
-                                       surface->display);
+   chain->display = wsi_wl_get_display(wsi_device, surface->display);
    if (!chain->display) {
       result = VK_ERROR_INITIALIZATION_FAILED;
       goto fail;
@@ -791,6 +794,23 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
       goto fail;
    }
 
+   chain->surface = wl_proxy_create_wrapper(surface->surface);
+   if (!chain->surface) {
+      result = VK_ERROR_INITIALIZATION_FAILED;
+      goto fail;
+   }
+   wl_proxy_set_queue((struct wl_proxy *) chain->surface, chain->queue);
+   chain->surface_version = wl_proxy_get_version((void *)surface->surface);
+
+   chain->drm_wrapper = wl_proxy_create_wrapper(chain->display->drm);
+   if (!chain->drm_wrapper) {
+      result = VK_ERROR_INITIALIZATION_FAILED;
+      goto fail;
+   }
+   wl_proxy_set_queue((struct wl_proxy *) chain->drm_wrapper, chain->queue);
+
+   chain->fifo_ready = true;
+
    for (uint32_t i = 0; i < chain->base.image_count; i++) {
       result = wsi_wl_image_init(chain, &chain->images[i],
                                  pCreateInfo, pAllocator);
-- 
2.12.2



More information about the mesa-dev mailing list