[RFC xserver v3 11/11] modesetting: Add implementation for out-fences

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Mon Nov 6 21:43:00 UTC 2017


Create out-fence using eglCreateSyncKHR or OUT_FENCE_PTR DRM
property when page-flipping.

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 glamor/glamor.c                                  |  9 ++++++
 glamor/glamor.h                                  |  2 ++
 glamor/glamor_egl.c                              | 37 ++++++++++++++++++++++++
 glamor/glamor_egl_stubs.c                        |  6 ++++
 hw/xfree86/drivers/modesetting/dri2.c            |  2 +-
 hw/xfree86/drivers/modesetting/driver.h          |  1 +
 hw/xfree86/drivers/modesetting/drmmode_display.c | 10 +++++--
 hw/xfree86/drivers/modesetting/drmmode_display.h |  3 +-
 hw/xfree86/drivers/modesetting/pageflip.c        | 22 ++++++++++++--
 hw/xfree86/drivers/modesetting/present.c         | 23 +++++++++++++--
 hw/xwayland/xwayland-glamor.c                    |  6 ++++
 11 files changed, 111 insertions(+), 10 deletions(-)

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 673b7b2d4..556330bc0 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -279,6 +279,15 @@ glamor_add_fence(ScreenPtr screen, SyncFence *fence)
         glamor_egl_add_fence(screen, fence);
 }
 
+void
+glamor_create_fence(ScreenPtr screen, SyncFence *fence)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN)
+        glamor_egl_create_fence(screen, fence);
+}
+
 static void
 glamor_set_debug_level(int *debug_level)
 {
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 32f342339..f0265049e 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -120,6 +120,7 @@ extern _X_EXPORT void glamor_block_handler(ScreenPtr screen);
 
 extern _X_EXPORT Bool glamor_support_fence(ScreenPtr screen, SyncFence *fence);
 extern _X_EXPORT void glamor_add_fence(ScreenPtr screen, SyncFence *fence);
+extern _X_EXPORT void glamor_create_fence(ScreenPtr screen, SyncFence *fence);
 
 extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h,
                                                 int depth, unsigned int usage);
@@ -133,6 +134,7 @@ extern _X_EXPORT Bool glamor_destroy_pixmap(PixmapPtr pixmap);
 
 extern _X_EXPORT Bool glamor_egl_support_fence(ScreenPtr screen, SyncFence *fence);
 extern _X_EXPORT Bool glamor_egl_add_fence(ScreenPtr screen, SyncFence *fence);
