xserver: Branch 'master' - 7 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jul 4 08:17:13 UTC 2024


 hw/xwayland/xwayland-glamor-gbm.c     |  144 ++++++++++++++++++++++++++++++++++
 hw/xwayland/xwayland-glamor-gbm.h     |    8 +
 hw/xwayland/xwayland-types.h          |    1 
 hw/xwayland/xwayland-window-buffers.c |  132 ++++++++-----------------------
 hw/xwayland/xwayland-window-buffers.h |    5 -
 hw/xwayland/xwayland-window.c         |    4 
 6 files changed, 194 insertions(+), 100 deletions(-)

New commits:
commit bc9bf563603c4cd22e30448cb03c20a6a86b0364
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jun 18 14:02:03 2024 +0200

    xwayland/window-buffers: Set syncpnts for all pixmaps
    
    The wp_linux_drm_syncobj_v1 protocol states that :
    
    | If at surface commit time there is a pending buffer attached but no
    | pending release timeline point set, the no_release_point protocol
    | error is raised.
    
    So we need to set a release timeline point in any case from the swap
    pixmap routine, even for the early out code paths.
    
    Failing to do so may cause a Wayland protocol error that is fatal to the
    Wayland client, in this case Xwayland:
    
    | wp_linux_drm_syncobj_surface_v1: error 4: No Acquire point provided
    | (EE) failed to dispatch Wayland events: Protocol error
    
    Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1688
    Fixes: 87bf2cafcc - xwayland: add support for wp_linux_drm_syncobj_v1
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1571>

diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index ad2cef156..8c8475c0b 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -414,6 +414,8 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window, Bool handle_sync)
         if (xwl_is_client_pixmap(window_pixmap)) {
             xwl_window_buffer->pixmap = NULL;
             xwl_window_buffer_maybe_dispose(xwl_window_buffer);
+            if (handle_sync)
+                xwl_window_handle_pixmap_sync(xwl_window, window_pixmap, NULL);
             return window_pixmap;
         }
     } else {
@@ -424,8 +426,11 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window, Bool handle_sync)
         window_pixmap->refcnt++;
         xwl_window_realloc_pixmap(xwl_window);
 
-        if (!xwl_window_buffer)
+        if (!xwl_window_buffer) {
+            if (handle_sync)
+                xwl_window_handle_pixmap_sync(xwl_window, window_pixmap, NULL);
             return window_pixmap;
+        }
     }
 
     xwl_window_buffer->pixmap = window_pixmap;
commit 33330f0dc96c126895e2670b22de4d7980a60283
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jun 18 13:58:45 2024 +0200

    xwayland/window-buffers: Move code to submit pixmaps
    
    Move the code which takes care of submitting pixmaps and the
    synchronization points to its own function.
    
    This will allow to reuse that code from different code path.
    
    No functional change intended.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1571>

diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index e3f8ffe21..ad2cef156 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -349,6 +349,32 @@ xwl_window_realloc_pixmap(struct xwl_window *xwl_window)
     screen->DestroyPixmap(window_pixmap);
 }
 
+static Bool
+xwl_window_handle_pixmap_sync(struct xwl_window *xwl_window,
+                              PixmapPtr pixmap,
+                              struct xwl_window_buffer *xwl_window_buffer)
+{
+    Bool implicit_sync = TRUE;
+#ifdef XWL_HAS_GLAMOR
+    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+
+    if (!xwl_glamor_supports_implicit_sync(xwl_screen)) {
+        if (xwl_screen->explicit_sync && xwl_glamor_gbm_set_syncpts(xwl_window, pixmap)) {
+            implicit_sync = FALSE;
+            /* wait until the release fence is available before re-using this buffer */
+            xwl_glamor_gbm_wait_release_fence(xwl_window, pixmap, xwl_window_buffer);
+        } else {
+            /* If glamor does not support implicit sync and we can't use
+             * explicit sync, wait for the GPU to be idle before presenting.
+             * Note that buffer re-use will still be unsynchronized :(
+             */
+            glamor_finish(xwl_screen->screen);
+        }
+    }
+#endif /* XWL_HAS_GLAMOR */
+    return implicit_sync;
+}
+
 PixmapPtr
 xwl_window_swap_pixmap(struct xwl_window *xwl_window, Bool handle_sync)
 {
@@ -356,7 +382,6 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window, Bool handle_sync)
     WindowPtr surface_window = xwl_window->surface_window;
     struct xwl_window_buffer *xwl_window_buffer;
     PixmapPtr window_pixmap;
