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'])