summaryrefslogtreecommitdiff
path: root/randr/rrcrtc.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-10-06 10:02:22 +0100
committerAdam Jackson <ajax@redhat.com>2015-09-21 14:42:51 -0400
commit245040f0d0b937efe14d947468a641a95398776a (patch)
tree8a7d8d60a22ec754d61f52f211030b5de1e5c97e /randr/rrcrtc.c
parent9d65a0de95a20632f2a6a04ba596dcdd76d9f5e2 (diff)
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>
Diffstat (limited to 'randr/rrcrtc.c')
-rw-r--r--randr/rrcrtc.c67
1 files changed, 45 insertions, 22 deletions
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 050d9751a..9bc456bdc 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -1695,23 +1695,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) {
@@ -1719,32 +1726,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;
}
+ }
- if (changed && pScrPriv->rrCrtcSet) {
+ for (i = 0; i < pScrPriv->numCrtcs; i++) {
+ RRCrtcPtr crtc = pScrPriv->crtcs[i];
+
+ if (crtc->scanout_pixmap == saved_scanout_pixmap[i])
+ continue;
+
+ 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;
}