vulkan/wsi/wayland: move wl_surface and wl_display from chain to struct wsi_wl_surface

When a swapchain is re-created, if the old swapchain is not passed to
us, we need to re-create the wl_display and the Wayland objects. As
described in "vulkan/wsi/wayland: introduce struct wsi_wl_surface", this
gets in the way when adding the dma-buf feedback implementation.

With this change now the lifetime of the Wayland objects is tied to the
VkSurface. When the swapchain gets re-created, we won't have to
re-create the wl_display (and consequently the Wayland objects).

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 21:22:01 -03:00 committed by Marge Bot
parent ba571c3657
commit 3adba6b18d

View file

@ -105,15 +105,13 @@ struct wsi_wl_surface {
VkIcdSurfaceWayland base;
struct wsi_wl_swapchain *chain;
struct wl_surface *surface;
struct wsi_wl_display *display;
};
struct wsi_wl_swapchain {
struct wsi_swapchain base;
struct wsi_wl_display *display;
struct wl_surface *surface;
struct wsi_wl_surface *wsi_wl_surface;
struct wl_callback *frame;
@ -937,9 +935,45 @@ wsi_wl_surface_destroy(VkIcdSurfaceBase *icd_surface, VkInstance _instance,
struct wsi_wl_surface *wsi_wl_surface =
wl_container_of((VkIcdSurfaceWayland *)icd_surface, wsi_wl_surface, base);
if (wsi_wl_surface->surface)
wl_proxy_wrapper_destroy(wsi_wl_surface->surface);
if (wsi_wl_surface->display)
wsi_wl_display_unref(wsi_wl_surface->display);
vk_free2(&instance->alloc, pAllocator, wsi_wl_surface);
}
static VkResult wsi_wl_surface_init(struct wsi_wl_surface *wsi_wl_surface,
struct wsi_device *wsi_device)
{
struct wsi_wayland *wsi =
(struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND];
VkResult result;
/* wsi_wl_surface has already been initialized. */
if (wsi_wl_surface->display)
return VK_SUCCESS;
result = wsi_wl_display_create(wsi, wsi_wl_surface->base.display,
wsi_device->sw, &wsi_wl_surface->display);
if (result != VK_SUCCESS)
goto fail;
wsi_wl_surface->surface = wl_proxy_create_wrapper(wsi_wl_surface->base.surface);
if (!wsi_wl_surface->surface) {
result = VK_ERROR_OUT_OF_HOST_MEMORY;
goto fail;
}
wl_proxy_set_queue((struct wl_proxy *) wsi_wl_surface->surface,
wsi_wl_surface->display->queue);
return VK_SUCCESS;
fail:
return result;
}
VKAPI_ATTR VkResult VKAPI_CALL
wsi_CreateWaylandSurfaceKHR(VkInstance _instance,
const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
@ -982,9 +1016,10 @@ wsi_wl_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain,
uint32_t *image_index)
{
struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
struct wsi_wl_surface *wsi_wl_surface = chain->wsi_wl_surface;
struct timespec start_time, end_time;
struct timespec rel_timeout;
int wl_fd = wl_display_get_fd(chain->display->wl_display);
int wl_fd = wl_display_get_fd(wsi_wl_surface->display->wl_display);
timespec_from_nsec(&rel_timeout, info->timeout);
@ -993,8 +1028,8 @@ wsi_wl_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain,
while (1) {
/* Try to dispatch potential events. */
int ret = wl_display_dispatch_queue_pending(chain->display->wl_display,
chain->display->queue);
int ret = wl_display_dispatch_queue_pending(wsi_wl_surface->display->wl_display,
wsi_wl_surface->display->queue);
if (ret < 0)
return VK_ERROR_OUT_OF_DATE_KHR;
@ -1015,8 +1050,8 @@ wsi_wl_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain,
return VK_NOT_READY;
/* Try to read events from the server. */
ret = wl_display_prepare_read_queue(chain->display->wl_display,
chain->display->queue);
ret = wl_display_prepare_read_queue(wsi_wl_surface->display->wl_display,
wsi_wl_surface->display->queue);
if (ret < 0) {
/* Another thread might have read events for our queue already. Go
* back to dispatch them.
@ -1034,7 +1069,7 @@ wsi_wl_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain,
ret = ppoll(&pollfd, 1, &rel_timeout, NULL);
if (ret <= 0) {
int lerrno = errno;
wl_display_cancel_read(chain->display->wl_display);
wl_display_cancel_read(wsi_wl_surface->display->wl_display);
if (ret < 0) {
/* If ppoll() was interrupted, try again. */
if (lerrno == EINTR || lerrno == EAGAIN)
@ -1045,7 +1080,7 @@ wsi_wl_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain,
continue;
}
ret = wl_display_read_events(chain->display->wl_display);
ret = wl_display_read_events(wsi_wl_surface->display->wl_display);
if (ret < 0)
return VK_ERROR_OUT_OF_DATE_KHR;
}
@ -1072,6 +1107,7 @@ wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain,
const VkPresentRegionKHR *damage)
{
struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
struct wsi_wl_surface *wsi_wl_surface = chain->wsi_wl_surface;
if (chain->buffer_type == WSI_WL_BUFFER_SHM_MEMCPY) {
struct wsi_wl_image *image = &chain->images[image_index];
@ -1080,38 +1116,38 @@ wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain,
}
if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) {
while (!chain->fifo_ready) {
int ret = wl_display_dispatch_queue(chain->display->wl_display,
chain->display->queue);
int ret = wl_display_dispatch_queue(wsi_wl_surface->display->wl_display,
wsi_wl_surface->display->queue);
if (ret < 0)
return VK_ERROR_OUT_OF_DATE_KHR;
}
}
assert(image_index < chain->base.image_count);
wl_surface_attach(chain->surface, chain->images[image_index].buffer, 0, 0);
wl_surface_attach(wsi_wl_surface->surface, chain->images[image_index].buffer, 0, 0);
if (wl_surface_get_version(chain->surface) >= 4 && damage &&
if (wl_surface_get_version(wsi_wl_surface->surface) >= 4 && damage &&
damage->pRectangles && damage->rectangleCount > 0) {
for (unsigned i = 0; i < damage->rectangleCount; i++) {
const VkRectLayerKHR *rect = &damage->pRectangles[i];
assert(rect->layer == 0);
wl_surface_damage_buffer(chain->surface,
wl_surface_damage_buffer(wsi_wl_surface->surface,
rect->offset.x, rect->offset.y,
rect->extent.width, rect->extent.height);
}
} else {
wl_surface_damage(chain->surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_damage(wsi_wl_surface->surface, 0, 0, INT32_MAX, INT32_MAX);
}
if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) {
chain->frame = wl_surface_frame(chain->surface);
chain->frame = wl_surface_frame(wsi_wl_surface->surface);
wl_callback_add_listener(chain->frame, &frame_listener, chain);
chain->fifo_ready = false;
}
chain->images[image_index].busy = true;
wl_surface_commit(chain->surface);
wl_display_flush(chain->display->wl_display);
wl_surface_commit(wsi_wl_surface->surface);
wl_display_flush(wsi_wl_surface->display->wl_display);
return VK_SUCCESS;
}
@ -1159,7 +1195,7 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain,
const VkSwapchainCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks* pAllocator)
{
struct wsi_wl_display *display = chain->display;
struct wsi_wl_display *display = chain->wsi_wl_surface->display;
VkResult result;
result = wsi_create_image(&chain->base, &chain->base.image_info,
@ -1255,14 +1291,9 @@ wsi_wl_swapchain_chain_free(struct wsi_wl_swapchain *chain,
{
if (chain->frame)
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);
wsi_swapchain_finish(&chain->base);
vk_free(pAllocator, chain);
@ -1288,11 +1319,8 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
const VkAllocationCallbacks* pAllocator,
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;
VkResult result;
@ -1300,26 +1328,10 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
int num_images = pCreateInfo->minImageCount;
struct wsi_wl_display *display = NULL;
if (pCreateInfo->oldSwapchain) {
/* If we have an oldSwapchain parameter, copy the display struct over
* from the old one so we don't have to fully re-initialize it.
*/
VK_FROM_HANDLE(wsi_wl_swapchain, old_chain, pCreateInfo->oldSwapchain);
display = wsi_wl_display_ref(old_chain->display);
} else {
result = wsi_wl_display_create(wsi, surface->display,
wsi_device->sw, &display);
if (result != VK_SUCCESS)
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);
if (chain == NULL)
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
/* We are taking ownership of the wsi_wl_surface, so remove ownership from
* oldSwapchain.
@ -1339,6 +1351,10 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
chain->wsi_wl_surface = wsi_wl_surface;
wsi_wl_surface->chain = chain;
result = wsi_wl_surface_init(wsi_wl_surface, wsi_device);
if (result != VK_SUCCESS)
goto fail;
enum wsi_wl_buffer_type buffer_type;
struct wsi_base_image_params *image_params = NULL;
struct wsi_cpu_image_params cpu_image_params;
@ -1365,8 +1381,8 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
/* Use explicit DRM format modifiers when both the server and the driver
* support them.
*/
if (display->wl_dmabuf && wsi_device->supports_modifiers) {
struct wsi_wl_format *f = find_format(&display->formats,
if (wsi_wl_surface->display->wl_dmabuf && wsi_device->supports_modifiers) {
struct wsi_wl_format *f = find_format(&wsi_wl_surface->display->formats,
pCreateInfo->imageFormat);
if (f != NULL) {
num_drm_modifiers = u_vector_length(&f->modifiers);
@ -1383,7 +1399,6 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
result = wsi_swapchain_init(wsi_device, &chain->base, device,
pCreateInfo, image_params, pAllocator);
if (result != VK_SUCCESS) {
wsi_wl_display_unref(display);
vk_free(pAllocator, chain);
return result;
}
@ -1397,7 +1412,6 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
chain->base.queue_present = wsi_wl_swapchain_queue_present;
chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, pCreateInfo);
chain->base.image_count = num_images;
chain->display = display;
chain->extent = pCreateInfo->imageExtent;
chain->vk_format = pCreateInfo->imageFormat;
chain->buffer_type = buffer_type;
@ -1408,15 +1422,6 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
}
chain->num_drm_modifiers = num_drm_modifiers;
chain->drm_modifiers = drm_modifiers;
chain->surface = wl_proxy_create_wrapper(surface->surface);
if (!chain->surface) {
result = VK_ERROR_OUT_OF_HOST_MEMORY;
goto fail;
}
wl_proxy_set_queue((struct wl_proxy *) chain->surface,
chain->display->queue);
chain->fifo_ready = true;
for (uint32_t i = 0; i < chain->base.image_count; i++) {