From 613dcb6a77d831cd0a6d1e19671b548491ada934 Mon Sep 17 00:00:00 2001 From: Erik Kurzinger Date: Tue, 16 Aug 2022 11:57:40 -0700 Subject: [PATCH] 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 Part-of: --- 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 +- meson.build | 2 +- 7 files changed, 168 insertions(+), 3 deletions(-) diff --git a/dri3/dri3.c b/dri3/dri3.c index 191252969..f9c517277 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 02d3b03ee..14f9a1efa 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 f319d1770..71d2da957 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 a5cc7ccc9..98c37aa91 100644 --- a/dri3/dri3_request.c +++ b/dri3/dri3_request.c @@ -29,6 +29,17 @@ #include #include "randrstr_priv.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) { @@ -62,6 +73,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++) { @@ -69,6 +84,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: @@ -576,6 +595,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, RT_NONE); + return Success; +} + int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { proc_dri3_query_version, /* 0 */ proc_dri3_open, /* 1 */ @@ -587,6 +651,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 @@ -731,6 +797,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 */ @@ -742,6 +831,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 bc96e5339..5614a22b3 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 ee58e8a67..6d1b4daa5 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 /* Generic event extension */ #define SERVER_GE_MAJOR_VERSION 1 diff --git a/meson.build b/meson.build index 77721b411..cd52cefaf 100644 --- a/meson.build +++ b/meson.build @@ -91,7 +91,7 @@ scrnsaverproto_dep = dependency('scrnsaverproto', version: '>= 1.1', fallback: [ resourceproto_dep = dependency('resourceproto', version: '>= 1.2.0', fallback: ['xorgproto', 'ext_xorgproto']) xf86driproto_dep = dependency('xf86driproto', version: '>= 2.1.0', fallback: ['xorgproto', 'ext_xorgproto'], required: get_option('dri1') == 'true') dri2proto_dep = dependency('dri2proto', version: '>= 2.8', fallback: ['xorgproto', 'ext_xorgproto'], required: get_option('dri2') == 'true') -dri3proto_dep = dependency('dri3proto', version: '>= 1.3', fallback: ['xorgproto', 'ext_xorgproto'], required: get_option('dri3') == 'true') +dri3proto_dep = dependency('dri3proto', version: '>= 1.4', fallback: ['xorgproto', 'ext_xorgproto'], required: get_option('dri3') == 'true') xineramaproto_dep = dependency('xineramaproto', fallback: ['xorgproto', 'ext_xorgproto']) xf86bigfontproto_dep = dependency('xf86bigfontproto', version: '>= 1.2.0', fallback: ['xorgproto', 'ext_xorgproto'], required: get_option('xf86bigfont')) xf86vidmodeproto_dep = dependency('xf86vidmodeproto', version: '>= 2.2.99.1', fallback: ['xorgproto', 'ext_xorgproto'])