DRM lease and CRTC-based vblank APIs. Kernel code has already been posted.
From: Keith Packard keithp@keithp.com
drmModeCreateLease drmModeListLessees drmModeGetLease drmModeRevokeLease
Changes for v2:
Remove lessee id from GetLease Remove lessor_id from ListLeases Add revoke Renumber to track kernel rebase on drm-next
Signed-off-by: Keith Packard keithp@keithp.com --- include/drm/drm.h | 4 +++ include/drm/drm_mode.h | 66 ++++++++++++++++++++++++++++++++++++ xf86drmMode.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ xf86drmMode.h | 23 +++++++++++++ 4 files changed, 184 insertions(+)
diff --git a/include/drm/drm.h b/include/drm/drm.h index bf3674ae..7c736765 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -829,6 +829,10 @@ extern "C" { #define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) #define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob) #define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob) +#define DRM_IOCTL_MODE_CREATE_LEASE DRM_IOWR(0xC3, struct drm_mode_create_lease) +#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC4, struct drm_mode_list_lessees) +#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC5, struct drm_mode_get_lease) +#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC6, struct drm_mode_revoke_lease)
#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create) #define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy) diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index 70571af6..a2b71614 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -677,6 +677,72 @@ struct drm_mode_destroy_blob { __u32 blob_id; };
+/** + * Lease mode resources to another user. + */ +struct drm_mode_create_lease { + /** Pointer to array of object ids (__u32) */ + __u64 object_ids; + /** Number of object ids */ + __u32 object_count; + /** flags for new FD (O_CLOEXEC, etc) */ + __u32 flags; + + /** Return: unique identifier for lessee. */ + __u32 lessee_id; + /** Return: file descriptor to new drm_master file */ + __u32 fd; +}; + +/** + * List lesses from a drm_master + */ +struct drm_mode_list_lessees { + /** Number of lessees. + * On input, provides length of the array. + * On output, provides total number. No + * more than the input number will be written + * back, so two calls can be used to get + * the size and then the data. + */ + __u32 count_lessees; + __u32 pad; + + /** Pointer to lessees. + * pointer to __u64 array of lessee ids + */ + __u64 lessees_ptr; +}; + +/** + * Get leased objects for a lessee + */ +struct drm_mode_get_lease { + /** Number of leased objects. + * On input, provides length of the array. + * On output, provides total number. No + * more than the input number will be written + * back, so two calls can be used to get + * the size and then the data. + */ + __u32 count_objects; + __u32 pad; + + /** Pointer to objects. + * pointer to __u32 array of object ids + */ + __u64 objects_ptr; +}; + +/** + * Revoke lease + */ +struct drm_mode_revoke_lease { + /** Unique ID of lessee + */ + __u32 lessee_id; +}; + #if defined(__cplusplus) } #endif diff --git a/xf86drmMode.c b/xf86drmMode.c index d3bc20ea..affd3fb7 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -1485,3 +1485,94 @@ drmModeDestroyPropertyBlob(int fd, uint32_t id) destroy.blob_id = id; return DRM_IOCTL(fd, DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy); } + +int +drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id) +{ + struct drm_mode_create_lease create; + int ret; + + memclear(create); + create.object_ids = (uintptr_t) objects; + create.object_count = num_objects; + create.flags = flags; + + ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_CREATE_LEASE, &create); + if (ret == 0) { + *lessee_id = create.lessee_id; + return create.fd; + } + return -errno; +} + +drmModeLesseeListPtr +drmModeListLessees(int fd) +{ + struct drm_mode_list_lessees list; + uint32_t count; + drmModeLesseeListPtr ret; + + memclear(list); + + if (DRM_IOCTL(fd, DRM_IOCTL_MODE_LIST_LESSEES, &list)) + return NULL; + + count = list.count_lessees; + ret = drmMalloc(sizeof (drmModeLesseeListRes) + count * sizeof (ret->lessees[0])); + if (!ret) + return NULL; + + list.lessees_ptr = VOID2U64(&ret->lessees[0]); + if (DRM_IOCTL(fd, DRM_IOCTL_MODE_LIST_LESSEES, &list)) { + drmFree(ret); + return NULL; + } + + ret->count = count; + return ret; +} + +drmModeObjectListPtr +drmModeGetLease(int fd) +{ + struct drm_mode_get_lease get; + uint32_t count; + drmModeObjectListPtr ret; + + memclear(get); + + if (DRM_IOCTL(fd, DRM_IOCTL_MODE_GET_LEASE, &get)) + return NULL; + + count = get.count_objects; + ret = drmMalloc(sizeof (drmModeObjectListRes) + count * sizeof (ret->objects[0])); + if (!ret) + return NULL; + + get.objects_ptr = VOID2U64(&ret->objects[0]); + if (DRM_IOCTL(fd, DRM_IOCTL_MODE_GET_LEASE, &get)) { + drmFree(ret); + return NULL; + } + + ret->count = count; + return ret; +} + +int +drmModeRevokeLease(int fd, uint32_t lessee_id) +{ + struct drm_mode_revoke_lease revoke; + int ret; + + memclear(revoke); + + revoke.lessee_id = lessee_id; + + ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_REVOKE_LEASE, &revoke); + if (ret == 0) + return 0; + return -errno; +} + + diff --git a/xf86drmMode.h b/xf86drmMode.h index 5b390d9f..b5e22720 100644 --- a/xf86drmMode.h +++ b/xf86drmMode.h @@ -521,6 +521,29 @@ extern int drmModeCreatePropertyBlob(int fd, const void *data, size_t size, extern int drmModeDestroyPropertyBlob(int fd, uint32_t id);
+/* + * DRM mode lease APIs. These create and manage new drm_masters with + * access to a subset of the available DRM resources + */ + +extern int drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id); + +typedef struct drmModeLesseeList { + uint32_t count; + uint32_t lessees[0]; +} drmModeLesseeListRes, *drmModeLesseeListPtr; + +extern drmModeLesseeListPtr drmModeListLessees(int fd); + +typedef struct drmModeObjectList { + uint32_t count; + uint32_t objects[0]; +} drmModeObjectListRes, *drmModeObjectListPtr; + +extern drmModeObjectListPtr drmModeGetLease(int fd); + +extern int drmModeRevokeLease(int fd, uint32_t lessee_id); + #if defined(__cplusplus) } #endif
From: Keith Packard keithp@keithp.com
These provide a crtc-id based interface to get the current sequence (frame) number and to queue an event to be delivered at a specific sequence.
Signed-off-by: Keith Packard keithp@keithp.com --- include/drm/drm.h | 32 ++++++++++++++++++++++++++++++++ xf86drm.c | 33 +++++++++++++++++++++++++++++++++ xf86drm.h | 11 ++++++++++- xf86drmMode.c | 9 +++++++++ 4 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/include/drm/drm.h b/include/drm/drm.h index 7c736765..076040d4 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -712,6 +712,27 @@ struct drm_syncobj_handle { __u32 pad; };
+/* Query current scanout sequence number */ +struct drm_crtc_get_sequence { + __u32 crtc_id; + __u32 active; + __u64 sequence; + __s64 sequence_ns; +}; + +/* Queue event to be delivered at specified sequence */ + +#define DRM_CRTC_SEQUENCE_RELATIVE 0x00000001 /* sequence is relative to current */ +#define DRM_CRTC_SEQUENCE_NEXT_ON_MISS 0x00000002 /* Use next sequence if we've missed */ +#define DRM_CRTC_SEQUENCE_FIRST_PIXEL_OUT 0x00000004 /* Signal when first pixel is displayed */ + +struct drm_crtc_queue_sequence { + __u32 crtc_id; + __u32 flags; + __u64 sequence; /* on input, target sequence. on output, actual sequence */ + __u64 user_data; /* user data passed to event */ +}; + #if defined(__cplusplus) } #endif @@ -794,6 +815,9 @@ extern "C" {
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank)
+#define DRM_IOCTL_CRTC_GET_SEQUENCE DRM_IOWR(0x3b, struct drm_crtc_get_sequence) +#define DRM_IOCTL_CRTC_QUEUE_SEQUENCE DRM_IOWR(0x3c, struct drm_crtc_queue_sequence) + #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw)
#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) @@ -869,6 +893,7 @@ struct drm_event {
#define DRM_EVENT_VBLANK 0x01 #define DRM_EVENT_FLIP_COMPLETE 0x02 +#define DRM_EVENT_CRTC_SEQUENCE 0x03
struct drm_event_vblank { struct drm_event base; @@ -879,6 +904,13 @@ struct drm_event_vblank { __u32 crtc_id; /* 0 on older kernels that do not support this */ };
+struct drm_event_crtc_sequence { + struct drm_event base; + __u64 user_data; + __s64 time_ns; + __u64 sequence; +}; + /* typedef area */ typedef struct drm_clip_rect drm_clip_rect_t; typedef struct drm_drawable_info drm_drawable_info_t; diff --git a/xf86drm.c b/xf86drm.c index 6ea01129..bffcd7e5 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -1695,6 +1695,39 @@ int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, return 0; }
+int drmCrtcGetSequence(int fd, uint32_t crtcId, uint64_t *sequence, uint64_t *ns) +{ + struct drm_crtc_get_sequence get_seq; + int ret; + + memclear(get_seq); + get_seq.crtc_id = crtcId; + ret = drmIoctl(fd, DRM_IOCTL_CRTC_GET_SEQUENCE, &get_seq); + if (ret) + return ret; + + if (sequence) + *sequence = get_seq.sequence; + if (ns) + *ns = get_seq.sequence_ns; + return 0; +} + +int drmCrtcQueueSequence(int fd, uint32_t crtcId, uint32_t flags, uint64_t sequence, uint64_t user_data) +{ + struct drm_crtc_queue_sequence queue_seq; + int ret; + + memclear(queue_seq); + queue_seq.crtc_id = crtcId; + queue_seq.flags = flags; + queue_seq.sequence = sequence; + queue_seq.user_data = user_data; + + ret = drmIoctl(fd, DRM_IOCTL_CRTC_QUEUE_SEQUENCE, &queue_seq); + return ret; +} + /** * Acquire the AGP device. * diff --git a/xf86drm.h b/xf86drm.h index 2855a3ee..ed1cacda 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -636,6 +636,11 @@ extern int drmCtlUninstHandler(int fd); extern int drmSetClientCap(int fd, uint64_t capability, uint64_t value);
+extern int drmCrtcGetSequence(int fd, uint32_t crtcId, + uint64_t *sequence, uint64_t *ns); +extern int drmCrtcQueueSequence(int fd, uint32_t crtcId, + uint32_t flags, uint64_t sequence, + uint64_t user_data); /* General user-level programmer's API: authenticated client and/or X */ extern int drmMap(int fd, drm_handle_t handle, @@ -728,7 +733,7 @@ extern void drmMsg(const char *format, ...) DRM_PRINTFLIKE(1, 2); extern int drmSetMaster(int fd); extern int drmDropMaster(int fd);
-#define DRM_EVENT_CONTEXT_VERSION 3 +#define DRM_EVENT_CONTEXT_VERSION 4
typedef struct _drmEventContext {
@@ -755,6 +760,10 @@ typedef struct _drmEventContext { unsigned int crtc_id, void *user_data);
+ void (*sequence_handler)(int fd, + uint64_t sequence, + uint64_t ns, + uint64_t user_data); } drmEventContext, *drmEventContextPtr;
extern int drmHandleEvent(int fd, drmEventContextPtr evctx); diff --git a/xf86drmMode.c b/xf86drmMode.c index affd3fb7..0780198e 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -889,6 +889,7 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx) int len, i; struct drm_event *e; struct drm_event_vblank *vblank; + struct drm_event_crtc_sequence *seq; void *user_data;
/* The DRM read semantics guarantees that we always get only @@ -933,6 +934,14 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx) vblank->tv_usec, user_data); break; + case DRM_EVENT_CRTC_SEQUENCE: + seq = (struct drm_event_crtc_sequence *) e; + if (evctx->version >= 4 && evctx->sequence_handler) + evctx->sequence_handler(fd, + seq->sequence, + seq->time_ns, + seq->user_data); + break; default: break; }
dri-devel@lists.freedesktop.org