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 <ekurzinger@nvidia.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/967>
This commit is contained in:
Erik Kurzinger 2022-08-16 11:57:40 -07:00 committed by Olivier Fourdan
parent f051a2449d
commit 613dcb6a77
7 changed files with 168 additions and 3 deletions

View File

@ -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:

View File

@ -28,7 +28,35 @@
#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 (*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

View File

@ -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_ */

View File

@ -29,6 +29,17 @@
#include <drm_fourcc.h>
#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

View File

@ -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;
}

View File

@ -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

View File

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