diff --git a/debian/changelog b/debian/changelog index 6c0b3cc..0e96e37 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -xwayland (2:23.2.3-100pika5) pikauwu; urgency=medium +xwayland (2:24.1.0-100pika1) pikauwu; urgency=medium * Update to pikauwu diff --git a/main.sh b/main.sh index cc24e32..41e5859 100755 --- a/main.sh +++ b/main.sh @@ -1,5 +1,5 @@ # Clone Upstream -git clone https://gitlab.freedesktop.org/ekurzinger/xserver ./xwayland +git clone https://gitlab.freedesktop.org/xorg/xserver ./xwayland cp -rvf ./debian ./xwayland/ #cp -vf ./meson.build ./xwayland/ cd ./xwayland diff --git a/meson.build b/meson.build index c7e0e99..6fa7e5a 100644 --- a/meson.build +++ b/meson.build @@ -3,7 +3,7 @@ project('xwayland', 'c', 'buildtype=debugoptimized', 'c_std=gnu99', ], - version: '23.2.4', + version: '24.1.0', meson_version: '>= 0.52.0', ) release_date = '2024-01-16' diff --git a/patches/1120.patch b/patches/1120.patch deleted file mode 100644 index ba9bbb8..0000000 --- a/patches/1120.patch +++ /dev/null @@ -1,290 +0,0 @@ -From e25d1a5095f2267ba0c15396784abb7a99881624 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michel=20D=C3=A4nzer?= -Date: Thu, 11 May 2023 17:52:49 +0200 -Subject: [PATCH 1/2] xwayland: Add xwl_glamor_pixmap_is_from_fds - -Determines whether or not the pixmap was created by importing dma-buf -file descriptors. - -Will be used by the next commit. ---- - hw/xwayland/xwayland-glamor-gbm.c | 18 +++++++++++++++--- - hw/xwayland/xwayland-glamor.c | 11 +++++++++++ - hw/xwayland/xwayland-glamor.h | 6 ++++++ - 3 files changed, 32 insertions(+), 3 deletions(-) - -diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c -index 4086e78ba2..d0748c2c9a 100644 ---- a/hw/xwayland/xwayland-glamor-gbm.c -+++ b/hw/xwayland/xwayland-glamor-gbm.c -@@ -69,6 +69,7 @@ struct xwl_pixmap { - EGLImage image; - unsigned int texture; - struct gbm_bo *bo; -+ Bool from_fds; - Bool implicit_modifier; - }; - -@@ -118,7 +119,7 @@ is_device_path_render_node (const char *device_path) - static PixmapPtr - xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, - int depth, -- Bool implicit_modifier) -+ Bool implicit_modifier, Bool from_fds) - { - PixmapPtr pixmap; - struct xwl_pixmap *xwl_pixmap; -@@ -190,6 +191,7 @@ xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, - xwl_glamor_egl_make_current(xwl_screen); - xwl_pixmap->bo = bo; - xwl_pixmap->buffer = NULL; -+ xwl_pixmap->from_fds = from_fds; - xwl_pixmap->implicit_modifier = implicit_modifier; - - #ifdef GBM_BO_FD_FOR_PLANE -@@ -336,7 +338,8 @@ xwl_glamor_gbm_create_pixmap_internal(struct xwl_screen *xwl_screen, - } - - if (bo) { -- pixmap = xwl_glamor_gbm_create_pixmap_for_bo(xwl_screen->screen, bo, depth, implicit); -+ pixmap = xwl_glamor_gbm_create_pixmap_for_bo(xwl_screen->screen, bo, depth, -+ implicit, FALSE); - - if (!pixmap) { - gbm_bo_destroy(bo); -@@ -553,6 +556,14 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap) - return xwl_pixmap->buffer; - } - -+static Bool -+xwl_glamor_gbm_pixmap_is_from_fds(PixmapPtr pixmap) -+{ -+ struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); -+ -+ return xwl_pixmap && xwl_pixmap->from_fds; -+} -+ - static void - xwl_glamor_gbm_cleanup(struct xwl_screen *xwl_screen) - { -@@ -722,7 +733,7 @@ glamor_pixmap_from_fds(ScreenPtr screen, CARD8 num_fds, const int *fds, - if (bo == NULL) - goto error; - -- pixmap = xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth, implicit); -+ pixmap = xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth, implicit, TRUE); - if (pixmap == NULL) { - gbm_bo_destroy(bo); - goto error; -@@ -1246,6 +1257,7 @@ xwl_glamor_init_gbm(struct xwl_screen *xwl_screen) - xwl_screen->gbm_backend.init_egl = xwl_glamor_gbm_init_egl; - xwl_screen->gbm_backend.init_screen = xwl_glamor_gbm_init_screen; - xwl_screen->gbm_backend.get_wl_buffer_for_pixmap = xwl_glamor_gbm_get_wl_buffer_for_pixmap; -+ xwl_screen->gbm_backend.pixmap_is_from_fds = xwl_glamor_gbm_pixmap_is_from_fds; - xwl_screen->gbm_backend.check_flip = NULL; - xwl_screen->gbm_backend.get_main_device = xwl_gbm_get_main_device; - xwl_screen->gbm_backend.is_available = TRUE; -diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c -index 3c03b2523c..1e7029ab3e 100644 ---- a/hw/xwayland/xwayland-glamor.c -+++ b/hw/xwayland/xwayland-glamor.c -@@ -865,6 +865,17 @@ xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap) - return NULL; - } - -+Bool -+xwl_glamor_pixmap_is_from_fds(PixmapPtr pixmap) -+{ -+ struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen); -+ -+ if (xwl_screen->egl_backend->pixmap_is_from_fds) -+ return xwl_screen->egl_backend->pixmap_is_from_fds(pixmap); -+ -+ return FALSE; -+} -+ - Bool - xwl_glamor_post_damage(struct xwl_window *xwl_window, - PixmapPtr pixmap, RegionPtr region) -diff --git a/hw/xwayland/xwayland-glamor.h b/hw/xwayland/xwayland-glamor.h -index 313d7faf17..cbdacc5a7c 100644 ---- a/hw/xwayland/xwayland-glamor.h -+++ b/hw/xwayland/xwayland-glamor.h -@@ -80,6 +80,11 @@ struct xwl_egl_backend { - */ - struct wl_buffer *(*get_wl_buffer_for_pixmap)(PixmapPtr pixmap); - -+ /* Called by Xwayland to check whether this pixmap was created by importing -+ * dma-buf file descriptors. -+ */ -+ Bool (*pixmap_is_from_fds)(PixmapPtr pixmap); -+ - /* Called by Xwayland to perform any pre-wl_surface damage routines - * that are required by the backend. If your backend is poorly - * designed and lacks the ability to render directly to a surface, -@@ -123,6 +128,7 @@ Bool xwl_dmabuf_setup_feedback_for_window(struct xwl_window *xwl_window); - Bool xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version); - struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap); -+Bool xwl_glamor_pixmap_is_from_fds(PixmapPtr pixmap); - void xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen, - struct wl_registry *registry, - uint32_t id, const char *interface, --- -GitLab - - -From 1b7bd5be91a40172843312f6c03f0aa6a7491112 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michel=20D=C3=A4nzer?= -Date: Thu, 11 May 2023 18:12:27 +0200 -Subject: [PATCH 2/2] xwayland: Poll dma-buf fds in xwl_present_pixmap - -Wait for all of them to become readable before processing the -PresentPixmap request. This corresponds to the GPU drawing to the buffer -having completed. - -This has various benefits, e.g. the target MSC calculation can be more -accurate in some cases. - -A potential downside is that it may impact the frame rate of very light -clients such as vblank_mode=0 glxgears. Shouldn't affect real-world apps -though. ---- - hw/xwayland/xwayland-present.c | 106 +++++++++++++++++++++++++++++++++ - 1 file changed, 106 insertions(+) - -diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c -index 189e7cfd65..6f12ea66fd 100644 ---- a/hw/xwayland/xwayland-present.c -+++ b/hw/xwayland/xwayland-present.c -@@ -27,7 +27,9 @@ - - #include - #include -+#include - -+#include "xwayland-glamor.h" - #include "xwayland-present.h" - #include "xwayland-screen.h" - #include "xwayland-window.h" -@@ -898,6 +900,105 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) - present_execute_post(vblank, ust, crtc_msc); - } - -+struct xwl_present_busy_dmabufs { -+ ClientPtr client; -+ int fds[4]; -+}; -+ -+/* Called when a dma-buf fd has become readable */ -+static void -+xwl_present_dmabuf_ready(int fd, int ready, void *data) -+{ -+ struct xwl_present_busy_dmabufs *busy_dmabufs = data; -+ int i, num_fds; -+ -+ for (i = 0, num_fds = 0; i < 4; i++) { -+ if (busy_dmabufs->fds[i] == fd) -+ busy_dmabufs->fds[i] = -1; -+ else if (busy_dmabufs->fds[i] >= 0) -+ num_fds++; -+ } -+ -+ RemoveNotifyFd(fd); -+ close(fd); -+ -+ if (num_fds > 0) -+ return; -+ -+ /* All dma-buf fds have become readable, resume processing client requests */ -+ AttendClient(busy_dmabufs->client); -+ free(busy_dmabufs); -+} -+ -+/* Wait for all dma-buf fds to become readable before processing the -+ * PresentPixmap request. This corresponds to the GPU drawing to the buffer -+ * having completed. -+ */ -+static Bool -+xwl_present_is_dmabuf_busy(PixmapPtr pixmap) -+{ -+ ScreenPtr screen = pixmap->drawable.pScreen; -+ ClientPtr client = GetCurrentClient(); -+ struct xwl_present_busy_dmabufs *busy_dmabufs; -+ int fds[4], num_fds; -+ uint32_t strides[4], offsets[4]; -+ uint64_t modifier; -+ int i, j; -+ -+ num_fds = glamor_egl_fds_from_pixmap(screen, pixmap, fds, strides, offsets, &modifier); -+ if (num_fds <= 0) -+ return FALSE; -+ -+ busy_dmabufs = XNFalloc(sizeof(struct xwl_present_busy_dmabufs)); -+ -+ for (i = num_fds; i < 4; i++) -+ busy_dmabufs->fds[i] = -1; -+ -+ /* Deduplicate fds */ -+ for (i = 0; i < num_fds; i++) { -+ for (j = 0; j < i; j++) { -+ if (busy_dmabufs->fds[j] == fds[i]) -+ break; -+ } -+ -+ if (j == i) -+ busy_dmabufs->fds[i] = fds[i]; -+ else -+ busy_dmabufs->fds[i] = -1; -+ } -+ -+ for (i = 0, num_fds = 0; i < 4; i++) { -+ struct pollfd poll_fd = { .fd = busy_dmabufs->fds[i] }; -+ -+ if (poll_fd.fd < 0) -+ continue; -+ -+ poll_fd.events = POLLIN; -+ if (xserver_poll(&poll_fd, 1, 0) > 0) { -+ close(busy_dmabufs->fds[i]); -+ busy_dmabufs->fds[i] = -1; -+ continue; -+ } -+ -+ if (busy_dmabufs->fds[i] < MAXCLIENTS) -+ busy_dmabufs->fds[i] = os_move_fd(busy_dmabufs->fds[i]); -+ -+ num_fds++; -+ SetNotifyFd(busy_dmabufs->fds[i], xwl_present_dmabuf_ready, X_NOTIFY_READ, busy_dmabufs); -+ } -+ -+ if (num_fds == 0) { -+ free(busy_dmabufs); -+ return FALSE; -+ } -+ -+ busy_dmabufs->client = client; -+ ResetCurrentRequest(client); -+ client->sequence--; -+ IgnoreClient(client); -+ return TRUE; -+} -+ - static int - xwl_present_pixmap(WindowPtr window, - PixmapPtr pixmap, -@@ -929,6 +1030,11 @@ xwl_present_pixmap(WindowPtr window, - if (!window_priv) - return BadAlloc; - -+ if (pixmap && -+ xwl_glamor_pixmap_is_from_fds(pixmap) && -+ xwl_present_is_dmabuf_busy(pixmap)) -+ return Success; -+ - target_crtc = xwl_present_get_crtc(screen_priv, window); - - ret = xwl_present_get_ust_msc(screen, window, &ust, &crtc_msc); --- -GitLab - diff --git a/patches/967.patch b/patches/967.patch deleted file mode 100644 index 198e2fa..0000000 --- a/patches/967.patch +++ /dev/null @@ -1,2676 +0,0 @@ -From ed9991b1152359079b72d8193509aea0de395f1b Mon Sep 17 00:00:00 2001 -From: Erik Kurzinger -Date: Tue, 24 Oct 2023 16:14:17 -0700 -Subject: [PATCH 1/6] DRI3: provide stub implementation of - DRI3SetDRMDeviceInUse - -DRI3 version 1.3 introduced a new request which allows clients to -provide a hint to the server about which DRM device they are using, so -that the server might return DRM format modifiers specific to that -device. However, implementing such functionality, for Xwayland in -particular, will require fairly significant architectural changes. - -To avoid blocking future versions of the DRI3 extension, we provide here -a stub implementation for the request in question. The spec explicitly -states that it is only a hint that the server is free to ignore, so -strictly speaking this implementation is still correct. - -Signed-off-by: Erik Kurzinger ---- - dri3/dri3_request.c | 34 ++++++++++++++++++++++++++++++++++ - include/protocol-versions.h | 2 +- - 2 files changed, 35 insertions(+), 1 deletion(-) - -diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c -index 6871689308..f7170518f4 100644 ---- a/dri3/dri3_request.c -+++ b/dri3/dri3_request.c -@@ -554,6 +554,27 @@ proc_dri3_buffers_from_pixmap(ClientPtr client) - return Success; - } - -+static int -+proc_dri3_set_drm_device_in_use(ClientPtr client) -+{ -+ REQUEST(xDRI3SetDRMDeviceInUseReq); -+ WindowPtr window; -+ int status; -+ -+ REQUEST_SIZE_MATCH(xDRI3SetDRMDeviceInUseReq); -+ status = dixLookupWindow(&window, stuff->window, client, -+ DixGetAttrAccess); -+ if (status != Success) -+ return status; -+ -+ /* TODO Eventually we should use this information to have -+ * DRI3GetSupportedModifiers return device-specific modifiers, but for now -+ * we will ignore it until multi-device support is more complete. -+ * Otherwise we can't advertise support for DRI3 1.4. -+ */ -+ return Success; -+} -+ - int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { - proc_dri3_query_version, /* 0 */ - proc_dri3_open, /* 1 */ -@@ -564,6 +585,7 @@ int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { - proc_dri3_get_supported_modifiers, /* 6 */ - proc_dri3_pixmap_from_buffers, /* 7 */ - proc_dri3_buffers_from_pixmap, /* 8 */ -+ proc_dri3_set_drm_device_in_use, /* 9 */ - }; - - int -@@ -697,6 +719,17 @@ sproc_dri3_buffers_from_pixmap(ClientPtr client) - return (*proc_dri3_vector[stuff->dri3ReqType]) (client); - } - -+static int _X_COLD -+sproc_dri3_set_drm_device_in_use(ClientPtr client) -+{ -+ REQUEST(xDRI3SetDRMDeviceInUseReq); -+ REQUEST_SIZE_MATCH(xDRI3SetDRMDeviceInUseReq); -+ swapl(&stuff->window); -+ swapl(&stuff->drmMajor); -+ swapl(&stuff->drmMinor); -+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client); -+} -+ - int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { - sproc_dri3_query_version, /* 0 */ - sproc_dri3_open, /* 1 */ -@@ -707,6 +740,7 @@ int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { - sproc_dri3_get_supported_modifiers, /* 6 */ - sproc_dri3_pixmap_from_buffers, /* 7 */ - sproc_dri3_buffers_from_pixmap, /* 8 */ -+ sproc_dri3_set_drm_device_in_use, /* 9 */ - }; - - int _X_COLD -diff --git a/include/protocol-versions.h b/include/protocol-versions.h -index bb2b81b8f9..951cc6357e 100644 ---- a/include/protocol-versions.h -+++ b/include/protocol-versions.h -@@ -52,7 +52,7 @@ - - /* DRI3 */ - #define SERVER_DRI3_MAJOR_VERSION 1 --#define SERVER_DRI3_MINOR_VERSION 2 -+#define SERVER_DRI3_MINOR_VERSION 3 - - /* DMX */ - #define SERVER_DMX_MAJOR_VERSION 2 --- -GitLab - - -From 7bdf16ff9725990ed1e54437748bed3899e9d67b Mon Sep 17 00:00:00 2001 -From: Erik Kurzinger -Date: Tue, 16 Aug 2022 11:57:40 -0700 -Subject: [PATCH 2/6] DRI3: add DRI3ImportSyncobj and DRI3FreeSyncobj - -Adds the required infrastructure in the core DRI3 code to support -importing DRM synchronization objects from clients. This includes -support for the two new protocol requests from DRI3 version 1.4, an -internal representation of these objects in the form of the dri3_syncobj -structure, and an import_syncobj screen info callback. - -The following operations are defined for dri3_syncobj objects -* free - release any server-side resources associated with the object -* has_fence - check if the fence for a timeline point is submitted -* is_signaled - check if a timeline point is signaled -* export_fence - return a sync fd corresponding to a timeline point -* import_fence - submit a sync fd as the fence for a timeline point -* signal - immediately signal a timeline point -* submitted_eventfd and signaled_eventfd - register an eventfd to be - signaled when the given timeline point is either submitted or - signaled - -Implementations will be responsible for populating these function -pointers when importing a syncobj. - -Signed-off-by: Erik Kurzinger ---- - dri3/dri3.c | 15 ++++++ - dri3/dri3.h | 38 +++++++++++++++- - dri3/dri3_priv.h | 3 ++ - dri3/dri3_request.c | 91 +++++++++++++++++++++++++++++++++++++ - dri3/dri3_screen.c | 20 ++++++++ - include/protocol-versions.h | 2 +- - 6 files changed, 167 insertions(+), 2 deletions(-) - -diff --git a/dri3/dri3.c b/dri3/dri3.c -index 1912529695..f9c5172774 100644 ---- a/dri3/dri3.c -+++ b/dri3/dri3.c -@@ -63,6 +63,16 @@ dri3_screen_init(ScreenPtr screen, const dri3_screen_info_rec *info) - return TRUE; - } - -+RESTYPE dri3_syncobj_type; -+ -+static int dri3_syncobj_free(void *data, XID id) -+{ -+ struct dri3_syncobj *syncobj = data; -+ if (--syncobj->refcount == 0) -+ syncobj->free(syncobj); -+ return 0; -+} -+ - void - dri3_extension_init(void) - { -@@ -92,6 +102,11 @@ dri3_extension_init(void) - if (!dri3_screen_init(screenInfo.screens[i], NULL)) - goto bail; - } -+ -+ dri3_syncobj_type = CreateNewResourceType(dri3_syncobj_free, "DRI3Syncobj"); -+ if (!dri3_syncobj_type) -+ goto bail; -+ - return; - - bail: -diff --git a/dri3/dri3.h b/dri3/dri3.h -index 02d3b03eec..14f9a1efa7 100644 ---- a/dri3/dri3.h -+++ b/dri3/dri3.h -@@ -28,7 +28,35 @@ - #include - #include - --#define DRI3_SCREEN_INFO_VERSION 2 -+#define DRI3_SCREEN_INFO_VERSION 4 -+ -+extern RESTYPE dri3_syncobj_type; -+ -+struct dri3_syncobj -+{ -+ XID id; -+ ScreenPtr screen; -+ uint32_t refcount; -+ -+ void (*free)(struct dri3_syncobj *syncobj); -+ Bool (*has_fence)(struct dri3_syncobj *syncobj, uint64_t point); -+ Bool (*is_signaled)(struct dri3_syncobj *syncobj, uint64_t point); -+ int (*export_fence)(struct dri3_syncobj *syncobj, uint64_t point); -+ void (*import_fence)(struct dri3_syncobj *syncobj, uint64_t point, int fd); -+ void (*signal)(struct dri3_syncobj *syncobj, uint64_t point); -+ void (*submitted_eventfd)(struct dri3_syncobj *syncobj, uint64_t point, int efd); -+ void (*signaled_eventfd)(struct dri3_syncobj *syncobj, uint64_t point, int efd); -+}; -+ -+#define VERIFY_DRI3_SYNCOBJ(id, ptr, a)\ -+ do {\ -+ int rc = dixLookupResourceByType((void **)&(ptr), id,\ -+ dri3_syncobj_type, client, a);\ -+ if (rc != Success) {\ -+ client->errorValue = id;\ -+ return rc;\ -+ }\ -+ } while (0); - - typedef int (*dri3_open_proc)(ScreenPtr screen, - RRProviderPtr provider, -@@ -84,6 +112,11 @@ typedef int (*dri3_get_drawable_modifiers_proc) (DrawablePtr draw, - uint32_t *num_modifiers, - uint64_t **modifiers); - -+typedef struct dri3_syncobj *(*dri3_import_syncobj_proc) (ClientPtr client, -+ ScreenPtr screen, -+ XID id, -+ int fd); -+ - typedef struct dri3_screen_info { - uint32_t version; - -@@ -101,6 +134,9 @@ typedef struct dri3_screen_info { - dri3_get_modifiers_proc get_modifiers; - dri3_get_drawable_modifiers_proc get_drawable_modifiers; - -+ /* Version 4 */ -+ dri3_import_syncobj_proc import_syncobj; -+ - } dri3_screen_info_rec, *dri3_screen_info_ptr; - - extern _X_EXPORT Bool -diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h -index f319d17702..71d2da9571 100644 ---- a/dri3/dri3_priv.h -+++ b/dri3/dri3_priv.h -@@ -102,4 +102,7 @@ dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable, - CARD32 *num_screen_modifiers, - CARD64 **screen_modifiers); - -+int -+dri3_import_syncobj(ClientPtr client, ScreenPtr screen, XID id, int fd); -+ - #endif /* _DRI3PRIV_H_ */ -diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c -index f7170518f4..520cd60c20 100644 ---- a/dri3/dri3_request.c -+++ b/dri3/dri3_request.c -@@ -28,6 +28,17 @@ - #include - #include - -+static Bool -+dri3_screen_can_one_point_four(ScreenPtr screen) -+{ -+ dri3_screen_priv_ptr dri3 = dri3_screen_priv(screen); -+ -+ return dri3 && -+ dri3->info && -+ dri3->info->version >= 4 && -+ dri3->info->import_syncobj; -+} -+ - static Bool - dri3_screen_can_one_point_two(ScreenPtr screen) - { -@@ -61,6 +72,10 @@ proc_dri3_query_version(ClientPtr client) - rep.minorVersion = 0; - break; - } -+ if (!dri3_screen_can_one_point_four(screenInfo.screens[i])) { -+ rep.minorVersion = 2; -+ break; -+ } - } - - for (int i = 0; i < screenInfo.numGPUScreens; i++) { -@@ -68,6 +83,10 @@ proc_dri3_query_version(ClientPtr client) - rep.minorVersion = 0; - break; - } -+ if (!dri3_screen_can_one_point_four(screenInfo.gpuscreens[i])) { -+ rep.minorVersion = 2; -+ break; -+ } - } - - /* From DRI3 proto: -@@ -575,6 +594,51 @@ proc_dri3_set_drm_device_in_use(ClientPtr client) - return Success; - } - -+static int -+proc_dri3_import_syncobj(ClientPtr client) -+{ -+ REQUEST(xDRI3ImportSyncobjReq); -+ DrawablePtr drawable; -+ ScreenPtr screen; -+ int fd; -+ int status; -+ -+ SetReqFds(client, 1); -+ REQUEST_SIZE_MATCH(xDRI3ImportSyncobjReq); -+ LEGAL_NEW_RESOURCE(stuff->syncobj, client); -+ -+ status = dixLookupDrawable(&drawable, stuff->drawable, client, -+ M_ANY, DixGetAttrAccess); -+ if (status != Success) -+ return status; -+ -+ screen = drawable->pScreen; -+ -+ fd = ReadFdFromClient(client); -+ if (fd < 0) -+ return BadValue; -+ -+ return dri3_import_syncobj(client, screen, stuff->syncobj, fd); -+} -+ -+static int -+proc_dri3_free_syncobj(ClientPtr client) -+{ -+ REQUEST(xDRI3FreeSyncobjReq); -+ struct dri3_syncobj *syncobj; -+ int status; -+ -+ REQUEST_SIZE_MATCH(xDRI3FreeSyncobjReq); -+ -+ status = dixLookupResourceByType((void **) &syncobj, stuff->syncobj, -+ dri3_syncobj_type, client, DixWriteAccess); -+ if (status != Success) -+ return status; -+ -+ FreeResource(stuff->syncobj, dri3_syncobj_type); -+ return Success; -+} -+ - int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { - proc_dri3_query_version, /* 0 */ - proc_dri3_open, /* 1 */ -@@ -586,6 +650,8 @@ int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { - proc_dri3_pixmap_from_buffers, /* 7 */ - proc_dri3_buffers_from_pixmap, /* 8 */ - proc_dri3_set_drm_device_in_use, /* 9 */ -+ proc_dri3_import_syncobj, /* 10 */ -+ proc_dri3_free_syncobj, /* 11 */ - }; - - int -@@ -730,6 +796,29 @@ sproc_dri3_set_drm_device_in_use(ClientPtr client) - return (*proc_dri3_vector[stuff->dri3ReqType]) (client); - } - -+static int _X_COLD -+sproc_dri3_import_syncobj(ClientPtr client) -+{ -+ REQUEST(xDRI3ImportSyncobjReq); -+ REQUEST_SIZE_MATCH(xDRI3ImportSyncobjReq); -+ -+ swaps(&stuff->length); -+ swapl(&stuff->syncobj); -+ swapl(&stuff->drawable); -+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client); -+} -+ -+static int _X_COLD -+sproc_dri3_free_syncobj(ClientPtr client) -+{ -+ REQUEST(xDRI3FreeSyncobjReq); -+ REQUEST_SIZE_MATCH(xDRI3FreeSyncobjReq); -+ -+ swaps(&stuff->length); -+ swapl(&stuff->syncobj); -+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client); -+} -+ - int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { - sproc_dri3_query_version, /* 0 */ - sproc_dri3_open, /* 1 */ -@@ -741,6 +830,8 @@ int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { - sproc_dri3_pixmap_from_buffers, /* 7 */ - sproc_dri3_buffers_from_pixmap, /* 8 */ - sproc_dri3_set_drm_device_in_use, /* 9 */ -+ sproc_dri3_import_syncobj, /* 10 */ -+ sproc_dri3_free_syncobj, /* 11 */ - }; - - int _X_COLD -diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c -index bc96e5339c..5614a22b35 100644 ---- a/dri3/dri3_screen.c -+++ b/dri3/dri3_screen.c -@@ -272,3 +272,23 @@ dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable, - - return Success; - } -+ -+int dri3_import_syncobj(ClientPtr client, ScreenPtr screen, XID id, int fd) -+{ -+ const dri3_screen_info_rec *info = dri3_screen_priv(screen)->info; -+ struct dri3_syncobj *syncobj = NULL; -+ -+ if (info->version < 4 || !info->import_syncobj) -+ return BadImplementation; -+ -+ syncobj = info->import_syncobj(client, screen, id, fd); -+ close(fd); -+ -+ if (!syncobj) -+ return BadAlloc; -+ -+ if (!AddResource(id, dri3_syncobj_type, syncobj)) -+ return BadAlloc; -+ -+ return Success; -+} -diff --git a/include/protocol-versions.h b/include/protocol-versions.h -index 951cc6357e..2b0f85e392 100644 ---- a/include/protocol-versions.h -+++ b/include/protocol-versions.h -@@ -52,7 +52,7 @@ - - /* DRI3 */ - #define SERVER_DRI3_MAJOR_VERSION 1 --#define SERVER_DRI3_MINOR_VERSION 3 -+#define SERVER_DRI3_MINOR_VERSION 4 - - /* DMX */ - #define SERVER_DMX_MAJOR_VERSION 2 --- -GitLab - - -From 1faf528c3c99884a8d04031ee96a1ff44531f77f Mon Sep 17 00:00:00 2001 -From: Erik Kurzinger -Date: Tue, 16 Aug 2022 11:59:14 -0700 -Subject: [PATCH 3/6] xwayland: implement support for DRI3 syncobjs - -Adds an implementation of the import_syncobj DRI3 screen info callback -for Xwayland along with the various operations defined for dri3_syncobj -objects. - -Signed-off-by: Erik Kurzinger ---- - hw/xwayland/xwayland-glamor-gbm.c | 214 +++++++++++++++++++++++++++++- - 1 file changed, 213 insertions(+), 1 deletion(-) - -diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c -index 69ead78f26..35c06f5bee 100644 ---- a/hw/xwayland/xwayland-glamor-gbm.c -+++ b/hw/xwayland/xwayland-glamor-gbm.c -@@ -843,7 +843,213 @@ glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, - return -1; - } - --static const dri3_screen_info_rec xwl_dri3_info = { -+struct xwl_dri3_syncobj -+{ -+ struct dri3_syncobj base; -+ uint32_t handle; -+}; -+ -+static Bool -+xwl_dri3_check_syncobj(struct dri3_syncobj *syncobj, uint64_t point, Bool check_avail) -+{ -+ struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; -+ struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); -+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -+ -+ return !drmSyncobjTimelineWait(xwl_gbm->drm_fd, -+ &xwl_syncobj->handle, &point, 1, -+ 0 /* timeout */, -+ check_avail ? -+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : -+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, -+ NULL /* first_signaled */); -+} -+ -+static Bool -+xwl_dri3_syncobj_has_fence(struct dri3_syncobj *syncobj, uint64_t point) -+{ -+ return xwl_dri3_check_syncobj(syncobj, point, TRUE /* check_avail */); -+} -+ -+static Bool -+xwl_dri3_syncobj_is_signaled(struct dri3_syncobj *syncobj, uint64_t point) -+{ -+ return xwl_dri3_check_syncobj(syncobj, point, FALSE /* check_avail */); -+} -+ -+extern int -+drmSyncobjImportSyncFileTimeline(int fd, uint32_t handle, -+ uint64_t point, int sync_file_fd) -+ __attribute__((weak)); -+extern int -+drmSyncobjExportSyncFileTimeline(int fd, uint32_t handle, -+ uint64_t point, int *sync_file_fd) -+ __attribute__((weak)); -+ -+static int -+xwl_dri3_syncobj_export_fence(struct dri3_syncobj *syncobj, uint64_t point) -+{ -+ struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; -+ struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); -+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -+ int fd = -1; -+ -+ if (!drmSyncobjExportSyncFileTimeline || -+ drmSyncobjExportSyncFileTimeline(xwl_gbm->drm_fd, -+ xwl_syncobj->handle, -+ point, &fd)) { -+ /* try legacy export procedure */ -+ uint32_t temp_syncobj; -+ drmSyncobjCreate(xwl_gbm->drm_fd, 0, &temp_syncobj); -+ drmSyncobjTransfer(xwl_gbm->drm_fd, temp_syncobj, 0, -+ xwl_syncobj->handle, point, 0); -+ drmSyncobjExportSyncFile(xwl_gbm->drm_fd, temp_syncobj, &fd); -+ drmSyncobjDestroy(xwl_gbm->drm_fd, temp_syncobj); -+ } -+ return fd; -+} -+ -+static void -+xwl_dri3_syncobj_import_fence(struct dri3_syncobj *syncobj, -+ uint64_t point, int fd) -+{ -+ struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; -+ struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); -+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -+ -+ if (!drmSyncobjImportSyncFileTimeline || -+ drmSyncobjImportSyncFileTimeline(xwl_gbm->drm_fd, -+ xwl_syncobj->handle, -+ point, fd)) { -+ /* try legacy import procedure */ -+ uint32_t temp_syncobj; -+ drmSyncobjCreate(xwl_gbm->drm_fd, 0, &temp_syncobj); -+ drmSyncobjImportSyncFile(xwl_gbm->drm_fd, temp_syncobj, fd); -+ drmSyncobjTransfer(xwl_gbm->drm_fd, xwl_syncobj->handle, point, -+ temp_syncobj, 0, 0); -+ drmSyncobjDestroy(xwl_gbm->drm_fd, temp_syncobj); -+ } -+ close(fd); -+} -+ -+static void -+xwl_dri3_signal_syncobj(struct dri3_syncobj *syncobj, uint64_t point) -+{ -+ struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; -+ struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); -+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -+ -+ drmSyncobjTimelineSignal(xwl_gbm->drm_fd, &xwl_syncobj->handle, &point, 1); -+} -+ -+static void -+xwl_dri3_free_syncobj(struct dri3_syncobj *syncobj) -+{ -+ struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; -+ struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); -+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -+ -+ if (xwl_syncobj->handle) -+ drmSyncobjDestroy(xwl_gbm->drm_fd, xwl_syncobj->handle); -+ -+ free(xwl_syncobj); -+} -+ -+static void -+xwl_dri3_syncobj_eventfd(struct dri3_syncobj *syncobj, uint64_t point, -+ int efd, Bool wait_avail) -+{ -+ struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; -+ struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); -+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -+ -+ drmSyncobjEventfd(xwl_gbm->drm_fd, xwl_syncobj->handle, point, efd, -+ wait_avail ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0); -+} -+ -+static void -+xwl_dri3_syncobj_submitted_eventfd(struct dri3_syncobj *syncobj, -+ uint64_t point, int efd) -+{ -+ xwl_dri3_syncobj_eventfd(syncobj, point, efd, TRUE /* wait_avail */); -+} -+ -+static void -+xwl_dri3_syncobj_signaled_eventfd(struct dri3_syncobj *syncobj, -+ uint64_t point, int efd) -+{ -+ xwl_dri3_syncobj_eventfd(syncobj, point, efd, FALSE /* wait_avail */); -+} -+ -+static struct dri3_syncobj * -+xwl_dri3_create_syncobj(struct xwl_screen *xwl_screen, uint32_t handle) -+{ -+ struct xwl_dri3_syncobj *syncobj = calloc(1, sizeof (*syncobj)); -+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -+ -+ if (!syncobj) -+ return NULL; -+ -+ syncobj->handle = handle; -+ syncobj->base.screen = xwl_screen->screen; -+ syncobj->base.refcount = 1; -+ -+ syncobj->base.free = xwl_dri3_free_syncobj; -+ syncobj->base.has_fence = xwl_dri3_syncobj_has_fence; -+ syncobj->base.is_signaled = xwl_dri3_syncobj_is_signaled; -+ syncobj->base.export_fence = xwl_dri3_syncobj_export_fence; -+ syncobj->base.import_fence = xwl_dri3_syncobj_import_fence; -+ syncobj->base.signal = xwl_dri3_signal_syncobj; -+ syncobj->base.signaled_eventfd = xwl_dri3_syncobj_signaled_eventfd; -+ syncobj->base.submitted_eventfd = xwl_dri3_syncobj_submitted_eventfd; -+ return &syncobj->base; -+ -+fail: -+ free(syncobj); -+ return NULL; -+} -+ -+static struct dri3_syncobj * -+xwl_dri3_import_syncobj(ClientPtr client, ScreenPtr screen, XID id, int fd) -+{ -+ struct xwl_screen *xwl_screen = xwl_screen_get(screen); -+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -+ struct xwl_dri3_syncobj *syncobj = NULL; -+ uint32_t handle; -+ -+ if (drmSyncobjFDToHandle(xwl_gbm->drm_fd, fd, &handle)) -+ return NULL; -+ -+ syncobj = (struct xwl_dri3_syncobj *)xwl_dri3_create_syncobj(xwl_screen, handle); -+ if (!syncobj) { -+ drmSyncobjDestroy(xwl_gbm->drm_fd, handle); -+ return NULL; -+ } -+ -+ syncobj->base.id = id; -+ -+ return &syncobj->base; -+} -+ -+static Bool -+xwl_gbm_supports_syncobjs(struct xwl_screen *xwl_screen) -+{ -+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -+ uint64_t syncobj_cap = 0; -+ -+ if (drmGetCap(xwl_gbm->drm_fd, DRM_CAP_SYNCOBJ_TIMELINE, -+ &syncobj_cap) || !syncobj_cap) -+ return FALSE; -+ -+ /* Check if syncobj eventfd is supported. */ -+ drmSyncobjEventfd(xwl_gbm->drm_fd, 0, 0, -1, 0); -+ if (errno != ENOENT) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+static dri3_screen_info_rec xwl_dri3_info = { - .version = 2, - .open = NULL, - .pixmap_from_fds = glamor_pixmap_from_fds, -@@ -852,6 +1058,7 @@ static const dri3_screen_info_rec xwl_dri3_info = { - .get_formats = xwl_glamor_get_formats, - .get_modifiers = xwl_glamor_get_modifiers, - .get_drawable_modifiers = xwl_glamor_get_drawable_modifiers, -+ .import_syncobj = NULL, /* need to check for kernel support */ - }; - - static const char * -@@ -1265,6 +1472,11 @@ xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen) - { - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - -+ if (xwl_gbm_supports_syncobjs(xwl_screen)) { -+ xwl_dri3_info.version = 4; -+ xwl_dri3_info.import_syncobj = xwl_dri3_import_syncobj; -+ } -+ - if (!dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) { - ErrorF("Failed to initialize dri3\n"); - goto error; --- -GitLab - - -From 9609ec156eb29bd66e3a5cf2001d6b222e0dada3 Mon Sep 17 00:00:00 2001 -From: Erik Kurzinger -Date: Tue, 16 Aug 2022 12:03:59 -0700 -Subject: [PATCH 4/6] Present: implement PresentPixmapSynced - -Adds support for an augmented version of PresentPixmap supporting -explicit synchronization with the GPU by way of a DRM synchronization -object. The new request will accept a previously imported timeline -syncobj along with acquire and release points on that timeline. - -If the backend reports support for PresentCapabilitySyncobj, the -syncobj, acquire, and release points will be attached to the vblank -structure for the present request, taking an extra reference to the -syncobj to ensure it is not freed before the request has completed. - -Initially, only the Xwayland backend will advertise -PresentCapabilitySyncobj, provided that the EGL driver supports the -ANDROID_native_fence_sync extension. - -Before executing a present request, if the given vblank has an attached -syncobj, we will first poll the acquire point. If it has not yet been -signaled, we will export the fence as a sync fd and add that to the -server's event loop. When the fence eventually is signaled, the request -will be re-executed. - -After executing a request, the release point must be signaled after any -GPU operations on the pixmap have completed. For flips, this can be done -as soon as the buffer has been released by the Wayland compositor (in -the case of Xwayland). For copies, we must insert a fence release into -the GPU command stream after the copy and transfer it to the syncobj. -This requires a new flush_fenced callback, which must be implemented by -any backends advertising PresentCapabilitySyncobj. This will perform the -same function as the current flush callback, but also return a sync fd -corresponding to the aforementioned fence. - -Signed-off-by: Erik Kurzinger ---- - hw/xfree86/common/xf86Module.h | 2 +- - hw/xwayland/xwayland-glamor.c | 24 +++++ - hw/xwayland/xwayland-glamor.h | 1 + - hw/xwayland/xwayland-present.c | 108 ++++++++++++++++++--- - hw/xwayland/xwayland-present.h | 5 +- - hw/xwayland/xwayland-screen.h | 2 + - include/protocol-versions.h | 2 +- - present/present.c | 9 ++ - present/present_execute.c | 34 ++++++- - present/present_priv.h | 25 +++++ - present/present_request.c | 170 ++++++++++++++++++++++++++------- - present/present_scmd.c | 8 ++ - present/present_screen.c | 1 + - present/present_vblank.c | 36 +++++++ - 14 files changed, 376 insertions(+), 51 deletions(-) - -diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h -index 6166e85590..b6eb806228 100644 ---- a/hw/xfree86/common/xf86Module.h -+++ b/hw/xfree86/common/xf86Module.h -@@ -74,7 +74,7 @@ - * mask is 0xFFFF0000. - */ - #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4) --#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(26, 1) -+#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(27, 0) - #define ABI_XINPUT_VERSION SET_ABI_VERSION(24, 4) - #define ABI_EXTENSION_VERSION SET_ABI_VERSION(10, 0) - -diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c -index 074594cc7a..850e25db05 100644 ---- a/hw/xwayland/xwayland-glamor.c -+++ b/hw/xwayland/xwayland-glamor.c -@@ -1073,6 +1073,30 @@ xwl_glamor_create_pixmap_for_window(struct xwl_window *xwl_window) - return NullPixmap; - } - -+int -+xwl_glamor_get_fence(struct xwl_screen *xwl_screen) -+{ -+ EGLint attribs[3]; -+ EGLSyncKHR sync; -+ int fence_fd = -1; -+ -+ if (!xwl_screen->glamor) -+ return -1; -+ -+ xwl_glamor_egl_make_current(xwl_screen); -+ -+ attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID; -+ attribs[1] = EGL_NO_NATIVE_FENCE_FD_ANDROID; -+ attribs[2] = EGL_NONE; -+ sync = eglCreateSyncKHR(xwl_screen->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); -+ if (sync != EGL_NO_SYNC_KHR) { -+ fence_fd = eglDupNativeFenceFDANDROID(xwl_screen->egl_display, sync); -+ eglDestroySyncKHR(xwl_screen->egl_display, sync); -+ } -+ -+ return fence_fd; -+} -+ - void - xwl_glamor_init_backends(struct xwl_screen *xwl_screen, Bool use_eglstream) - { -diff --git a/hw/xwayland/xwayland-glamor.h b/hw/xwayland/xwayland-glamor.h -index 97e8fb6642..260c60b652 100644 ---- a/hw/xwayland/xwayland-glamor.h -+++ b/hw/xwayland/xwayland-glamor.h -@@ -158,6 +158,7 @@ Bool xwl_glamor_get_drawable_modifiers(DrawablePtr drawable, uint32_t format, - uint32_t *num_modifiers, uint64_t **modifiers); - Bool xwl_glamor_check_flip(WindowPtr present_window, PixmapPtr pixmap); - PixmapPtr xwl_glamor_create_pixmap_for_window (struct xwl_window *xwl_window); -+int xwl_glamor_get_fence(struct xwl_screen *screen); - - #ifdef XV - /* glamor Xv Adaptor */ -diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c -index 783b04ff43..fb5a37b907 100644 ---- a/hw/xwayland/xwayland-present.c -+++ b/hw/xwayland/xwayland-present.c -@@ -30,6 +30,7 @@ - #endif - #include - #include -+#include - - #include "xwayland-present.h" - #include "xwayland-screen.h" -@@ -214,10 +215,18 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) - static void - xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); - -+static int -+xwl_present_queue_vblank(ScreenPtr screen, -+ WindowPtr present_window, -+ RRCrtcPtr crtc, -+ uint64_t event_id, -+ uint64_t msc); -+ - static uint32_t - xwl_present_query_capabilities(present_screen_priv_ptr screen_priv) - { -- return XWL_PRESENT_CAPS; -+ struct xwl_screen *xwl_screen = xwl_screen_get(screen_priv->pScreen); -+ return xwl_screen->present_capabilities; - } - - static int -@@ -236,6 +245,16 @@ xwl_present_get_ust_msc(ScreenPtr screen, - return Success; - } - -+static uint64_t -+xwl_present_get_exec_msc(uint32_t options, uint64_t target_msc) -+{ -+ /* Synchronous Xwayland presentations always complete (at least) one frame after they -+ * are executed -+ */ -+ return (options & PresentOptionAsyncMayTear) ? -+ target_msc : target_msc - 1; -+} -+ - /* - * When the wait fence or previous flip is completed, it's time - * to re-try the request -@@ -243,9 +262,27 @@ xwl_present_get_ust_msc(ScreenPtr screen, - static void - xwl_present_re_execute(present_vblank_ptr vblank) - { -+ struct xwl_present_event *event = xwl_present_event_from_vblank(vblank); - uint64_t ust = 0, crtc_msc = 0; - - (void) xwl_present_get_ust_msc(vblank->screen, vblank->window, &ust, &crtc_msc); -+ /* re-compute target / exec msc */ -+ vblank->target_msc = present_get_target_msc(0, crtc_msc, -+ event->divisor, -+ event->remainder, -+ event->options); -+ vblank->exec_msc = xwl_present_get_exec_msc(event->options, -+ vblank->target_msc); -+ -+ vblank->queued = TRUE; -+ if (msc_is_after(vblank->exec_msc, crtc_msc) && -+ xwl_present_queue_vblank(vblank->screen, vblank->window, -+ vblank->crtc, -+ vblank->event_id, -+ vblank->exec_msc) == Success) { -+ return; -+ } -+ - xwl_present_execute(vblank, ust, crtc_msc); - } - -@@ -284,6 +321,10 @@ xwl_present_free_event(struct xwl_present_event *event) - static void - xwl_present_free_idle_vblank(present_vblank_ptr vblank) - { -+ if (vblank->release_syncobj) -+ vblank->release_syncobj->signal(vblank->release_syncobj, -+ vblank->release_point); -+ - present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); - xwl_present_free_event(xwl_present_event_from_vblank(vblank)); - } -@@ -445,6 +486,11 @@ xwl_present_buffer_release(void *data) - return; - - vblank = &event->vblank; -+ -+ if (vblank->release_syncobj) -+ vblank->release_syncobj->signal(vblank->release_syncobj, -+ vblank->release_point); -+ - present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); - - xwl_present_window = xwl_present_window_priv(vblank->window); -@@ -641,6 +687,19 @@ xwl_present_maybe_set_reason(struct xwl_window *xwl_window, PresentFlipReason *r - } - } - -+static int -+xwl_present_flush_fenced(WindowPtr window) -+{ -+ int fence = -1; -+#ifdef XWL_HAS_GLAMOR -+ struct xwl_window *xwl_window = xwl_window_from_window(window); -+ if (xwl_window) -+ fence = xwl_glamor_get_fence(xwl_window->xwl_screen); -+ xwl_present_flush(window); -+#endif /* XWL_HAS_GLAMOR */ -+ return fence; -+} -+ - static Bool - xwl_present_check_flip(RRCrtcPtr crtc, - WindowPtr present_window, -@@ -814,7 +873,7 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage) - - if (xwl_window->tearing_control) { - uint32_t hint; -- if (event->async_may_tear) -+ if (event->options & PresentOptionAsyncMayTear) - hint = WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC; - else - hint = WP_TEARING_CONTROL_V1_PRESENTATION_HINT_VSYNC; -@@ -855,6 +914,7 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) - - xorg_list_del(&vblank->event_queue); - -+retry: - if (present_execute_wait(vblank, crtc_msc)) - return; - -@@ -920,6 +980,8 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) - } - - vblank->flip = FALSE; -+ /* re-execute, falling through to copy */ -+ goto retry; - } - DebugPresent(("\tc %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", - vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); -@@ -956,6 +1018,10 @@ xwl_present_pixmap(WindowPtr window, - RRCrtcPtr target_crtc, - SyncFence *wait_fence, - SyncFence *idle_fence, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point, - uint32_t options, - uint64_t target_window_msc, - uint64_t divisor, -@@ -972,11 +1038,17 @@ xwl_present_pixmap(WindowPtr window, - ScreenPtr screen = window->drawable.pScreen; - present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); - present_screen_priv_ptr screen_priv = present_screen_priv(screen); -+ struct xwl_screen *xwl_screen = xwl_screen_get(screen_priv->pScreen); -+ uint32_t caps = xwl_screen->present_capabilities; - struct xwl_present_event *event; - - if (!window_priv) - return BadAlloc; - -+ if (!(caps & PresentCapabilitySyncobj) && -+ (acquire_syncobj || release_syncobj)) -+ return BadValue; -+ - target_crtc = xwl_present_get_crtc(screen_priv, window); - - ret = xwl_present_get_ust_msc(screen, window, &ust, &crtc_msc); -@@ -1011,6 +1083,10 @@ xwl_present_pixmap(WindowPtr window, - if (vblank->target_msc != target_msc) - continue; - -+ if (vblank->release_syncobj) -+ vblank->release_syncobj->signal(vblank->release_syncobj, -+ vblank->release_point); -+ - present_vblank_scrap(vblank); - if (vblank->flip_ready) - xwl_present_re_execute(vblank); -@@ -1023,22 +1099,18 @@ xwl_present_pixmap(WindowPtr window, - - vblank = &event->vblank; - if (!present_vblank_init(vblank, window, pixmap, serial, valid, update, x_off, y_off, -- target_crtc, wait_fence, idle_fence, options, XWL_PRESENT_CAPS, -- notifies, num_notifies, target_msc, crtc_msc)) { -+ target_crtc, wait_fence, idle_fence, -+ acquire_syncobj, release_syncobj, acquire_point, release_point, -+ options, caps, notifies, num_notifies, target_msc, crtc_msc)) { - present_vblank_destroy(vblank); - return BadAlloc; - } - - vblank->event_id = ++xwl_present_event_id; -- event->async_may_tear = options & PresentOptionAsyncMayTear; -- -- /* Synchronous Xwayland presentations always complete (at least) one frame after they -- * are executed -- */ -- if (event->async_may_tear) -- vblank->exec_msc = vblank->target_msc; -- else -- vblank->exec_msc = vblank->target_msc - 1; -+ event->options = options; -+ event->divisor = divisor; -+ event->remainder = remainder; -+ vblank->exec_msc = xwl_present_get_exec_msc(options, vblank->target_msc); - - vblank->queued = TRUE; - if (crtc_msc < vblank->exec_msc) { -@@ -1068,6 +1140,7 @@ xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window) - Bool - xwl_present_init(ScreenPtr screen) - { -+ struct xwl_screen *xwl_screen = xwl_screen_get(screen); - present_screen_priv_ptr screen_priv; - - if (!present_screen_register_priv_keys()) -@@ -1083,6 +1156,14 @@ xwl_present_init(ScreenPtr screen) - if (!dixRegisterPrivateKey(&xwl_present_window_private_key, PRIVATE_WINDOW, 0)) - return FALSE; - -+ xwl_screen->present_capabilities = XWL_PRESENT_CAPS; -+#ifdef XWL_HAS_GLAMOR -+ if (epoxy_has_egl_extension(xwl_screen->egl_display, -+ "ANDROID_native_fence_sync")) -+ xwl_screen->present_capabilities |= -+ PresentCapabilitySyncobj; -+#endif /* XWL_HAS_GLAMOR */ -+ - screen_priv->query_capabilities = xwl_present_query_capabilities; - screen_priv->get_crtc = xwl_present_get_crtc; - -@@ -1093,6 +1174,7 @@ xwl_present_init(ScreenPtr screen) - screen_priv->present_pixmap = xwl_present_pixmap; - screen_priv->queue_vblank = xwl_present_queue_vblank; - screen_priv->flush = xwl_present_flush; -+ screen_priv->flush_fenced = xwl_present_flush_fenced; - screen_priv->re_execute = xwl_present_re_execute; - - screen_priv->abort_vblank = xwl_present_abort_vblank; -diff --git a/hw/xwayland/xwayland-present.h b/hw/xwayland/xwayland-present.h -index dab636c844..b10198a40b 100644 ---- a/hw/xwayland/xwayland-present.h -+++ b/hw/xwayland/xwayland-present.h -@@ -58,7 +58,10 @@ struct xwl_present_event { - present_vblank_rec vblank; - - PixmapPtr pixmap; -- Bool async_may_tear; -+ Bool released; -+ uint32_t options; -+ uint64_t divisor; -+ uint64_t remainder; - }; - - Bool xwl_present_entered_for_each_frame_callback(void); -diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h -index a53d18bad8..0a41986099 100644 ---- a/hw/xwayland/xwayland-screen.h -+++ b/hw/xwayland/xwayland-screen.h -@@ -147,6 +147,8 @@ struct xwl_screen { - struct libdecor *libdecor_context; - #endif - const char *output_name; -+ -+ uint32_t present_capabilities; - }; - - /* Apps which use randr/vidmode to change the mode when going fullscreen, -diff --git a/include/protocol-versions.h b/include/protocol-versions.h -index 2b0f85e392..aa3ba41fe1 100644 ---- a/include/protocol-versions.h -+++ b/include/protocol-versions.h -@@ -73,7 +73,7 @@ - - /* Present */ - #define SERVER_PRESENT_MAJOR_VERSION 1 --#define SERVER_PRESENT_MINOR_VERSION 2 -+#define SERVER_PRESENT_MINOR_VERSION 4 - - /* RandR */ - #define SERVER_RANDR_MAJOR_VERSION 1 -diff --git a/present/present.c b/present/present.c -index 211868341d..e0764fab1f 100644 ---- a/present/present.c -+++ b/present/present.c -@@ -230,6 +230,10 @@ present_pixmap(WindowPtr window, - RRCrtcPtr target_crtc, - SyncFence *wait_fence, - SyncFence *idle_fence, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point, - uint32_t options, - uint64_t window_msc, - uint64_t divisor, -@@ -250,6 +254,10 @@ present_pixmap(WindowPtr window, - target_crtc, - wait_fence, - idle_fence, -+ acquire_syncobj, -+ release_syncobj, -+ acquire_point, -+ release_point, - options, - window_msc, - divisor, -@@ -272,6 +280,7 @@ present_notify_msc(WindowPtr window, - 0, 0, - NULL, - NULL, NULL, -+ NULL, NULL, 0, 0, - divisor == 0 ? PresentOptionAsync : 0, - target_msc, divisor, remainder, NULL, 0); - } -diff --git a/present/present_execute.c b/present/present_execute.c -index 68a5878be9..913a8b67ba 100644 ---- a/present/present_execute.c -+++ b/present/present_execute.c -@@ -21,6 +21,7 @@ - */ - - #include "present_priv.h" -+#include - - /* - * Called when the wait fence is triggered; just gets the current msc/ust and -@@ -37,6 +38,19 @@ present_wait_fence_triggered(void *param) - screen_priv->re_execute(vblank); - } - -+static void present_syncobj_triggered(int fd, int xevents, void *data) -+{ -+ present_vblank_ptr vblank = data; -+ ScreenPtr screen = vblank->screen; -+ present_screen_priv_ptr screen_priv = present_screen_priv(screen); -+ -+ SetNotifyFd(fd, NULL, 0, NULL); -+ close(fd); -+ vblank->efd = -1; -+ -+ screen_priv->re_execute(vblank); -+} -+ - Bool - present_execute_wait(present_vblank_ptr vblank, uint64_t crtc_msc) - { -@@ -58,6 +72,18 @@ present_execute_wait(present_vblank_ptr vblank, uint64_t crtc_msc) - return TRUE; - } - } -+ -+ if (vblank->acquire_syncobj && -+ !vblank->acquire_syncobj->is_signaled(vblank->acquire_syncobj, -+ vblank->acquire_point)) { -+ vblank->efd = eventfd(0, EFD_CLOEXEC); -+ SetNotifyFd(vblank->efd, present_syncobj_triggered, X_NOTIFY_READ, vblank); -+ vblank->acquire_syncobj->signaled_eventfd(vblank->acquire_syncobj, -+ vblank->acquire_point, -+ vblank->efd); -+ return TRUE; -+ } -+ - return FALSE; - } - -@@ -85,7 +111,13 @@ present_execute_copy(present_vblank_ptr vblank, uint64_t crtc_msc) - * which is then freed, freeing the region - */ - vblank->update = NULL; -- screen_priv->flush(window); -+ if (vblank->release_syncobj) { -+ int fence_fd = screen_priv->flush_fenced(window); -+ vblank->release_syncobj->import_fence(vblank->release_syncobj, -+ vblank->release_point, fence_fd); -+ } else { -+ screen_priv->flush(window); -+ } - - present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); - } -diff --git a/present/present_priv.h b/present/present_priv.h -index 4ad7298647..727d523109 100644 ---- a/present/present_priv.h -+++ b/present/present_priv.h -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include "dri3.h" - - #if 0 - #define DebugPresent(x) ErrorF x -@@ -90,6 +91,11 @@ struct present_vblank { - Bool abort_flip; /* aborting this flip */ - PresentFlipReason reason; /* reason for which flip is not possible */ - Bool has_suboptimal; /* whether client can support SuboptimalCopy mode */ -+ struct dri3_syncobj *acquire_syncobj; -+ struct dri3_syncobj *release_syncobj; -+ uint64_t acquire_point; -+ uint64_t release_point; -+ int efd; - }; - - typedef struct present_screen_priv present_screen_priv_rec, *present_screen_priv_ptr; -@@ -124,6 +130,10 @@ typedef int (*present_priv_pixmap_ptr)(WindowPtr window, - RRCrtcPtr target_crtc, - SyncFence *wait_fence, - SyncFence *idle_fence, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point, - uint32_t options, - uint64_t window_msc, - uint64_t divisor, -@@ -137,6 +147,7 @@ typedef int (*present_priv_queue_vblank_ptr)(ScreenPtr screen, - uint64_t event_id, - uint64_t msc); - typedef void (*present_priv_flush_ptr)(WindowPtr window); -+typedef int (*present_priv_flush_fenced_ptr)(WindowPtr window); - typedef void (*present_priv_re_execute_ptr)(present_vblank_ptr vblank); - - typedef void (*present_priv_abort_vblank_ptr)(ScreenPtr screen, -@@ -147,6 +158,7 @@ typedef void (*present_priv_abort_vblank_ptr)(ScreenPtr screen, - typedef void (*present_priv_flip_destroy_ptr)(ScreenPtr screen); - - struct present_screen_priv { -+ ScreenPtr pScreen; - CloseScreenProcPtr CloseScreen; - ConfigNotifyProcPtr ConfigNotify; - DestroyWindowProcPtr DestroyWindow; -@@ -180,6 +192,7 @@ struct present_screen_priv { - - present_priv_queue_vblank_ptr queue_vblank; - present_priv_flush_ptr flush; -+ present_priv_flush_fenced_ptr flush_fenced; - present_priv_re_execute_ptr re_execute; - - present_priv_abort_vblank_ptr abort_vblank; -@@ -290,6 +303,10 @@ present_pixmap(WindowPtr window, - RRCrtcPtr target_crtc, - SyncFence *wait_fence, - SyncFence *idle_fence, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point, - uint32_t options, - uint64_t target_msc, - uint64_t divisor, -@@ -464,6 +481,10 @@ present_vblank_init(present_vblank_ptr vblank, - RRCrtcPtr target_crtc, - SyncFence *wait_fence, - SyncFence *idle_fence, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point, - uint32_t options, - const uint32_t capabilities, - present_notify_ptr notifies, -@@ -482,6 +503,10 @@ present_vblank_create(WindowPtr window, - RRCrtcPtr target_crtc, - SyncFence *wait_fence, - SyncFence *idle_fence, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point, - uint32_t options, - const uint32_t capabilities, - present_notify_ptr notifies, -diff --git a/present/present_request.c b/present/present_request.c -index f3e5679b5d..411798ab96 100644 ---- a/present/present_request.c -+++ b/present/present_request.c -@@ -79,79 +79,117 @@ proc_present_query_version(ClientPtr client) - } while (0) - - static int --proc_present_pixmap(ClientPtr client) -+proc_present_pixmap_common(ClientPtr client, -+ Window req_window, -+ Pixmap req_pixmap, -+ CARD32 req_serial, -+ CARD32 req_valid, -+ CARD32 req_update, -+ INT16 req_x_off, -+ INT16 req_y_off, -+ CARD32 req_target_crtc, -+ XSyncFence req_wait_fence, -+ XSyncFence req_idle_fence, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ CARD64 req_acquire_point, -+ CARD64 req_release_point, -+ CARD32 req_options, -+ CARD64 req_target_msc, -+ CARD64 req_divisor, -+ CARD64 req_remainder, -+ size_t base_req_size, -+ xPresentNotify *req_notifies) - { -- REQUEST(xPresentPixmapReq); -- WindowPtr window; -- PixmapPtr pixmap; -- RegionPtr valid = NULL; -- RegionPtr update = NULL; -- SyncFence *wait_fence; -- SyncFence *idle_fence; -- RRCrtcPtr target_crtc; -- int ret; -- int nnotifies; -- present_notify_ptr notifies = NULL; -- -- REQUEST_AT_LEAST_SIZE(xPresentPixmapReq); -- ret = dixLookupWindow(&window, stuff->window, client, DixWriteAccess); -+ WindowPtr window; -+ PixmapPtr pixmap; -+ RegionPtr valid = NULL; -+ RegionPtr update = NULL; -+ RRCrtcPtr target_crtc; -+ SyncFence *wait_fence; -+ SyncFence *idle_fence; -+ int nnotifies; -+ present_notify_ptr notifies = NULL; -+ int ret; -+ -+ ret = dixLookupWindow(&window, req_window, client, DixWriteAccess); - if (ret != Success) - return ret; -- ret = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess); -+ ret = dixLookupResourceByType((void **) &pixmap, req_pixmap, RT_PIXMAP, client, DixReadAccess); - if (ret != Success) - return ret; - - if (window->drawable.depth != pixmap->drawable.depth) - return BadMatch; - -- VERIFY_REGION_OR_NONE(valid, stuff->valid, client, DixReadAccess); -- VERIFY_REGION_OR_NONE(update, stuff->update, client, DixReadAccess); -+ VERIFY_REGION_OR_NONE(valid, req_valid, client, DixReadAccess); -+ VERIFY_REGION_OR_NONE(update, req_update, client, DixReadAccess); - -- VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess); -+ VERIFY_CRTC_OR_NONE(target_crtc, req_target_crtc, client, DixReadAccess); - -- VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess); -- VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess); -+ VERIFY_FENCE_OR_NONE(wait_fence, req_wait_fence, client, DixReadAccess); -+ VERIFY_FENCE_OR_NONE(idle_fence, req_idle_fence, client, DixWriteAccess); - -- if (stuff->options & ~(PresentAllOptions)) { -- client->errorValue = stuff->options; -+ if (req_options & ~(PresentAllOptions)) { -+ client->errorValue = req_options; - return BadValue; - } - - /* - * Check to see if remainder is sane - */ -- if (stuff->divisor == 0) { -- if (stuff->remainder != 0) { -- client->errorValue = (CARD32) stuff->remainder; -+ if (req_divisor == 0) { -+ if (req_remainder != 0) { -+ client->errorValue = (CARD32)req_remainder; - return BadValue; - } - } else { -- if (stuff->remainder >= stuff->divisor) { -- client->errorValue = (CARD32) stuff->remainder; -+ if (req_remainder >= req_divisor) { -+ client->errorValue = (CARD32)req_remainder; - return BadValue; - } - } - -- nnotifies = (client->req_len << 2) - sizeof (xPresentPixmapReq); -+ nnotifies = (client->req_len << 2) - base_req_size; - if (nnotifies % sizeof (xPresentNotify)) - return BadLength; - - nnotifies /= sizeof (xPresentNotify); - if (nnotifies) { -- ret = present_create_notifies(client, nnotifies, (xPresentNotify *) (stuff + 1), ¬ifies); -+ ret = present_create_notifies(client, nnotifies, req_notifies, ¬ifies); - if (ret != Success) - return ret; - } - -- ret = present_pixmap(window, pixmap, stuff->serial, valid, update, -- stuff->x_off, stuff->y_off, target_crtc, -- wait_fence, idle_fence, stuff->options, -- stuff->target_msc, stuff->divisor, stuff->remainder, notifies, nnotifies); -+ ret = present_pixmap(window, pixmap, req_serial, -+ valid, update, req_x_off, req_y_off, target_crtc, -+ wait_fence, idle_fence, -+ acquire_syncobj, release_syncobj, -+ req_acquire_point, req_release_point, -+ req_options, req_target_msc, req_divisor, req_remainder, -+ notifies, nnotifies); -+ - if (ret != Success) - present_destroy_notifies(notifies, nnotifies); - return ret; - } - -+static int -+proc_present_pixmap(ClientPtr client) -+{ -+ REQUEST(xPresentPixmapReq); -+ REQUEST_AT_LEAST_SIZE(xPresentPixmapReq); -+ return proc_present_pixmap_common(client, stuff->window, stuff->pixmap, stuff->serial, -+ stuff->valid, stuff->update, stuff->x_off, stuff->y_off, -+ stuff->target_crtc, -+ stuff->wait_fence, stuff->idle_fence, -+ None, None, 0, 0, -+ stuff->options, stuff->target_msc, -+ stuff->divisor, stuff->remainder, -+ sizeof (xPresentPixmapReq), -+ (xPresentNotify *)(stuff + 1)); -+} -+ - static int - proc_present_notify_msc(ClientPtr client) - { -@@ -240,12 +278,41 @@ proc_present_query_capabilities (ClientPtr client) - return Success; - } - -+static int -+proc_present_pixmap_synced (ClientPtr client) -+{ -+ REQUEST(xPresentPixmapSyncedReq); -+ struct dri3_syncobj *acquire_syncobj; -+ struct dri3_syncobj *release_syncobj; -+ -+ REQUEST_AT_LEAST_SIZE(xPresentPixmapSyncedReq); -+ VERIFY_DRI3_SYNCOBJ(stuff->acquire_syncobj, acquire_syncobj, DixWriteAccess); -+ VERIFY_DRI3_SYNCOBJ(stuff->release_syncobj, release_syncobj, DixWriteAccess); -+ -+ if (stuff->acquire_point == 0 || stuff->release_point == 0 || -+ (stuff->acquire_syncobj == stuff->release_syncobj && -+ stuff->acquire_point >= stuff->release_point)) -+ return BadValue; -+ -+ return proc_present_pixmap_common(client, stuff->window, stuff->pixmap, stuff->serial, -+ stuff->valid, stuff->update, stuff->x_off, stuff->y_off, -+ stuff->target_crtc, -+ None, None, -+ acquire_syncobj, release_syncobj, -+ stuff->acquire_point, stuff->release_point, -+ stuff->options, stuff->target_msc, -+ stuff->divisor, stuff->remainder, -+ sizeof (xPresentPixmapSyncedReq), -+ (xPresentNotify *)(stuff + 1)); -+} -+ - static int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = { - proc_present_query_version, /* 0 */ - proc_present_pixmap, /* 1 */ - proc_present_notify_msc, /* 2 */ - proc_present_select_input, /* 3 */ - proc_present_query_capabilities, /* 4 */ -+ proc_present_pixmap_synced, /* 5 */ - }; - - int -@@ -325,12 +392,47 @@ sproc_present_query_capabilities (ClientPtr client) - return (*proc_present_vector[stuff->presentReqType]) (client); - } - -+ -+static int _X_COLD -+sproc_present_pixmap_synced(ClientPtr client) -+{ -+ REQUEST(xPresentPixmapSyncedReq); -+ REQUEST_AT_LEAST_SIZE(xPresentPixmapSyncedReq); -+ -+ swaps(&stuff->length); -+ -+ swapl(&stuff->window); -+ -+ swapl(&stuff->pixmap); -+ swapl(&stuff->serial); -+ -+ swapl(&stuff->valid); -+ swapl(&stuff->update); -+ -+ swaps(&stuff->x_off); -+ swaps(&stuff->y_off); -+ swapl(&stuff->target_crtc); -+ -+ swapl(&stuff->acquire_syncobj); -+ swapl(&stuff->release_syncobj); -+ swapll(&stuff->acquire_point); -+ swapll(&stuff->release_point); -+ -+ swapl(&stuff->options); -+ -+ swapll(&stuff->target_msc); -+ swapll(&stuff->divisor); -+ swapll(&stuff->remainder); -+ return (*proc_present_vector[stuff->presentReqType]) (client); -+} -+ - static int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = { - sproc_present_query_version, /* 0 */ - sproc_present_pixmap, /* 1 */ - sproc_present_notify_msc, /* 2 */ - sproc_present_select_input, /* 3 */ - sproc_present_query_capabilities, /* 4 */ -+ sproc_present_pixmap_synced, /* 5 */ - }; - - int _X_COLD -diff --git a/present/present_scmd.c b/present/present_scmd.c -index d378f00167..07dd41cd69 100644 ---- a/present/present_scmd.c -+++ b/present/present_scmd.c -@@ -738,6 +738,10 @@ present_scmd_pixmap(WindowPtr window, - RRCrtcPtr target_crtc, - SyncFence *wait_fence, - SyncFence *idle_fence, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point, - uint32_t options, - uint64_t target_window_msc, - uint64_t divisor, -@@ -824,6 +828,10 @@ present_scmd_pixmap(WindowPtr window, - target_crtc, - wait_fence, - idle_fence, -+ acquire_syncobj, -+ release_syncobj, -+ acquire_point, -+ release_point, - options, - screen_priv->info ? screen_priv->info->capabilities : 0, - notifies, -diff --git a/present/present_screen.c b/present/present_screen.c -index ef56ff779a..0589b2ee91 100644 ---- a/present/present_screen.c -+++ b/present/present_screen.c -@@ -187,6 +187,7 @@ present_screen_priv_init(ScreenPtr screen) - wrap(screen_priv, screen, ClipNotify, present_clip_notify); - - dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv); -+ screen_priv->pScreen = screen; - - return screen_priv; - } -diff --git a/present/present_vblank.c b/present/present_vblank.c -index 4f94f16e44..2eb57abfff 100644 ---- a/present/present_vblank.c -+++ b/present/present_vblank.c -@@ -55,6 +55,10 @@ present_vblank_init(present_vblank_ptr vblank, - RRCrtcPtr target_crtc, - SyncFence *wait_fence, - SyncFence *idle_fence, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point, - uint32_t options, - const uint32_t capabilities, - present_notify_ptr notifies, -@@ -106,6 +110,7 @@ present_vblank_init(present_vblank_ptr vblank, - vblank->notifies = notifies; - vblank->num_notifies = num_notifies; - vblank->has_suboptimal = (options & PresentOptionSuboptimal); -+ vblank->efd = -1; - - if (pixmap != NULL && - !(options & PresentOptionCopy) && -@@ -135,6 +140,18 @@ present_vblank_init(present_vblank_ptr vblank, - goto no_mem; - } - -+ if (acquire_syncobj) { -+ vblank->acquire_syncobj = acquire_syncobj; -+ ++acquire_syncobj->refcount; -+ vblank->acquire_point = acquire_point; -+ } -+ -+ if (release_syncobj) { -+ vblank->release_syncobj = release_syncobj; -+ ++release_syncobj->refcount; -+ vblank->release_point = release_point; -+ } -+ - if (pixmap) - DebugPresent(("q %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p) flip %d vsync %d serial %d\n", - vblank->event_id, vblank, target_msc, -@@ -158,6 +175,10 @@ present_vblank_create(WindowPtr window, - RRCrtcPtr target_crtc, - SyncFence *wait_fence, - SyncFence *idle_fence, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point, - uint32_t options, - const uint32_t capabilities, - present_notify_ptr notifies, -@@ -172,6 +193,8 @@ present_vblank_create(WindowPtr window, - - if (present_vblank_init(vblank, window, pixmap, serial, valid, update, - x_off, y_off, target_crtc, wait_fence, idle_fence, -+ acquire_syncobj, release_syncobj, -+ acquire_point, release_point, - options, capabilities, notifies, num_notifies, - target_msc, crtc_msc)) - return vblank; -@@ -229,5 +252,18 @@ present_vblank_destroy(present_vblank_ptr vblank) - if (vblank->notifies) - present_destroy_notifies(vblank->notifies, vblank->num_notifies); - -+ if (vblank->efd >= 0) { -+ SetNotifyFd(vblank->efd, NULL, 0, NULL); -+ close(vblank->efd); -+ } -+ -+ if (vblank->acquire_syncobj && -+ --vblank->acquire_syncobj->refcount == 0) -+ vblank->acquire_syncobj->free(vblank->acquire_syncobj); -+ -+ if (vblank->release_syncobj && -+ --vblank->release_syncobj->refcount == 0) -+ vblank->release_syncobj->free(vblank->release_syncobj); -+ - free(vblank); - } --- -GitLab - - -From bcb2a82b5c83a25351ff806df29a2a6bad4648e6 Mon Sep 17 00:00:00 2001 -From: Erik Kurzinger -Date: Tue, 15 Aug 2023 15:32:47 -0700 -Subject: [PATCH 5/6] xwayland: add support for wp_linux_drm_syncobj_v1 - -This protocol allows for explicit synchronization of GPU operations by -Wayland clients and the compositor. Xwayland can make use of this to -ensure any rendering it initiates has completed before the target image -is accessed by the compositor, without having to rely on kernel-level -implicit synchronization. - -Furthermore, for X11 clients that also support explicit synchronization -using the mechanisms exposed in the DRI3 and Present extensions, this -Wayland protocol allows us to simply forward the timeline, acquire, and -release points directly to the compositor, ideally avoiding any -premature stalls in the presentation pipeline. - -Signed-off-by: Erik Kurzinger ---- - hw/xwayland/meson.build | 3 + - hw/xwayland/xwayland-glamor-gbm.c | 146 +++++++++++++++++++++++++- - hw/xwayland/xwayland-glamor.c | 94 +++++++++++++++++ - hw/xwayland/xwayland-glamor.h | 30 ++++++ - hw/xwayland/xwayland-present.c | 82 ++++++++++++--- - hw/xwayland/xwayland-present.h | 1 - - hw/xwayland/xwayland-screen.c | 1 + - hw/xwayland/xwayland-screen.h | 1 + - hw/xwayland/xwayland-window-buffers.c | 110 ++++++++++++++++++- - hw/xwayland/xwayland-window.c | 10 ++ - hw/xwayland/xwayland-window.h | 1 + - present/present_execute.c | 5 +- - 12 files changed, 464 insertions(+), 20 deletions(-) - -diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build -index 8898f3e6c1..df4fa19178 100644 ---- a/hw/xwayland/meson.build -+++ b/hw/xwayland/meson.build -@@ -49,6 +49,7 @@ drm_lease_xml = join_paths(protodir, 'staging', 'drm-lease', 'drm-lease-v1.xml') - shortcuts_inhibit_xml = join_paths(protodir, 'unstable', 'keyboard-shortcuts-inhibit', 'keyboard-shortcuts-inhibit-unstable-v1.xml') - xwayland_shell_xml = join_paths(protodir, 'staging', 'xwayland-shell', 'xwayland-shell-v1.xml') - tearing_xml = join_paths(protodir, 'staging', 'tearing-control', 'tearing-control-v1.xml') -+syncobj_xml = join_paths(protodir, 'staging', 'linux-drm-syncobj', 'linux-drm-syncobj-v1.xml') - - client_header = generator(scanner, - output : '@BASENAME@-client-protocol.h', -@@ -78,6 +79,7 @@ srcs += client_header.process(drm_lease_xml) - srcs += client_header.process(shortcuts_inhibit_xml) - srcs += client_header.process(xwayland_shell_xml) - srcs += client_header.process(tearing_xml) -+srcs += client_header.process(syncobj_xml) - srcs += code.process(relative_xml) - srcs += code.process(pointer_xml) - srcs += code.process(gestures_xml) -@@ -91,6 +93,7 @@ srcs += code.process(drm_lease_xml) - srcs += code.process(shortcuts_inhibit_xml) - srcs += code.process(xwayland_shell_xml) - srcs += code.process(tearing_xml) -+srcs += code.process(syncobj_xml) - - if build_ei - xwayland_dep += libei_dep -diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c -index 35c06f5bee..da8ae6c32f 100644 ---- a/hw/xwayland/xwayland-glamor-gbm.c -+++ b/hw/xwayland/xwayland-glamor-gbm.c -@@ -35,6 +35,9 @@ - #include - #include - #include -+#include -+#include -+#include - - #define MESA_EGL_NO_X11_HEADERS - #define EGL_NO_X11 -@@ -51,6 +54,7 @@ - #include "xwayland-screen.h" - - #include "linux-dmabuf-unstable-v1-client-protocol.h" -+#include "linux-drm-syncobj-v1-client-protocol.h" - - struct xwl_gbm_private { - drmDevice *device; -@@ -599,6 +603,8 @@ xwl_glamor_gbm_cleanup(struct xwl_screen *xwl_screen) - wl_drm_destroy(xwl_gbm->drm); - if (xwl_gbm->gbm) - gbm_device_destroy(xwl_gbm->gbm); -+ if (xwl_screen->explicit_sync) -+ wp_linux_drm_syncobj_manager_v1_destroy(xwl_screen->explicit_sync); - - free(xwl_gbm); - } -@@ -843,12 +849,88 @@ glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, - return -1; - } - -+static int xwl_glamor_gbm_dmabuf_export_sync_file(PixmapPtr pixmap) -+{ -+ struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); -+ int num_planes = gbm_bo_get_plane_count(xwl_pixmap->bo); -+ int sync_file = -1; -+ int p; -+ -+ for (p = 0; p < num_planes; ++p) { -+ int plane_fd = gbm_bo_get_fd_for_plane(xwl_pixmap->bo, p); -+ struct dma_buf_export_sync_file export_args = { 0 }; -+ export_args.fd = -1; -+ export_args.flags = DMA_BUF_SYNC_READ; -+ drmIoctl(plane_fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &export_args); -+ close(plane_fd); -+ if (sync_file == -1) { -+ sync_file = export_args.fd; -+ } else { -+ struct sync_merge_data merge_args = { 0 }; -+ merge_args.fd2 = export_args.fd; -+ ioctl(sync_file, SYNC_IOC_MERGE, &merge_args); -+ close(export_args.fd); -+ close(sync_file); -+ sync_file = merge_args.fence; -+ } -+ } -+ -+ return sync_file; -+} -+ -+static void xwl_glamor_gbm_dmabuf_import_sync_file(PixmapPtr pixmap, int sync_file) -+{ -+ struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); -+ int num_planes = gbm_bo_get_plane_count(xwl_pixmap->bo); -+ int p; -+ -+ for (p = 0; p < num_planes; ++p) { -+ int plane_fd = gbm_bo_get_fd_for_plane(xwl_pixmap->bo, p); -+ struct dma_buf_import_sync_file import_args = { 0 }; -+ import_args.fd = sync_file; -+ import_args.flags = DMA_BUF_SYNC_READ; -+ drmIoctl(plane_fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, &import_args); -+ close(plane_fd); -+ } -+ close(sync_file); -+} -+ - struct xwl_dri3_syncobj - { - struct dri3_syncobj base; - uint32_t handle; -+ struct wp_linux_drm_syncobj_timeline_v1 *timeline; - }; - -+static void -+xwl_glamor_gbm_dri3_syncobj_passthrough(WindowPtr window, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point) -+{ -+ struct xwl_window *xwl_window = xwl_window_get(window); -+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen; -+ struct xwl_dri3_syncobj *xwl_acquire_syncobj = (struct xwl_dri3_syncobj *)acquire_syncobj; -+ struct xwl_dri3_syncobj *xwl_release_syncobj = (struct xwl_dri3_syncobj *)release_syncobj; -+ uint32_t acquire_hi = acquire_point >> 32; -+ uint32_t acquire_lo = acquire_point & 0xffffffff; -+ uint32_t release_hi = release_point >> 32; -+ uint32_t release_lo = release_point & 0xffffffff; -+ -+ if (!xwl_window->surface_sync) -+ xwl_window->surface_sync = -+ wp_linux_drm_syncobj_manager_v1_get_surface(xwl_screen->explicit_sync, -+ xwl_window->surface); -+ -+ wp_linux_drm_syncobj_surface_v1_set_acquire_point(xwl_window->surface_sync, -+ xwl_acquire_syncobj->timeline, -+ acquire_hi, acquire_lo); -+ wp_linux_drm_syncobj_surface_v1_set_release_point(xwl_window->surface_sync, -+ xwl_release_syncobj->timeline, -+ release_hi, release_lo); -+} -+ - static Bool - xwl_dri3_check_syncobj(struct dri3_syncobj *syncobj, uint64_t point, Bool check_avail) - { -@@ -949,6 +1031,9 @@ xwl_dri3_free_syncobj(struct dri3_syncobj *syncobj) - struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - -+ if (xwl_syncobj->timeline) -+ wp_linux_drm_syncobj_timeline_v1_destroy(xwl_syncobj->timeline); -+ - if (xwl_syncobj->handle) - drmSyncobjDestroy(xwl_gbm->drm_fd, xwl_syncobj->handle); - -@@ -986,10 +1071,27 @@ xwl_dri3_create_syncobj(struct xwl_screen *xwl_screen, uint32_t handle) - { - struct xwl_dri3_syncobj *syncobj = calloc(1, sizeof (*syncobj)); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -+ Bool create = !handle; - - if (!syncobj) - return NULL; - -+ if (create && drmSyncobjCreate(xwl_gbm->drm_fd, 0, &handle)) -+ goto fail; -+ -+ if (xwl_screen->explicit_sync) { -+ int syncobj_fd = -1; -+ if (drmSyncobjHandleToFD(xwl_gbm->drm_fd, handle, &syncobj_fd)) -+ goto fail; -+ -+ syncobj->timeline = -+ wp_linux_drm_syncobj_manager_v1_import_timeline(xwl_screen->explicit_sync, -+ syncobj_fd); -+ close(syncobj_fd); -+ if (!syncobj->timeline) -+ goto fail; -+ } -+ - syncobj->handle = handle; - syncobj->base.screen = xwl_screen->screen; - syncobj->base.refcount = 1; -@@ -1005,10 +1107,18 @@ xwl_dri3_create_syncobj(struct xwl_screen *xwl_screen, uint32_t handle) - return &syncobj->base; - - fail: -+ if (create && handle) -+ drmSyncobjDestroy(xwl_gbm->drm_fd, handle); - free(syncobj); - return NULL; - } - -+static struct dri3_syncobj * -+xwl_glamor_gbm_dri3_syncobj_create(struct xwl_screen *xwl_screen) -+{ -+ return xwl_dri3_create_syncobj(xwl_screen, 0 /* allocate new handle */); -+} -+ - static struct dri3_syncobj * - xwl_dri3_import_syncobj(ClientPtr client, ScreenPtr screen, XID id, int fd) - { -@@ -1220,6 +1330,11 @@ xwl_glamor_gbm_init_wl_registry(struct xwl_screen *xwl_screen, - } else if (strcmp(name, zwp_linux_dmabuf_v1_interface.name) == 0) { - xwl_screen_set_dmabuf_interface(xwl_screen, id, version); - return TRUE; -+ } else if (strcmp(name, wp_linux_drm_syncobj_manager_v1_interface.name) == 0) { -+ xwl_screen->explicit_sync = -+ wl_registry_bind(xwl_screen->registry, id, -+ &wp_linux_drm_syncobj_manager_v1_interface, -+ version); - } - - /* no match */ -@@ -1390,7 +1505,7 @@ xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen) - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - EGLint major, minor; - const GLubyte *renderer; -- const char *gbm_backend_name; -+ const char *gbm_backend_name, *egl_vendor; - - if (!xwl_gbm->drm && !xwl_glamor_gbm_init_main_dev(xwl_screen)) - return FALSE; -@@ -1455,6 +1570,25 @@ xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen) - xwl_screen->glvnd_vendor = gbm_backend_name; - xwl_gbm->glamor_gles = !epoxy_is_desktop_gl(); - -+ egl_vendor = eglQueryString(xwl_screen->egl_display, EGL_VENDOR); -+ /* NVIDIA driver does not support implicit sync */ -+ if (egl_vendor && strstr(egl_vendor, "NVIDIA")) -+ xwl_screen->gbm_backend.backend_flags &= -+ ~XWL_EGL_BACKEND_SUPPORTS_IMPLICIT_SYNC; -+ -+ if (xwl_gbm_supports_syncobjs(xwl_screen) && -+ epoxy_has_egl_extension(xwl_screen->egl_display, -+ "ANDROID_native_fence_sync")) -+ xwl_screen->gbm_backend.backend_flags |= -+ XWL_EGL_BACKEND_SUPPORTS_SYNCOBJS; -+ -+ if (!xwl_glamor_supports_syncobjs(xwl_screen) && -+ xwl_screen->explicit_sync) { -+ /* explicit sync requires syncobj support */ -+ wp_linux_drm_syncobj_manager_v1_destroy(xwl_screen->explicit_sync); -+ xwl_screen->explicit_sync = NULL; -+ } -+ - return TRUE; - error: - if (xwl_screen->egl_display != EGL_NO_DISPLAY) { -@@ -1472,7 +1606,7 @@ xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen) - { - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - -- if (xwl_gbm_supports_syncobjs(xwl_screen)) { -+ if (xwl_glamor_supports_syncobjs(xwl_screen)) { - xwl_dri3_info.version = 4; - xwl_dri3_info.import_syncobj = xwl_dri3_import_syncobj; - } -@@ -1545,6 +1679,12 @@ xwl_glamor_init_gbm(struct xwl_screen *xwl_screen) - xwl_screen->gbm_backend.get_main_device = xwl_gbm_get_main_device; - xwl_screen->gbm_backend.is_available = TRUE; - xwl_screen->gbm_backend.backend_flags = XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH | -- XWL_EGL_BACKEND_NEEDS_N_BUFFERING; -+ XWL_EGL_BACKEND_NEEDS_N_BUFFERING | -+ /* may be overriden during EGL initialization */ -+ XWL_EGL_BACKEND_SUPPORTS_IMPLICIT_SYNC; - xwl_screen->gbm_backend.create_pixmap_for_window = xwl_glamor_gbm_create_pixmap_for_window; -+ xwl_screen->gbm_backend.dmabuf_export_sync_file = xwl_glamor_gbm_dmabuf_export_sync_file; -+ xwl_screen->gbm_backend.dmabuf_import_sync_file = xwl_glamor_gbm_dmabuf_import_sync_file; -+ xwl_screen->gbm_backend.dri3_syncobj_create = xwl_glamor_gbm_dri3_syncobj_create; -+ xwl_screen->gbm_backend.dri3_syncobj_passthrough = xwl_glamor_gbm_dri3_syncobj_passthrough; - } -diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c -index 850e25db05..dcc1c2f5fe 100644 ---- a/hw/xwayland/xwayland-glamor.c -+++ b/hw/xwayland/xwayland-glamor.c -@@ -1059,6 +1059,26 @@ xwl_glamor_needs_n_buffering(struct xwl_screen *xwl_screen) - XWL_EGL_BACKEND_NEEDS_N_BUFFERING); - } - -+Bool -+xwl_glamor_supports_implicit_sync(struct xwl_screen *xwl_screen) -+{ -+ if (!xwl_screen->glamor || !xwl_screen->egl_backend) -+ return TRUE; -+ -+ return xwl_screen->egl_backend->backend_flags & -+ XWL_EGL_BACKEND_SUPPORTS_IMPLICIT_SYNC; -+} -+ -+Bool -+xwl_glamor_supports_syncobjs(struct xwl_screen *xwl_screen) -+{ -+ if (!xwl_screen->glamor || !xwl_screen->egl_backend) -+ return FALSE; -+ -+ return xwl_screen->egl_backend->backend_flags & -+ XWL_EGL_BACKEND_SUPPORTS_SYNCOBJS; -+} -+ - PixmapPtr - xwl_glamor_create_pixmap_for_window(struct xwl_window *xwl_window) - { -@@ -1097,6 +1117,80 @@ xwl_glamor_get_fence(struct xwl_screen *xwl_screen) - return fence_fd; - } - -+void -+xwl_glamor_wait_fence(struct xwl_screen *xwl_screen, int fence_fd) -+{ -+ EGLint attribs[3]; -+ EGLSyncKHR sync; -+ -+ if (!xwl_screen->glamor) -+ return; -+ -+ xwl_glamor_egl_make_current(xwl_screen); -+ -+ attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID; -+ attribs[1] = fence_fd; -+ attribs[2] = EGL_NONE; -+ sync = eglCreateSyncKHR(xwl_screen->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); -+ if (sync != EGL_NO_SYNC_KHR) { -+ eglWaitSyncKHR(xwl_screen->egl_display, sync, 0); -+ eglDestroySyncKHR(xwl_screen->egl_display, sync); -+ } -+} -+ -+int -+xwl_glamor_dmabuf_export_sync_file(PixmapPtr pixmap) -+{ -+ ScreenPtr screen = pixmap->drawable.pScreen; -+ struct xwl_screen *xwl_screen = xwl_screen_get(screen); -+ -+ if (xwl_screen->glamor && xwl_screen->egl_backend && -+ xwl_screen->egl_backend->dmabuf_export_sync_file) -+ return xwl_screen->egl_backend->dmabuf_export_sync_file(pixmap); -+ -+ return -1; -+} -+ -+void -+xwl_glamor_dmabuf_import_sync_file(PixmapPtr pixmap, int sync_file) -+{ -+ ScreenPtr screen = pixmap->drawable.pScreen; -+ struct xwl_screen *xwl_screen = xwl_screen_get(screen); -+ -+ if (xwl_screen->glamor && xwl_screen->egl_backend && -+ xwl_screen->egl_backend->dmabuf_import_sync_file) -+ xwl_screen->egl_backend->dmabuf_import_sync_file(pixmap, sync_file); -+} -+ -+struct dri3_syncobj * -+xwl_glamor_dri3_syncobj_create(struct xwl_screen *xwl_screen) -+{ -+ if (xwl_screen->glamor && xwl_screen->egl_backend && -+ xwl_screen->egl_backend->dri3_syncobj_create) -+ return xwl_screen->egl_backend->dri3_syncobj_create(xwl_screen); -+ -+ return NULL; -+} -+ -+void -+xwl_glamor_dri3_syncobj_passthrough(WindowPtr window, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point) -+{ -+ ScreenPtr screen = window->drawable.pScreen; -+ struct xwl_screen *xwl_screen = xwl_screen_get(screen); -+ -+ if (xwl_screen->glamor && xwl_screen->egl_backend && -+ xwl_screen->egl_backend->dri3_syncobj_passthrough) -+ xwl_screen->egl_backend->dri3_syncobj_passthrough(window, -+ acquire_syncobj, -+ release_syncobj, -+ acquire_point, -+ release_point); -+} -+ - void - xwl_glamor_init_backends(struct xwl_screen *xwl_screen, Bool use_eglstream) - { -diff --git a/hw/xwayland/xwayland-glamor.h b/hw/xwayland/xwayland-glamor.h -index 260c60b652..7e3eea014b 100644 ---- a/hw/xwayland/xwayland-glamor.h -+++ b/hw/xwayland/xwayland-glamor.h -@@ -34,11 +34,14 @@ - #include - - #include "xwayland-types.h" -+#include "dri3.h" - - typedef enum _xwl_egl_backend_flags { - XWL_EGL_BACKEND_NO_FLAG = 0, - XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH = (1 << 0), - XWL_EGL_BACKEND_NEEDS_N_BUFFERING = (1 << 1), -+ XWL_EGL_BACKEND_SUPPORTS_IMPLICIT_SYNC = (1 << 2), -+ XWL_EGL_BACKEND_SUPPORTS_SYNCOBJS = (1 << 3), - } xwl_egl_backend_flags; - - typedef enum _xwl_glamor_mode_flags{ -@@ -114,6 +117,22 @@ struct xwl_egl_backend { - - /* Direct hook to create the backing pixmap for a window */ - PixmapPtr (*create_pixmap_for_window)(struct xwl_window *xwl_window); -+ -+ /* Merge the implicit read fences of each plane into a sync file */ -+ int (*dmabuf_export_sync_file)(PixmapPtr pixmap); -+ -+ /* Sets the implicit read fence of each plane to the given sync file */ -+ void (*dmabuf_import_sync_file)(PixmapPtr pixmap, int sync_file); -+ -+ /* Creates a new dri3 syncobj */ -+ struct dri3_syncobj *(*dri3_syncobj_create)(struct xwl_screen *xwl_screen); -+ -+ /* Sets the explicit sync acquire and release points for the given Window */ -+ void (*dri3_syncobj_passthrough)(WindowPtr window, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point); - }; - - #ifdef XWL_HAS_GLAMOR -@@ -142,6 +161,8 @@ Bool xwl_glamor_allow_commits(struct xwl_window *xwl_window); - void xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen); - Bool xwl_glamor_needs_buffer_flush(struct xwl_screen *xwl_screen); - Bool xwl_glamor_needs_n_buffering(struct xwl_screen *xwl_screen); -+Bool xwl_glamor_supports_implicit_sync(struct xwl_screen *xwl_screen); -+Bool xwl_glamor_supports_syncobjs(struct xwl_screen *xwl_screen); - Bool xwl_glamor_is_modifier_supported(struct xwl_screen *xwl_screen, - uint32_t format, uint64_t modifier); - uint32_t wl_drm_format_for_depth(int depth); -@@ -159,6 +180,15 @@ Bool xwl_glamor_get_drawable_modifiers(DrawablePtr drawable, uint32_t format, - Bool xwl_glamor_check_flip(WindowPtr present_window, PixmapPtr pixmap); - PixmapPtr xwl_glamor_create_pixmap_for_window (struct xwl_window *xwl_window); - int xwl_glamor_get_fence(struct xwl_screen *screen); -+void xwl_glamor_wait_fence(struct xwl_screen *xwl_screen, int fence); -+int xwl_glamor_dmabuf_export_sync_file(PixmapPtr pixmap); -+void xwl_glamor_dmabuf_import_sync_file(PixmapPtr pixmap, int sync_file); -+struct dri3_syncobj *xwl_glamor_dri3_syncobj_create(struct xwl_screen *xwl_screen); -+void xwl_glamor_dri3_syncobj_passthrough(WindowPtr window, -+ struct dri3_syncobj *acquire_syncobj, -+ struct dri3_syncobj *release_syncobj, -+ uint64_t acquire_point, -+ uint64_t release_point); - - #ifdef XV - /* glamor Xv Adaptor */ -diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c -index fb5a37b907..b7afc4d8b9 100644 ---- a/hw/xwayland/xwayland-present.c -+++ b/hw/xwayland/xwayland-present.c -@@ -39,6 +39,7 @@ - #include "xwayland-pixmap.h" - - #include "tearing-control-v1-client-protocol.h" -+#include "linux-drm-syncobj-v1-client-protocol.h" - - #define XWL_PRESENT_CAPS PresentCapabilityAsync | PresentCapabilityAsyncMayTear - -@@ -321,10 +322,6 @@ xwl_present_free_event(struct xwl_present_event *event) - static void - xwl_present_free_idle_vblank(present_vblank_ptr vblank) - { -- if (vblank->release_syncobj) -- vblank->release_syncobj->signal(vblank->release_syncobj, -- vblank->release_point); -- - present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); - xwl_present_free_event(xwl_present_event_from_vblank(vblank)); - } -@@ -479,6 +476,7 @@ static void - xwl_present_buffer_release(void *data) - { - struct xwl_present_window *xwl_present_window; -+ struct xwl_screen *xwl_screen; - struct xwl_present_event *event = data; - present_vblank_ptr vblank; - -@@ -487,9 +485,16 @@ xwl_present_buffer_release(void *data) - - vblank = &event->vblank; - -- if (vblank->release_syncobj) -- vblank->release_syncobj->signal(vblank->release_syncobj, -- vblank->release_point); -+ xwl_screen = xwl_screen_get(vblank->screen); -+#ifdef XWL_HAS_GLAMOR -+ if (vblank->release_syncobj && !xwl_screen->explicit_sync) { -+ /* transfer implicit fence to release syncobj */ -+ int fence_fd = xwl_glamor_dmabuf_export_sync_file(vblank->pixmap); -+ vblank->release_syncobj->import_fence(vblank->release_syncobj, -+ vblank->release_point, -+ fence_fd); -+ } -+#endif /* XWL_HAS_GLAMOR */ - - present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); - -@@ -713,6 +718,7 @@ xwl_present_check_flip(RRCrtcPtr crtc, - WindowPtr toplvl_window = xwl_present_toplvl_pixmap_window(present_window); - struct xwl_window *xwl_window = xwl_window_from_window(present_window); - ScreenPtr screen = pixmap->drawable.pScreen; -+ struct xwl_screen *xwl_screen = xwl_screen_get(screen); - - if (reason) - *reason = PRESENT_FLIP_REASON_UNKNOWN; -@@ -753,7 +759,11 @@ xwl_present_check_flip(RRCrtcPtr crtc, - if (xwl_window->xwl_screen->glamor && - !xwl_glamor_check_flip(present_window, pixmap)) - return FALSE; --#endif -+ -+ if (!xwl_glamor_supports_implicit_sync(xwl_screen) && -+ !xwl_screen->explicit_sync) -+ return FALSE; -+#endif /* XWL_HAS_GLAMOR */ - - /* Can't flip if the window pixmap doesn't match the xwl_window parent - * window's, e.g. because a client redirected this window or one of its -@@ -833,6 +843,7 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage) - PixmapPtr pixmap = vblank->pixmap; - struct xwl_window *xwl_window = xwl_window_from_window(present_window); - struct xwl_present_window *xwl_present_window = xwl_present_window_priv(present_window); -+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - BoxPtr damage_box; - struct wl_buffer *buffer; - struct xwl_present_event *event = xwl_present_event_from_vblank(vblank); -@@ -846,12 +857,35 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage) - return FALSE; - } - -+ if (xwl_window->surface_sync) { -+ wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync); -+ xwl_window->surface_sync = NULL; -+ } -+ - damage_box = RegionExtents(damage); - - pixmap->refcnt++; - - event->pixmap = pixmap; - -+#ifdef XWL_HAS_GLAMOR -+ if (vblank->acquire_syncobj && vblank->release_syncobj) { -+ if (xwl_screen->explicit_sync) -+ xwl_glamor_dri3_syncobj_passthrough(present_window, -+ vblank->acquire_syncobj, -+ vblank->release_syncobj, -+ vblank->acquire_point, -+ vblank->release_point); -+ else { -+ /* transfer from acquire syncobj to implicit fence */ -+ int fence_fd = -+ vblank->acquire_syncobj->export_fence(vblank->acquire_syncobj, -+ vblank->acquire_point); -+ xwl_glamor_dmabuf_import_sync_file(vblank->pixmap, fence_fd); -+ } -+ } -+#endif /* XWL_HAS_GLAMOR */ -+ - xwl_pixmap_set_buffer_release_cb(pixmap, xwl_present_buffer_release, event); - - /* We can flip directly to the main surface (full screen window without clips) */ -@@ -896,6 +930,18 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage) - return TRUE; - } - -+static void -+xwl_present_acquire_fence_avail(int fd, int xevents, void *data) -+{ -+ present_vblank_ptr vblank = data; -+ -+ SetNotifyFd(fd, NULL, 0, NULL); -+ close(fd); -+ vblank->efd = -1; -+ -+ xwl_present_re_execute(vblank); -+} -+ - /* - * Once the required MSC has been reached, execute the pending request. - * -@@ -911,6 +957,7 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) - WindowPtr window = vblank->window; - struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window); - present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window); -+ struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen); - - xorg_list_del(&vblank->event_queue); - -@@ -938,6 +985,19 @@ retry: - vblank->event_id, vblank, crtc_msc, - vblank->pixmap->drawable.id, vblank->window->drawable.id)); - -+ /* if the client is using explicit sync but the compositor does not -+ * support it, we must wait for the acquire fence to be available */ -+ if (vblank->acquire_syncobj && !xwl_screen->explicit_sync && -+ !vblank->acquire_syncobj->has_fence(vblank->acquire_syncobj, -+ vblank->acquire_point)) { -+ vblank->efd = eventfd(0, EFD_CLOEXEC); -+ SetNotifyFd(vblank->efd, xwl_present_acquire_fence_avail, X_NOTIFY_READ, vblank); -+ vblank->acquire_syncobj->submitted_eventfd(vblank->acquire_syncobj, -+ vblank->acquire_point, -+ vblank->efd); -+ return; -+ } -+ - /* Set update region as damaged */ - if (vblank->update) { - damage = RegionDuplicate(vblank->update); -@@ -1158,10 +1218,8 @@ xwl_present_init(ScreenPtr screen) - - xwl_screen->present_capabilities = XWL_PRESENT_CAPS; - #ifdef XWL_HAS_GLAMOR -- if (epoxy_has_egl_extension(xwl_screen->egl_display, -- "ANDROID_native_fence_sync")) -- xwl_screen->present_capabilities |= -- PresentCapabilitySyncobj; -+ if (xwl_glamor_supports_syncobjs(xwl_screen)) -+ xwl_screen->present_capabilities |= PresentCapabilitySyncobj; - #endif /* XWL_HAS_GLAMOR */ - - screen_priv->query_capabilities = xwl_present_query_capabilities; -diff --git a/hw/xwayland/xwayland-present.h b/hw/xwayland/xwayland-present.h -index b10198a40b..f518068fbd 100644 ---- a/hw/xwayland/xwayland-present.h -+++ b/hw/xwayland/xwayland-present.h -@@ -58,7 +58,6 @@ struct xwl_present_event { - present_vblank_rec vblank; - - PixmapPtr pixmap; -- Bool released; - uint32_t options; - uint64_t divisor; - uint64_t remainder; -diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c -index 5c71b55e29..94a047bf63 100644 ---- a/hw/xwayland/xwayland-screen.c -+++ b/hw/xwayland/xwayland-screen.c -@@ -68,6 +68,7 @@ - #include "xdg-shell-client-protocol.h" - #include "xwayland-shell-v1-client-protocol.h" - #include "tearing-control-v1-client-protocol.h" -+#include "linux-drm-syncobj-v1-client-protocol.h" - - static DevPrivateKeyRec xwl_screen_private_key; - static DevPrivateKeyRec xwl_client_private_key; -diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h -index 0a41986099..2799be773d 100644 ---- a/hw/xwayland/xwayland-screen.h -+++ b/hw/xwayland/xwayland-screen.h -@@ -112,6 +112,7 @@ struct xwl_screen { - struct wp_viewporter *viewporter; - struct xwayland_shell_v1 *xwayland_shell; - struct wp_tearing_control_manager_v1 *tearing_control_manager; -+ struct wp_linux_drm_syncobj_manager_v1 *explicit_sync; - struct xorg_list drm_lease_devices; - struct xorg_list queued_drm_lease_devices; - struct xorg_list drm_leases; -diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c -index 40e19e3495..fe19caaaed 100644 ---- a/hw/xwayland/xwayland-window-buffers.c -+++ b/hw/xwayland/xwayland-window-buffers.c -@@ -32,6 +32,14 @@ - #include "xwayland-pixmap.h" - #include "xwayland-screen.h" - #include "xwayland-window-buffers.h" -+#include "dri3.h" -+#ifdef XWL_HAS_GLAMOR -+#include "glamor.h" -+#endif -+ -+#include -+#include -+#include "linux-drm-syncobj-v1-client-protocol.h" - - #define BUFFER_TIMEOUT 1 * 1000 /* ms */ - -@@ -39,6 +47,9 @@ struct xwl_window_buffer { - struct xwl_window *xwl_window; - PixmapPtr pixmap; - RegionPtr damage_region; -+ struct dri3_syncobj *syncobj; -+ uint64_t timeline_point; -+ int efd; - int refcnt; - uint32_t time; - struct xorg_list link_buffer; -@@ -76,6 +87,7 @@ xwl_window_buffer_new(struct xwl_window *xwl_window) - xwl_window_buffer->xwl_window = xwl_window; - xwl_window_buffer->damage_region = RegionCreate(NullBox, 1); - xwl_window_buffer->pixmap = NullPixmap; -+ xwl_window_buffer->efd = -1; - xwl_window_buffer->refcnt = 1; - - xorg_list_append(&xwl_window_buffer->link_buffer, -@@ -107,6 +119,14 @@ xwl_window_buffer_maybe_dispose(struct xwl_window_buffer *xwl_window_buffer) - if (xwl_window_buffer->pixmap) - xwl_window_buffer_destroy_pixmap (xwl_window_buffer); - -+ 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); -+ } -+ - xorg_list_del(&xwl_window_buffer->link_buffer); - free(xwl_window_buffer); - -@@ -213,6 +233,18 @@ xwl_window_buffer_release_callback(void *data) - xwl_window); - } - -+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); -+} -+ - void - xwl_window_buffers_init(struct xwl_window *xwl_window) - { -@@ -331,6 +363,46 @@ xwl_window_recycle_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->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_buffers_get_pixmap(struct xwl_window *xwl_window, - RegionPtr damage_region) -@@ -349,11 +421,22 @@ xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window, - xwl_window_buffer_add_damage_region(xwl_window, damage_region); - - xwl_window_buffer = xwl_window_buffer_get_available(xwl_window); -+ - if (xwl_window_buffer) { - 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); -+ } -+#endif /* XWL_HAS_GLAMOR */ -+ - new_window_pixmap = xwl_window_buffer->pixmap; - - while (nBox--) { -@@ -388,9 +471,30 @@ xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window, - - /* Hold a reference on the buffer until it's released by the compositor */ - xwl_window_buffer->refcnt++; -- xwl_pixmap_set_buffer_release_cb(xwl_window_buffer->pixmap, -- xwl_window_buffer_release_callback, -- xwl_window_buffer); -+ -+#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)) { -+ /* 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 -+ /* 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 (xwl_window_buffer->efd == -1) -+ xwl_pixmap_set_buffer_release_cb(xwl_window_buffer->pixmap, -+ xwl_window_buffer_release_callback, -+ xwl_window_buffer); - - xorg_list_del(&xwl_window_buffer->link_buffer); - xorg_list_append(&xwl_window_buffer->link_buffer, -diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c -index d2434de8f5..023d58ba34 100644 ---- a/hw/xwayland/xwayland-window.c -+++ b/hw/xwayland/xwayland-window.c -@@ -51,6 +51,7 @@ - #include "viewporter-client-protocol.h" - #include "xdg-shell-client-protocol.h" - #include "xwayland-shell-v1-client-protocol.h" -+#include "linux-drm-syncobj-v1-client-protocol.h" - - #define DELAYED_WL_SURFACE_DESTROY 1000 /* ms */ - -@@ -1182,6 +1183,9 @@ xwl_unrealize_window(WindowPtr window) - if (xwl_window->tearing_control) - wp_tearing_control_v1_destroy(xwl_window->tearing_control); - -+ if (xwl_window->surface_sync) -+ wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync); -+ - release_wl_surface_for_window(xwl_window); - xorg_list_del(&xwl_window->link_damage); - xorg_list_del(&xwl_window->link_window); -@@ -1384,6 +1388,12 @@ xwl_window_attach_buffer(struct xwl_window *xwl_window) - pixmap = xwl_window_buffers_get_pixmap(xwl_window, region); - buffer = xwl_pixmap_get_wl_buffer(pixmap); - -+ if (xwl_window->surface_sync) { -+ /* default to implicit sync */ -+ wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync); -+ xwl_window->surface_sync = NULL; -+ } -+ - if (!buffer) { - ErrorF("Error getting buffer\n"); - return FALSE; -diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h -index 3370c45aaa..d415415f31 100644 ---- a/hw/xwayland/xwayland-window.h -+++ b/hw/xwayland/xwayland-window.h -@@ -120,6 +120,7 @@ struct xwl_window { - /* If TRUE, the window buffer format supports scanout with implicit modifier */ - Bool has_implicit_scanout_support; - struct wp_tearing_control_v1 *tearing_control; -+ struct wp_linux_drm_syncobj_surface_v1 *surface_sync; - }; - - struct xwl_window *xwl_window_get(WindowPtr window); -diff --git a/present/present_execute.c b/present/present_execute.c -index 913a8b67ba..2fb49749eb 100644 ---- a/present/present_execute.c -+++ b/present/present_execute.c -@@ -73,7 +73,10 @@ present_execute_wait(present_vblank_ptr vblank, uint64_t crtc_msc) - } - } - -- if (vblank->acquire_syncobj && -+ /* Defer execution of explicitly synchronized copies. -+ * Flip synchronization is managed by the driver. -+ */ -+ if (!vblank->flip && vblank->acquire_syncobj && - !vblank->acquire_syncobj->is_signaled(vblank->acquire_syncobj, - vblank->acquire_point)) { - vblank->efd = eventfd(0, EFD_CLOEXEC); --- -GitLab - - -From b28cb0a1dd8872a667843c6be297588ba5c405e9 Mon Sep 17 00:00:00 2001 -From: Erik Kurzinger -Date: Tue, 23 Jan 2024 14:17:57 -0800 -Subject: [PATCH 6/6] xwayland: start present timer when waiting for fence - -Before executing a present request, xwl_present_execute will call -present_execute_wait, which may cause execution to be deferred until -either the wait-fence (for PresentPixmap requests) or the acquire -timeline point (for PresentPixmapSynced requests) has been signaled. - -If another present request is received targeting the same window and msc -before the first request is re-executed the older request will be -scrapped in favor of the newer request. - -However, execution this newer request may also be deferred by -present_execute_wait for the same reason, and if yet another request -arrives quickly enough, the second request will also be scrapped. Thus, -we can get stuck in an endless loop and nothing ever ends up on the -screen. - -This cycle *should* be broken when we bump the msc, causing the last -request before that to be executed for real. But, assuming all of these -requests are targeted for immediate execution, that never actually -happens because we only start the frame timer when queueing a request -for a future msc. - -To fix this, we make two changes. Firstly, if present_execute_wait -causes execution to be deferred and the frame timer for the window is -not running, we will start it. Note that present_execute_wait may have -already called xwl_present_queue_vblank under certain circumstances, -which will have started the timer itself, but not if the request is -deferred due to a fence wait. - -Secondly, we change xwl_present_has_pending_events to return true if the -vblank list of the present_window_priv is non-empty, instead of only -returning true if there are any queued vblanks or a pending flip. So it -will now return true if there are any vblanks waiting on their fence to -be signaled, meaning xwl_present_reset_timer will start the timer in -that case, which is what we want. - -Signed-off-by: Erik Kurzinger ---- - hw/xwayland/xwayland-present.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c -index b7afc4d8b9..1b75808654 100644 ---- a/hw/xwayland/xwayland-present.c -+++ b/hw/xwayland/xwayland-present.c -@@ -168,10 +168,8 @@ xwl_present_get_pending_flip(struct xwl_present_window *xwl_present_window) - static inline Bool - xwl_present_has_pending_events(struct xwl_present_window *xwl_present_window) - { -- present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window); -- -- return (flip_pending && flip_pending->sync_flip) || -- !xorg_list_is_empty(&xwl_present_window->wait_list); -+ present_window_priv_ptr window_priv = present_window_priv(xwl_present_window->window); -+ return !xorg_list_is_empty(&window_priv->vblank); - } - - void -@@ -962,8 +960,11 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) - xorg_list_del(&vblank->event_queue); - - retry: -- if (present_execute_wait(vblank, crtc_msc)) -+ if (present_execute_wait(vblank, crtc_msc)) { -+ if (!xwl_present_window->frame_timer) -+ xwl_present_reset_timer(xwl_present_window); - return; -+ } - - if (flip_pending && vblank->flip && vblank->pixmap && vblank->window) { - DebugPresent(("\tr %" PRIu64 " %p (pending %p)\n", --- -GitLab