diff options
author | Michel Dänzer <mdaenzer@redhat.com> | 2019-09-26 15:56:59 +0200 |
---|---|---|
committer | Michel Dänzer <mdaenzer@redhat.com> | 2019-09-26 15:56:59 +0200 |
commit | a1b7263277c033e109629829c370c0e95978e061 (patch) | |
tree | e967947f2988150aeaf14c452d9e2808d497a71c | |
parent | 5b8bc9fc505c551dcd9b0ed5ab835a49fa4f9fda (diff) |
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: c16ff42f927d ("Make all active CRTCs scan out an all-black
framebuffer in LeaveVT")
(Ported from radeon commit 2faaecc69b127248718e759c6c98c84d56dd1b6b)
-rw-r--r-- | src/amdgpu_kms.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c index 6263bd7..6a60f54 100644 --- a/src/amdgpu_kms.c +++ b/src/amdgpu_kms.c @@ -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); |