[PATCH xserver 2/2] xf86-video-modesetting: Support new vblank kernel API

Keith Packard keithp at keithp.com
Fri Sep 29 06:20:47 UTC 2017


drmCrtcGetSequence returns the current vblank sequence and time.

drmCrtcQueueSequence queues an event for delivery at a specified
vblank sequence.

Use these (when available) in preference to drmWaitVBlank.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 hw/xfree86/drivers/modesetting/vblank.c | 47 ++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index ab66b7b27..db8edde61 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -182,6 +182,21 @@ ms_get_kernel_ust_msc(xf86CrtcPtr crtc,
     drmVBlank vbl;
     int ret;
 
+#ifdef DRM_IOCTL_CRTC_QUEUE_SEQUENCE
+    if (ms->has_queue_sequence || !ms->tried_queue_sequence) {
+        uint64_t ns;
+        ms->tried_queue_sequence = TRUE;
+
+        ret = drmCrtcGetSequence(ms->fd, drmmode_crtc->mode_crtc->crtc_id,
+                                 msc, &ns);
+        if (ret != -1 || errno != ENOTTY) {
+            ms->has_queue_sequence = TRUE;
+            if (ret == 0)
+                *ust = ns / 1000;
+            return ret == 0;
+        }
+    }
+#endif
     /* Get current count */
     vbl.request.type = DRM_VBLANK_RELATIVE | drmmode_crtc->vblank_pipe;
     vbl.request.sequence = 0;
@@ -211,6 +226,35 @@ ms_queue_vblank(xf86CrtcPtr crtc, ms_queue_flag flags,
 
     for (;;) {
         /* Queue an event at the specified sequence */
+#ifdef DRM_IOCTL_CRTC_QUEUE_SEQUENCE
+        if (ms->has_queue_sequence || !ms->tried_queue_sequence) {
+            uint32_t drm_flags = DRM_CRTC_SEQUENCE_FIRST_PIXEL_OUT;
+            uint64_t kernel;
+            uint64_t kernel_queued;
+
+            ms->tried_queue_sequence = TRUE;
+
+            if (flags & MS_QUEUE_RELATIVE)
+                drm_flags |= DRM_CRTC_SEQUENCE_RELATIVE;
+            if (flags & MS_QUEUE_NEXT_ON_MISS)
+                drm_flags |= DRM_CRTC_SEQUENCE_NEXT_ON_MISS;
+
+            kernel = ms_crtc_msc_to_kernel_msc(crtc, msc);
+            ret = drmCrtcQueueSequence(ms->fd, drmmode_crtc->mode_crtc->crtc_id,
+                                       drm_flags,
+                                       kernel, &kernel_queued, seq);
+            if (ret == 0) {
+                if (msc_queued)
+                    *msc_queued = ms_kernel_msc_to_crtc_msc(crtc, kernel_queued);
+                return TRUE;
+            }
+
+            if (ret != -1 || errno != ENOTTY) {
+                ms->has_queue_sequence = TRUE;
+                goto check;
+            }
+        }
+#endif
         vbl.request.type = DRM_VBLANK_EVENT | drmmode_crtc->vblank_pipe;
         if (flags & MS_QUEUE_RELATIVE)
             vbl.request.type = DRM_VBLANK_RELATIVE;
@@ -448,9 +492,10 @@ ms_vblank_screen_init(ScreenPtr screen)
     modesettingEntPtr ms_ent = ms_ent_priv(scrn);
     xorg_list_init(&ms_drm_queue);
 
-    ms->event_context.version = 2;
+    ms->event_context.version = 4;
     ms->event_context.vblank_handler = ms_drm_handler;
     ms->event_context.page_flip_handler = ms_drm_handler;
+    ms->event_context.sequence_handler = ms_drm_sequence_handler;
 
     /* We need to re-register the DRM fd for the synchronisation
      * feedback on every server generation, so perform the
-- 
2.14.1



More information about the xorg-devel mailing list