sna: Avoid confusing failure to flip and flipping zero CRTC
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 17 Jul 2014 09:06:06 +0000 (10:06 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 17 Jul 2014 09:06:06 +0000 (10:06 +0100)
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>
src/sna/sna_display.c
src/sna/sna_dri2.c
src/sna/sna_present.c

index 747d261..7c70b4c 100644 (file)
@@ -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;
index 0b343ce..be5d814 100644 (file)
@@ -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;
index dd4771c..a1dfc91 100644 (file)
@@ -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;
        }
 }