[PATCH] randr/prime: Don't stop on the first pipe when disabling ReplaceScanoutPixmap

Chris Wilson chris at chris-wilson.co.uk
Mon Oct 6 02:02:22 PDT 2014


As we define sizeFits based on whether a CRTC is active, and skip trying
to redirect the scanout on a disable pipe, we then attempt to undo it
later and fail because crtc->scanout_pixmap != DRI2_Pixmap and
!sizeFits. Paper over this failure by skipping unredirected CRTC when
disabling.

v2: Unwind upon failure

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=84653
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Dave Airlie <airlied at redhat.com>
---
 randr/rrcrtc.c | 67 +++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 45 insertions(+), 22 deletions(-)

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 7a42582..a6f2028 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -1687,23 +1687,30 @@ Bool
 RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable)
 {
     rrScrPriv(pDrawable->pScreen);
-    int i;
-    Bool size_fits = FALSE;
-    Bool changed = FALSE;
     Bool ret = TRUE;
+    PixmapPtr *saved_scanout_pixmap;
+    int i;
+
+    saved_scanout_pixmap = malloc(sizeof(PixmapPtr)*pScrPriv->numCrtcs);
+    if (saved_scanout_pixmap == NULL)
+        return FALSE;
 
     for (i = 0; i < pScrPriv->numCrtcs; i++) {
         RRCrtcPtr crtc = pScrPriv->crtcs[i];
+        Bool size_fits;
+
+        saved_scanout_pixmap[i] = crtc->scanout_pixmap;
 
         if (!crtc->mode && enable)
             continue;
+        if (!crtc->scanout_pixmap && !enable)
+            continue;
 
-        changed = FALSE;
-        if (crtc->mode && crtc->x == pDrawable->x &&
-            crtc->y == pDrawable->y &&
-            crtc->mode->mode.width == pDrawable->width &&
-            crtc->mode->mode.height == pDrawable->height)
-            size_fits = TRUE;
+        size_fits = (crtc->mode &&
+                     crtc->x == pDrawable->x &&
+                     crtc->y == pDrawable->y &&
+                     crtc->mode->mode.width == pDrawable->width &&
+                     crtc->mode->mode.height == pDrawable->height);
 
         /* is the pixmap already set? */
         if (crtc->scanout_pixmap == pPixmap) {
@@ -1711,32 +1718,48 @@ RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable)
             if (enable == FALSE) {
                 /* set scanout to NULL */
                 crtc->scanout_pixmap = NULL;
-                changed = TRUE;
-            } else {
-                /* if the size fits then we are already setup */
-                if (size_fits)
-                    return TRUE;
+            }
+            else if (!size_fits) {
                 /* if the size no longer fits then drop off */
                 crtc->scanout_pixmap = NULL;
-                changed = TRUE;
+                pScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap);
+
+                (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y,
+                                        crtc->rotation, crtc->numOutputs, crtc->outputs);
+                saved_scanout_pixmap[i] = crtc->scanout_pixmap;
                 ret = FALSE;
             }
-        } else {
+            else {
+                /* if the size fits then we are already setup */
+            }
+        }
+        else {
             if (!size_fits)
-                return FALSE;
-            if (enable) {
+                ret = FALSE;
+            else if (enable)
                 crtc->scanout_pixmap = pPixmap;
-                pScrPriv->rrCrtcSetScanoutPixmap(crtc, pPixmap);
-                changed = TRUE;
-            }
+            else
+                /* reject an attempt to disable someone else's scanout_pixmap */
+                ret = FALSE;
         }
+    }
+
+    for (i = 0; i < pScrPriv->numCrtcs; i++) {
+        RRCrtcPtr crtc = pScrPriv->crtcs[i];
+
+        if (crtc->scanout_pixmap == saved_scanout_pixmap[i])
+            continue;
 
-        if (changed && pScrPriv->rrCrtcSet) {
+        if (ret) {
             pScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap);
 
             (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y,
                                     crtc->rotation, crtc->numOutputs, crtc->outputs);
         }
+        else
+            crtc->scanout_pixmap = saved_scanout_pixmap[i];
     }
+    free(saved_scanout_pixmap);
+
     return ret;
 }
-- 
2.1.1



More information about the xorg-devel mailing list