2485 lines
93 KiB
Diff
2485 lines
93 KiB
Diff
From f1fc5cfab4bffd8a96df6fbe560946274024b904 Mon Sep 17 00:00:00 2001
|
|
From: Erik Kurzinger <ekurzinger@nvidia.com>
|
|
Date: Tue, 24 Oct 2023 16:14:17 -0700
|
|
Subject: [PATCH 1/5] 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 <ekurzinger@nvidia.com>
|
|
---
|
|
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 d7bfc6dca2..2c38a15ae0 100644
|
|
--- a/include/protocol-versions.h
|
|
+++ b/include/protocol-versions.h
|
|
@@ -48,7 +48,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 85da52868b21b8998ab1826df40534297c6df280 Mon Sep 17 00:00:00 2001
|
|
From: Erik Kurzinger <ekurzinger@nvidia.com>
|
|
Date: Tue, 16 Aug 2022 11:57:40 -0700
|
|
Subject: [PATCH 2/5] 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
|
|
* check - poll a timeline point and return whether it 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
|
|
* eventfd - register an eventfd to be signaled when the given timeline
|
|
point is either submitted or signaled, depending on wait_avail
|
|
|
|
Implementations will be responsible for populating these function
|
|
pointers when importing a syncobj.
|
|
|
|
Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
|
|
---
|
|
dri3/dri3.c | 15 ++++++
|
|
dri3/dri3.h | 36 ++++++++++++++-
|
|
dri3/dri3_priv.h | 3 ++
|
|
dri3/dri3_request.c | 91 +++++++++++++++++++++++++++++++++++++
|
|
dri3/dri3_screen.c | 20 ++++++++
|
|
include/protocol-versions.h | 2 +-
|
|
6 files changed, 165 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..f7f4bb1c1b 100644
|
|
--- a/dri3/dri3.h
|
|
+++ b/dri3/dri3.h
|
|
@@ -28,7 +28,33 @@
|
|
#include <X11/extensions/dri3proto.h>
|
|
#include <randrstr.h>
|
|
|
|
-#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 (*check)(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 (*eventfd)(struct dri3_syncobj *syncobj, uint64_t point, int efd, Bool wait_avail);
|
|
+};
|
|
+
|
|
+#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 +110,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 +132,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 <protocol-versions.h>
|
|
#include <drm_fourcc.h>
|
|
|
|
+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 2c38a15ae0..ffd7d0e239 100644
|
|
--- a/include/protocol-versions.h
|
|
+++ b/include/protocol-versions.h
|
|
@@ -48,7 +48,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 982ad9c2f4ff6c29ce1ded6123a81dfd8422dd72 Mon Sep 17 00:00:00 2001
|
|
From: Erik Kurzinger <ekurzinger@nvidia.com>
|
|
Date: Tue, 16 Aug 2022 11:59:14 -0700
|
|
Subject: [PATCH 3/5] 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 <ekurzinger@nvidia.com>
|
|
---
|
|
hw/xwayland/xwayland-glamor-gbm.c | 184 +++++++++++++++++++++++++++++-
|
|
1 file changed, 183 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
|
|
index b177b77e08..5bd2373500 100644
|
|
--- a/hw/xwayland/xwayland-glamor-gbm.c
|
|
+++ b/hw/xwayland/xwayland-glamor-gbm.c
|
|
@@ -811,7 +811,183 @@ 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)
|
|
+{
|
|
+ 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 */,
|
|
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
|
|
+ NULL /* first_signaled */);
|
|
+}
|
|
+
|
|
+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 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.check = xwl_dri3_check_syncobj;
|
|
+ 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.eventfd = xwl_dri3_syncobj_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,
|
|
@@ -820,6 +996,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 *
|
|
@@ -1182,6 +1359,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 5b3744ecbc40f45650f961dd7d8ea82987519230 Mon Sep 17 00:00:00 2001
|
|
From: Erik Kurzinger <ekurzinger@nvidia.com>
|
|
Date: Tue, 16 Aug 2022 12:03:59 -0700
|
|
Subject: [PATCH 4/5] 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 <ekurzinger@nvidia.com>
|
|
---
|
|
hw/xfree86/common/xf86Module.h | 2 +-
|
|
hw/xwayland/xwayland-glamor.c | 24 +++++
|
|
hw/xwayland/xwayland-glamor.h | 1 +
|
|
hw/xwayland/xwayland-present.c | 101 +++++++++++++++++---
|
|
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 | 169 ++++++++++++++++++++++++++-------
|
|
present/present_scmd.c | 8 ++
|
|
present/present_screen.c | 1 +
|
|
present/present_vblank.c | 36 +++++++
|
|
14 files changed, 368 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 c6aa8eb172..f9a4ef0b49 100644
|
|
--- a/hw/xwayland/xwayland-glamor.c
|
|
+++ b/hw/xwayland/xwayland-glamor.c
|
|
@@ -1074,6 +1074,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 183fe755ae..6f46043642 100644
|
|
--- a/hw/xwayland/xwayland-glamor.h
|
|
+++ b/hw/xwayland/xwayland-glamor.h
|
|
@@ -151,6 +151,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 5ede33e4cf..3a0c1d40f4 100644
|
|
--- a/hw/xwayland/xwayland-present.c
|
|
+++ b/hw/xwayland/xwayland-present.c
|
|
@@ -27,6 +27,7 @@
|
|
|
|
#include <windowstr.h>
|
|
#include <present.h>
|
|
+#include <sys/eventfd.h>
|
|
|
|
#include "xwayland-present.h"
|
|
#include "xwayland-screen.h"
|
|
@@ -211,10 +212,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
|
|
@@ -233,6 +242,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
|
|
@@ -240,9 +259,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);
|
|
}
|
|
|
|
@@ -281,6 +318,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));
|
|
}
|
|
@@ -440,6 +481,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);
|
|
@@ -630,6 +676,15 @@ xwl_present_maybe_set_reason(struct xwl_window *xwl_window, PresentFlipReason *r
|
|
}
|
|
}
|
|
|
|
+static int
|
|
+xwl_present_flush_fenced(WindowPtr window)
|
|
+{
|
|
+ struct xwl_window *xwl_window = xwl_window_from_window(window);
|
|
+ int fence = xwl_glamor_get_fence(xwl_window->xwl_screen);
|
|
+ xwl_present_flush(window);
|
|
+ return fence;
|
|
+}
|
|
+
|
|
static Bool
|
|
xwl_present_check_flip(RRCrtcPtr crtc,
|
|
WindowPtr present_window,
|
|
@@ -797,7 +852,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;
|
|
@@ -838,6 +893,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;
|
|
|
|
@@ -898,6 +954,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));
|
|
@@ -934,6 +992,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,
|
|
@@ -950,11 +1012,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);
|
|
@@ -989,6 +1057,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);
|
|
@@ -1001,22 +1073,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) {
|
|
@@ -1065,6 +1133,12 @@ xwl_present_init(ScreenPtr screen)
|
|
if (!dixRegisterPrivateKey(&xwl_present_window_private_key, PRIVATE_WINDOW, 0))
|
|
return FALSE;
|
|
|
|
+ xwl_screen->present_capabilities = XWL_PRESENT_CAPS;
|
|
+ if (epoxy_has_egl_extension(xwl_screen->egl_display,
|
|
+ "ANDROID_native_fence_sync"))
|
|
+ xwl_screen->present_capabilities |=
|
|
+ PresentCapabilitySyncobj;
|
|
+
|
|
screen_priv->query_capabilities = xwl_present_query_capabilities;
|
|
screen_priv->get_crtc = xwl_present_get_crtc;
|
|
|
|
@@ -1075,6 +1149,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 4fd1e579ff..8a6f11ec4e 100644
|
|
--- a/hw/xwayland/xwayland-present.h
|
|
+++ b/hw/xwayland/xwayland-present.h
|
|
@@ -59,7 +59,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 94033aabf9..97af13baeb 100644
|
|
--- a/hw/xwayland/xwayland-screen.h
|
|
+++ b/hw/xwayland/xwayland-screen.h
|
|
@@ -144,6 +144,8 @@ struct xwl_screen {
|
|
int libdecor_fd;
|
|
struct libdecor *libdecor_context;
|
|
#endif
|
|
+
|
|
+ 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 ffd7d0e239..e28e2384d8 100644
|
|
--- a/include/protocol-versions.h
|
|
+++ b/include/protocol-versions.h
|
|
@@ -69,7 +69,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..795c70c88c 100644
|
|
--- a/present/present_execute.c
|
|
+++ b/present/present_execute.c
|
|
@@ -21,6 +21,7 @@
|
|
*/
|
|
|
|
#include "present_priv.h"
|
|
+#include <sys/eventfd.h>
|
|
|
|
/*
|
|
* Called when the wait fence is triggered; just gets the current msc/ust and
|
|
@@ -37,6 +38,21 @@ 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);
|
|
+ uint64_t efd_value;
|
|
+
|
|
+ read(fd, &efd_value, sizeof (efd_value));
|
|
+ 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 +74,16 @@ present_execute_wait(present_vblank_ptr vblank, uint64_t crtc_msc)
|
|
return TRUE;
|
|
}
|
|
}
|
|
+
|
|
+ if (vblank->acquire_syncobj && !vblank->acquire_syncobj->check(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->eventfd(vblank->acquire_syncobj, vblank->acquire_point,
|
|
+ vblank->efd, FALSE /* wait_avail */);
|
|
+ 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 <xfixes.h>
|
|
#include <randrstr.h>
|
|
#include <inttypes.h>
|
|
+#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..1f4f8a4dc3 100644
|
|
--- a/present/present_request.c
|
|
+++ b/present/present_request.c
|
|
@@ -79,79 +79,121 @@ 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, req_target_crtc, client, DixReadAccess);
|
|
|
|
- VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess);
|
|
+ VERIFY_FENCE_OR_NONE(wait_fence, req_wait_fence, client, DixReadAccess);
|
|
+ VERIFY_FENCE_OR_NONE(idle_fence, req_idle_fence, client, DixWriteAccess);
|
|
|
|
- VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess);
|
|
- VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess);
|
|
+ if ((acquire_syncobj && req_acquire_point == 0) ||
|
|
+ (release_syncobj && req_release_point == 0))
|
|
+ return BadValue;
|
|
|
|
- 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 +282,36 @@ 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);
|
|
+
|
|
+ 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 +391,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 2c29aafd23..df6a6a215e 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 02621661f676debe73956c0a8fc0d914664711a4 Mon Sep 17 00:00:00 2001
|
|
From: Erik Kurzinger <ekurzinger@nvidia.com>
|
|
Date: Tue, 15 Aug 2023 15:32:47 -0700
|
|
Subject: [PATCH 5/5] 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 <ekurzinger@nvidia.com>
|
|
---
|
|
hw/xwayland/meson.build | 3 +
|
|
hw/xwayland/xwayland-glamor-gbm.c | 174 +++++++++++++++++++++++++-
|
|
hw/xwayland/xwayland-glamor.c | 84 +++++++++++++
|
|
hw/xwayland/xwayland-glamor.h | 26 ++++
|
|
hw/xwayland/xwayland-present.c | 51 ++++++--
|
|
hw/xwayland/xwayland-present.h | 1 -
|
|
hw/xwayland/xwayland-screen.c | 1 +
|
|
hw/xwayland/xwayland-screen.h | 7 ++
|
|
hw/xwayland/xwayland-window-buffers.c | 68 ++++++++++
|
|
hw/xwayland/xwayland-window.c | 11 ++
|
|
hw/xwayland/xwayland-window.h | 1 +
|
|
present/present_execute.c | 7 +-
|
|
12 files changed, 420 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build
|
|
index f2038ab7c3..434b0ceade 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 5bd2373500..6a06be2daa 100644
|
|
--- a/hw/xwayland/xwayland-glamor-gbm.c
|
|
+++ b/hw/xwayland/xwayland-glamor-gbm.c
|
|
@@ -35,6 +35,9 @@
|
|
#include <sys/stat.h>
|
|
#include <xf86drm.h>
|
|
#include <drm_fourcc.h>
|
|
+#include <linux/dma-buf.h>
|
|
+#include <linux/sync_file.h>
|
|
+#include <sys/ioctl.h>
|
|
|
|
#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;
|
|
@@ -553,6 +557,28 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
|
|
return xwl_pixmap->buffer;
|
|
}
|
|
|
|
+static void
|
|
+xwl_screen_destroy_explicit_sync(struct xwl_screen *xwl_screen)
|
|
+{
|
|
+ if (xwl_screen->glamor_syncobj) {
|
|
+ xwl_screen->glamor_syncobj->free(xwl_screen->glamor_syncobj);
|
|
+ xwl_screen->glamor_syncobj = NULL;
|
|
+ }
|
|
+
|
|
+ if (xwl_screen->server_syncobj) {
|
|
+ xwl_screen->server_syncobj->free(xwl_screen->server_syncobj);
|
|
+ xwl_screen->server_syncobj = NULL;
|
|
+ }
|
|
+
|
|
+ if (xwl_screen->explicit_sync) {
|
|
+ wp_linux_drm_syncobj_v1_destroy(xwl_screen->explicit_sync);
|
|
+ xwl_screen->explicit_sync = NULL;
|
|
+ }
|
|
+
|
|
+ xwl_screen->glamor_timeline_point = 0;
|
|
+ xwl_screen->server_timeline_point = 0;
|
|
+}
|
|
+
|
|
static void
|
|
xwl_glamor_gbm_cleanup(struct xwl_screen *xwl_screen)
|
|
{
|
|
@@ -567,6 +593,7 @@ 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);
|
|
+ xwl_screen_destroy_explicit_sync(xwl_screen);
|
|
|
|
free(xwl_gbm);
|
|
}
|
|
@@ -811,12 +838,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_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)
|
|
{
|
|
@@ -903,6 +1006,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);
|
|
|
|
@@ -926,10 +1032,23 @@ 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);
|
|
+ int syncobj_fd = -1;
|
|
|
|
if (!syncobj)
|
|
return NULL;
|
|
|
|
+ if (xwl_screen->explicit_sync) {
|
|
+ if (drmSyncobjHandleToFD(xwl_gbm->drm_fd, handle, &syncobj_fd))
|
|
+ goto fail;
|
|
+
|
|
+ syncobj->timeline =
|
|
+ wp_linux_drm_syncobj_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;
|
|
@@ -987,6 +1106,29 @@ xwl_gbm_supports_syncobjs(struct xwl_screen *xwl_screen)
|
|
return TRUE;
|
|
}
|
|
|
|
+static Bool
|
|
+xwl_screen_init_explicit_sync(struct xwl_screen *xwl_screen)
|
|
+{
|
|
+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
|
+ uint32_t glamor_syncobj_handle, server_syncobj_handle;
|
|
+
|
|
+ if (!xwl_screen->explicit_sync)
|
|
+ return FALSE;
|
|
+
|
|
+ if (drmSyncobjCreate(xwl_gbm->drm_fd, 0, &glamor_syncobj_handle) ||
|
|
+ drmSyncobjCreate(xwl_gbm->drm_fd, 0, &server_syncobj_handle))
|
|
+ return FALSE;
|
|
+
|
|
+ xwl_screen->glamor_syncobj = xwl_dri3_create_syncobj(xwl_screen, glamor_syncobj_handle);
|
|
+ xwl_screen->server_syncobj = xwl_dri3_create_syncobj(xwl_screen, server_syncobj_handle);
|
|
+ if (!xwl_screen->glamor_syncobj || !xwl_screen->server_syncobj)
|
|
+ return FALSE;
|
|
+
|
|
+ xwl_screen->glamor_timeline_point = 1;
|
|
+ xwl_screen->server_timeline_point = 1;
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
static dri3_screen_info_rec xwl_dri3_info = {
|
|
.version = 2,
|
|
.open = NULL,
|
|
@@ -1158,6 +1300,11 @@ xwl_glamor_gbm_init_wl_registry(struct xwl_screen *xwl_screen,
|
|
} else if (strcmp(name, "zwp_linux_dmabuf_v1") == 0) {
|
|
xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
|
|
return TRUE;
|
|
+ } else if (strcmp(name, "wp_linux_drm_syncobj_v1") == 0) {
|
|
+ xwl_screen->explicit_sync =
|
|
+ wl_registry_bind(xwl_screen->registry, id,
|
|
+ &wp_linux_drm_syncobj_v1_interface,
|
|
+ version);
|
|
}
|
|
|
|
/* no match */
|
|
@@ -1281,7 +1428,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->fd_render_node && !xwl_gbm->drm_authenticated) {
|
|
ErrorF("Failed to get wl_drm, disabling Glamor and DRI3\n");
|
|
@@ -1342,6 +1489,22 @@ xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen)
|
|
if (gbm_backend_name && strcmp(gbm_backend_name, "drm") != 0)
|
|
xwl_screen->glvnd_vendor = gbm_backend_name;
|
|
|
|
+ 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_init_explicit_sync(xwl_screen))
|
|
+ xwl_screen_destroy_explicit_sync(xwl_screen);
|
|
+
|
|
return TRUE;
|
|
error:
|
|
if (xwl_screen->egl_display != EGL_NO_DISPLAY) {
|
|
@@ -1359,7 +1522,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;
|
|
}
|
|
@@ -1432,6 +1595,11 @@ 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_passthrough = xwl_glamor_gbm_dri3_syncobj_passthrough;
|
|
}
|
|
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
|
|
index f9a4ef0b49..b4e912cb56 100644
|
|
--- a/hw/xwayland/xwayland-glamor.c
|
|
+++ b/hw/xwayland/xwayland-glamor.c
|
|
@@ -1060,6 +1060,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 FALSE;
|
|
+
|
|
+ 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)
|
|
{
|
|
@@ -1098,6 +1118,70 @@ 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);
|
|
+}
|
|
+
|
|
+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 6f46043642..d1a8982b88 100644
|
|
--- a/hw/xwayland/xwayland-glamor.h
|
|
+++ b/hw/xwayland/xwayland-glamor.h
|
|
@@ -34,11 +34,14 @@
|
|
#include <xf86drm.h>
|
|
|
|
#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;
|
|
|
|
struct xwl_egl_backend {
|
|
@@ -107,6 +110,19 @@ 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);
|
|
+
|
|
+ /* 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
|
|
@@ -135,6 +151,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);
|
|
@@ -152,6 +170,14 @@ 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);
|
|
+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 3a0c1d40f4..fb1df379f7 100644
|
|
--- a/hw/xwayland/xwayland-present.c
|
|
+++ b/hw/xwayland/xwayland-present.c
|
|
@@ -27,7 +27,6 @@
|
|
|
|
#include <windowstr.h>
|
|
#include <present.h>
|
|
-#include <sys/eventfd.h>
|
|
|
|
#include "xwayland-present.h"
|
|
#include "xwayland-screen.h"
|
|
@@ -36,6 +35,7 @@
|
|
#include "glamor.h"
|
|
|
|
#include "tearing-control-v1-client-protocol.h"
|
|
+#include "linux-drm-syncobj-v1-client-protocol.h"
|
|
|
|
#define XWL_PRESENT_CAPS PresentCapabilityAsync | PresentCapabilityAsyncMayTear
|
|
|
|
@@ -474,6 +474,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;
|
|
|
|
@@ -482,9 +483,14 @@ 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);
|
|
+ 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);
|
|
+ }
|
|
|
|
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
|
|
|
|
@@ -698,6 +704,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;
|
|
@@ -734,6 +741,13 @@ xwl_present_check_flip(RRCrtcPtr crtc,
|
|
if (!xwl_glamor_check_flip(present_window, pixmap))
|
|
return FALSE;
|
|
|
|
+ /* If glamor doesn't support implicit sync and the compositor doesn't
|
|
+ * support explicit sync, we cannot flip
|
|
+ */
|
|
+ if (!xwl_glamor_supports_implicit_sync(xwl_screen) &&
|
|
+ !xwl_screen->explicit_sync)
|
|
+ return FALSE;
|
|
+
|
|
/* 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
|
|
* parents.
|
|
@@ -812,6 +826,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);
|
|
@@ -831,6 +846,28 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage)
|
|
|
|
event->pixmap = pixmap;
|
|
|
|
+ assert(xwl_glamor_supports_implicit_sync(xwl_screen) ||
|
|
+ xwl_screen->explicit_sync);
|
|
+
|
|
+ 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);
|
|
+ }
|
|
+ } else if (xwl_window->surface_sync) {
|
|
+ wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync);
|
|
+ xwl_window->surface_sync = NULL;
|
|
+ }
|
|
+
|
|
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) */
|
|
@@ -1134,10 +1171,8 @@ xwl_present_init(ScreenPtr screen)
|
|
return FALSE;
|
|
|
|
xwl_screen->present_capabilities = XWL_PRESENT_CAPS;
|
|
- 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;
|
|
|
|
screen_priv->query_capabilities = xwl_present_query_capabilities;
|
|
screen_priv->get_crtc = xwl_present_get_crtc;
|
|
diff --git a/hw/xwayland/xwayland-present.h b/hw/xwayland/xwayland-present.h
|
|
index 8a6f11ec4e..ffc16f52e6 100644
|
|
--- a/hw/xwayland/xwayland-present.h
|
|
+++ b/hw/xwayland/xwayland-present.h
|
|
@@ -59,7 +59,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 6b57fbe9d7..5845c6f757 100644
|
|
--- a/hw/xwayland/xwayland-screen.c
|
|
+++ b/hw/xwayland/xwayland-screen.c
|
|
@@ -64,6 +64,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 97af13baeb..a593f01d35 100644
|
|
--- a/hw/xwayland/xwayland-screen.h
|
|
+++ b/hw/xwayland/xwayland-screen.h
|
|
@@ -110,6 +110,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_v1 *explicit_sync;
|
|
struct xorg_list drm_lease_devices;
|
|
struct xorg_list queued_drm_lease_devices;
|
|
struct xorg_list drm_leases;
|
|
@@ -146,6 +147,12 @@ struct xwl_screen {
|
|
#endif
|
|
|
|
uint32_t present_capabilities;
|
|
+
|
|
+ /* For use with explicit sync */
|
|
+ struct dri3_syncobj *glamor_syncobj;
|
|
+ struct dri3_syncobj *server_syncobj;
|
|
+ uint64_t glamor_timeline_point;
|
|
+ uint64_t server_timeline_point;
|
|
};
|
|
|
|
/* Apps which use randr/vidmode to change the mode when going fullscreen,
|
|
diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
|
|
index f7bb571bbf..0b7cb5d160 100644
|
|
--- a/hw/xwayland/xwayland-window-buffers.c
|
|
+++ b/hw/xwayland/xwayland-window-buffers.c
|
|
@@ -32,6 +32,13 @@
|
|
#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 <poll.h>
|
|
+#include <sys/eventfd.h>
|
|
|
|
#define BUFFER_TIMEOUT 1 * 1000 /* ms */
|
|
|
|
@@ -40,6 +47,8 @@ struct xwl_window_buffer {
|
|
PixmapPtr pixmap;
|
|
RegionPtr damage_region;
|
|
Bool recycle_on_release;
|
|
+ uint64_t release_point;
|
|
+ int sync_fd;
|
|
int refcnt;
|
|
uint32_t time;
|
|
struct xorg_list link_buffer;
|
|
@@ -80,6 +89,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->sync_fd = -1;
|
|
xwl_window_buffer->refcnt = 1;
|
|
|
|
xorg_list_append(&xwl_window_buffer->link_buffer,
|
|
@@ -111,6 +121,9 @@ xwl_window_buffer_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->sync_fd >= 0)
|
|
+ close(xwl_window_buffer->sync_fd);
|
|
+
|
|
xorg_list_del(&xwl_window_buffer->link_buffer);
|
|
free(xwl_window_buffer);
|
|
|
|
@@ -194,6 +207,7 @@ xwl_window_buffer_release_callback(void *data)
|
|
{
|
|
struct xwl_window_buffer *xwl_window_buffer = data;
|
|
struct xwl_window *xwl_window = xwl_window_buffer->xwl_window;
|
|
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
|
struct xwl_window_buffer *oldest_available_buffer;
|
|
|
|
/* Drop the reference on the buffer we took in get_pixmap. If that
|
|
@@ -221,6 +235,14 @@ xwl_window_buffer_release_callback(void *data)
|
|
struct xwl_window_buffer,
|
|
link_buffer);
|
|
|
|
+ if (xwl_window_buffer->release_point) {
|
|
+ /* We will wait for this fence before re-using the buffer */
|
|
+ xwl_window_buffer->sync_fd =
|
|
+ xwl_screen->server_syncobj->export_fence(xwl_screen->server_syncobj,
|
|
+ xwl_window_buffer->release_point);
|
|
+ xwl_window_buffer->release_point = 0;
|
|
+ }
|
|
+
|
|
/* Schedule next timer based on time of the oldest buffer */
|
|
xwl_window->window_buffers_timer =
|
|
TimerSet(xwl_window->window_buffers_timer,
|
|
@@ -289,6 +311,34 @@ xwl_window_buffers_dispose(struct xwl_window *xwl_window)
|
|
}
|
|
}
|
|
|
|
+static void
|
|
+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_screen->glamor_timeline_point++;
|
|
+ uint64_t release_point = xwl_screen->server_timeline_point++;
|
|
+
|
|
+ int fence_fd = xwl_glamor_get_fence(xwl_screen);
|
|
+ if (fence_fd >= 0) {
|
|
+ xwl_screen->glamor_syncobj->import_fence(xwl_screen->glamor_syncobj,
|
|
+ acquire_point, fence_fd);
|
|
+ } else {
|
|
+#ifdef XWL_HAS_GLAMOR
|
|
+ glamor_finish(xwl_screen->screen);
|
|
+#endif /* XWL_HAS_GLAMOR */
|
|
+ xwl_screen->glamor_syncobj->signal(xwl_screen->glamor_syncobj,
|
|
+ acquire_point);
|
|
+ }
|
|
+
|
|
+ xwl_window_buffer->release_point = release_point;
|
|
+ xwl_glamor_dri3_syncobj_passthrough(xwl_window->window,
|
|
+ xwl_screen->glamor_syncobj,
|
|
+ xwl_screen->server_syncobj,
|
|
+ acquire_point,
|
|
+ release_point);
|
|
+}
|
|
+
|
|
PixmapPtr
|
|
xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
|
|
RegionPtr damage_region)
|
|
@@ -313,6 +363,14 @@ xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
|
|
|
|
full_damage = xwl_window_buffer->damage_region;
|
|
|
|
+#ifdef XWL_HAS_GLAMOR
|
|
+ if (xwl_window_buffer->sync_fd >= 0) {
|
|
+ xwl_glamor_wait_fence(xwl_screen, xwl_window_buffer->sync_fd);
|
|
+ close(xwl_window_buffer->sync_fd);
|
|
+ xwl_window_buffer->sync_fd = -1;
|
|
+ }
|
|
+#endif /* XWL_HAS_GLAMOR */
|
|
+
|
|
if (xwl_window_buffer->pixmap) {
|
|
BoxPtr pBox = RegionRects(full_damage);
|
|
int nBox = RegionNumRects(full_damage);
|
|
@@ -359,6 +417,16 @@ 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++;
|
|
+
|
|
+#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);
|
|
+ else
|
|
+ glamor_finish(xwl_screen->screen);
|
|
+ }
|
|
+#endif /* XWL_HAS_GLAMOR */
|
|
+
|
|
xwl_pixmap_set_buffer_release_cb(xwl_window_buffer->pixmap,
|
|
xwl_window_buffer_release_callback,
|
|
xwl_window_buffer);
|
|
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
|
|
index f1d6580e67..a75faa2ec5 100644
|
|
--- a/hw/xwayland/xwayland-window.c
|
|
+++ b/hw/xwayland/xwayland-window.c
|
|
@@ -50,6 +50,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 */
|
|
|
|
@@ -1149,6 +1150,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);
|
|
@@ -1354,6 +1358,13 @@ xwl_window_attach_buffer(struct xwl_window *xwl_window)
|
|
pixmap = xwl_window_buffers_get_pixmap(xwl_window, region);
|
|
|
|
#ifdef XWL_HAS_GLAMOR
|
|
+ if (xwl_glamor_supports_implicit_sync(xwl_screen) &&
|
|
+ xwl_window->surface_sync) {
|
|
+ /* prefer implicit sync when possible */
|
|
+ wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync);
|
|
+ xwl_window->surface_sync = NULL;
|
|
+ }
|
|
+
|
|
if (xwl_screen->glamor)
|
|
buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap);
|
|
else
|
|
diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h
|
|
index 45ae16da0f..51ce91b577 100644
|
|
--- a/hw/xwayland/xwayland-window.h
|
|
+++ b/hw/xwayland/xwayland-window.h
|
|
@@ -122,6 +122,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 795c70c88c..6d8ac2929c 100644
|
|
--- a/present/present_execute.c
|
|
+++ b/present/present_execute.c
|
|
@@ -75,8 +75,11 @@ present_execute_wait(present_vblank_ptr vblank, uint64_t crtc_msc)
|
|
}
|
|
}
|
|
|
|
- if (vblank->acquire_syncobj && !vblank->acquire_syncobj->check(vblank->acquire_syncobj,
|
|
- vblank->acquire_point)) {
|
|
+ /* Defer execution of explicitly synchronized copies.
|
|
+ * Flip synchronization is managed by the driver.
|
|
+ */
|
|
+ if (!vblank->flip && vblank->acquire_syncobj &&
|
|
+ !vblank->acquire_syncobj->check(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->eventfd(vblank->acquire_syncobj, vblank->acquire_point,
|
|
--
|
|
GitLab
|
|
|