[RFC xserver 08/12] present: Add hooks for the drivers to create out-fences
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Wed Aug 30 05:16: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>
---
present/present.c | 34 ++++++++++++++++++++++++++++++----
present/present.h | 8 ++++++++
present/present_priv.h | 1 +
present/present_request.c | 9 ++++++++-
4 files changed, 47 insertions(+), 5 deletions(-)
diff --git a/present/present.c b/present/present.c
index 69307f6e0..20e6394c7 100644
--- a/present/present.c
+++ b/present/present.c
@@ -193,18 +193,27 @@ 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)
+ idle_fence = present_fence_get_fence(vblank->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);
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() hook should have returned FALSE before we tried to
@@ -291,8 +300,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);
@@ -302,7 +312,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
@@ -779,7 +794,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);
}
@@ -972,6 +987,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 0d5d72652..d81fb78e7 100644
--- a/present/present.h
+++ b/present/present.h
@@ -56,6 +56,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);
@@ -82,6 +88,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
@@ -115,6 +122,7 @@ typedef struct present_screen_info {
present_check_flip_ptr check_flip;
present_flip_ptr flip;
present_unflip_ptr unflip;
+ present_flush_with_fence_ptr flush_with_fence;
present_flip_with_fence_ptr flip_with_fence;
present_can_wait_ptr can_wait;
present_wait_ptr wait;
diff --git a/present/present_priv.h b/present/present_priv.h
index c742c48a8..0af95db10 100644
--- a/present/present_priv.h
+++ b/present/present_priv.h
@@ -75,6 +75,7 @@ struct present_vblank {
Bool flip_ready; /* wants to flip, but waiting for previous flip or unflip */
Bool sync_flip; /* do flip synchronous to vblank */
Bool abort_flip; /* aborting this flip */
+ Bool notify_fence; /* send fence with Idle event */
};
typedef struct present_screen_priv {
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