sna/present: Avoid tricks with the TearFree flag

Modifying the flag may cause havoc if we need to modeset whilst Present
is in control as the CRTC will be setup without reference to TearFree, but
then when Present unflips, we restore the stale configuration. So let's
have a separate flag just to disable TearFree flips when a Present flip
chain is active.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2015-02-15 09:30:52 +00:00
parent 74553bf4d2
commit 3fc942b374
3 changed files with 17 additions and 21 deletions

View File

@ -287,6 +287,7 @@ struct sna {
unsigned rr_active;
unsigned flip_active;
unsigned hidden;
bool shadow_enabled;
bool dirty;
int max_crtc_width, max_crtc_height;
@ -356,7 +357,6 @@ struct sna {
bool open;
#if HAVE_PRESENT
uint64_t unflip;
void *tearfree;
#endif
} present;

View File

@ -1399,6 +1399,7 @@ static bool sna_mode_enable_shadow(struct sna *sna)
return false;
DamageRegister(&sna->front->drawable, sna->mode.shadow_damage);
sna->mode.shadow_enabled = true;
return true;
}
@ -1406,8 +1407,10 @@ static void sna_mode_disable_shadow(struct sna *sna)
{
struct sna_pixmap *priv;
if (!sna->mode.shadow_damage)
if (!sna->mode.shadow_damage) {
assert(!sna->mode.shadow_enabled);
return;
}
DBG(("%s\n", __FUNCTION__));
@ -1418,6 +1421,7 @@ static void sna_mode_disable_shadow(struct sna *sna)
DamageUnregister(&sna->front->drawable, sna->mode.shadow_damage);
DamageDestroy(sna->mode.shadow_damage);
sna->mode.shadow_damage = NULL;
sna->mode.shadow_enabled = false;
if (sna->mode.shadow) {
kgem_bo_destroy(&sna->kgem, sna->mode.shadow);
@ -4448,6 +4452,7 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
for (i = 0; i < sna->mode.num_real_crtc; i++)
sna_crtc_disable_shadow(sna, to_sna_crtc(config->crtc[i]));
assert(sna->mode.shadow_active == 0);
assert(!sna->mode.shadow_enabled);
assert(sna->mode.shadow_damage == NULL);
assert(sna->mode.shadow == NULL);
@ -5422,7 +5427,6 @@ sna_page_flip(struct sna *sna,
assert(bo->refcnt);
assert((sna->flags & SNA_IS_HOSTED) == 0);
assert((sna->flags & SNA_TEAR_FREE) == 0);
assert(sna->mode.flip_active == 0);
assert(sna->mode.front_active);
assert(!sna->mode.hidden);
@ -7233,7 +7237,7 @@ void sna_mode_redisplay(struct sna *sna)
return;
}
if (!sna->mode.shadow_damage)
if (!sna->mode.shadow_enabled || !sna->mode.shadow_damage)
return;
DBG(("%s: posting shadow damage? %d (flips pending? %d, mode reconfiguration pending? %d)\n",

View File

@ -533,11 +533,9 @@ sna_present_flip(RRCrtcPtr crtc,
return FALSE;
}
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->flags & SNA_TEAR_FREE)
sna->mode.shadow_enabled = false;
assert(!sna->mode.shadow_enabled);
if (sna->mode.flip_active) {
DBG(("%s: flips still pending\n", __FUNCTION__));
@ -555,7 +553,6 @@ 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) {
@ -580,6 +577,9 @@ notify:
return;
}
if (sna->flags & SNA_TEAR_FREE)
sna->mode.shadow_enabled = sna->mode.shadow_damage != NULL;
bo = get_flip_bo(screen->GetScreenPixmap(screen));
if (bo == NULL) {
reset_mode:
@ -588,21 +588,13 @@ reset_mode:
goto notify;
}
ok = false;
if (sna->flags & SNA_HAS_ASYNC_FLIP) {
DBG(("%s: trying async flip restore\n", __FUNCTION__));
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__async(sna, NULL, event_id, 0, bo))
return;
}
if (!ok)
if (!flip(sna, NULL, event_id, 0, bo))
goto reset_mode;
}