summaryrefslogtreecommitdiffstats
path: root/abs/core/xf86-video-intel/0001-SNA-fix-PRIME-output-support-since-xserver-1.20.patch
blob: ca794780babdee4c11879e158539ecfb04e485e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
From e85424325911626556fbe5a313c698a5da701163 Mon Sep 17 00:00:00 2001
From: Peter Wu <peter@lekensteyn.nl>
Date: Mon, 13 Aug 2018 22:59:50 +0200
Subject: [PATCH xf86-video-intel] SNA: fix PRIME output support since xserver
 1.20

Since xorg-server 1.20, an external monitor would remain blank when used
in a PRIME output slave setup. Only a cursor was visible. The cause is
"Make PixmapDirtyUpdateRec::src a DrawablePtr" in xserver, the "src"
pointer might point to the root window (created by the server) instead
of a pixmap (as created by xf86-video-intel). Use get_drawable_pixmap to
handle both cases.

When built with -fsanitize=address, the following test will trigger a
heap-buffer-overflow error due to to_sna_from_pixmap receiving a window
instead of a pixmap.

Test on a hybrid graphics laptop (Intel + modesetting/nouveau):

    xrandr --setprovideroutputsource modesetting Intel
    xrandr --output DP-1-1 --mode 2560x1440  # should not crash
    glxgears  # should display gears on both screens

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100086
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
---
Tested with xserver 1.20.1 with ASAN enabled. Survives multiple
resolution changes, works with a Plasma desktop session, it seems
stable. Something like this patch is required to make multi-monitor
setups usable in a hybrid graphics setting with Xorg 1.20.
---
 src/sna/sna_accel.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 2f669bcf..80b116a3 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -17510,7 +17510,11 @@ static bool has_offload_slaves(struct sna *sna)
 	PixmapDirtyUpdatePtr dirty;
 
 	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
+#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC
+		assert(dirty->src == &sna->front->drawable);
+#else
 		assert(dirty->src == sna->front);
+#endif
 		if (RegionNotEmpty(DamageRegion(dirty->damage)))
 			return true;
 	}
@@ -17671,7 +17675,11 @@ static void sna_accel_post_damage(struct sna *sna)
 		if (RegionNil(damage))
 			continue;
 
+#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC
+		src = get_drawable_pixmap(dirty->src);
+#else
 		src = dirty->src;
+#endif
 		dst = dirty->slave_dst->master_pixmap;
 
 		region.extents.x1 = dirty->x;
@@ -17922,9 +17930,15 @@ migrate_dirty_tracking(PixmapPtr old_front, PixmapPtr new_front)
 	PixmapDirtyUpdatePtr dirty, safe;
 
 	xorg_list_for_each_entry_safe(dirty, safe, &screen->pixmap_dirty_list, ent) {
+#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC
+		assert(dirty->src == &old_front->drawable);
+		if (dirty->src != &old_front->drawable)
+			continue;
+#else
 		assert(dirty->src == old_front);
 		if (dirty->src != old_front)
 			continue;
+#endif
 
 		DamageUnregister(&dirty->src->drawable, dirty->damage);
 		DamageDestroy(dirty->damage);
@@ -17939,7 +17953,11 @@ migrate_dirty_tracking(PixmapPtr old_front, PixmapPtr new_front)
 		}
 
 		DamageRegister(&new_front->drawable, dirty->damage);
+#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC
+		dirty->src = &new_front->drawable;
+#else
 		dirty->src = new_front;
+#endif
 	}
 #endif
 }
-- 
2.18.0