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:
parent
9d65a0de95
commit
245040f0d0
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue