From cc021aca9985c9105fa0bed58920393723599dd4 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Tue, 18 Jun 2024 11:11:34 +0200 Subject: [PATCH] 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 Part-of: --- hw/xwayland/xwayland-glamor-gbm.c | 144 ++++++++++++++++++++++++++++++ hw/xwayland/xwayland-glamor-gbm.h | 8 ++ 2 files changed, 152 insertions(+) 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 #include +#include +#include #include #include #include @@ -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 */