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: c16ff42f92 ("Make all active CRTCs scan out an all-black
                      framebuffer in LeaveVT")
(Ported from radeon commit 2faaecc69b127248718e759c6c98c84d56dd1b6b)
This commit is contained in:
Michel Dänzer
2019-09-26 15:56:59 +02:00
parent 5b8bc9fc50
commit a1b7263277

View File

@@ -2240,16 +2240,25 @@ Bool AMDGPUEnterVT_KMS(ScrnInfoPtr pScrn)
}
static void
pixmap_unref_fb(void *value, XID id, void *cdata)
pixmap_unref_fb(PixmapPtr pixmap)
{
PixmapPtr pixmap = value;
AMDGPUEntPtr pAMDGPUEnt = cdata;
ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
struct drmmode_fb **fb_ptr = amdgpu_pixmap_get_fb_ptr(pixmap);
AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
if (fb_ptr)
drmmode_fb_reference(pAMDGPUEnt->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 AMDGPULeaveVT_KMS(ScrnInfoPtr pScrn)
{
AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
@@ -2311,11 +2320,9 @@ void AMDGPULeaveVT_KMS(ScrnInfoPtr pScrn)
if (pScrn->is_gpu) {
if (drmmode_crtc->scanout[0].pixmap)
pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap,
None, pAMDGPUEnt);
pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap);
if (drmmode_crtc->scanout[1].pixmap)
pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap,
None, pAMDGPUEnt);
pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap);
} else {
drmmode_crtc_scanout_free(crtc);
}
@@ -2335,11 +2342,11 @@ void AMDGPULeaveVT_KMS(ScrnInfoPtr pScrn)
(!clients[i] || clients[i]->clientState != ClientStateRunning))
continue;
FindClientResourcesByType(clients[i], RT_PIXMAP, pixmap_unref_fb,
pAMDGPUEnt);
FindClientResourcesByType(clients[i], RT_PIXMAP,
client_pixmap_unref_fb, pScreen);
}
pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pAMDGPUEnt);
pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen));
} else {
memset(info->front_buffer->cpu_ptr, 0, pScrn->virtualX *
info->pixel_bytes * pScrn->virtualY);