summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <daenzer@vmware.com>2009-08-26 13:18:37 +0200
committerMichel Dänzer <daenzer@vmware.com>2009-08-26 13:18:37 +0200
commitb2e1b258812167ce8d33f5978f877439e280a1e4 (patch)
tree03a7ea0b11fd9bc65072ca637690673bbc518495
parentdadf138ddbaecd7fff239df7961aac25e74f14f6 (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.c65
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.c14
-rw-r--r--src/gallium/state_trackers/xorg/xorg_tracker.h8
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 53d1a33095..923662b24a 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 9f3f82c6c8..3c90c2c942 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 910782dbc4..da850bbf64 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))