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>
This commit is contained in:
Chris Wilson 2014-10-06 10:02:22 +01:00 committed by Adam Jackson
parent 9d65a0de95
commit 245040f0d0

View File

@ -1695,23 +1695,30 @@ Bool
RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable) RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable)
{ {
rrScrPriv(pDrawable->pScreen); rrScrPriv(pDrawable->pScreen);
int i;
Bool size_fits = FALSE;
Bool changed = FALSE;
Bool ret = TRUE; 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++) { for (i = 0; i < pScrPriv->numCrtcs; i++) {
RRCrtcPtr crtc = pScrPriv->crtcs[i]; RRCrtcPtr crtc = pScrPriv->crtcs[i];
Bool size_fits;
saved_scanout_pixmap[i] = crtc->scanout_pixmap;
if (!crtc->mode && enable) if (!crtc->mode && enable)
continue; continue;
if (!crtc->scanout_pixmap && !enable)
continue;
changed = FALSE; size_fits = (crtc->mode &&
if (crtc->mode && crtc->x == pDrawable->x && crtc->x == pDrawable->x &&
crtc->y == pDrawable->y && crtc->y == pDrawable->y &&
crtc->mode->mode.width == pDrawable->width && crtc->mode->mode.width == pDrawable->width &&
crtc->mode->mode.height == pDrawable->height) crtc->mode->mode.height == pDrawable->height);
size_fits = TRUE;
/* is the pixmap already set? */ /* is the pixmap already set? */
if (crtc->scanout_pixmap == pPixmap) { if (crtc->scanout_pixmap == pPixmap) {
@ -1719,32 +1726,48 @@ RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable)
if (enable == FALSE) { if (enable == FALSE) {
/* set scanout to NULL */ /* set scanout to NULL */
crtc->scanout_pixmap = NULL; crtc->scanout_pixmap = NULL;
changed = TRUE; }
} else { else if (!size_fits) {
/* if the size fits then we are already setup */
if (size_fits)
return TRUE;
/* if the size no longer fits then drop off */ /* if the size no longer fits then drop off */
crtc->scanout_pixmap = NULL; 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; ret = FALSE;
} }
} else { else {
if (!size_fits) /* if the size fits then we are already setup */
return FALSE;
if (enable) {
crtc->scanout_pixmap = pPixmap;
pScrPriv->rrCrtcSetScanoutPixmap(crtc, pPixmap);
changed = TRUE;
} }
} }
else {
if (!size_fits)
ret = FALSE;
else if (enable)
crtc->scanout_pixmap = pPixmap;
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->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap);
(*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y, (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y,
crtc->rotation, crtc->numOutputs, crtc->outputs); crtc->rotation, crtc->numOutputs, crtc->outputs);
} }
else
crtc->scanout_pixmap = saved_scanout_pixmap[i];
} }
free(saved_scanout_pixmap);
return ret; return ret;
} }