Mesa (main): wsi/x11: Avoid using xcb_wait_for_special_event in FIFO modes

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed May 4 15:39:33 UTC 2022


Module: Mesa
Branch: main
Commit: 44a20baeb8bb51c7ab99e30fd7f4bb19a0b555b6
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=44a20baeb8bb51c7ab99e30fd7f4bb19a0b555b6

Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Apr 25 15:24:08 2022 -0400

wsi/x11: Avoid using xcb_wait_for_special_event in FIFO modes

If the window is destroyed from underneath us while we happen to be in
xcb_wait_for_special_event, there's no recovery. The special event will
never match because the XID is no longer valid, and Present doesn't have
an in-band DestroyNotify. We're going to work around this by using the
poll API instead. If we get an event we short-circuit back to the top of
the "wait for available image" loop, so we drain the whole special event
queue before any other logic. Which means if we run out of special
events (and the connection and swapchain are still valid) that we
_don't_ have enough images available, so to hurry along any events that
the X server hasn't flushed out yet we call GetGeometry on the
swapchain's window. As a side effect this verifies that the window is
still alive.

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15800>

---

 src/vulkan/wsi/wsi_common_x11.c | 35 +++++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index 7dfb4c1b82d..3bcf152baff 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -1457,25 +1457,44 @@ x11_manage_fifo_queues(void *state)
          goto fail;
 
       if (chain->has_acquire_queue) {
+        xcb_generic_event_t *event = NULL;
+        xcb_connection_t *conn = chain->conn;
+
          /* Wait for our presentation to occur and ensure we have at least one
           * image that can be acquired by the client afterwards. This ensures we
           * can pull on the present-queue on the next loop.
           */
          while (chain->images[image_index].present_queued ||
                 chain->sent_image_count == chain->base.image_count) {
-            xcb_generic_event_t *event =
-               xcb_wait_for_special_event(chain->conn, chain->special_event);
-            if (!event) {
+
+            event = xcb_poll_for_special_event(conn, chain->special_event);
+            if (event) {
+               result = x11_handle_dri3_present_event(chain, (void *)event);
+               /* Ensure that VK_SUBOPTIMAL_KHR is reported to the application */
+               result = x11_swapchain_result(chain, result);
+               free(event);
+               if (result < 0)
+                  goto fail;
+
+               continue;
+            }
+
+            if (chain->status < 0 || xcb_connection_has_error(conn)) {
                result = VK_ERROR_SURFACE_LOST_KHR;
                goto fail;
             }
 
-            result = x11_handle_dri3_present_event(chain, (void *)event);
-            /* Ensure that VK_SUBOPTIMAL_KHR is reported to the application */
-            result = x11_swapchain_result(chain, result);
-            free(event);
-            if (result < 0)
+            /* poke the window to see if it got destroyed from under us, and
+             * to flush any pending special events out of the server
+             */
+            xcb_get_geometry_reply_t *geometry =
+               xcb_get_geometry_reply(conn,
+                                      xcb_get_geometry(conn, chain->window),
+                                      NULL);
+            if (geometry == NULL) {
+               result = VK_ERROR_SURFACE_LOST_KHR;
                goto fail;
+            }
          }
       }
    }



More information about the mesa-commit mailing list