From 0f1a05bd0d88b6633022772b2c075cb1803ca18b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 7 Oct 2017 16:58:14 +0100 Subject: [PATCH xf86-video-intel] sna/present: Flush the current vblank queue when queuing a new one We only ever expect to have at most 2 vblanks in flight, this msc and the next. So when queuing a fresh vblank, flush the current queue. This primarily should help with slow systems that are not processing the drm event queue fast enough, and for them it will help reduce the vblank latency. Also note that we do not need to add a vblank on getmsc if we already have an active vblank set. Reported-by: Adric Blake References: https://bugs.freedesktop.org/show_bug.cgi?id=103025#c13 Signed-off-by: Chris Wilson --- src/sna/sna.h | 2 ++ src/sna/sna_present.c | 40 ++++++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/sna/sna.h b/src/sna/sna.h index 7861110a..a60b8c84 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -657,12 +657,14 @@ static inline bool sna_crtc_is_on(xf86CrtcPtr crtc) static inline void sna_crtc_set_vblank(xf86CrtcPtr crtc) { + DBG(("%s: current vblank count: %d\n", __FUNCTION__, *sna_crtc_flags(crtc) & CRTC_VBLANK)); assert((*sna_crtc_flags(crtc) & CRTC_VBLANK) < 3); ++*sna_crtc_flags(crtc); } static inline void sna_crtc_clear_vblank(xf86CrtcPtr crtc) { + DBG(("%s: current vblank count: %d\n", __FUNCTION__, *sna_crtc_flags(crtc) & CRTC_VBLANK)); assert(*sna_crtc_flags(crtc) & CRTC_VBLANK); --*sna_crtc_flags(crtc); } diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c index efe80387..997f4d46 100644 --- a/src/sna/sna_present.c +++ b/src/sna/sna_present.c @@ -197,6 +197,18 @@ static uint32_t msc_to_delay(xf86CrtcPtr crtc, uint64_t target) return MIN(delay, INT32_MAX); } +static void add_to_vblank_queue(struct sna_present_event *info, + int delta) +{ + info->queued = true; + if (delta == 1 && info->crtc) { + sna_crtc_set_vblank(info->crtc); + info->crtc = mark_crtc(info->crtc); + } + + sna_mode_wakeup(info->sna); /* Flush the current vblank queue */ +} + static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data) { struct sna_present_event *info = data; @@ -225,11 +237,7 @@ static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data) vbl.request.signal = (uintptr_t)MARK_PRESENT(info); if (sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc)) == 0) { DBG(("%s: scheduled new vblank event for %lld\n", __FUNCTION__, (long long)info->target_msc)); - info->queued = true; - if (delta == 1) { - sna_crtc_set_vblank(info->crtc); - info->crtc = mark_crtc(info->crtc); - } + add_to_vblank_queue(info, delta); free(timer); return 0; } @@ -326,11 +334,7 @@ static bool sna_present_queue(struct sna_present_event *info, if (!sna_fake_vblank(info)) return false; } else { - info->queued = true; - if (delta == 1) { - sna_crtc_set_vblank(info->crtc); - info->crtc = mark_crtc(info->crtc); - } + add_to_vblank_queue(info, delta); } return true; @@ -382,7 +386,9 @@ sna_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc) *ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec); *msc = sna_crtc_record_vblank(crtc->devPrivate, &vbl); - info = info_alloc(sna); + info = NULL; + if (!has_vblank(crtc->devPrivate)) + info = info_alloc(sna); if (info) { info->crtc = crtc->devPrivate; info->sna = sna; @@ -399,9 +405,7 @@ sna_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc) sna_crtc_pipe(info->crtc)) == 0) { list_add(&info->link, &sna->present.vblank_queue); - info->queued = true; - sna_crtc_set_vblank(info->crtc); - info->crtc = mark_crtc(info->crtc); + add_to_vblank_queue(info, 1); } else info_free(info); } @@ -692,8 +696,10 @@ present_flip_handler(struct drm_event_vblank *event, void *data) swap.tv_sec = event->tv_sec; swap.tv_usec = event->tv_usec; swap.msc = event->sequence; - } else + } else { + info->crtc = unmask_crtc(info->crtc); swap = *sna_crtc_last_swap(info->crtc); + } DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld (target %lld), event=%lld complete%s\n", __FUNCTION__, info->crtc ? sna_crtc_pipe(info->crtc) : -1, @@ -747,9 +753,7 @@ flip(struct sna *sna, return FALSE; } - info->queued = true; - if (info->crtc) - sna_crtc_set_vblank(info->crtc); + add_to_vblank_queue(info, 1); return TRUE; } -- 2.14.2