diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-07-17 10:06:06 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-07-17 10:06:06 +0100 |
commit | 62f62f70eda97a3ef18c5144031fdf1cb2b7dad0 (patch) | |
tree | cd5a377c36f2a64d2ede3386de18e4879cc08cb4 | |
parent | 95f08c171ebd9b594112ab006c4460702a22bec1 (diff) |
sna: Avoid confusing failure to flip and flipping zero CRTC
During the present unflip path we blindly try to restore the original
mode after a flip failure. However, it confuses flipping zero CRTC with
a genuine failure. This has the result of undoing a DPMS change (e.g.
xset dpms force dpms) under a DRI3 compositor.
Reported-by: Jiri Slaby <jirislaby@gmail.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=81456
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_display.c | 2 | ||||
-rw-r--r-- | src/sna/sna_dri2.c | 6 | ||||
-rw-r--r-- | src/sna/sna_present.c | 26 |
3 files changed, 22 insertions, 12 deletions
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 747d261f..7c70b4cc 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -4863,6 +4863,8 @@ sna_page_flip(struct sna *sna, 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->scrn->vtSema); if ((sna->flags & (data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP)) == 0) return 0; diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 0b343cec..be5d8141 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -1560,11 +1560,13 @@ can_flip(struct sna * sna, if (draw->type == DRAWABLE_PIXMAP) return false; - if (!sna->scrn->vtSema) { - DBG(("%s: no, not attached to VT\n", __FUNCTION__)); + if (!sna->mode.front_active) { + DBG(("%s: no, active CRTC\n", __FUNCTION__)); return false; } + assert(sna->scrn->vtSema); + if ((sna->flags & (SNA_HAS_FLIP | SNA_HAS_ASYNC_FLIP)) == 0) { DBG(("%s: no, pageflips disabled\n", __FUNCTION__)); return false; diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c index dd4771c9..a1dfc91e 100644 --- a/src/sna/sna_present.c +++ b/src/sna/sna_present.c @@ -193,16 +193,13 @@ static bool check_flip__crtc(struct sna *sna, RRCrtcPtr crtc) { - if (!sna->scrn->vtSema) { - DBG(("%s: not master\n", __FUNCTION__)); - return false; - } - if (!sna_crtc_is_on(crtc->devPrivate)) { DBG(("%s: CRTC off\n", __FUNCTION__)); return false; } + assert(sna->scrn->vtSema); + if (sna->mode.shadow_active) { DBG(("%s: shadow buffer active\n", __FUNCTION__)); return false; @@ -415,19 +412,28 @@ sna_present_flip(RRCrtcPtr crtc, static void sna_present_unflip(ScreenPtr screen, uint64_t event_id) { + struct sna *sna = to_sna_from_screen(screen); struct kgem_bo *bo; DBG(("%s(event=%lld)\n", __FUNCTION__, (long long)event_id)); - bo = get_flip_bo(screen->GetScreenPixmap(screen)); - if (bo == NULL || !page_flip(screen, NULL, event_id, bo)) { - struct sna *sna = to_sna_from_screen(screen); + if (sna->mode.front_active == 0) { const struct ust_msc *swap; - DBG(("%s: failed, trying to restore original mode\n", __FUNCTION__)); - xf86SetDesiredModes(sna->scrn); + + DBG(("%s: no CRTC active, perform no-op flip\n", __FUNCTION__)); + +notify: swap = sna_crtc_last_swap(sna_mode_first_crtc(sna)); present_event_notify(event_id, ust64(swap->tv_sec, swap->tv_usec), swap->msc); + return; + } + + bo = get_flip_bo(screen->GetScreenPixmap(screen)); + if (bo == NULL || !page_flip(screen, NULL, event_id, bo)) { + DBG(("%s: failed, trying to restore original mode\n", __FUNCTION__)); + xf86SetDesiredModes(sna->scrn); + goto notify; } } |