summaryrefslogtreecommitdiff
path: root/src/radeon_kms.c
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 /src/radeon_kms.c
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")
Diffstat (limited to 'src/radeon_kms.c')
-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);