From c14994713b87eef67037903f40819793d5959d10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Sat, 13 Feb 2021 14:44:08 +0200 Subject: sna: Fix async flips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to wait for flip events even when doing async flips, otherwise the kernel will just hand us -EBUSY if we try to flip too fast. Signed-off-by: Ville Syrjälä --- src/sna/sna.h | 1 + src/sna/sna_display.c | 20 ++++++++--------- src/sna/sna_dri2.c | 7 +++--- src/sna/sna_present.c | 61 +++++++++++++++++++++++---------------------------- 4 files changed, 41 insertions(+), 48 deletions(-) diff --git a/src/sna/sna.h b/src/sna/sna.h index f2bc1896..29d08a9b 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -491,6 +491,7 @@ typedef void (*sna_flip_handler_t)(struct drm_event_vblank *e, extern bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo); extern int sna_page_flip(struct sna *sna, struct kgem_bo *bo, + bool async, sna_flip_handler_t handler, void *data); diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 874292bc..a26f4906 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -7143,6 +7143,7 @@ bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo) int sna_page_flip(struct sna *sna, struct kgem_bo *bo, + bool async, sna_flip_handler_t handler, void *data) { @@ -7162,7 +7163,7 @@ sna_page_flip(struct sna *sna, assert(!sna->mode.hidden); assert(sna->scrn->vtSema); - if ((sna->flags & (data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP)) == 0) + if ((sna->flags & (async ? SNA_HAS_ASYNC_FLIP : SNA_HAS_FLIP)) == 0) return 0; kgem_bo_submit(&sna->kgem, bo); @@ -7186,7 +7187,7 @@ sna_page_flip(struct sna *sna, assert(crtc->flip_bo == NULL); assert_crtc_fb(sna, crtc); - if (data == NULL && crtc->bo == bo) + if (async && crtc->bo == bo) goto next_crtc; arg.crtc_id = __sna_crtc_id(crtc); @@ -7224,7 +7225,7 @@ update_scanout: crtc->bo = kgem_bo_reference(bo); crtc->bo->active_scanout++; - if (data == NULL) + if (async) goto next_crtc; /* queue a flip in order to send the event */ @@ -7235,13 +7236,10 @@ update_scanout: /* Only the reference crtc will finally deliver its page flip * completion event. All other crtc's events will be discarded. */ - if (data) { - arg.user_data = (uintptr_t)crtc; - arg.flags = DRM_MODE_PAGE_FLIP_EVENT; - } else { - arg.user_data = 0; - arg.flags = DRM_MODE_PAGE_FLIP_ASYNC; - } + arg.user_data = (uintptr_t)crtc; + arg.flags = DRM_MODE_PAGE_FLIP_EVENT; + if (async) + arg.flags |= DRM_MODE_PAGE_FLIP_ASYNC; arg.reserved = 0; retry_flip: @@ -7281,7 +7279,7 @@ retry_flip: error: xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR, "page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n", - __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), data ? "synchronous": "asynchronous"); + __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), async ? "asynchronous": "synchronous"); if (count || crtc->bo == bo) sna_mode_restore(sna); diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 4ee76627..4361af71 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -1963,8 +1963,8 @@ sna_dri2_flip(struct sna_dri2_event *info) } assert(!info->queued); - if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler, - info->type == FLIP_ASYNC ? NULL : info)) + if (!sna_page_flip(info->sna, bo, info->type == FLIP_ASYNC, + sna_dri2_flip_handler, info)) return false; DBG(("%s: queued flip=%p\n", __FUNCTION__, info->type == FLIP_ASYNC ? NULL : info)); @@ -2855,7 +2855,8 @@ sna_dri2_flip_continue(struct sna_dri2_event *info) return false; assert(!info->queued); - if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler, info)) + if (!sna_page_flip(info->sna, bo, false, + sna_dri2_flip_handler, info)) return false; DBG(("%s: queued flip=%p\n", __FUNCTION__, info)); diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c index 6bb7b927..b86dc97e 100644 --- a/src/sna/sna_present.c +++ b/src/sna/sna_present.c @@ -675,34 +675,6 @@ sna_present_check_flip(RRCrtcPtr crtc, return TRUE; } -static Bool -flip__async(struct sna *sna, - RRCrtcPtr crtc, - uint64_t event_id, - uint64_t target_msc, - struct kgem_bo *bo) -{ - DBG(("%s(pipe=%d, event=%lld, handle=%d)\n", - __FUNCTION__, - pipe_from_crtc(crtc), - (long long)event_id, - bo->handle)); - - if (!sna_page_flip(sna, bo, NULL, NULL)) { - DBG(("%s: async pageflip failed\n", __FUNCTION__)); - present_info.capabilities &= ~PresentCapabilityAsync; - return FALSE; - } - - DBG(("%s: pipe=%d tv=%ld.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__, - pipe_from_crtc(crtc), - (long)(gettime_ust64() / 1000000), (int)(gettime_ust64() % 1000000), - crtc ? (long long)sna_crtc_last_swap(crtc->devPrivate)->msc : 0LL, - (long long)target_msc, (long long)event_id)); - present_event_notify(event_id, gettime_ust64(), target_msc); - return TRUE; -} - static void present_flip_handler(struct drm_event_vblank *event, void *data) { @@ -748,11 +720,12 @@ present_flip_handler(struct drm_event_vblank *event, void *data) } static Bool -flip(struct sna *sna, - RRCrtcPtr crtc, - uint64_t event_id, - uint64_t target_msc, - struct kgem_bo *bo) +do_flip(struct sna *sna, + RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + struct kgem_bo *bo, + bool async) { struct sna_present_event *info; @@ -774,7 +747,7 @@ flip(struct sna *sna, info->target_msc = target_msc; info->active = false; - if (!sna_page_flip(sna, bo, present_flip_handler, info)) { + if (!sna_page_flip(sna, bo, async, present_flip_handler, info)) { DBG(("%s: pageflip failed\n", __FUNCTION__)); info_free(info); return FALSE; @@ -784,6 +757,26 @@ flip(struct sna *sna, return TRUE; } +static Bool +flip__async(struct sna *sna, + RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + struct kgem_bo *bo) +{ + return do_flip(sna, crtc, event_id, target_msc, bo, true); +} + +static Bool +flip(struct sna *sna, + RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + struct kgem_bo *bo) +{ + return do_flip(sna, crtc, event_id, target_msc, bo, false); +} + static struct kgem_bo * get_flip_bo(PixmapPtr pixmap) { -- cgit v1.2.1