diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-10-06 10:02:22 +0100 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2015-10-26 12:18:53 -0400 |
commit | 7a53179425ab5112adcace1489cad6e8072af6b1 (patch) | |
tree | 25c984d694b78c7b2706298cfab17f54afc119d4 | |
parent | a85808ce3fc26511996d01e7e6ec1192b8c3d216 (diff) | |
download | xserver-7a53179425ab5112adcace1489cad6e8072af6b1.tar.gz |
randr/prime: Don't stop on the first pipe when disabling ReplaceScanoutPixmap
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@chris-wilson.co.uk>
Cc: Dave Airlie <airlied@redhat.com>
Reported-by: Christoph Haag <haagch@frickel.club>
Tested-by: Christoph Haag <haagch@frickel.club>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 245040f0d0b937efe14d947468a641a95398776a)
-rw-r--r-- | randr/rrcrtc.c | 67 |
1 files changed, 45 insertions, 22 deletions
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c index dca0691ac..349874514 100644 --- a/randr/rrcrtc.c +++ b/randr/rrcrtc.c @@ -1663,23 +1663,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) { @@ -1687,32 +1694,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; } |