drm: Add CrtcGetSequence and CrtcQueueSequence IOCTLs [v2]
authorKeith Packard <keithp@keithp.com>
Sat, 1 Jul 2017 07:43:15 +0000 (00:43 -0700)
committerDave Airlie <airlied@redhat.com>
Mon, 18 Dec 2017 00:04:02 +0000 (10:04 +1000)
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.

v2: Remove FIRST_PIXEL_OUT flag. This has been removed from the
    proposed kernel API

Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
xf86drm.c
xf86drm.h
xf86drmMode.c

index deb76e4..74b4e23 100644 (file)
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -1695,6 +1695,43 @@ 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 *sequence_queued, 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);
+    if (ret == 0 && sequence_queued)
+        *sequence_queued = queue_seq.sequence;
+
+    return ret;
+}
+
 /**
  * Acquire the AGP device.
  *
index 0dbf494..7773d71 100644 (file)
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -636,6 +636,12 @@ 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 *sequence_queued,
+                                         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 +734,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 +761,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);
index eddad8c..15957ff 100644 (file)
@@ -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;
                }