diff mbox

[libdrm,2/2] Add CrtcGetSequence and CrtcQueueSequence IOCTLs

Message ID 20170802100400.21463-3-keithp@keithp.com (mailing list archive)
State New, archived
Headers show

Commit Message

Keith Packard Aug. 2, 2017, 10:04 a.m. UTC
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 mbox

Patch

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