diff options
author | Michel Dänzer <[email protected]> | 2009-08-26 13:18:37 +0200 |
---|---|---|
committer | Michel Dänzer <[email protected]> | 2009-08-26 13:18:37 +0200 |
commit | b2e1b258812167ce8d33f5978f877439e280a1e4 (patch) | |
tree | 03a7ea0b11fd9bc65072ca637690673bbc518495 | |
parent | dadf138ddbaecd7fff239df7961aac25e74f14f6 (diff) |
st/xorg: Add support for dirty framebuffer region reporting.
Add a BlockHandler which flushes the context and reports the dirty region
gathered using the X server damage layer.
In the interim, with dirty region reporting only allocate textures for the
framebuffer and shared pixmaps (e.g. DRI2 buffers) and fall back to software
for other pixmaps. This will be improved in the future.
-rw-r--r-- | src/gallium/state_trackers/xorg/xorg_driver.c | 65 | ||||
-rw-r--r-- | src/gallium/state_trackers/xorg/xorg_exa.c | 14 | ||||
-rw-r--r-- | src/gallium/state_trackers/xorg/xorg_tracker.h | 8 |
3 files changed, 86 insertions, 1 deletions
diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c index 53d1a330951..923662b24a9 100644 --- a/src/gallium/state_trackers/xorg/xorg_driver.c +++ b/src/gallium/state_trackers/xorg/xorg_driver.c @@ -54,6 +54,7 @@ #include <pciaccess.h> +#include "pipe/p_context.h" #include "xorg_tracker.h" #include "xorg_winsys.h" @@ -424,6 +425,44 @@ RestoreHWState(ScrnInfoPtr pScrn) return TRUE; } +static void xorgBlockHandler(int i, pointer blockData, pointer pTimeout, + pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]); + + pScreen->BlockHandler = ms->blockHandler; + pScreen->BlockHandler(i, blockData, pTimeout, pReadmask); + pScreen->BlockHandler = xorgBlockHandler; + + ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, NULL); + +#ifdef DRM_MODE_FEATURE_DIRTYFB + { + RegionPtr dirty = DamageRegion(ms->damage); + unsigned num_cliprects = REGION_NUM_RECTS(dirty); + + if (num_cliprects) { + drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip)); + BoxPtr rect = REGION_RECTS(dirty); + int i; + + for (i = 0; i < num_cliprects; i++, rect++) { + clip[i].x = rect->x1; + clip[i].y = rect->y1; + clip[i].width = rect->x2 - rect->x1; + clip[i].height = rect->y2 - rect->y1; + } + + /* TODO query connector property to see if this is needed */ + drmModeDirtyFB(ms->fd, ms->fb_id, clip, num_cliprects); + + DamageEmpty(ms->damage); + } + } +#endif +} + static Bool CreateScreenResources(ScreenPtr pScreen) { @@ -460,6 +499,21 @@ CreateScreenResources(ScreenPtr pScreen) AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); +#ifdef DRM_MODE_FEATURE_DIRTYFB + ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, + pScreen, rootPixmap); + + if (ms->damage) { + DamageRegister(&rootPixmap->drawable, ms->damage); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to create screen damage record\n"); + return FALSE; + } +#endif + return ret; } @@ -536,6 +590,8 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) fbPictureInit(pScreen, NULL, 0); + ms->blockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = xorgBlockHandler; ms->createScreenResources = pScreen->CreateScreenResources; pScreen->CreateScreenResources = CreateScreenResources; @@ -699,8 +755,17 @@ CloseScreen(int scrnIndex, ScreenPtr pScreen) driCloseScreen(pScreen); #endif + pScreen->BlockHandler = ms->blockHandler; pScreen->CreateScreenResources = ms->createScreenResources; +#ifdef DRM_MODE_FEATURE_DIRTYFB + if (ms->damage) { + DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage); + DamageDestroy(ms->damage); + ms->damage = NULL; + } +#endif + if (ms->exa) xorg_exa_close(pScrn); diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index 9f3f82c6c89..3c90c2c9429 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -472,7 +472,11 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, pipe_texture_reference(&priv->tex, NULL); } - if (!priv->tex) { + if (!priv->tex +#ifdef DRM_MODE_FEATURE_DIRTYFB + && priv->flags +#endif + ) { struct pipe_texture template; memset(&template, 0, sizeof(template)); @@ -488,6 +492,14 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, priv->tex = exa->scrn->texture_create(exa->scrn, &template); } +#ifdef DRM_MODE_FEATURE_DIRTYFB + if (!priv->tex) { + if (pPixData) + pPixmap->devPrivate.ptr = pPixData; + else + pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height * pPixmap->devKind); + } else +#endif if (pPixData) { struct pipe_transfer *transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h index 910782dbc44..da850bbf649 100644 --- a/src/gallium/state_trackers/xorg/xorg_tracker.h +++ b/src/gallium/state_trackers/xorg/xorg_tracker.h @@ -41,6 +41,10 @@ #include <xf86.h> #include <exa.h> +#ifdef DRM_MODE_FEATURE_DIRTYFB +#include <damage.h> +#endif + #include "pipe/p_screen.h" #include "state_tracker/drm_api.h" @@ -76,6 +80,7 @@ typedef struct _modesettingRec unsigned int SaveGeneration; + void (*blockHandler)(int, pointer, pointer, pointer); CreateScreenResourcesProcPtr createScreenResources; /* gallium */ @@ -87,6 +92,9 @@ typedef struct _modesettingRec void *exa; Bool noEvict; +#ifdef DRM_MODE_FEATURE_DIRTYFB + DamagePtr damage; +#endif } modesettingRec, *modesettingPtr; #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate)) |