Blame SOURCES/0001-kms-implement-a-double-buffered-shadow-mode.patch

82b592
From ce813f9c98d9074fe089ce9f74494abfe4dddce8 Mon Sep 17 00:00:00 2001
47f74b
From: Fedora X Ninjas <x@fedoraproject.org>
47f74b
Date: Wed, 19 Aug 2015 13:45:43 -0400
47f74b
Subject: [PATCH] kms: implement a double-buffered shadow mode
47f74b
82b592
v2: Free the rect list.
82b592
47f74b
Signed-off-by: Fedora X Ninjas <x@fedoraproject.org>
47f74b
---
82b592
 hw/xfree86/drivers/modesetting/driver.c          | 128 ++++++++++++++++++++++-
47f74b
 hw/xfree86/drivers/modesetting/drmmode_display.c |   7 ++
47f74b
 hw/xfree86/drivers/modesetting/drmmode_display.h |   2 +
82b592
 3 files changed, 132 insertions(+), 5 deletions(-)
47f74b
47f74b
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
82b592
index 1215cb3..1189df7 100644
47f74b
--- a/hw/xfree86/drivers/modesetting/driver.c
47f74b
+++ b/hw/xfree86/drivers/modesetting/driver.c
47f74b
@@ -124,6 +124,7 @@ typedef enum {
47f74b
     OPTION_DEVICE_PATH,
47f74b
     OPTION_SHADOW_FB,
47f74b
     OPTION_ACCEL_METHOD,
47f74b
+    OPTION_DOUBLE_SHADOW,
47f74b
 } modesettingOpts;
47f74b
 
47f74b
 static const OptionInfoRec Options[] = {
47f74b
@@ -131,6 +132,7 @@ static const OptionInfoRec Options[] = {
47f74b
     {OPTION_DEVICE_PATH, "kmsdev", OPTV_STRING, {0}, FALSE},
47f74b
     {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE},
47f74b
     {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
47f74b
+    {OPTION_DOUBLE_SHADOW, "DoubleShadow", OPTV_BOOLEAN, {0}, FALSE},
47f74b
     {-1, NULL, OPTV_NONE, {0}, FALSE}
47f74b
 };
47f74b
 
47f74b
@@ -615,6 +617,32 @@ try_enable_glamor(ScrnInfoPtr pScrn)
47f74b
 #endif
47f74b
 }
47f74b
 
47f74b
+static Bool
47f74b
+msShouldDoubleShadow(ScrnInfoPtr pScrn, modesettingPtr ms)
47f74b
+{
47f74b
+    Bool ret = FALSE, asked;
47f74b
+    int from;
47f74b
+    drmVersionPtr v = drmGetVersion(ms->fd);
47f74b
+
47f74b
+    if (!strcmp(v->name, "mgag200") ||
47f74b
+	!strcmp(v->name, "ast")) /* XXX || rn50 */
47f74b
+	ret = TRUE;
47f74b
+
47f74b
+    drmFreeVersion(v);
47f74b
+
47f74b
+    asked = xf86GetOptValBool(ms->Options, OPTION_DOUBLE_SHADOW, &ret;;
47f74b
+
47f74b
+    if (asked)
47f74b
+	from = X_CONFIG;
47f74b
+    else
47f74b
+	from = X_INFO;
47f74b
+
47f74b
+    xf86DrvMsg(pScrn->scrnIndex, from,
47f74b
+	       "Double-buffered shadow updates: %s", ret ? "on" : "off");
47f74b
+
47f74b
+    return ret;
47f74b
+}
47f74b
+
47f74b
 #ifndef DRM_CAP_CURSOR_WIDTH
47f74b
 #define DRM_CAP_CURSOR_WIDTH 0x8
47f74b
 #endif
47f74b
@@ -814,6 +842,8 @@ PreInit(ScrnInfoPtr pScrn, int flags)
47f74b
                    prefer_shadow ? "YES" : "NO",
47f74b
 		   ms->drmmode.force_24_32 ? "FORCE" :
47f74b
                    ms->drmmode.shadow_enable ? "YES" : "NO");
47f74b
+
47f74b
+	ms->drmmode.shadow_enable2 = msShouldDoubleShadow(pScrn, ms);
47f74b
     }
47f74b
 
47f74b
     if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
