summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <mdaenzer@redhat.com>2019-09-20 17:24:19 +0200
committerMichel Dänzer <michel@daenzer.net>2019-09-25 09:23:25 +0200
commit2faaecc69b127248718e759c6c98c84d56dd1b6b (patch)
tree0f74c0d06f8478cf36892e31e26a2c0180abcaf8
parent2cbbd8648cdd27db8076565943b932ef81337053 (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: 06a465484101 ("Make all active CRTCs scan out an all-black framebuffer in LeaveVT")
-rw-r--r--src/radeon_kms.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 107c1ce7..b3db7c41 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -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);