sna: Reorder frontbuffer resize vs flip event queue draining

If we are not careful, we may process an unflip in the middle of
resizing the frontbuffer - when the ScreenPixmap state is ill-defined.
First flush all the pending flip events, cancel any residual unflips,
then update the screen pixmap. This should be enough to close the race.

References: https://bugs.freedesktop.org/show_bug.cgi?id=98855#c11
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2016-12-05 21:28:35 +00:00
parent fcf943f45b
commit ff25ad3402
2 changed files with 10 additions and 10 deletions

View File

@ -5679,6 +5679,14 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
assert(sna->mode.shadow_damage == NULL);
assert(sna->mode.shadow == NULL);
/* Flush pending shadow updates */
if (sna->mode.flip_active) {
DBG(("%s: waiting for %d outstanding TearFree flips\n",
__FUNCTION__, sna->mode.flip_active));
while (sna->mode.flip_active && sna_mode_wait_for_event(sna))
sna_mode_wakeup(sna);
}
/* Cancel a pending [un]flip (as the pixmaps no longer match) */
sna_present_cancel_flip(sna);
copy_front(sna, sna->front, new_front);
@ -5692,14 +5700,6 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
scrn->virtualY = height;
scrn->displayWidth = width;
/* Flush pending shadow updates */
if (sna->mode.flip_active) {
DBG(("%s: waiting for %d outstanding TearFree flips\n",
__FUNCTION__, sna->mode.flip_active));
while (sna->mode.flip_active && sna_mode_wait_for_event(sna))
sna_mode_wakeup(sna);
}
/* Only update the CRTCs if we are in control */
if (!scrn->vtSema)
return TRUE;

View File

@ -926,12 +926,12 @@ reset_mode:
goto notify;
}
assert(sna_pixmap(screen->GetScreenPixmap(screen))->pinned & PIN_SCANOUT);
/* Are we unflipping after a failure that left our ScreenP in place? */
if (!sna_needs_page_flip(sna, bo))
goto notify;
assert(sna_pixmap(screen->GetScreenPixmap(screen))->pinned & PIN_SCANOUT);
if (sna->flags & SNA_HAS_ASYNC_FLIP) {
DBG(("%s: trying async flip restore\n", __FUNCTION__));
if (flip__async(sna, NULL, event_id, 0, bo))