diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2017-05-02 11:47:58 +0900 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2017-05-11 18:52:43 +0900 |
commit | 7dc68e26755466f9056f8c72195ab8690660693d (patch) | |
tree | 63b603b5d280784d5fdc024bb525a51d428afdd7 | |
parent | 55e513b978b2afc52b7cafc5bfcb0d1dc78d75f6 (diff) |
Simplify tracking of PRIME scanout pixmap
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.
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | src/drmmode_display.c | 21 | ||||
-rw-r--r-- | src/drmmode_display.h | 3 | ||||
-rw-r--r-- | 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 ec307262..e2899cf5 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 14d1cb03..df2c4b7b 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 2b410eb3..c4bdfcfa 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)) |