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 <[email protected]> --- 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 262b6ce9c..8c3811d73 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_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 @@ -632,6 +650,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 +663,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; } @@ -682,7 +705,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 +765,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 aab2e168a..49b265859 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_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 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_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 408cc7a86..0dc34465c 100644 --- a/present/present_priv.h +++ b/present/present_priv.h @@ -256,6 +256,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 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel
