summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2011-09-29 15:55:36 +0100
committerDave Airlie <airlied@redhat.com>2011-09-29 15:56:15 +0100
commitbb848a788f8dae6f54eb2c03eb2046066732e6e8 (patch)
tree670153639d44045adedc809d6f86e353709bd83c
parentf699c4dc6fd2a34555045950d75ba287723a1e06 (diff)
add shadowfb support, default to on.
we should probably expose a bit from kernel to say if shadow is preferred or wasteful.
-rw-r--r--src/driver.c62
-rw-r--r--src/driver.h2
2 files changed, 64 insertions, 0 deletions
diff --git a/src/driver.c b/src/driver.c
index 1192878..bde690c 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -49,6 +49,7 @@
#include "xf86Crtc.h"
#include "miscstruct.h"
#include "dixstruct.h"
+#include "shadow.h"
#include "xf86xv.h"
#include <X11/extensions/Xv.h>
#include <xorg-server.h>
@@ -110,11 +111,13 @@ typedef enum
{
OPTION_SW_CURSOR,
OPTION_DEVICE_PATH,
+ OPTION_SHADOW_FB,
} modesettingOpts;
static const OptionInfoRec Options[] = {
{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_DEVICE_PATH, "kmsdev", OPTV_STRING, {0}, FALSE },
+ {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
@@ -472,6 +475,8 @@ PreInit(ScrnInfoPtr pScrn, int flags)
ms->SWCursor = TRUE;
}
+ ms->shadow_enable = xf86ReturnOptValBool(ms->Options, OPTION_SHADOW_FB, TRUE);
+
ms->drmmode.fd = ms->fd;
if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "KMS setup failed\n");
@@ -504,11 +509,31 @@ PreInit(ScrnInfoPtr pScrn, int flags)
return FALSE;
}
+ if (ms->shadow_enable) {
+ if (!xf86LoadSubModule(pScrn, "shadow")) {
+ return FALSE;
+ }
+ }
+
return TRUE;
fail:
return FALSE;
}
+static void *
+msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
+ CARD32 *size, void *closure)
+{
+ ScrnInfoPtr pScrn = xf86Screens[screen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ int stride;
+
+ stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
+ *size = stride;
+
+ return ((uint8_t *)ms->drmmode.front_bo->ptr + row * stride + offset);
+}
+
static Bool
CreateScreenResources(ScreenPtr pScreen)
{
@@ -532,9 +557,19 @@ CreateScreenResources(ScreenPtr pScreen)
return FALSE;
rootPixmap = pScreen->GetScreenPixmap(pScreen);
+
+ if (ms->shadow_enable)
+ pixels = ms->shadow_fb;
+
if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels))
FatalError("Couldn't adjust screen pixmap\n");
+ if (ms->shadow_enable) {
+ if (!shadowAdd(pScreen, rootPixmap, shadowUpdatePackedWeak(),
+ msShadowWindow, 0, 0))
+ return FALSE;
+ }
+
ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
pScreen, rootPixmap);
@@ -551,6 +586,15 @@ CreateScreenResources(ScreenPtr pScreen)
}
static Bool
+msShadowInit(ScreenPtr pScreen)
+{
+ if (!shadowSetup(pScreen)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool
ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
@@ -571,6 +615,13 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
if (!drmmode_create_initial_bos(pScrn, &ms->drmmode))
return FALSE;
+ if (ms->shadow_enable) {
+ ms->shadow_fb = calloc(1, pScrn->displayWidth * pScrn->virtualY *
+ ((pScrn->bitsPerPixel + 7) >> 3));
+ if (!ms->shadow_fb)
+ ms->shadow_enable = FALSE;
+ }
+
miClearVisualTypes();
if (!miSetVisualTypes(pScrn->depth,
@@ -607,6 +658,12 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
fbPictureInit(pScreen, NULL, 0);
+ if (ms->shadow_enable && !msShadowInit(pScreen)) {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "shadow fb init failed\n");
+ return FALSE;
+ }
+
ms->createScreenResources = pScreen->CreateScreenResources;
pScreen->CreateScreenResources = CreateScreenResources;
@@ -715,6 +772,11 @@ CloseScreen(int scrnIndex, ScreenPtr pScreen)
ms->damage = NULL;
}
+ if (ms->shadow_enable) {
+ shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
+ free(ms->shadow_fb);
+ ms->shadow_fb = NULL;
+ }
drmmode_uevent_fini(pScrn, &ms->drmmode);
drmmode_free_bos(pScrn, &ms->drmmode);
diff --git a/src/driver.h b/src/driver.h
index beb5f8d..494ca0c 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -76,6 +76,8 @@ typedef struct _modesettingRec
DamagePtr damage;
Bool dirty_enabled;
+ Bool shadow_enable;
+ void *shadow_fb;
} modesettingRec, *modesettingPtr;
#define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))