From 1f37991dec98073d5dfbf0c30213f838999bd9da Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 29 Sep 2011 15:55:36 +0100 Subject: [PATCH] add shadowfb support, default to on. we should probably expose a bit from kernel to say if shadow is preferred or wasteful. --- hw/xfree86/drivers/modesetting/driver.c | 62 +++++++++++++++++++++++++ hw/xfree86/drivers/modesetting/driver.h | 2 + 2 files changed, 64 insertions(+) diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c index 119287840..bde690c7a 100644 --- a/hw/xfree86/drivers/modesetting/driver.c +++ b/hw/xfree86/drivers/modesetting/driver.c @@ -49,6 +49,7 @@ #include "xf86Crtc.h" #include "miscstruct.h" #include "dixstruct.h" +#include "shadow.h" #include "xf86xv.h" #include #include @@ -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); @@ -550,6 +585,15 @@ CreateScreenResources(ScreenPtr pScreen) return ret; } +static Bool +msShadowInit(ScreenPtr pScreen) +{ + if (!shadowSetup(pScreen)) { + return FALSE; + } + return TRUE; +} + static Bool ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { @@ -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/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h index beb5f8daf..494ca0ccf 100644 --- a/hw/xfree86/drivers/modesetting/driver.h +++ b/hw/xfree86/drivers/modesetting/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))