Don't unreference FBs of pixmaps from different screens in LeaveVT

FindClientResourcesByType finds pixmaps from all screens, but trying to
process ones from other screens here makes no sense and likely results
in a crash or memory corruption.

Fixes: 06a4654841 ("Make all active CRTCs scan out an all-black
                      framebuffer in LeaveVT")
This commit is contained in:
Michel Dänzer
2019-09-20 17:24:19 +02:00
committed by Michel Dänzer
parent 2cbbd8648c
commit 2faaecc69b

View File

@@ -2602,16 +2602,25 @@ CARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data)
}
static void
pixmap_unref_fb(void *value, XID id, void *cdata)
pixmap_unref_fb(PixmapPtr pixmap)
{
PixmapPtr pixmap = value;
RADEONEntPtr pRADEONEnt = cdata;
ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
struct drmmode_fb **fb_ptr = radeon_pixmap_get_fb_ptr(pixmap);
RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
if (fb_ptr)
drmmode_fb_reference(pRADEONEnt->fd, fb_ptr, NULL);
}
static void
client_pixmap_unref_fb(void *value, XID id, void *pScreen)
{
PixmapPtr pixmap = value;
if (pixmap->drawable.pScreen == pScreen)
pixmap_unref_fb(pixmap);
}
void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -2673,11 +2682,9 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn)
if (pScrn->is_gpu) {
if (drmmode_crtc->scanout[0].pixmap)
pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap,
None, pRADEONEnt);
pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap);
if (drmmode_crtc->scanout[1].pixmap)
pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap,
None, pRADEONEnt);
pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap);
} else {
drmmode_crtc_scanout_free(crtc);
}
@@ -2697,11 +2704,11 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn)
(!clients[i] || clients[i]->clientState != ClientStateRunning))
continue;
FindClientResourcesByType(clients[i], RT_PIXMAP, pixmap_unref_fb,
pRADEONEnt);
FindClientResourcesByType(clients[i], RT_PIXMAP,
client_pixmap_unref_fb, pScreen);
}
pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pRADEONEnt);
pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen));
} else {
memset(info->front_buffer->bo.radeon->ptr, 0,
pScrn->displayWidth * info->pixel_bytes * pScrn->virtualY);