From 74553bf4d25f5876ef6e682d06f5825feb9e1da4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 14 Feb 2015 22:31:06 +0000 Subject: [PATCH] sna/present: Integrate into TearFree, take 2 Following on from the previous attempt is the realisation that we can simply disable TearFree during a Present flip queue, and re-enable TearFree upon unflip. Signed-off-by: Chris Wilson --- src/sna/sna.h | 8 +-- src/sna/sna_display.c | 33 +--------- src/sna/sna_present.c | 149 +++++------------------------------------- 3 files changed, 20 insertions(+), 170 deletions(-) diff --git a/src/sna/sna.h b/src/sna/sna.h index 1bddf7ad..bbcea080 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -311,13 +311,6 @@ struct sna { Bool (*rrGetInfo)(ScreenPtr, Rotation *); } mode; - struct sna_tearfree { - struct notifier { - void (*func)(struct sna *, void *); - void *data; - } hook[2]; - } tearfree; - struct { struct sna_cursor *cursors; xf86CursorInfoPtr info; @@ -363,6 +356,7 @@ struct sna { bool open; #if HAVE_PRESENT uint64_t unflip; + void *tearfree; #endif } present; diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 286e4701..ac130c75 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -1398,39 +1398,24 @@ static bool sna_mode_enable_shadow(struct sna *sna) if (!sna->mode.shadow_damage) return false; - DamageRegister(&screen->GetScreenPixmap(screen)->drawable, - sna->mode.shadow_damage); + DamageRegister(&sna->front->drawable, sna->mode.shadow_damage); return true; } -inline static PixmapPtr sna_screen_pixmap(struct sna *sna) -{ - return to_screen_from_sna(sna)->GetScreenPixmap(to_screen_from_sna(sna)); -} - static void sna_mode_disable_shadow(struct sna *sna) { struct sna_pixmap *priv; - struct notifier *nb; if (!sna->mode.shadow_damage) return; DBG(("%s\n", __FUNCTION__)); - nb = &sna->tearfree.hook[0]; - if (nb->func) { - nb->func(sna, nb->data); - nb->func = NULL; - } - assert(sna->tearfree.hook[1].func == NULL); - priv = sna_pixmap(sna->front); if (priv->move_to_gpu == wait_for_shadow) priv->move_to_gpu(sna, priv, 0); - DamageUnregister(&sna_screen_pixmap(sna)->drawable, - sna->mode.shadow_damage); + DamageUnregister(&sna->front->drawable, sna->mode.shadow_damage); DamageDestroy(sna->mode.shadow_damage); sna->mode.shadow_damage = NULL; @@ -7121,14 +7106,6 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo) static void shadow_flip_handler(struct drm_event_vblank *e, void *data) { - struct sna *sna = data; - - if (sna->tearfree.hook[0].func) - sna->tearfree.hook[0].func(sna, sna->tearfree.hook[0].data); - - sna->tearfree.hook[0] = sna->tearfree.hook[1]; - sna->tearfree.hook[1].func = NULL; - sna_mode_redisplay(data); } @@ -7731,12 +7708,6 @@ fixup_flip: assert(old == sna->mode.shadow); assert(old->refcnt >= 1); set_shadow(sna, region); - } else { - if (sna->tearfree.hook[0].func) { - sna->tearfree.hook[0].func(sna, sna->tearfree.hook[0].data); - sna->tearfree.hook[0].func = NULL; - } - assert(sna->tearfree.hook[1].func == NULL); } } else kgem_submit(&sna->kgem); diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c index 266d7432..613721c3 100644 --- a/src/sna/sna_present.c +++ b/src/sna/sna_present.c @@ -503,128 +503,6 @@ get_flip_bo(PixmapPtr pixmap) return priv->gpu_bo; } -static bool set_front(struct sna *sna, PixmapPtr pixmap) -{ - RegionRec *damage; - - DBG(("%s: pixmap=%ld\n", __FUNCTION__, pixmap->drawable.serialNumber)); - - if (pixmap == sna->front) - return false; - - sna_pixmap_discard_shadow_damage(sna_pixmap(sna->front), NULL); - sna->front = pixmap; - - /* We rely on unflip restoring the real front before any drawing */ - damage = DamageRegion(sna->mode.shadow_damage); - RegionUninit(damage); - damage->extents.x1 = 0; - damage->extents.y1 = 0; - damage->extents.x2 = pixmap->drawable.width; - damage->extents.y2 = pixmap->drawable.height; - damage->data = NULL; - - return true; -} - -static void -xchg_handler(struct sna *sna, void *data) -{ - struct sna_present_event *info = data; - const struct ust_msc *swap = sna_crtc_last_swap(info->crtc); - - DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__, - sna_crtc_to_pipe(info->crtc), - swap->tv_sec, swap->tv_usec, - (long long)swap->msc, - (long long)info->target_msc, (long long)info->event_id)); - present_event_notify(info->event_id, swap_ust(swap), swap->msc); - free(info); -} - -static Bool -xchg(struct sna *sna, - RRCrtcPtr crtc, - uint64_t event_id, - uint64_t target_msc, - PixmapPtr pixmap, - Bool sync_flip) -{ - struct sna_present_event *info; - bool queued; - - DBG(("%s(pipe=%d, event=%lld, sync_flip=%d)\n", - __FUNCTION__, - pipe_from_crtc(crtc), - (long long)event_id, - sync_flip)); - - assert(sna->flags & SNA_TEAR_FREE); - assert(sna->mode.shadow_damage); - assert(sna_pixmap(pixmap) && sna_pixmap(pixmap)->gpu_bo); - assert(sync_flip); - - /* This effectively disables TearFree giving the client direct - * access into the scanout with their Pixmap. - */ - queued = set_front(sna, pixmap); - - info = malloc(sizeof(struct sna_present_event)); - if (info == NULL) - return BadAlloc; - - info->crtc = crtc->devPrivate; - info->sna = sna; - info->target_msc = target_msc; - info->event_id = event_id; - - if (queued) { - struct notifier *nb; - - nb = &sna->tearfree.hook[0]; - if (nb->func) - nb++; - if (nb->func) { - DBG(("%s: executing existing notifier\n", __FUNCTION__)); - nb->func(sna, nb->data); - } - DBG(("%s: queueing tearfree notifier: sequence %d\n", - __FUNCTION__, nb - &sna->tearfree.hook[0])); - nb->func = xchg_handler; - nb->data = info; - } else { - union drm_wait_vblank vbl; - - DBG(("%s: queueing vblank notifier\n", __FUNCTION__)); - - VG_CLEAR(vbl); - vbl.request.type = - DRM_VBLANK_ABSOLUTE | - DRM_VBLANK_EVENT | - DRM_VBLANK_NEXTONMISS; - vbl.request.sequence = target_msc; - vbl.request.signal = (uintptr_t)MARK_PRESENT(info); - if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(info->crtc))) { - DBG(("%s: vblank enqueue failed\n", __FUNCTION__)); - if (!sna_fake_vblank(info)) { - free(info); - goto notify; - } - } - } - - return TRUE; - -notify: - DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__, - pipe_from_crtc(crtc), - gettime_ust64() / 1000000, gettime_ust64() % 1000000, - (long long)sna_crtc_last_swap(crtc->devPrivate)->msc, - (long long)target_msc, (long long)event_id)); - present_event_notify(event_id, gettime_ust64(), target_msc); - return TRUE; -} - static Bool sna_present_flip(RRCrtcPtr crtc, uint64_t event_id, @@ -655,8 +533,11 @@ sna_present_flip(RRCrtcPtr crtc, return FALSE; } - if (sna->flags & SNA_TEAR_FREE) - return xchg(sna, crtc, event_id, target_msc, pixmap, sync_flip); + if (sna->flags & SNA_TEAR_FREE) { + sna->present.tearfree = sna->mode.shadow_damage; + sna->mode.shadow_damage = NULL; + sna->flags &= ~SNA_TEAR_FREE; + } if (sna->mode.flip_active) { DBG(("%s: flips still pending\n", __FUNCTION__)); @@ -674,6 +555,7 @@ sna_present_unflip(ScreenPtr screen, uint64_t event_id) { struct sna *sna = to_sna_from_screen(screen); struct kgem_bo *bo; + bool ok; DBG(("%s(event=%lld)\n", __FUNCTION__, (long long)event_id)); if (sna->mode.front_active == 0 || sna->mode.rr_active) { @@ -691,11 +573,6 @@ notify: return; } - if (sna->flags & SNA_TEAR_FREE) { - set_front(sna, screen->GetScreenPixmap(screen)); - goto notify; - } - if (sna->mode.flip_active) { DBG(("%s: %d outstanding flips, queueing unflip\n", __FUNCTION__, sna->mode.flip_active)); assert(sna->present.unflip == 0); @@ -711,13 +588,21 @@ reset_mode: goto notify; } + ok = false; if (sna->flags & SNA_HAS_ASYNC_FLIP) { DBG(("%s: trying async flip restore\n", __FUNCTION__)); - if (flip__async(sna, NULL, event_id, 0, bo)) - return; + ok = flip__async(sna, NULL, event_id, 0, bo); + } + if (!ok) + ok = flip(sna, NULL, event_id, 0, bo); + + if (sna->present.tearfree) { + sna->flags |= SNA_TEAR_FREE; + sna->mode.shadow_damage = sna->present.tearfree; + sna->present.tearfree = NULL; } - if (!flip(sna, NULL, event_id, 0, bo)) + if (!ok) goto reset_mode; }