[RFC xserver v3 07/11] present: Allow present implementations to wait on fences

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


Instead of relying on the present module to wait on in-fences,
we added some hooks to allow the drivers/hardware to do the work.
Drivers need to implement can_wait_fence, wait_fence and
flip_with_fence to handle it.

v2: Rename hooks to can_wait_fence and wait_fence

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 present/present.c       | 48 +++++++++++++++++++++++++++++++++++++++---------
 present/present.h       | 23 ++++++++++++++++++++++-
 present/present_fence.c |  8 ++++++++
 present/present_priv.h  |  3 +++
 4 files changed, 72 insertions(+), 10 deletions(-)

diff --git a/present/present.c b/present/present.c
index f866ea107..a6f85fe59 100644
--- a/present/present.c
+++ b/present/present.c
@@ -194,16 +194,34 @@ present_check_flip(RRCrtcPtr    crtc,
 }
 
 static Bool
-present_flip(RRCrtcPtr crtc,
-             uint64_t event_id,
-             uint64_t target_msc,
-             PixmapPtr pixmap,
-             Bool sync_flip)
+present_flip(present_vblank_ptr vblank)
 {
-    ScreenPtr                   screen = crtc->pScreen;
+    ScreenPtr                   screen = vblank->crtc->pScreen;
     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
 
-    return (*screen_priv->info->flip) (crtc, event_id, target_msc, pixmap, sync_flip);
+    if (vblank->wait_fence &&
+        screen_priv->info->flip_with_fence != NULL) {
+        Bool ret;
+
+        ret = (*screen_priv->info->flip_with_fence) (vblank->crtc,
+                                                     vblank->event_id,
+                                                     vblank->target_msc,
+                                                     vblank->pixmap,
+                                                     present_fence_get_fence(vblank->wait_fence),
+                                                     vblank->sync_flip);
+
+        return ret;
+    } else if (vblank->wait_fence) {
+        if (!present_fence_check_triggered(vblank->wait_fence)) {
+           /* The can_wait_fence() hook should have returned FALSE before we
+            * tried to flip with an untriggered wait fence */
+           return FALSE;
+        }
+    }
+
+    return (*screen_priv->info->flip) (vblank->crtc, vblank->event_id,
+                                       vblank->target_msc, vblank->pixmap,
+                                       vblank->sync_flip);
 }
 
 static void
@@ -678,6 +696,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
     ScreenPtr                   screen = window->drawable.pScreen;
     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
     uint8_t                     mode;
+    Bool                        wait = FALSE;
 
     if (vblank->requeue) {
         vblank->requeue = FALSE;
@@ -690,7 +709,11 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
     }
 
     if (vblank->wait_fence) {
-        if (!present_fence_check_triggered(vblank->wait_fence)) {
+        /* Check if present implementation can wait for the fence itself */
+        if (screen_priv->info->can_wait_fence &&
+            (*screen_priv->info->can_wait_fence) (vblank->crtc, present_fence_get_fence(vblank->wait_fence))) {
+            wait = TRUE;
+        } else if (!present_fence_check_triggered(vblank->wait_fence)) {
             present_fence_set_callback(vblank->wait_fence, present_wait_fence_triggered, vblank);
             return;
         }
@@ -728,7 +751,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
             xorg_list_add(&vblank->event_queue, &present_flip_queue);
             /* Try to flip
              */
-            if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip)) {
+            if (present_flip(vblank)) {
                 RegionPtr damage;
 
                 /* Fix window pixmaps:
@@ -788,6 +811,13 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
             return;
         }
 
+        if (wait) {
+            (*screen_priv->info->wait_fence)(vblank->crtc,
+                                             present_fence_get_fence(vblank->wait_fence));
+            present_fence_destroy(vblank->wait_fence);
+            vblank->wait_fence = NULL;
+        }
+
         present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off);
 
         /* present_copy_region sticks the region into a scratch GC,
diff --git a/present/present.h b/present/present.h
index be41e8412..2c7175f4a 100644
--- a/present/present.h
+++ b/present/present.h
@@ -25,6 +25,7 @@
 
 #include <X11/extensions/presentproto.h>
 #include "randrstr.h"
+#include "misync.h"
 #include "presentext.h"
 
 #define PresentFlipReasonUnknown       0
@@ -83,6 +84,13 @@ typedef Bool (*present_flip_ptr) (RRCrtcPtr crtc,
                                   PixmapPtr pixmap,
                                   Bool sync_flip);
 
+typedef Bool (*present_flip_with_fence_ptr) (RRCrtcPtr crtc,
+                                             uint64_t event_id,
+                                             uint64_t target_msc,
+                                             PixmapPtr pixmap,
+                                             SyncFence *wait_fence,
+                                             Bool sync_flip);
+
 /* "unflip" back to the regular screen scanout buffer
  *
  * present_event_notify should be called with 'event_id' when the unflip occurs.
@@ -90,7 +98,17 @@ typedef Bool (*present_flip_ptr) (RRCrtcPtr crtc,
 typedef void (*present_unflip_ptr) (ScreenPtr screen,
                                     uint64_t event_id);
 
-#define PRESENT_SCREEN_INFO_VERSION        1
+/* Return whether the fence can be waited upon
+ */
+typedef Bool (*present_can_wait_fence_ptr) (RRCrtcPtr crtc,
+                                            SyncFence *fence);
+
+/* Wait for the fence to be triggered
+ */
+typedef void (*present_wait_fence_ptr) (RRCrtcPtr crtc,
+                                        SyncFence *fence);
+
+#define PRESENT_SCREEN_INFO_VERSION        2
 
 typedef struct present_screen_info {
     uint32_t                            version;
@@ -105,6 +123,9 @@ typedef struct present_screen_info {
     present_flip_ptr                    flip;
     present_unflip_ptr                  unflip;
     present_check_flip2_ptr             check_flip2;
+    present_flip_with_fence_ptr         flip_with_fence;
+    present_can_wait_fence_ptr          can_wait_fence;
+    present_wait_fence_ptr              wait_fence;
 
 } present_screen_info_rec, *present_screen_info_ptr;
 
diff --git a/present/present_fence.c b/present/present_fence.c
index 87e7e17d8..019d06e09 100644
--- a/present/present_fence.c
+++ b/present/present_fence.c
@@ -91,6 +91,14 @@ present_fence_create(SyncFence *fence)
     return present_fence;
 }
 
+SyncFence *
+present_fence_get_fence(struct present_fence *present_fence)
+{
+    if (present_fence)
+        return present_fence->fence;
+    return NULL;
+}
+
 void
 present_fence_destroy(struct present_fence *present_fence)
 {
diff --git a/present/present_priv.h b/present/present_priv.h
index 2fb9a2344..985780d01 100644
--- a/present/present_priv.h
+++ b/present/present_priv.h
@@ -255,6 +255,9 @@ present_fake_queue_init(void);
 struct present_fence *
 present_fence_create(SyncFence *sync_fence);
 
+SyncFence *
+present_fence_get_fence(struct present_fence *present_fence);
+
 void
 present_fence_destroy(struct present_fence *present_fence);
 
-- 
2.13.0



More information about the xorg-devel mailing list