From: Michel Dänzer <michel.daen...@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.

(Ported from radeon commit 7dc68e26755466f9056f8c72195ab8690660693d)

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

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 4df81f993..a418cf9d3 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -562,8 +562,7 @@ amdgpu_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;
        }
 
@@ -576,13 +575,11 @@ amdgpu_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))
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 9996d2f70..add8287a0 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -681,9 +681,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;
@@ -838,7 +836,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr 
mode,
 
                fb_id = drmmode->fb_id;
 #ifdef AMDGPU_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_id, &x, &y);
                } else
@@ -1242,14 +1240,15 @@ static Bool 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;
 
@@ -1266,6 +1265,8 @@ static Bool 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 2d5698f61..6a57fd23b 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -83,6 +83,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;
-- 
2.11.0

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to