[RFC xserver v3 08/11] present: Add hooks for the drivers to create out-fences

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


Drivers need to implement flip_with_fence and flush_with_fence
to create out-fences.

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 configure.ac                |  2 +-
 include/protocol-versions.h |  2 +-
 present/meson.build         |  2 +-
 present/present.c           | 68 +++++++++++++++++++++++++++++++++------------
 present/present.h           | 10 ++++++-
 present/present_priv.h      |  2 ++
 present/present_request.c   |  9 +++++-
 7 files changed, 73 insertions(+), 22 deletions(-)

diff --git a/configure.ac b/configure.ac
index 435daf71f..81d18b2e7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -755,7 +755,7 @@ DAMAGEPROTO="damageproto >= 1.1"
 XCMISCPROTO="xcmiscproto >= 1.2.0"
 BIGREQSPROTO="bigreqsproto >= 1.1.0"
 XTRANS="xtrans >= 1.3.5"
-PRESENTPROTO="presentproto >= 1.1"
+PRESENTPROTO="presentproto >= 1.2"
 
 dnl List of libraries that require a specific version
 LIBAPPLEWM="applewm >= 1.4"
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index 524a630e8..0147c708c 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -69,7 +69,7 @@
 
 /* Present */
 #define SERVER_PRESENT_MAJOR_VERSION            1
-#define SERVER_PRESENT_MINOR_VERSION            1
+#define SERVER_PRESENT_MINOR_VERSION            2
 
 /* RandR */
 #define SERVER_RANDR_MAJOR_VERSION		1
diff --git a/present/meson.build b/present/meson.build
index cf725302a..66d58bd34 100644
--- a/present/meson.build
+++ b/present/meson.build
@@ -13,7 +13,7 @@ libxserver_present = static_library('libxserver_present',
     include_directories: inc,
     dependencies: [
         common_dep,
-        dependency('presentproto', version: '>= 1.1')
+        dependency('presentproto', version: '>= 1.2')
     ],
     c_args: '-DHAVE_XORG_CONFIG_H'
 )
diff --git a/present/present.c b/present/present.c
index a6f85fe59..694bee890 100644
--- a/present/present.c
+++ b/present/present.c
@@ -193,24 +193,49 @@ present_check_flip(RRCrtcPtr    crtc,
     return TRUE;
 }
 