-    Bool implicit_sync = TRUE;
 
     window_pixmap = (*xwl_screen->screen->GetWindowPixmap) (surface_window);
 
@@ -408,23 +433,8 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window, Bool handle_sync)
     /* Hold a reference on the buffer until it's released by the compositor */
     xwl_window_buffer->refcnt++;
 
-#ifdef XWL_HAS_GLAMOR
-    if (handle_sync && !xwl_glamor_supports_implicit_sync(xwl_screen)) {
-        if (xwl_screen->explicit_sync && xwl_glamor_gbm_set_syncpts(xwl_window, window_pixmap)) {
-            implicit_sync = FALSE;
-            /* wait until the release fence is available before re-using this buffer */
-            xwl_glamor_gbm_wait_release_fence(xwl_window, window_pixmap, xwl_window_buffer);
-        } else {
-            /* If glamor does not support implicit sync and we can't use
-             * explicit sync, wait for the GPU to be idle before presenting.
-             * Note that buffer re-use will still be unsynchronized :(
-             */
-            glamor_finish(xwl_screen->screen);
-        }
-    }
-#endif /* XWL_HAS_GLAMOR */
-
-    if (implicit_sync) {
+    if (handle_sync &&
+        xwl_window_handle_pixmap_sync(xwl_window, window_pixmap, xwl_window_buffer)) {
         xwl_pixmap_set_buffer_release_cb(xwl_window_buffer->pixmap,
                                          xwl_window_buffer_release_callback,
                                          xwl_window_buffer);
commit aab01c73914eeadf75672ab954538cd34d07e817
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jul 2 12:36:01 2024 +0200

    xwayland/window-buffers: Do not always set syncpnts
    
    The function xwl_window_swap_pixmap() can be called from two places,
    either from xwl_window_attach_buffer() or from damage_report().
    
    When called from xwl_window_attach_buffer(), the new buffer is attached
    and the surface committed.
    
    However, when called from damage_report(), a new buffer might not be
    attached before the surface is committed.
    
    That's fine with implicit synchronization, but if we use explicit
    synchronization, committing a surface without a new buffer attached but
    with a release timeline point set is a protocol error:
    
    | If at surface commit time there is a pending release timeline point
    | set but no pending buffer attached, a no_buffer error is raised.
    
    To avoid such an issue, add a new parameter to xwl_window_swap_pixmap()
    to hint whether it should set the synchronization points, and have the
    synchronization points set only from xwl_window_attach_buffer().
    
    v2: Rename param to handle_sync (Michel)
    
    Suggested-by: Michel Dänzer <mdaenzer at redhat.com>
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1571>

diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index 442e9e2fd..e3f8ffe21 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -350,7 +350,7 @@ xwl_window_realloc_pixmap(struct xwl_window *xwl_window)
 }
 
 PixmapPtr
-xwl_window_swap_pixmap(struct xwl_window *xwl_window)
+xwl_window_swap_pixmap(struct xwl_window *xwl_window, Bool handle_sync)
 {
     struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
     WindowPtr surface_window = xwl_window->surface_window;
@@ -409,7 +409,7 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window)
     xwl_window_buffer->refcnt++;
 
 #ifdef XWL_HAS_GLAMOR
-    if (!xwl_glamor_supports_implicit_sync(xwl_screen)) {
+    if (handle_sync && !xwl_glamor_supports_implicit_sync(xwl_screen)) {
         if (xwl_screen->explicit_sync && xwl_glamor_gbm_set_syncpts(xwl_window, window_pixmap)) {
             implicit_sync = FALSE;
             /* wait until the release fence is available before re-using this buffer */
diff --git a/hw/xwayland/xwayland-window-buffers.h b/hw/xwayland/xwayland-window-buffers.h
index ee26d3244..af46eb91b 100644
--- a/hw/xwayland/xwayland-window-buffers.h
+++ b/hw/xwayland/xwayland-window-buffers.h
@@ -36,6 +36,6 @@ void xwl_window_buffer_release(struct xwl_window_buffer *xwl_window_buffer);
 void xwl_window_buffers_init(struct xwl_window *xwl_window);
 void xwl_window_buffers_dispose(struct xwl_window *xwl_window);
 void xwl_window_realloc_pixmap(struct xwl_window *xwl_window);
-PixmapPtr xwl_window_swap_pixmap(struct xwl_window *xwl_window);
+PixmapPtr xwl_window_swap_pixmap(struct xwl_window *xwl_window, Bool handle_sync);
 
 #endif /* XWAYLAND_WINDOW_BUFFERS_H */
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 12bb3009c..90ece334a 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -318,7 +318,7 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
 
     window_pixmap = xwl_screen->screen->GetWindowPixmap(xwl_window->surface_window);
     if (xwl_is_client_pixmap(window_pixmap))
-        xwl_screen->screen->DestroyPixmap(xwl_window_swap_pixmap(xwl_window));
+        xwl_screen->screen->DestroyPixmap(xwl_window_swap_pixmap(xwl_window, FALSE));
 }
 
 static void
@@ -1955,7 +1955,7 @@ xwl_window_attach_buffer(struct xwl_window *xwl_window)
     PixmapPtr pixmap;
     int i;
 
-    pixmap = xwl_window_swap_pixmap(xwl_window);
+    pixmap = xwl_window_swap_pixmap(xwl_window, TRUE);
     buffer = xwl_pixmap_get_wl_buffer(pixmap);
 
     if (!buffer) {
commit 256cef8b201047ba4d840043e89573f4574c24df
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jun 18 11:26:26 2024 +0200

    xwayland/window-buffers: Use synchronization from GLAMOR/GBM
    
    Now that we have the buffer synchronization implemented in the
    GLAMOR/GBM code, switch to use that code.
    
    At this point, there is still not functional change intended, this is
    still preparation work for a fix that is still to come.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1571>

diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index 0b9861fbb..442e9e2fd 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -31,6 +31,7 @@
 #include "xwayland-window.h"
 #include "xwayland-pixmap.h"
 #include "xwayland-screen.h"
+#include "xwayland-glamor-gbm.h"
 #include "xwayland-window-buffers.h"
 #ifdef XWL_HAS_GLAMOR
 #include "glamor.h"
@@ -47,11 +48,6 @@ struct xwl_window_buffer {
     struct xwl_window *xwl_window;
     PixmapPtr pixmap;
     RegionPtr damage_region;
-#ifdef XWL_HAS_GLAMOR
-    struct dri3_syncobj *syncobj;
-    uint64_t timeline_point;
-    int efd;
-#endif /* XWL_HAS_GLAMOR */
     int refcnt;
     uint32_t time;
     struct xorg_list link_buffer;
@@ -90,9 +86,6 @@ xwl_window_buffer_new(struct xwl_window *xwl_window)
     xwl_window_buffer->damage_region = RegionCreate(NullBox, 1);
     xwl_window_buffer->pixmap = NullPixmap;
     xwl_window_buffer->refcnt = 1;
-#ifdef XWL_HAS_GLAMOR
-    xwl_window_buffer->efd = -1;
-#endif /* XWL_HAS_GLAMOR */
 
     xorg_list_init(&xwl_window_buffer->link_buffer);
 
@@ -119,18 +112,12 @@ xwl_window_buffer_maybe_dispose(struct xwl_window_buffer *xwl_window_buffer)
 
     RegionDestroy(xwl_window_buffer->damage_region);
 
-    if (xwl_window_buffer->pixmap)
-        xwl_window_buffer_destroy_pixmap (xwl_window_buffer);
-
+    if (xwl_window_buffer->pixmap) {
 #ifdef XWL_HAS_GLAMOR
-    if (xwl_window_buffer->syncobj)
-        xwl_window_buffer->syncobj->free(xwl_window_buffer->syncobj);
-
-    if (xwl_window_buffer->efd >= 0) {
-        SetNotifyFd(xwl_window_buffer->efd, NULL, 0, NULL);
-        close(xwl_window_buffer->efd);
-    }
+        xwl_glamor_gbm_dispose_syncpts(xwl_window_buffer->pixmap);
 #endif /* XWL_HAS_GLAMOR */
+        xwl_window_buffer_destroy_pixmap (xwl_window_buffer);
+    }
 
     xorg_list_del(&xwl_window_buffer->link_buffer);
     free(xwl_window_buffer);
@@ -244,20 +231,6 @@ xwl_window_buffer_release(struct xwl_window_buffer *xwl_window_buffer)
     xwl_window_buffer_release_callback(xwl_window_buffer);
 }
 
-#ifdef XWL_HAS_GLAMOR
-static void
-xwl_window_buffers_release_fence_avail(int fd, int xevents, void *data)
-{
-    struct xwl_window_buffer *xwl_window_buffer = data;
-
-    SetNotifyFd(fd, NULL, 0, NULL);
-    close(fd);
-    xwl_window_buffer->efd = -1;
-
-    xwl_window_buffer_release_callback(data);
-}
-#endif /* XWL_HAS_GLAMOR */
-
 void
 xwl_window_buffers_init(struct xwl_window *xwl_window)
 {
@@ -376,46 +349,6 @@ xwl_window_realloc_pixmap(struct xwl_window *xwl_window)
     screen->DestroyPixmap(window_pixmap);
 }
 
-#ifdef XWL_HAS_GLAMOR
-static Bool
-xwl_window_buffers_set_syncpts(struct xwl_window_buffer *xwl_window_buffer)
-{
-    struct xwl_window *xwl_window = xwl_window_buffer->xwl_window;
-    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
-    uint64_t acquire_point = ++xwl_window_buffer->timeline_point;
-    uint64_t release_point = ++xwl_window_buffer->timeline_point;
-
-    if (!xwl_window_buffer->syncobj) {
-        struct dri3_syncobj *syncobj = xwl_glamor_dri3_syncobj_create(xwl_screen);
-        if (!syncobj)
-            goto fail;
-        xwl_window_buffer->syncobj = syncobj;
-    }
-
-    int fence_fd = xwl_glamor_get_fence(xwl_screen);
-    if (fence_fd >= 0)
-        xwl_window_buffer->syncobj->import_fence(xwl_window_buffer->syncobj,
-                                                 acquire_point, fence_fd);
-    else
-        goto fail;
-
-    xwl_glamor_dri3_syncobj_passthrough(xwl_window,
-                                        xwl_window_buffer->syncobj,
-                                        xwl_window_buffer->syncobj,
-                                        acquire_point,
-                                        release_point);
-    return TRUE;
-
-fail:
-    /* can't use explicit sync, we will do a glFinish() before presenting */
-    if (xwl_window_buffer->syncobj) {
-        xwl_window_buffer->syncobj->free(xwl_window_buffer->syncobj);
-        xwl_window_buffer->syncobj = NULL;
-    }
-    return FALSE;
-}
-#endif /* XWL_HAS_GLAMOR */
-
 PixmapPtr
 xwl_window_swap_pixmap(struct xwl_window *xwl_window)
 {
@@ -434,17 +367,9 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window)
         RegionPtr full_damage = xwl_window_buffer->damage_region;
         BoxPtr pBox = RegionRects(full_damage);
         int nBox = RegionNumRects(full_damage);
-
 #ifdef XWL_HAS_GLAMOR
-        if (xwl_window_buffer->syncobj) {
-            int fence_fd =
-                xwl_window_buffer->syncobj->export_fence(xwl_window_buffer->syncobj,
-                                                         xwl_window_buffer->timeline_point);
-            xwl_glamor_wait_fence(xwl_screen, fence_fd);
-            close(fence_fd);
-        }
+        xwl_glamor_gbm_wait_syncpts(xwl_window_buffer->pixmap);
 #endif /* XWL_HAS_GLAMOR */
-
         while (nBox--) {
             copy_pixmap_area(window_pixmap,
                              xwl_window_buffer->pixmap,
@@ -485,21 +410,17 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window)
 
 #ifdef XWL_HAS_GLAMOR
     if (!xwl_glamor_supports_implicit_sync(xwl_screen)) {
-        if (xwl_screen->explicit_sync && xwl_window_buffers_set_syncpts(xwl_window_buffer)) {
+        if (xwl_screen->explicit_sync && xwl_glamor_gbm_set_syncpts(xwl_window, window_pixmap)) {
             implicit_sync = FALSE;
             /* wait until the release fence is available before re-using this buffer */
-            xwl_window_buffer->efd = eventfd(0, EFD_CLOEXEC);
-            SetNotifyFd(xwl_window_buffer->efd, xwl_window_buffers_release_fence_avail,
-                        X_NOTIFY_READ, xwl_window_buffer);
-            xwl_window_buffer->syncobj->submitted_eventfd(xwl_window_buffer->syncobj,
-                                                          xwl_window_buffer->timeline_point,
-                                                          xwl_window_buffer->efd);
-        } else
+            xwl_glamor_gbm_wait_release_fence(xwl_window, window_pixmap, xwl_window_buffer);
+        } else {
             /* If glamor does not support implicit sync and we can't use
              * explicit sync, wait for the GPU to be idle before presenting.
              * Note that buffer re-use will still be unsynchronized :(
              */
             glamor_finish(xwl_screen->screen);
+        }
     }
 #endif /* XWL_HAS_GLAMOR */
 
commit cc021aca9985c9105fa0bed58920393723599dd4
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jun 18 11:11:34 2024 +0200

    xwayland/glamor/gbm: Copy explicit sync code to GLAMOR/GBM
    
    Copy the code to deal with synchronization objects from the window
    buffers to the GLAMOR/GBM code.
    
    The idea is to deal with synchronizations for all pixmaps, even when
    there is no window buffer involved.
    
    This is still preparation work for the following commits, no functional
    change intended at this point.
    
    v2: Use a "xwl_window_buffer *" instead of a "void *data" (Michel)
    v3: Bail early if there's no xwl_window_buffer (Michel)
    v4: Rename xwl_window_submit_pixmap() to
        xwl_glamor_gbm_wait_release_fence() (Michel)
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1571>

diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index 8307f74b1..ebc990b57 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -32,6 +32,8 @@
 
 #include <fcntl.h>
 #include <errno.h>
+#include <poll.h>
+#include <sys/eventfd.h>
 #include <sys/stat.h>
 #include <xf86drm.h>
 #include <drm_fourcc.h>
@@ -55,6 +57,7 @@
 #include "xwayland-glamor-gbm.h"
 #include "xwayland-pixmap.h"
 #include "xwayland-screen.h"
+#include "xwayland-window-buffers.h"
 
 #include "linux-dmabuf-unstable-v1-client-protocol.h"
 #include "linux-drm-syncobj-v1-client-protocol.h"
@@ -82,6 +85,12 @@ struct xwl_pixmap {
     unsigned int texture;
     struct gbm_bo *bo;
     Bool implicit_modifier;
+#ifdef DRI3
+    struct dri3_syncobj *syncobj;
+    uint64_t timeline_point;
+    int efd;
+    struct xwl_window_buffer *xwl_window_buffer;
+#endif /* DRI3 */
 };
 
 static DevPrivateKeyRec xwl_gbm_private_key;
@@ -225,6 +234,9 @@ xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo,
     xwl_pixmap->bo = bo;
     xwl_pixmap->buffer = NULL;
     xwl_pixmap->implicit_modifier = implicit_modifier;
+#ifdef XWL_HAS_GLAMOR
+    xwl_pixmap->efd = -1;
+#endif /* XWL_HAS_GLAMOR */
 
 #ifdef GBM_BO_FD_FOR_PLANE
     if (xwl_gbm->dmabuf_capable) {
@@ -445,6 +457,7 @@ xwl_glamor_gbm_destroy_pixmap(PixmapPtr pixmap)
         eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
         if (xwl_pixmap->bo)
            gbm_bo_destroy(xwl_pixmap->bo);
+        xwl_glamor_gbm_dispose_syncpts(pixmap);
         free(xwl_pixmap);
     }
 
@@ -1388,6 +1401,21 @@ xwl_glamor_gbm_has_egl_extension(void)
             epoxy_has_egl_extension(NULL, "EGL_KHR_platform_gbm"));
 }
 
+#ifdef DRI3
+static void
+xwl_glamor_gbm_release_fence_avail(int fd, int xevents, void *data)
+{
+    struct xwl_pixmap *xwl_pixmap = data;
+    struct xwl_window_buffer *xwl_window_buffer = xwl_pixmap->xwl_window_buffer;
+
+    SetNotifyFd(fd, NULL, 0, NULL);
+    close(fd);
+    xwl_pixmap->efd = -1;
+
+    xwl_window_buffer_release(xwl_window_buffer);
+}
+#endif /* DRI3 */
+
 Bool
 xwl_glamor_supports_implicit_sync(struct xwl_screen *xwl_screen)
 {
@@ -1403,6 +1431,122 @@ xwl_glamor_supports_syncobjs(struct xwl_screen *xwl_screen)
         xwl_gbm_get(xwl_screen)->supports_syncobjs;
 }
 
+Bool
+xwl_glamor_gbm_set_syncpts(struct xwl_window *xwl_window, PixmapPtr pixmap)
+{
+#ifdef DRI3
+    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+    uint64_t acquire_point;
+    uint64_t release_point;
+    int fence_fd;
+
+    if (!xwl_screen->glamor)
+        return FALSE;
+
+    if (!xwl_pixmap) {
+        ErrorF("XWAYLAND: Failed to set synchronization point, no backing xwl_pixmap!\n");
+        return FALSE;
+    }
+
+    acquire_point = ++xwl_pixmap->timeline_point;
+    release_point = ++xwl_pixmap->timeline_point;
+
+    if (!xwl_pixmap->syncobj) {
+        struct dri3_syncobj *syncobj = xwl_glamor_dri3_syncobj_create(xwl_screen);
+        if (!syncobj)
+            goto fail;
+        xwl_pixmap->syncobj = syncobj;
+    }
+
+    fence_fd = xwl_glamor_get_fence(xwl_screen);
+    if (fence_fd >= 0)
+        xwl_pixmap->syncobj->import_fence(xwl_pixmap->syncobj, acquire_point, fence_fd);
+    else
+        goto fail;
+
+    xwl_glamor_dri3_syncobj_passthrough(xwl_window,
+                                        xwl_pixmap->syncobj,
+                                        xwl_pixmap->syncobj,
+                                        acquire_point,
+                                        release_point);
+    return TRUE;
+
+fail:
+    /* can't use explicit sync, we will do a glFinish() before presenting */
+    if (xwl_pixmap->syncobj) {
+        xwl_pixmap->syncobj->free(xwl_pixmap->syncobj);
+        xwl_pixmap->syncobj = NULL;
+    }
+#endif /* DRI3 */
+    return FALSE;
+}
+
+void
+xwl_glamor_gbm_dispose_syncpts(PixmapPtr pixmap)
+{
+#ifdef DRI3
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
+
+    if (!xwl_screen->glamor || !xwl_pixmap)
+        return;
+
+    if (xwl_pixmap->syncobj) {
+        xwl_pixmap->syncobj->free(xwl_pixmap->syncobj);
+        xwl_pixmap->syncobj = NULL;
+    }
+
+    if (xwl_pixmap->efd >= 0) {
+        SetNotifyFd(xwl_pixmap->efd, NULL, 0, NULL);
+        close(xwl_pixmap->efd);
+    }
+#endif /* DRI3 */
+}
+
+void
+xwl_glamor_gbm_wait_syncpts(PixmapPtr pixmap)
+{
+#ifdef DRI3
+    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+    int fence_fd;
+
+    if (!xwl_screen->glamor || !xwl_pixmap)
+        return;
+
+    if (xwl_pixmap->syncobj) {
+        fence_fd = xwl_pixmap->syncobj->export_fence(xwl_pixmap->syncobj,
+                                                     xwl_pixmap->timeline_point);
+        xwl_glamor_wait_fence(xwl_screen, fence_fd);
+        close(fence_fd);
+    }
+#endif /* DRI3 */
+}
+
+void
+xwl_glamor_gbm_wait_release_fence(struct xwl_window *xwl_window,
+                                  PixmapPtr pixmap,
+                                  struct xwl_window_buffer *xwl_window_buffer)
+{
+#ifdef DRI3
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
+
+    if (!xwl_screen->glamor || !xwl_pixmap || !xwl_window_buffer)
+        return;
+
+    xwl_pixmap->xwl_window_buffer = xwl_window_buffer;
+    /* wait until the release fence is available before re-using this buffer */
+    xwl_pixmap->efd = eventfd(0, EFD_CLOEXEC);
+    SetNotifyFd(xwl_pixmap->efd, xwl_glamor_gbm_release_fence_avail, X_NOTIFY_READ,
+                xwl_pixmap);
+    xwl_pixmap->syncobj->submitted_eventfd(xwl_pixmap->syncobj,
+                                           xwl_pixmap->timeline_point,
+                                           xwl_pixmap->efd);
+#endif /* DRI3 */
+}
+
 static Bool
 xwl_glamor_try_to_make_context_current(struct xwl_screen *xwl_screen)
 {
diff --git a/hw/xwayland/xwayland-glamor-gbm.h b/hw/xwayland/xwayland-glamor-gbm.h
index 9083f2578..b346a0ba6 100644
--- a/hw/xwayland/xwayland-glamor-gbm.h
+++ b/hw/xwayland/xwayland-glamor-gbm.h
@@ -42,4 +42,12 @@ Bool xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen);
 Bool xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen);
 drmDevice *xwl_gbm_get_main_device(struct xwl_screen *xwl_screen);
 
+/* Explicit buffer synchronization points */
+Bool xwl_glamor_gbm_set_syncpts(struct xwl_window *xwl_window, PixmapPtr pixmap);
+void xwl_glamor_gbm_dispose_syncpts(PixmapPtr pixmap);
+void xwl_glamor_gbm_wait_syncpts(PixmapPtr pixmap);
+void xwl_glamor_gbm_wait_release_fence(struct xwl_window *xwl_window,
+                                       PixmapPtr pixmap,
+                                       struct xwl_window_buffer *xwl_window_buffer);
+
 #endif /* XWAYLAND_GLAMOR_GBM_H */
commit b5082073b0ca49c27b1b6525760f9b3e0bca61c2
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jun 18 11:05:16 2024 +0200

    xwayland/window-buffers: Add xwl_window_buffer_release()
    
    We want to decorrelate the explicit buffer synchronization from the
    window buffers, and move that to the GLAMOR/GBM code instead.
    
    To do that, we need to be able to invoke the xwl_window_buffer's
    release_callback() routine from outside the window buffer code.
    
    For that purpose, introduce xwl_window_buffer_release() which calls
    xwl_window_buffer_release_callback() for us.
    
    This is preparation work for the following changes, no functional change
    intended at this point.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1571>

diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index 2e8b0859c..0b9861fbb 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -238,6 +238,12 @@ xwl_window_buffer_release_callback(void *data)
                  xwl_window);
 }
 
