[PATCH xf86-video-ati] Simplify tracking of PRIME scanout pixmap

Michel Dänzer michel at daenzer.net
Wed May 10 09:10:48 UTC 2017


From: Michel Dänzer <michel.daenzer at amd.com>

Remember the shared pixmap passed to drmmode_set_scanout_pixmap for each
CRTC, and just compare against that.

Fixes leaving stale entries in ScreenRec::pixmap_dirty_list under some
circumstances, which would usually result in use-after-free and a crash
down the line.

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/drmmode_display.c | 21 +++++++++++----------
 src/drmmode_display.h |  3 +++
 src/radeon_kms.c      |  7 ++-----
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index ec3072621..e2899cf50 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -732,9 +732,7 @@ drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
 
 		xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list,
 					 ent) {
-			if (dirty->src == crtc->randr_crtc->scanout_pixmap &&
-			    dirty->slave_dst ==
-			    drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap) {
+			if (dirty->src == drmmode_crtc->prime_scanout_pixmap) {
 				dirty->slave_dst =
 					drmmode_crtc->scanout[scanout_id].pixmap;
 				break;
@@ -887,7 +885,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
 
 #ifdef RADEON_PIXMAP_SHARING
-		if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
+		if (drmmode_crtc->prime_scanout_pixmap) {
 			drmmode_crtc_prime_scanout_update(crtc, mode, scanout_id,
 							  &fb, &x, &y);
 		} else
@@ -1278,14 +1276,15 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
 	PixmapDirtyUpdatePtr dirty;
 
 	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
-		if (dirty->slave_dst != drmmode_crtc->scanout[scanout_id].pixmap)
-			continue;
-
-		PixmapStopDirtyTracking(dirty->src, dirty->slave_dst);
-		drmmode_crtc_scanout_free(drmmode_crtc);
-		break;
+		if (dirty->src == drmmode_crtc->prime_scanout_pixmap) {
+			PixmapStopDirtyTracking(dirty->src, dirty->slave_dst);
+			break;
+		}
 	}
 
+	drmmode_crtc_scanout_free(drmmode_crtc);
+	drmmode_crtc->prime_scanout_pixmap = NULL;
+
 	if (!ppix)
 		return TRUE;
 
@@ -1302,6 +1301,8 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
 		return FALSE;
 	}
 
+	drmmode_crtc->prime_scanout_pixmap = ppix;
+
 #ifdef HAS_DIRTYTRACKING_ROTATION
 	PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[scanout_id].pixmap,
 				 0, 0, 0, 0, RR_Rotate_0);
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 14d1cb034..df2c4b7bb 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -92,6 +92,9 @@ typedef struct {
     unsigned scanout_id;
     Bool scanout_update_pending;
     Bool tear_free;
+
+    PixmapPtr prime_scanout_pixmap;
+
     int dpms_mode;
     /* For when a flip is pending when DPMS off requested */
     int pending_dpms_mode;
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 2b410eb3d..c4bdfcfac 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -657,8 +657,7 @@ radeon_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty)
 	xf86CrtcPtr xf86_crtc = xf86_config->crtc[c];
 	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
 
-	if (drmmode_crtc->scanout[0].pixmap == dirty->slave_dst ||
-	    drmmode_crtc->scanout[1].pixmap == dirty->slave_dst)
+	if (drmmode_crtc->prime_scanout_pixmap == dirty->src)
 	    return xf86_crtc;
     }
 
@@ -671,13 +670,11 @@ radeon_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
     ScrnInfoPtr scrn = crtc->scrn;
     ScreenPtr screen = scrn->pScreen;
     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-    PixmapPtr scanoutpix = crtc->randr_crtc->scanout_pixmap;
     PixmapDirtyUpdatePtr dirty;
     Bool ret = FALSE;
 
     xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
-	if (dirty->src == scanoutpix && dirty->slave_dst ==
-	    drmmode_crtc->scanout[scanout_id ^ drmmode_crtc->tear_free].pixmap) {
+	if (dirty->src == drmmode_crtc->prime_scanout_pixmap) {
 	    RegionPtr region;
 
 	    if (master_has_sync_shared_pixmap(scrn, dirty))
-- 
2.11.0



More information about the amd-gfx mailing list