82b592
@@ -872,10 +902,92 @@ msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
47f74b
     return ((uint8_t *) ms->drmmode.front_bo.dumb->ptr + row * stride + offset);
47f74b
 }
47f74b
 
47f74b
+/* somewhat arbitrary tile size, in pixels */
47f74b
+#define TILE 16
47f74b
+
47f74b
+static int
47f74b
+msUpdateIntersect(modesettingPtr ms, shadowBufPtr pBuf, BoxPtr box,
47f74b
+		  xRectangle *prect)
47f74b
+{
47f74b
+    int i, dirty = 0, stride = pBuf->pPixmap->devKind, cpp = ms->drmmode.cpp;
47f74b
+    int width = (box->x2 - box->x1) * cpp;
47f74b
+    unsigned char *old, *new;
47f74b
+
47f74b
+    old = ms->drmmode.shadow_fb2;
47f74b
+    old += (box->y1 * stride) + (box->x1 * cpp);
47f74b
+    new = ms->drmmode.shadow_fb;
47f74b
+    new += (box->y1 * stride) + (box->x1 * cpp);
47f74b
+
47f74b
+    for (i = box->y2 - box->y1 - 1; i >= 0; i--) {
47f74b
+	unsigned char *o = old + i * stride,
47f74b
+		      *n = new + i * stride;
47f74b
+	if (memcmp(o, n, width) != 0) {
47f74b
+	    dirty = 1;
47f74b
+	    memcpy(o, n, width);
47f74b
+	}
47f74b
+    }
47f74b
+
47f74b
+    if (dirty) {
47f74b
+	prect->x = box->x1;
47f74b
+	prect->y = box->y1;
47f74b
+	prect->width = box->x2 - box->x1;
47f74b
+	prect->height = box->y2 - box->y1;
47f74b
+    }
47f74b
+
47f74b
+    return dirty;
47f74b
+}
47f74b
+
47f74b
 static void
47f74b
 msUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
47f74b
 {
47f74b
-    shadowUpdatePacked(pScreen, pBuf);
47f74b
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
47f74b
+    modesettingPtr ms = modesettingPTR(pScrn);
47f74b
+    Bool use_ms_shadow = ms->drmmode.force_24_32 && pScrn->bitsPerPixel == 32;
47f74b
+
47f74b
+    if (ms->drmmode.shadow_enable2 && ms->drmmode.shadow_fb2) do {
47f74b
+	RegionPtr damage = DamageRegion(pBuf->pDamage), tiles;
47f74b
+	BoxPtr extents = RegionExtents(damage);
47f74b
+	xRectangle *prect;
47f74b
+	int nrects;
47f74b
+	int i, j, tx1, tx2, ty1, ty2;
47f74b
+
47f74b
+	tx1 = extents->x1 / TILE;
47f74b
+	tx2 = (extents->x2 + TILE - 1) / TILE;
47f74b
+	ty1 = extents->y1 / TILE;
47f74b
+	ty2 = (extents->y2 + TILE - 1) / TILE;
47f74b
+
47f74b
+	nrects = (tx2 - tx1) * (ty2 - ty1);
47f74b
+	if (!(prect = calloc(nrects, sizeof(xRectangle))))
47f74b
+	    break;
47f74b
+
47f74b
+	nrects = 0;
47f74b
+	for (j = ty2 - 1; j >= ty1; j--) {
47f74b
+	    for (i = tx2 - 1; i >= tx1; i--) {
47f74b
+		BoxRec box;
47f74b
+
47f74b
+		box.x1 = max(i * TILE, extents->x1);
47f74b
+		box.y1 = max(j * TILE, extents->y1);
47f74b
+		box.x2 = min((i+1) * TILE, extents->x2);
47f74b
+		box.y2 = min((j+1) * TILE, extents->y2);
47f74b
+
47f74b
+		if (RegionContainsRect(damage, &box) != rgnOUT) {
47f74b
+		    if (msUpdateIntersect(ms, pBuf, &box, prect + nrects)) {
47f74b
+			nrects++;
47f74b
+		    }
47f74b
+		}
47f74b
+	    }
47f74b
+	}
47f74b
+
47f74b
+	tiles = RegionFromRects(nrects, prect, CT_NONE);
47f74b
+	RegionIntersect(damage, damage, tiles);
47f74b
+	RegionDestroy(tiles);
82b592
+	free(prect);
47f74b
+    } while (0);
47f74b
+
47f74b
+    if (use_ms_shadow)
47f74b
+	ms_shadowUpdate32to24(pScreen, pBuf);
47f74b
+    else
47f74b
+	shadowUpdatePacked(pScreen, pBuf);
47f74b
 }
