[RFC v2 09/12] present: Add hooks for the drivers to create out-fences
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Wed Sep 27 05:20:00 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 | 68 +++++++++++++++++++++++++++++++++++------------
present/present.h | 8 ++++++
present/present_priv.h | 2 ++
present/present_request.c | 9 ++++++-
4 files changed, 69 insertions(+), 18 deletions(-)
diff --git a/present/present.c b/present/present.c
index 8c3811d73..599c490f9 100644
--- a/present/present.c
+++ b/present/present.c
@@ -187,24 +187,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
@@ -234,17 +259,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)
{
@@ -291,8 +305,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 +317,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
@@ -383,8 +403,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);
@@ -515,6 +537,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;
@@ -778,7 +801,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);
}
@@ -976,6 +999,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 49b265859..a81f7b407 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_fence_ptr can_wait_fence;
present_wait_fence_ptr wait_fence;
diff --git a/present/present_priv.h b/present/present_priv.h
index 0dc34465c..56fae9040 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 {
@@ -95,6 +96,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