summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 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))