From f4f6695c92b42f5419c081fb752f6b60bbf46db3 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 before queuing a new one We only ever expect to have at most 2 vblanks in flight, this msc and the next. So before 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. Reported-by: Adric Blake References: https://bugs.freedesktop.org/show_bug.cgi?id=103025#c13 Signed-off-by: Chris Wilson --- src/sna/sna_present.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c index efe80387..a18c8799 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) +{ + sna_mode_wakeup(info->sna); /* Flush the current vblank queue */ + + info->queued = true; + if (delta == 1 && info->crtc) { + sna_crtc_set_vblank(info->crtc); + info->crtc = mark_crtc(info->crtc); + } +} + 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; @@ -399,9 +403,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 +694,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 +751,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