|
|
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 |
|