47f74b
 
47f74b
 static Bool
82b592
@@ -887,7 +999,6 @@ CreateScreenResources(ScreenPtr pScreen)
47f74b
     Bool ret;
47f74b
     void *pixels = NULL;
47f74b
     int err;
47f74b
-    Bool use_ms_shadow = ms->drmmode.force_24_32 && pScrn->bitsPerPixel == 32;
47f74b
 
47f74b
     pScreen->CreateScreenResources = ms->createScreenResources;
47f74b
     ret = pScreen->CreateScreenResources(pScreen);
82b592
@@ -915,13 +1026,18 @@ CreateScreenResources(ScreenPtr pScreen)
47f74b
     if (ms->drmmode.shadow_enable)
47f74b
         pixels = ms->drmmode.shadow_fb;
47f74b
 
47f74b
+    if (ms->drmmode.shadow_enable2) {
47f74b
+	ms->drmmode.shadow_fb2 = calloc(1, pScrn->displayWidth * pScrn->virtualY * ((pScrn->bitsPerPixel + 7) >> 3));
47f74b
+	if (!ms->drmmode.shadow_fb2)
47f74b
+	    ms->drmmode.shadow_enable2 = FALSE;
47f74b
+    }
47f74b
+
47f74b
     if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels))
47f74b
         FatalError("Couldn't adjust screen pixmap\n");
47f74b
 
47f74b
     if (ms->drmmode.shadow_enable) {
47f74b
-        if (!shadowAdd(pScreen, rootPixmap,
47f74b
-		       use_ms_shadow ? ms_shadowUpdate32to24 : msUpdatePacked,
47f74b
-                       msShadowWindow, 0, 0))
47f74b
+        if (!shadowAdd(pScreen, rootPixmap, msUpdatePacked, msShadowWindow,
47f74b
+		       0, 0))
47f74b
             return FALSE;
47f74b
     }
47f74b
 
82b592
@@ -1238,6 +1354,8 @@ CloseScreen(ScreenPtr pScreen)
47f74b
         shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
47f74b
         free(ms->drmmode.shadow_fb);
47f74b
         ms->drmmode.shadow_fb = NULL;
47f74b
+	free(ms->drmmode.shadow_fb2);
47f74b
+	ms->drmmode.shadow_fb2 = NULL;
47f74b
     }
47f74b
     drmmode_uevent_fini(pScrn, &ms->drmmode);
47f74b
 
47f74b
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
82b592
index 349bddb..7dd85c8 100644
47f74b
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
47f74b
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
82b592
@@ -1393,6 +1393,13 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
47f74b
         drmmode->shadow_fb = new_pixels;
47f74b
     }
47f74b
 
47f74b
+    if (drmmode->shadow_enable2) {
47f74b
+        uint32_t size = scrn->displayWidth * scrn->virtualY * cpp;
47f74b
+        void *fb2 = calloc(1, size);
47f74b
+	free(drmmode->shadow_fb2);
47f74b
+	drmmode->shadow_fb2 = fb2;
47f74b
+    }
47f74b
+
47f74b
     screen->ModifyPixmapHeader(ppix, width, height, -1, -1,
47f74b
 			       scrn->displayWidth * cpp, new_pixels);
47f74b
 
47f74b
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
47f74b
index 927efec..3a7d222 100644
47f74b
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
47f74b
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
47f74b
@@ -65,8 +65,10 @@ typedef struct {
47f74b
 
47f74b
     Bool glamor;
47f74b
     Bool shadow_enable;
47f74b
+    Bool shadow_enable2;
47f74b
     Bool force_24_32;
47f74b
     void *shadow_fb;
47f74b
+    void *shadow_fb2;
47f74b
 
47f74b
     /**
47f74b
      * A screen-sized pixmap when we're doing triple-buffered DRI2
47f74b
-- 
82b592
2.7.0
47f74b