+extern _X_EXPORT Bool glamor_egl_create_fence(ScreenPtr screen, SyncFence *fence);
 
 /* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo).
  *
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 7f19373ff..660cd9f41 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -137,6 +137,43 @@ glamor_egl_add_fence(ScreenPtr pScreen,
     return TRUE;
 }
 
+Bool
+glamor_egl_create_fence(ScreenPtr pScreen,
+                        SyncFence *fence)
+{
+    struct glamor_egl_screen_private *glamor_egl;
+    EGLSyncKHR sync;
+    EGLint attribs[3];
+    int i = 0;
+    int fd;
+
+    glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(pScreen));
+    if (!glamor_egl->dmafence_capable)
+        return FALSE;
+
+    attribs[i++] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID;
+    attribs[i++] = EGL_NO_NATIVE_FENCE_FD_ANDROID;
+    attribs[i++] = EGL_NONE;
+
+    if (!eglMakeCurrent(glamor_egl->display,
+                        EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context))
+        return FALSE;
+
+    sync = eglCreateSyncKHR(glamor_egl->display, EGL_SYNC_NATIVE_FENCE_ANDROID,
+                            attribs);
+    if (sync == EGL_NO_SYNC_KHR)
+        return FALSE;
+
+    glFlush();
+
+    fd = eglDupNativeFenceFDANDROID(glamor_egl->display, sync);
+    miSyncInitFenceFromDMAFenceFD(pScreen, fence, fd);
+    close(fd);
+    eglDestroySyncKHR(glamor_egl->display, sync);
+
+    return TRUE;
+}
+
 static int
 glamor_get_flink_name(int fd, int handle, int *name)
 {
diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c
index 755f85959..8da35f890 100644
--- a/glamor/glamor_egl_stubs.c
+++ b/glamor/glamor_egl_stubs.c
@@ -63,3 +63,9 @@ glamor_egl_add_fence(ScreenPtr screen, SyncFence *fence)
 {
     return FALSE;
 }
+
+Bool
+glamor_egl_create_fence(ScreenPtr screen, SyncFence *fence)
+{
+    return FALSE;
+}
diff --git a/hw/xfree86/drivers/modesetting/dri2.c b/hw/xfree86/drivers/modesetting/dri2.c
index f249537d4..79fa2316a 100644
--- a/hw/xfree86/drivers/modesetting/dri2.c
+++ b/hw/xfree86/drivers/modesetting/dri2.c
@@ -494,7 +494,7 @@ ms_dri2_schedule_flip(ms_dri2_frame_event_ptr info)
     event->event_data = info->event_data;
 
     if (ms_do_pageflip(screen, back_priv->pixmap, event,
-                       drmmode_crtc->vblank_pipe, FALSE, NULL,
+                       drmmode_crtc->vblank_pipe, FALSE, NULL, NULL,
                        ms_dri2_flip_handler,
                        ms_dri2_flip_abort)) {
         ms->drmmode.dri2_flipping = TRUE;
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index c5e79b684..c8ce25eed 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -173,6 +173,7 @@ Bool ms_do_pageflip(ScreenPtr screen,
                     int ref_crtc_vblank_pipe,
                     Bool async,
                     SyncFence *in_fence,
+                    SyncFence *out_fence,
                     ms_pageflip_handler_proc pageflip_handler,
                     ms_pageflip_abort_proc pageflip_abort);
 
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 6092a3878..737cb85a5 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -53,6 +53,8 @@
 
 #include "driver.h"
 
+#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
+
 static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height);
 static PixmapPtr drmmode_create_pixmap_header(ScreenPtr pScreen, int width, int height,
                                               int depth, int bitsPerPixel, int devKind,
@@ -498,7 +500,8 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn,
 
 int
 drmmode_crtc_set_fb(xf86CrtcPtr crtc, DisplayModePtr mode, uint32_t fb_id,
-                    int x, int y, int in_fence_fd, uint32_t flags, void *data)
+                    int x, int y, int in_fence_fd, int *out_fence_ptr,
+                    uint32_t flags, void *data)
 {
     modesettingPtr ms = modesettingPTR(crtc->scrn);
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
@@ -572,6 +575,9 @@ drmmode_crtc_set_fb(xf86CrtcPtr crtc, DisplayModePtr mode, uint32_t fb_id,
         if (in_fence_fd > -1)
             ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_IN_FENCE_FD,
                                   in_fence_fd);
+        if (out_fence_ptr)
+            ret |= crtc_add_prop(req, drmmode_crtc, DRMMODE_CRTC_OUT_FENCE_PTR,
+                                 VOID2U64(out_fence_ptr));
 
         if (ret == 0)
             ret = drmModeAtomicCommit(ms->fd, req, flags, data);
@@ -1233,7 +1239,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
     }
 
     flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
-    if (drmmode_crtc_set_fb(crtc, mode, fb_id, x, y, -1, flags, NULL)) {
+    if (drmmode_crtc_set_fb(crtc, mode, fb_id, x, y, -1, NULL, flags, NULL)) {
         xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
                    "failed to set mode: %s\n", strerror(errno));
         ret = FALSE;
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 55471c80d..ff480162a 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -279,7 +279,8 @@ void drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmmode,
 void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
 
 int drmmode_crtc_set_fb(xf86CrtcPtr crtc, DisplayModePtr mode, uint32_t fb_id,
-                        int x, int y, int fence_fd, uint32_t flags, void *data);
+                        int x, int y, int in_fence_fd, int *out_fence_ptr,
+                        uint32_t flags, void *data);
 
 Bool drmmode_support_dma_fences(ScrnInfoPtr pScrn);
 
diff --git a/hw/xfree86/drivers/modesetting/pageflip.c b/hw/xfree86/drivers/modesetting/pageflip.c
index 75b3ae4ab..49e461ef7 100644
--- a/hw/xfree86/drivers/modesetting/pageflip.c
+++ b/hw/xfree86/drivers/modesetting/pageflip.c
@@ -77,6 +77,7 @@ struct ms_flipdata {
     ScreenPtr screen;
     void *event;
     int in_fence_fd;
+    SyncFence *out_fence;
     ms_pageflip_handler_proc event_handler;
     ms_pageflip_abort_proc abort_handler;
     /* number of CRTC events referencing this */
