diff -u xorg-server-1.18.4/debian/changelog xorg-server-1.18.4/debian/changelog --- xorg-server-1.18.4/debian/changelog +++ xorg-server-1.18.4/debian/changelog @@ -1,3 +1,9 @@ +xorg-server (2:1.18.4-0ubuntu0.5) xenial; urgency=medium + + * Fix shrinking behavior in rrCheckPixmapBounding. (LP: #1715586) + + -- Kai-Heng Feng Thu, 07 Sep 2017 17:23:55 +0800 + xorg-server (2:1.18.4-0ubuntu0.4) xenial; urgency=medium * control: Build against libxfont1-dev. (LP: #1687981, #1707691) diff -u xorg-server-1.18.4/debian/patches/series xorg-server-1.18.4/debian/patches/series --- xorg-server-1.18.4/debian/patches/series +++ xorg-server-1.18.4/debian/patches/series @@ -57,0 +58,2 @@ +randr-rrCheckPixmapBounding-Do-not-substract-crtc-no.patch +randr-rrCheckPixmapBounding-do-not-shrink-the-screen.patch only in patch2: unchanged: --- xorg-server-1.18.4.orig/debian/patches/randr-rrCheckPixmapBounding-Do-not-substract-crtc-no.patch +++ xorg-server-1.18.4/debian/patches/randr-rrCheckPixmapBounding-Do-not-substract-crtc-no.patch @@ -0,0 +1,58 @@ +From 3b624aa9a9df86dc7d48149e0f18ca223b4355f1 Mon Sep 17 00:00:00 2001 +From: Kai-Heng Feng +Date: Tue, 22 Nov 2016 14:48:14 +0100 +Subject: [PATCH 1/2] randr: rrCheckPixmapBounding: Do not substract crtc non 0 + x,y from screen size + +From: Hans de Goede + +The purpose of rrCheckPixmapBounding is to make sure that the +screen_pixmap is large enough for the slave-output which crtc is +being configured. + +This should include crtc->x and crtc->y, otherwise the crtc might +still end up scanning out an area outside of the screen-pixmap. + +For example: Take a laptop with an external monitor on a slave-output at +1920x1080+0+0 and its internal-screen at 3840x2160+1920+0 and in +gnome-settings-daemon move the external monitor to be on the ri ght of +the internal screen rather then on the left. First g-s-d will do a +RRSetScreenSize to 5760*2160 (which is a nop), then it calls RRSetCrtc +to move the slave output to 1920x1080+3840+0, since this is a slave +output, rrCheckPixmapBounding gets called, since the 2 crtcs now overlap +the code before this commit would shrinks the screen_pixmap to 3180*2160. +Then g-s-d calls RRSetCrtc to move the internal screen to 3180*2160+0+0. + +And we end up with the slave-output configured to scan-out an area +which completely falls outside of the screen-pixmap (and end up with +a black display on the external monitor). + +This commit fixes this by not substracting the x1 and y1 coordinates +of the union-ed region when determining the new screen_pixmap size. + +Cc: Nikhil Mahale +Cc: Dave Airlie +Signed-off-by: Hans de Goede +Reviewed-by: Dave Airlie +--- + randr/rrcrtc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c +index 5d404e84b..ac853eab6 100644 +--- a/randr/rrcrtc.c ++++ b/randr/rrcrtc.c +@@ -686,8 +686,8 @@ rrCheckPixmapBounding(ScreenPtr pScreen, + } + + newsize = RegionExtents(&total_region); +- new_width = newsize->x2 - newsize->x1; +- new_height = newsize->y2 - newsize->y1; ++ new_width = newsize->x2; ++ new_height = newsize->y2; + + if (new_width == screen_pixmap->drawable.width && + new_height == screen_pixmap->drawable.height) { +-- +2.14.1 + only in patch2: unchanged: --- xorg-server-1.18.4.orig/debian/patches/randr-rrCheckPixmapBounding-do-not-shrink-the-screen.patch +++ xorg-server-1.18.4/debian/patches/randr-rrCheckPixmapBounding-do-not-shrink-the-screen.patch @@ -0,0 +1,76 @@ +From a46afee84d45fbff4e4dad9376afc95bbcc31d7c Mon Sep 17 00:00:00 2001 +From: Kai-Heng Feng +Date: Tue, 22 Nov 2016 14:53:20 +0100 +Subject: [PATCH 2/2] randr: rrCheckPixmapBounding: do not shrink the + screen_pixmap + +From: Hans de Goede + +The purpose of rrCheckPixmapBounding is to make sure that the +screen_pixmap is *large* enough for the slave-output which crtc is +being configured. + +However until now rrCheckPixmapBounding would also shrink the +screen_pixmap in certain scenarios leading to various problems. + +For example: Take a laptop with its internalscreen on a slave-output and +currently disabled and an external monitor at 1920x1080+0+0. +Now lets say that we want to drive the external monitor at its native +resolution of 2560x1440 and have the internal screen mirror the top left +part of the external monitor, so we run: + + $ xrandr --output eDP --mode 1920x1080 --pos 0x0 --output HDMI \ + --mode 2560x1440 --pos 0x0 + +Here xrandr utility first calls RRSetScreenSize to 2560x1440, then it +calls RRSetCrtc 1920x1080+0+0 on the eDP, since this is a slave output, +rrCheckPixmapBounding gets called and resizes the screen_pixmap to +1920x1080, undoing the RRSetScreenSize. Then RRSetCrtc 2560x1440+0+0 +gets called on the HDMI, depending on crtc->transforms this will +either result in a BadValue error from ProcRRSetCrtcConfig; or +it will succeed, but the monitor ends up running at 2560x1440 +while showing a 1920x1080 screen_pixmap + black borders on the right +and bottom. Neither of which is what we want. + +This commit removes the troublesome shrinking behavior, fixing this. + +Note: + +1) One could argue that this will leave us with a too large screen_pixmap +in some cases, but rrCheckPixmapBounding only gets called for slave +outputs, so xrandr clients already must manually shrink the screen_pixmap +after disabling crtcs in normal setups. + +2) An alternative approach would be to also call rrCheckPixmapBounding +on RRSetCrtc on normal (non-slave) outputs, but that would result in +2 unnecessary resizes of the screen_pixmap in the above example, which +seems undesirable. + +Cc: Nikhil Mahale +Cc: Dave Airlie +Signed-off-by: Hans de Goede +Reviewed-by: Dave Airlie +--- + randr/rrcrtc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c +index ac853eab6..d1a51f0aa 100644 +--- a/randr/rrcrtc.c ++++ b/randr/rrcrtc.c +@@ -689,6 +689,12 @@ rrCheckPixmapBounding(ScreenPtr pScreen, + new_width = newsize->x2; + new_height = newsize->y2; + ++ if (new_width < screen_pixmap->drawable.width) ++ new_width = screen_pixmap->drawable.width; ++ ++ if (new_height < screen_pixmap->drawable.height) ++ new_height = screen_pixmap->drawable.height; ++ + if (new_width == screen_pixmap->drawable.width && + new_height == screen_pixmap->drawable.height) { + } else { +-- +2.14.1 +