From 09058ccbdb5138432af4fee9aa5263e4a4943157 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Tue, 25 Sep 2018 16:22:10 +0100 Subject: [PATCH] wsi/display: setup the connector earlier Instead of setting it up when the swapchain is presented, set it up when creating the swapchain. This means that multiple swapchains might use the same crtc, but only one can be active at a time, and the connectors are now refcounted. This is necessary for the next commit. Signed-off-by: Eric Engestrom Part-of: --- src/vulkan/wsi/wsi_common_display.c | 39 +++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c index 60829ce38d9..72bb2ec3a91 100644 --- a/src/vulkan/wsi/wsi_common_display.c +++ b/src/vulkan/wsi/wsi_common_display.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include "util/u_atomic.h" #include "util/macros.h" #include #include @@ -89,6 +90,7 @@ typedef struct wsi_display_connector { char *name; bool connected; bool active; + int refcount; /* swapchains using this connector */ struct list_head display_modes; wsi_display_mode *current_mode; drmModeModeInfo current_drm_mode; @@ -294,6 +296,18 @@ wsi_display_find_connector(struct wsi_device *wsi_device, return NULL; } + +static uint32_t +wsi_display_is_crtc_available(const struct wsi_display * const wsi, + const uint32_t crtc_id) +{ + wsi_for_each_connector(connector, wsi) + if (connector->crtc_id == crtc_id) + return false; + + return true; +} + static struct wsi_display_connector * wsi_display_alloc_connector(struct wsi_display *wsi, uint32_t connector_id) @@ -1231,7 +1245,13 @@ wsi_display_swapchain_destroy(struct wsi_swapchain *drv_chain, mtx_destroy(&chain->present_id_mutex); u_cnd_monotonic_destroy(&chain->present_id_cond); + wsi_display_mode *display_mode = + wsi_display_mode_from_handle(chain->surface->displayMode); + if (p_atomic_dec_zero(&display_mode->connector->refcount)) + display_mode->connector->crtc_id = 0; + wsi_swapchain_finish(&chain->base); + vk_free(allocator, chain); return VK_SUCCESS; } @@ -1581,7 +1601,8 @@ wsi_display_select_crtc(const struct wsi_display_connector *connector, uint32_t crtc_id = 0; for (int c = 0; crtc_id == 0 && c < mode_res->count_crtcs; c++) { drmModeCrtcPtr crtc = drmModeGetCrtc(wsi->fd, mode_res->crtcs[c]); - if (crtc && crtc->buffer_id == 0) + if (crtc && crtc->buffer_id == 0 && + wsi_display_is_crtc_available(wsi, crtc->crtc_id)) crtc_id = crtc->crtc_id; drmModeFreeCrtc(crtc); } @@ -1959,13 +1980,6 @@ _wsi_display_queue_next(struct wsi_swapchain *drv_chain) } if (ret == -EINVAL) { - VkResult result = wsi_display_setup_connector(connector, display_mode); - - if (result != VK_SUCCESS) { - image->state = WSI_IMAGE_IDLE; - return result; - } - /* XXX allow setting of position */ ret = drmModeSetCrtc(wsi->fd, connector->crtc_id, image->fb_id, 0, 0, @@ -2178,6 +2192,15 @@ wsi_display_surface_create_swapchain( chain->surface = (VkIcdSurfaceDisplay *) icd_surface; + wsi_display_mode *display_mode = + wsi_display_mode_from_handle(chain->surface->displayMode); + + result = wsi_display_setup_connector(display_mode->connector, display_mode); + if (result != VK_SUCCESS) + return result; + + p_atomic_inc(&display_mode->connector->refcount); + for (uint32_t image = 0; image < chain->base.image_count; image++) { result = wsi_display_image_init(&chain->base, create_info,