From 0dab94f9df990c5b9298a4f85fd8f60302045d70427b888e896c756144fa5058 Mon Sep 17 00:00:00 2001 From: Stefan Dirsch Date: Fri, 11 Jun 2021 14:28:41 +0000 Subject: [PATCH] Accepting request 899464 from home:patrikjakobsson:branches:X11:XOrg Modesetting: Fix dirty updates for sw rotation OBS-URL: https://build.opensuse.org/request/show/899464 OBS-URL: https://build.opensuse.org/package/show/X11:XOrg/xorg-x11-server?expand=0&rev=793 --- ...ng-Fix-dirty-updates-for-sw-rotation.patch | 167 ++++++++++++++++++ xorg-x11-server.changes | 7 + xorg-x11-server.spec | 7 +- 3 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 u_modesetting-Fix-dirty-updates-for-sw-rotation.patch diff --git a/u_modesetting-Fix-dirty-updates-for-sw-rotation.patch b/u_modesetting-Fix-dirty-updates-for-sw-rotation.patch new file mode 100644 index 0000000..735cac7 --- /dev/null +++ b/u_modesetting-Fix-dirty-updates-for-sw-rotation.patch @@ -0,0 +1,167 @@ +From 7d2802f13eecb38babeeb54ceae978a409b5c5d4 Mon Sep 17 00:00:00 2001 +From: Patrik Jakobsson +Date: Wed, 9 Jun 2021 20:58:59 +0200 +Subject: [PATCH] modesetting: Fix dirty updates for sw rotation +Patch-Mainline: To be upstreamed +References: bsc#1182955 + +Rotation is broken for all drm drivers not providing hardware rotation +support. Drivers that give direct access to vram and not needing dirty +updates still work but only by accident. The problem is caused by +modesetting not sending the correct fb_id to drmModeDirtyFB() and +passing the damage rects in the rotated state and not as the crtc +expects them. This patch takes care of both problems. + +Signed-off-by: Patrik Jakobsson +--- + hw/xfree86/drivers/modesetting/driver.c | 81 ++++++++++++++----- + .../drivers/modesetting/drmmode_display.c | 2 +- + .../drivers/modesetting/drmmode_display.h | 2 + + 3 files changed, 63 insertions(+), 22 deletions(-) + +diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c +index ef4a314..deca1ed 100644 +--- a/hw/xfree86/drivers/modesetting/driver.c ++++ b/hw/xfree86/drivers/modesetting/driver.c +@@ -503,9 +503,41 @@ GetRec(ScrnInfoPtr pScrn) + return TRUE; + } + ++static void ++rotate_clip(PixmapPtr pixmap, BoxPtr rect, drmModeClip *clip, Rotation rotation) ++{ ++ int w = pixmap->drawable.width; ++ int h = pixmap->drawable.height; ++ ++ if (rotation == RR_Rotate_90) { ++ /* Rotate 90 degrees counter clockwise */ ++ clip->x1 = rect->y1; ++ clip->x2 = rect->y2; ++ clip->y1 = w - rect->x2; ++ clip->y2 = w - rect->x1; ++ } else if (rotation == RR_Rotate_180) { ++ /* Rotate 180 degrees */ ++ clip->x1 = w - rect->x2; ++ clip->x2 = w - rect->x1; ++ clip->y1 = h - rect->y2; ++ clip->y2 = h - rect->y1; ++ } else if (rotation == RR_Rotate_270) { ++ /* Rotate 90 degrees clockwise */ ++ clip->x1 = h - rect->y2; ++ clip->x2 = h - rect->y1; ++ clip->y1 = rect->x1; ++ clip->y2 = rect->x2; ++ } else { ++ clip->x1 = rect->x1; ++ clip->x2 = rect->x2; ++ clip->y1 = rect->y1; ++ clip->y2 = rect->y2; ++ } ++} ++ + static int +-dispatch_dirty_region(ScrnInfoPtr scrn, +- PixmapPtr pixmap, DamagePtr damage, int fb_id) ++dispatch_dirty_region(ScrnInfoPtr scrn, xf86CrtcPtr crtc, ++ PixmapPtr pixmap, DamagePtr damage, int fb_id) + { + modesettingPtr ms = modesettingPTR(scrn); + RegionPtr dirty = DamageRegion(damage); +@@ -520,13 +552,9 @@ dispatch_dirty_region(ScrnInfoPtr scrn, + if (!clip) + return -ENOMEM; + +- /* XXX no need for copy? */ +- for (i = 0; i < num_cliprects; i++, rect++) { +- clip[i].x1 = rect->x1; +- clip[i].y1 = rect->y1; +- clip[i].x2 = rect->x2; +- clip[i].y2 = rect->y2; +- } ++ /* Rotate and copy rects into clips */ ++ for (i = 0; i < num_cliprects; i++, rect++) ++ rotate_clip(pixmap, rect, &clip[i], crtc->rotation); + + /* TODO query connector property to see if this is needed */ + ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects); +@@ -549,20 +577,31 @@ static void + dispatch_dirty(ScreenPtr pScreen) + { + ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); ++ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + modesettingPtr ms = modesettingPTR(scrn); + PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen); +- int fb_id = ms->drmmode.fb_id; +- int ret; ++ uint32_t fb_id; ++ int ret, c, x, y ; + +- ret = dispatch_dirty_region(scrn, pixmap, ms->damage, fb_id); +- if (ret == -EINVAL || ret == -ENOSYS) { +- ms->dirty_enabled = FALSE; +- DamageUnregister(ms->damage); +- DamageDestroy(ms->damage); +- ms->damage = NULL; +- xf86DrvMsg(scrn->scrnIndex, X_INFO, +- "Disabling kernel dirty updates, not required.\n"); +- return; ++ for (c = 0; c < xf86_config->num_crtc; c++) { ++ xf86CrtcPtr crtc = xf86_config->crtc[c]; ++ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; ++ ++ if (!drmmode_crtc) ++ continue; ++ ++ drmmode_crtc_get_fb_id(crtc, &fb_id, &x, &y); ++ ++ ret = dispatch_dirty_region(scrn, crtc, pixmap, ms->damage, fb_id); ++ if (ret == -EINVAL || ret == -ENOSYS) { ++ ms->dirty_enabled = FALSE; ++ DamageUnregister(ms->damage); ++ DamageDestroy(ms->damage); ++ ms->damage = NULL; ++ xf86DrvMsg(scrn->scrnIndex, X_INFO, ++ "Disabling kernel dirty updates, not required.\n"); ++ return; ++ } + } + } + +@@ -574,7 +613,7 @@ dispatch_dirty_pixmap(ScrnInfoPtr scrn, xf86CrtcPtr crtc, PixmapPtr ppix) + DamagePtr damage = ppriv->slave_damage; + int fb_id = ppriv->fb_id; + +- dispatch_dirty_region(scrn, ppix, damage, fb_id); ++ dispatch_dirty_region(scrn, crtc, ppix, damage, fb_id); + } + + static void +diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c +index 88992f5..b29db12 100644 +--- a/hw/xfree86/drivers/modesetting/drmmode_display.c ++++ b/hw/xfree86/drivers/modesetting/drmmode_display.c +@@ -598,7 +598,7 @@ drmmode_crtc_can_test_mode(xf86CrtcPtr crtc) + return ms->atomic_modeset; + } + +-static Bool ++Bool + drmmode_crtc_get_fb_id(xf86CrtcPtr crtc, uint32_t *fb_id, int *x, int *y) + { + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; +diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h +index 59d79e9..0ed96ab 100644 +--- a/hw/xfree86/drivers/modesetting/drmmode_display.h ++++ b/hw/xfree86/drivers/modesetting/drmmode_display.h +@@ -297,6 +297,8 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode); + + int drmmode_crtc_flip(xf86CrtcPtr crtc, uint32_t fb_id, uint32_t flags, void *data); + ++Bool drmmode_crtc_get_fb_id(xf86CrtcPtr crtc, uint32_t *fb_id, int *x, int *y); ++ + void drmmode_set_dpms(ScrnInfoPtr scrn, int PowerManagementMode, int flags); + + #endif +-- +2.31.1 + diff --git a/xorg-x11-server.changes b/xorg-x11-server.changes index 28694ee..a35cee6 100644 --- a/xorg-x11-server.changes +++ b/xorg-x11-server.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Fri Jun 11 11:03:18 UTC 2021 - Patrik Jakobsson + +- u_modesetting-Fix-dirty-updates-for-sw-rotation.patch + * Fixes broken rotation support for DRM drivers without hardware + rotation support or direct vram access (bsc#1182955) + ------------------------------------------------------------------- Mon Apr 19 11:29:31 UTC 2021 - Stefan Dirsch diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec index 5c88f56..6040578 100644 --- a/xorg-x11-server.spec +++ b/xorg-x11-server.spec @@ -156,8 +156,8 @@ Requires: libpixman-1-0 >= 0.24 %endif Requires: Mesa %if 0%{?suse_version} >= 1315 -Requires(post): update-alternatives -Requires(postun): update-alternatives +Requires(post): update-alternatives +Requires(postun):update-alternatives %endif Provides: xorg-x11-server-glx Obsoletes: xorg-x11-server-glx @@ -253,6 +253,8 @@ Patch1801: U_Fix-segfault-on-probing-a-non-PCI-platform-device-on.patch Patch1900: u_no-lto-for-tests.patch +Patch1910: u_modesetting-Fix-dirty-updates-for-sw-rotation.patch + %description This package contains the X.Org Server. @@ -405,6 +407,7 @@ sh %{SOURCE92} --verify . %{SOURCE91} %patch1600 -p1 %patch1801 -p1 %patch1900 -p1 +%patch1910 -p1 %build %global _lto_cflags %{?_lto_cflags} -ffat-lto-objects