diff options
-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)) |