summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2017-05-02 11:47:58 +0900
committerMichel Dänzer <michel@daenzer.net>2017-05-11 18:52:43 +0900
commit7dc68e26755466f9056f8c72195ab8690660693d (patch)
tree63b603b5d280784d5fdc024bb525a51d428afdd7
parent55e513b978b2afc52b7cafc5bfcb0d1dc78d75f6 (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.c21
-rw-r--r--src/drmmode_display.h3
-rw-r--r--src/radeon_kms.c7
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))