+static void
+present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence)
+{
+    if (present_fence)
+        present_fence_set_triggered(present_fence);
+    if (window) {
+        DebugPresent(("\ti %08lx\n", pixmap ? pixmap->drawable.id : 0));
+        present_send_idle_notify(window, serial, pixmap, present_fence);
+    }
+}
+
 static Bool
 present_flip(present_vblank_ptr vblank)
 {
     ScreenPtr                   screen = vblank->crtc->pScreen;
     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
 
-    if (vblank->wait_fence &&
+    if ((vblank->notify_fence || vblank->wait_fence) &&
         screen_priv->info->flip_with_fence != NULL) {
+        SyncFence *idle_fence = NULL;
         Bool ret;
 
+        if (vblank->notify_fence && screen_priv->flip_idle_fence)
+            idle_fence = present_fence_get_fence(screen_priv->flip_idle_fence);
+
         ret = (*screen_priv->info->flip_with_fence) (vblank->crtc,
                                                      vblank->event_id,
                                                      vblank->target_msc,
                                                      vblank->pixmap,
                                                      present_fence_get_fence(vblank->wait_fence),
+                                                     idle_fence,
                                                      vblank->sync_flip);
 
+        if (ret && screen_priv->flip_notify_fence) {
+            present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window,
+                                screen_priv->flip_serial, screen_priv->flip_idle_fence);
+        }
+
         return ret;
+    } else if (vblank->notify_fence) {
+        /* The driver shouldn't have advertised support for IdleFence capability
+         * or the client should have check for it before using the option */
+        return FALSE;
     } else if (vblank->wait_fence) {
         if (!present_fence_check_triggered(vblank->wait_fence)) {
            /* The can_wait_fence() hook should have returned FALSE before we
@@ -240,17 +265,6 @@ present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_
     }
 }
 
-static void
-present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence)
-{
-    if (present_fence)
-        present_fence_set_triggered(present_fence);
-    if (window) {
-        DebugPresent(("\ti %08lx\n", pixmap ? pixmap->drawable.id : 0));
-        present_send_idle_notify(window, serial, pixmap, present_fence);
-    }
-}
-
 RRCrtcPtr
 present_get_crtc(WindowPtr window)
 {
@@ -297,8 +311,9 @@ present_get_ust_msc(ScreenPtr screen, RRCrtcPtr crtc, uint64_t *ust, uint64_t *m
 }
 
 static void
-present_flush(WindowPtr window)
+present_flush(present_vblank_ptr vblank)
 {
+    WindowPtr                   window = vblank->window;
     ScreenPtr                   screen = window->drawable.pScreen;
     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
 
@@ -308,7 +323,12 @@ present_flush(WindowPtr window)
     if (!screen_priv->info)
         return;
 
-    (*screen_priv->info->flush) (window);
+    if (vblank->notify_fence && screen_priv->info->flush_with_fence) {
+        (*screen_priv->info->flush_with_fence) (window,
+                                                present_fence_get_fence(vblank->idle_fence));
+    } else {
+        (*screen_priv->info->flush) (window);
+    }
 }
 
 static int
@@ -389,8 +409,10 @@ present_flip_idle(ScreenPtr screen)
     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
 
     if (screen_priv->flip_pixmap) {
-        present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window,
-                            screen_priv->flip_serial, screen_priv->flip_idle_fence);
+        if (!screen_priv->flip_notify_fence) {
+            present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window,
+                                screen_priv->flip_serial, screen_priv->flip_idle_fence);
+        }
         if (screen_priv->flip_idle_fence)
             present_fence_destroy(screen_priv->flip_idle_fence);
         dixDestroyPixmap(screen_priv->flip_pixmap, screen_priv->flip_pixmap->drawable.id);
@@ -521,6 +543,7 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
     screen_priv->flip_pixmap = vblank->pixmap;
     screen_priv->flip_sync = vblank->sync_flip;
     screen_priv->flip_idle_fence = vblank->idle_fence;
+    screen_priv->flip_notify_fence = vblank->notify_fence;
 
     vblank->pixmap = NULL;
     vblank->idle_fence = NULL;
@@ -824,7 +847,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
          * which is then freed, freeing the region
          */
         vblank->update = NULL;
-        present_flush(window);
+        present_flush(vblank);
 
         present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
     }
@@ -1024,6 +1047,17 @@ present_pixmap(WindowPtr window,
             goto no_mem;
     }
 
+    if (options & PresentOptionIdleFence) {
+        if (vblank->idle_fence == NULL) {
+            vblank->notifies = NULL;
+            present_vblank_destroy(vblank);
+            return BadValue;
+        }
+        if (!(screen_priv->info->capabilities & PresentCapabilityIdleFence))
+            return BadValue;
+        vblank->notify_fence = TRUE;
+    }
+
     if (pixmap)
         DebugPresent(("q %lld %p %8lld: %08lx -> %08lx (crtc %p) flip %d vsync %d serial %d\n",
                       vblank->event_id, vblank, target_msc,
diff --git a/present/present.h b/present/present.h
index 2c7175f4a..af8395ad4 100644
--- a/present/present.h
+++ b/present/present.h
@@ -59,6 +59,12 @@ typedef void (*present_abort_vblank_ptr) (RRCrtcPtr crtc, uint64_t event_id, uin
  */
 typedef void (*present_flush_ptr) (WindowPtr window);
 
+/* Flush pending drawing on 'window' to the hardware.
+ *
+ * 'idle_fence' should return the out-fence
+ */
+typedef void (*present_flush_with_fence_ptr) (WindowPtr window, SyncFence *idle_fence);
+
 /* Check if 'pixmap' is suitable for flipping to 'window'.
  */
 typedef Bool (*present_check_flip_ptr) (RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip);
@@ -89,6 +95,7 @@ typedef Bool (*present_flip_with_fence_ptr) (RRCrtcPtr crtc,
                                              uint64_t target_msc,
                                              PixmapPtr pixmap,
                                              SyncFence *wait_fence,
+                                             SyncFence *idle_fence,
                                              Bool sync_flip);
 
 /* "unflip" back to the regular screen scanout buffer
@@ -108,7 +115,7 @@ typedef Bool (*present_can_wait_fence_ptr) (RRCrtcPtr crtc,
 typedef void (*present_wait_fence_ptr) (RRCrtcPtr crtc,
                                         SyncFence *fence);
 
-#define PRESENT_SCREEN_INFO_VERSION        2
+#define PRESENT_SCREEN_INFO_VERSION        3
 
 typedef struct present_screen_info {
     uint32_t                            version;
@@ -126,6 +133,7 @@ typedef struct present_screen_info {
     present_flip_with_fence_ptr         flip_with_fence;
     present_can_wait_fence_ptr          can_wait_fence;
     present_wait_fence_ptr              wait_fence;
+    present_flush_with_fence_ptr        flush_with_fence;
 
 } present_screen_info_rec, *present_screen_info_ptr;
 
diff --git a/present/present_priv.h b/present/present_priv.h
index 985780d01..1bfeb62ba 100644
--- a/present/present_priv.h
+++ b/present/present_priv.h
@@ -77,6 +77,7 @@ struct present_vblank {
     Bool                abort_flip;     /* aborting this flip */
     int                 reason;         /* reason for which flip is not possible */
     Bool                has_suboptimal; /* whether client can support SuboptimalCopy mode */
+    Bool                notify_fence;   /* send fence with Idle event */
 };
 
 typedef struct present_screen_priv {
@@ -97,6 +98,7 @@ typedef struct present_screen_priv {
     PixmapPtr                   flip_pixmap;
     present_fence_ptr           flip_idle_fence;
     Bool                        flip_sync;
+    Bool                        flip_notify_fence;
 
     present_screen_info_ptr     info;
 } present_screen_priv_rec, *present_screen_priv_ptr;
diff --git a/present/present_request.c b/present/present_request.c
index c6afe5fa7..4bad47fd2 100644
--- a/present/present_request.c
+++ b/present/present_request.c
@@ -102,13 +102,20 @@ proc_present_pixmap(ClientPtr client)
     VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess);
 
     VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess);
-    VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess);
 
     if (stuff->options & ~(PresentAllOptions)) {
         client->errorValue = stuff->options;
         return BadValue;
     }
 
+    if (stuff->options & PresentOptionIdleFence) {
+        LEGAL_NEW_RESOURCE(stuff->idle_fence, client);
+        ret = SyncCreateFenceFromDMAFenceFD(client, &pixmap->drawable, stuff->idle_fence, -1);
+        if (ret != Success)
+            return ret;
+    }
+    VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess);
+
     /*
      * Check to see if remainder is sane
      */
-- 
2.13.0



More information about the xorg-devel mailing list