summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Stone <[email protected]>2017-05-02 10:06:32 +0100
committerDaniel Stone <[email protected]>2017-05-19 09:36:06 +0100
commit5034c615582add2be9309dc1d7383fb0daba6dd3 (patch)
treef17e6f654a7a802452d8578a2b6249d41b339295
parentc902a1957d079941823006d56b6810e1e85be4b0 (diff)
vulkan/wsi/wayland: Use proxy wrappers for swapchain
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 <[email protected]> Reviewed-by: Lionel Landwerlin <[email protected]> Cc: [email protected]
-rw-r--r--src/vulkan/wsi/wsi_common_wayland.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index c11093d02f4..8950798882c 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -536,6 +536,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;
@@ -658,7 +659,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;
}
@@ -710,7 +710,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,
@@ -723,7 +723,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;
@@ -748,6 +747,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;
@@ -777,6 +783,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;
@@ -789,23 +804,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;
@@ -817,6 +820,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);