@@ -165,14 +166,16 @@ ms_pageflip_abort(void *data)
 
 static Bool
 do_queue_flip_on_crtc(modesettingPtr ms, xf86CrtcPtr crtc,
-                      int fence_fd, uint32_t flags, uint32_t seq)
+                      int in_fence_fd, int *out_fence_ptr,
+                      uint32_t flags, uint32_t seq)
 {
     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 
 #ifdef GLAMOR_HAS_DRM_ATOMIC
     if (ms->atomic_modeset) {
         flags |= DRM_MODE_ATOMIC_NONBLOCK;
-        return drmmode_crtc_set_fb(crtc, NULL, ms->drmmode.fb_id, 0, 0, fence_fd,
+        return drmmode_crtc_set_fb(crtc, NULL, ms->drmmode.fb_id, 0, 0,
+                                   in_fence_fd, out_fence_ptr,
                                    flags, (void *) (uintptr_t) seq);
     }
 #endif
@@ -193,6 +196,8 @@ queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc,
     struct ms_crtc_pageflip *flip;
     uint32_t seq;
     int err;
+    int out_fence_fd = -1;
+    int *out_fence_ptr = NULL;
 
     flip = calloc(1, sizeof(struct ms_crtc_pageflip));
     if (flip == NULL) {
@@ -216,7 +221,10 @@ queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc,
     /* take a reference on flipdata for use in flip */
     flipdata->flip_count++;
 
-    while (do_queue_flip_on_crtc(ms, crtc, flipdata->in_fence_fd, flags, seq)) {
+    if (flipdata->out_fence)
+        out_fence_ptr = &out_fence_fd;
+
+    while (do_queue_flip_on_crtc(ms, crtc, flipdata->in_fence_fd, out_fence_ptr, flags, seq)) {
         err = errno;
         /* We may have failed because the event queue was full.  Flush it
          * and retry.  If there was nothing to flush, then we failed for
@@ -234,6 +242,12 @@ queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc,
         xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue retry\n");
     }
 
+    if (flipdata->out_fence) {
+        miSyncInitFenceFromDMAFenceFD(screen, flipdata->out_fence, out_fence_fd);
+        if (out_fence_fd > -1)
+            close(out_fence_fd);
+    }
+
     /* The page flip succeded. */
     return TRUE;
 }
@@ -246,6 +260,7 @@ ms_do_pageflip(ScreenPtr screen,
                int ref_crtc_vblank_pipe,
                Bool async,
                SyncFence *in_fence,
+               SyncFence *out_fence,
                ms_pageflip_handler_proc pageflip_handler,
                ms_pageflip_abort_proc pageflip_abort)
 {
@@ -281,6 +296,7 @@ ms_do_pageflip(ScreenPtr screen,
     flipdata->event = event;
     flipdata->screen = screen;
     flipdata->in_fence_fd = in_fence ? dup(miSyncDMAFenceFDFromFence(screen, in_fence)) : -1;
+    flipdata->out_fence = out_fence;
     flipdata->event_handler = pageflip_handler;
     flipdata->abort_handler = pageflip_abort;
 
diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c
index b620a6009..1614487b8 100644
--- a/hw/xfree86/drivers/modesetting/present.c
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -324,7 +324,7 @@ ms_present_flip(RRCrtcPtr crtc,
     event->unflip = FALSE;
 
     ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip,
-                         NULL, ms_present_flip_handler, ms_present_flip_abort);
+                         NULL, NULL, ms_present_flip_handler, ms_present_flip_abort);
     if (!ret)
         xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n");
     else
@@ -364,7 +364,8 @@ ms_present_flip_with_fence(RRCrtcPtr crtc,
     event->unflip = FALSE;
 
     ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip,
-                         flip_fence, ms_present_flip_handler, ms_present_flip_abort);
+                         flip_fence, idle_fence,
+                         ms_present_flip_handler, ms_present_flip_abort);
     if (!ret)
         xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n");
     else
@@ -374,6 +375,21 @@ ms_present_flip_with_fence(RRCrtcPtr crtc,
 }
 
 /*
+ * Flush our batch buffer when requested by the Present extension.
+ */
+static void
+ms_present_flush_with_fence(WindowPtr window,
+                            SyncFence *idle_fence)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+
+    if (ms->drmmode.glamor)
+        glamor_create_fence(screen, idle_fence);
+}
+
+/*
  * Queue a flip back to the normal frame buffer
  */
 static void
@@ -394,7 +410,7 @@ ms_present_unflip(ScreenPtr screen, uint64_t event_id)
     event->unflip = TRUE;
 
     if (ms_present_check_flip(NULL, screen->root, pixmap, TRUE) &&
-        ms_do_pageflip(screen, pixmap, event, -1, FALSE, NULL,
+        ms_do_pageflip(screen, pixmap, event, -1, FALSE, NULL, NULL,
                        ms_present_flip_handler, ms_present_flip_abort)) {
         return;
     }
@@ -472,6 +488,7 @@ static present_screen_info_rec ms_present_screen_info = {
     .check_flip2 = ms_present_check_flip2,
     .flip = ms_present_flip,
     .flip_with_fence = ms_present_flip_with_fence,
+    .flush_with_fence = ms_present_flush_with_fence,
     .unflip = ms_present_unflip,
     .can_wait_fence = ms_present_can_wait_fence,
     .wait_fence = ms_present_wait_fence,
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 44218a1c8..1ce7b982e 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -549,6 +549,12 @@ glamor_egl_add_fence(ScreenPtr screen, SyncFence *fence)
    return FALSE;
 }
 
+Bool
+glamor_egl_create_fence(ScreenPtr screen, SyncFence *fence)
+{
+   return FALSE;
+}
+
 struct xwl_auth_state {
     int fd;
     ClientPtr client;
-- 
2.13.0



More information about the xorg-devel mailing list