+void
+xwl_window_buffer_release(struct xwl_window_buffer *xwl_window_buffer)
+{
+    xwl_window_buffer_release_callback(xwl_window_buffer);
+}
+
 #ifdef XWL_HAS_GLAMOR
 static void
 xwl_window_buffers_release_fence_avail(int fd, int xevents, void *data)
diff --git a/hw/xwayland/xwayland-window-buffers.h b/hw/xwayland/xwayland-window-buffers.h
index c43712a13..ee26d3244 100644
--- a/hw/xwayland/xwayland-window-buffers.h
+++ b/hw/xwayland/xwayland-window-buffers.h
@@ -32,6 +32,7 @@
 #include "xwayland-types.h"
 
 void xwl_window_buffer_add_damage_region(struct xwl_window *xwl_window);
+void xwl_window_buffer_release(struct xwl_window_buffer *xwl_window_buffer);
 void xwl_window_buffers_init(struct xwl_window *xwl_window);
 void xwl_window_buffers_dispose(struct xwl_window *xwl_window);
 void xwl_window_realloc_pixmap(struct xwl_window *xwl_window);
commit 0e0472a0050f1ec19673f9e04531c41d816e386d
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Thu Jun 20 17:12:45 2024 +0200

    xwayland/window-buffers: Promote xwl_window_buffer
    
    Make the (opaque) definition of the xwl_window_buffer generally
    available.
    
    No functional change.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1571>

diff --git a/hw/xwayland/xwayland-types.h b/hw/xwayland/xwayland-types.h
index 73a674633..d3fd2a0fc 100644
--- a/hw/xwayland/xwayland-types.h
+++ b/hw/xwayland/xwayland-types.h
@@ -31,5 +31,6 @@ struct xwl_window;
 struct xwl_screen;
 struct xwl_drm_lease;
 struct xwl_output;
+struct xwl_window_buffer;
 
 #endif /* XWAYLAND_TYPES_H */
diff --git a/hw/xwayland/xwayland-window-buffers.h b/hw/xwayland/xwayland-window-buffers.h
index 8b463e671..c43712a13 100644
--- a/hw/xwayland/xwayland-window-buffers.h
+++ b/hw/xwayland/xwayland-window-buffers.h
@@ -31,8 +31,6 @@
 
 #include "xwayland-types.h"
 
-struct xwl_window_buffer;
-
 void xwl_window_buffer_add_damage_region(struct xwl_window *xwl_window);
 void xwl_window_buffers_init(struct xwl_window *xwl_window);
 void xwl_window_buffers_dispose(struct xwl_window *xwl_window);


More information about the xorg-commit mailing list