[RFC xserver 07/12] present: Allow present implementations to wait on fences
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Wed Aug 30 05:16: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, wait and flip_with_fence
to handle it.
Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
present/present.c | 51 +++++++++++++++++++++++++++++++++++++++----------
present/present.h | 23 +++++++++++++++++++++-
present/present_fence.c | 8 ++++++++
present/present_priv.h | 3 +++
4 files changed, 74 insertions(+), 11 deletions(-)
diff --git a/present/present.c b/present/present.c
index 70cbad8f8..69307f6e0 100644
--- a/present/present.c
+++ b/present/present.c
@@ -188,16 +188,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() 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
@@ -486,7 +504,8 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
assert (vblank == screen_priv->flip_pending);
- present_flip_idle(screen);
+ if (!vblank->notify_fence)
+ present_flip_idle(screen);
xorg_list_del(&vblank->event_queue);
@@ -632,6 +651,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;
@@ -644,7 +664,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 &&
+ (*screen_priv->info->can_wait) (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;
}
@@ -682,7 +706,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:
@@ -742,6 +766,13 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
return;
}
+ if (wait) {
+ (*screen_priv->info->wait)(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 aab2e168a..0d5d72652 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"
typedef struct present_vblank present_vblank_rec, *present_vblank_ptr;
@@ -76,6 +77,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.
@@ -83,7 +91,17 @@ typedef Bool (*present_flip_ptr) (RRCrtcPtr crtc,
typedef void (*present_unflip_ptr) (ScreenPtr screen,
uint64_t event_id);
-#define PRESENT_SCREEN_INFO_VERSION 0
+/* Return whether the fence can be waited upon
+ */
+typedef Bool (*present_can_wait_ptr) (RRCrtcPtr crtc,
+ SyncFence *fence);
+
+/* Wait for the fence to be triggered
+ */
+typedef void (*present_wait_ptr) (RRCrtcPtr crtc,
+ SyncFence *fence);
+
+#define PRESENT_SCREEN_INFO_VERSION 1
typedef struct present_screen_info {
uint32_t version;
@@ -97,6 +115,9 @@ typedef struct present_screen_info {
present_check_flip_ptr check_flip;
present_flip_ptr flip;
present_unflip_ptr unflip;
+ present_flip_with_fence_ptr flip_with_fence;
+ present_can_wait_ptr can_wait;
+ present_wait_ptr wait;
} present_screen_info_rec, *present_screen_info_ptr;
diff --git a/present/present_fence.c b/present/present_fence.c
index e09657d31..b7512df88 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 dfb4bdea9..c742c48a8 100644
--- a/present/present_priv.h
+++ b/present/present_priv.h
@@ -253,6 +253,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