From f93aab9bbc3ecc64533a2eb646b7a6209ddd492f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 5 Feb 2015 07:55:08 +0000 Subject: [PATCH] sna/present: Queue the unflip if we have flips outstanding Rather than synchronously wait in the unflip for the pageflips to complete by forcing the modeset, try to queue the unflip to happen after the pending flip completes. Signed-off-by: Chris Wilson --- src/sna/sna.h | 1 + src/sna/sna_present.c | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/sna/sna.h b/src/sna/sna.h index 74a03f3c..3f01d55e 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -354,6 +354,7 @@ struct sna { bool available; bool open; #if HAVE_PRESENT + uint64_t unflip; #endif } present; diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c index 035a54b7..90d08b57 100644 --- a/src/sna/sna_present.c +++ b/src/sna/sna_present.c @@ -42,6 +42,8 @@ struct sna_present_event { xf86CrtcPtr crtc; }; +static void sna_present_unflip(ScreenPtr screen, uint64_t event_id); + static inline struct sna_present_event * to_present_event(uintptr_t data) { @@ -201,11 +203,21 @@ check_flip__crtc(struct sna *sna, assert(sna->scrn->vtSema); + if (!sna->mode.front_active) { + DBG(("%s: DPMS off, no flips\n", __FUNCTION__)); + return FALSE; + } + if (sna->mode.shadow_active) { DBG(("%s: shadow buffer active\n", __FUNCTION__)); return false; } + if (sna->mode.flip_active) { + DBG(("%s: flips still pending\n", __FUNCTION__)); + return false; + } + return true; } @@ -229,11 +241,6 @@ sna_present_check_flip(RRCrtcPtr crtc, return FALSE; } - if (!sna->mode.front_active) { - DBG(("%s: DPMS off, no flips\n", __FUNCTION__)); - return FALSE; - } - if (sna->flags & SNA_NO_FLIP) { DBG(("%s: flips not suported\n", __FUNCTION__)); return FALSE; @@ -312,6 +319,7 @@ present_flip_handler(struct drm_event_vblank *event, void *data) { struct sna_present_event *info = data; struct ust_msc swap; + struct sna *sna; DBG(("%s(sequence=%d)\n", __FUNCTION__, event->sequence)); @@ -327,6 +335,14 @@ present_flip_handler(struct drm_event_vblank *event, void *data) swap.tv_sec, swap.tv_usec, (long long)swap.msc, (long long)info->event_id)); present_event_notify(info->event_id, ust64(swap.tv_sec, swap.tv_usec), swap.msc); + + sna = info->crtc ? to_sna(info->crtc->scrn) : NULL; + if (sna && sna->present.unflip) { + DBG(("%s: executing queued unflip\n", __FUNCTION__)); + sna_present_unflip(xf86ScrnToScreen(sna->scrn), + sna->present.unflip); + sna->present.unflip = 0; + } free(info); } @@ -412,6 +428,8 @@ sna_present_flip(RRCrtcPtr crtc, return FALSE; } + assert(to_sna_from_pixmap(pixmap)->present.unflip == 0); + bo = get_flip_bo(pixmap); if (bo == NULL) { DBG(("%s: flip invalid bo\n", __FUNCTION__)); @@ -448,6 +466,13 @@ notify: return; } + if (sna->mode.flip_active) { + DBG(("%s: outstanding flips, queueing unflip\n", __FUNCTION__)); + assert(sna->present.unflip == 0); + sna->present.unflip = event_id; + return; + } + bo = get_flip_bo(screen->GetScreenPixmap(screen)); if (bo == NULL || !page_flip(screen, NULL, event_id, bo)) { DBG(("%s: failed, trying to restore original mode\n", __FUNCTION__));