[Mesa-dev] [RFC v3 23/23] vulkan/wsi: Return VK_SUBOPTIMAL_KHR when X11 window is moved

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Thu Sep 28 07:55:03 UTC 2017


When it is detected that a window has changed CRTC, the
current format modifier for the surface might no longer be
optimal (e.g. it might not allow direct scanout on the new
CRTC). The Vulkan client should then re-create the swapchain.

Note: It might be more performant to actually check the
new optimal modifiers instead of just assuming they have
changed.

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 src/vulkan/wsi/wsi_common_x11.c | 57 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 50 insertions(+), 7 deletions(-)

diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index 3d39324c29..4569c928c8 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -53,6 +53,7 @@ struct wsi_x11_connection {
    bool has_dri3;
    bool has_dri3_v1_1;
    bool has_present;
+   bool has_present_v1_1;
    bool is_proprietary_x11;
 };
 
@@ -180,6 +181,19 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc,
 #endif
 
    wsi_conn->has_present = pres_reply->present != 0;
+#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1
+   if (wsi_conn->has_present) {
+      xcb_present_query_version_cookie_t ver_cookie;
+      xcb_present_query_version_reply_t *ver_reply;
+
+      ver_cookie = xcb_present_query_version(conn, 1, 1);
+      ver_reply = xcb_present_query_version_reply(conn, ver_cookie, NULL);
+      wsi_conn->has_present_v1_1 =
+         (ver_reply->major_version > 1 || ver_reply->minor_version >= 1);
+      free(ver_reply);
+   }
+#endif
+
    wsi_conn->is_proprietary_x11 = false;
    if (amd_reply && amd_reply->present)
       wsi_conn->is_proprietary_x11 = true;
@@ -656,6 +670,7 @@ struct x11_swapchain {
 
    bool                                         threaded;
    VkResult                                     status;
+   bool                                         crtc_changed;
    struct wsi_queue                             present_queue;
    struct wsi_queue                             acquire_queue;
    pthread_t                                    queue_manager;
@@ -735,6 +750,13 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain,
       break;
    }
 
+#if XCB_PRESENT_MAJOR_VERSION > 1 || XCB_PRESENT_MINOR_VERSION >= 1
+   case XCB_PRESENT_WINDOW_CRTC_NOTIFY: {
+      chain->crtc_changed = true;
+      break;
+   }
+#endif
+
    default:
       break;
    }
@@ -895,11 +917,18 @@ x11_acquire_next_image(struct wsi_swapchain *anv_chain,
                        uint32_t *image_index)
 {
    struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
+   VkResult result;
 
    if (chain->threaded) {
-      return x11_acquire_next_image_from_queue(chain, image_index, timeout);
+      result = x11_acquire_next_image_from_queue(chain, image_index, timeout);
+   } else {
+      result = x11_acquire_next_image_poll_x11(chain, image_index, timeout);
+   }
+
+   if (result != VK_SUCCESS) {
+      return result;
    } else {
-      return x11_acquire_next_image_poll_x11(chain, image_index, timeout);
+      return chain->crtc_changed ? VK_SUBOPTIMAL_KHR : VK_SUCCESS;
    }
 }
 
@@ -909,12 +938,19 @@ x11_queue_present(struct wsi_swapchain *anv_chain,
                   const VkPresentRegionKHR *damage)
 {
    struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
+   VkResult result;
 
    if (chain->threaded) {
       wsi_queue_push(&chain->present_queue, image_index);
-      return chain->status;
+      result = chain->status;
    } else {
-      return x11_present_to_x11(chain, image_index, 0);
+      result = x11_present_to_x11(chain, image_index, 0);
+   }
+
+   if (result != VK_SUCCESS) {
+      return result;
+   } else {
+      return chain->crtc_changed ? VK_SUBOPTIMAL_KHR : VK_SUCCESS;
    }
 }
 
@@ -1246,6 +1282,7 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
    chain->last_present_msc = 0;
    chain->threaded = false;
    chain->status = VK_SUCCESS;
+   chain->crtc_changed = false;
 
    free(geometry);
 
@@ -1264,11 +1301,17 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
                               pCreateInfo->compositeAlpha,
                               modifiers, num_modifiers, &num_tranches, pAllocator);
 
+   uint32_t input_flags = XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY |
+                          XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY |
+                          XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY;
+#if XCB_PRESENT_MAJOR_VERSION > 1 || XCB_PRESENT_MINOR_VERSION >= 1
+   if (wsi_conn->has_present_v1_1)
+      input_flags |= XCB_PRESENT_EVENT_MASK_WINDOW_CRTC_NOTIFY;
+#endif
+
    chain->event_id = xcb_generate_id(chain->conn);
    xcb_present_select_input(chain->conn, chain->event_id, chain->window,
-                            XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY |
-                            XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY |
-                            XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
+                            input_flags);
 
    /* Create an XCB event queue to hold present events outside of the usual
     * application event queue
-- 
2.13.0



More information about the mesa-dev mailing list