summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2011-09-29 12:38:26 +0100
committerDave Airlie <airlied@redhat.com>2011-09-29 13:32:38 +0100
commit59a4776f7b4e0f9bbbafe62972487354a8fabda0 (patch)
tree09c7abf6f138f7eecd9a4ac3cbc4743ff5aa80d0
parent7307ff4dd1a6cbfa1e4311ec2c6efc26eb81a434 (diff)
port damage tracking code from st/xorg
-rw-r--r--src/driver.c75
-rw-r--r--src/driver.h6
2 files changed, 79 insertions, 2 deletions
diff --git a/src/driver.c b/src/driver.c
index 0aaafd1..bc80e30 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -307,6 +307,58 @@ GetRec(ScrnInfoPtr pScrn)
return TRUE;
}
+static void dispatch_dirty(ScreenPtr pScreen)
+{
+ ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(scrn);
+ 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, ret;
+
+ /* XXX no need for copy? */
+ for (i = 0; i < num_cliprects; i++, rect++) {
+ clip[i].x1 = rect->x1;
+ clip[i].y1 = rect->y1;
+ clip[i].x2 = rect->x2;
+ clip[i].y2 = rect->y2;
+ }
+
+ /* TODO query connector property to see if this is needed */
+ ret = drmModeDirtyFB(ms->fd, ms->fb_id, clip, num_cliprects);
+ if (ret) {
+ if (ret == -EINVAL) {
+ ms->dirty_enabled = FALSE;
+ DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage);
+ DamageDestroy(ms->damage);
+ ms->damage = NULL;
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "Disabling kernel dirty updates, not required.\n");
+ return;
+ } else
+ ErrorF("%s: failed to send dirty (%i, %s)\n",
+ __func__, ret, strerror(-ret));
+ }
+
+ DamageEmpty(ms->damage);
+ }
+}
+
+static void msBlockHandler(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 = msBlockHandler;
+ if (ms->dirty_enabled)
+ dispatch_dirty(pScreen);
+}
+
static void
FreeRec(ScrnInfoPtr pScrn)
{
@@ -494,6 +546,18 @@ CreateScreenResources(ScreenPtr pScreen)
if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels))
FatalError("Couldn't adjust screen pixmap\n");
+ ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
+ pScreen, rootPixmap);
+
+ if (ms->damage) {
+ DamageRegister(&rootPixmap->drawable, ms->damage);
+ ms->dirty_enabled = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to create screen damage record\n");
+ return FALSE;
+ }
return ret;
}
@@ -596,6 +660,9 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
ms->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = CloseScreen;
+ ms->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = msBlockHandler;
+
if (!xf86CrtcScreenInit(pScreen))
return FALSE;
@@ -669,6 +736,12 @@ CloseScreen(int scrnIndex, ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
modesettingPtr ms = modesettingPTR(pScrn);
+ if (ms->damage) {
+ DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage);
+ DamageDestroy(ms->damage);
+ ms->damage = NULL;
+ }
+
drmmode_uevent_fini(pScrn, &ms->drmmode);
drmmode_free_bos(pScrn, &ms->drmmode);
@@ -678,7 +751,7 @@ CloseScreen(int scrnIndex, ScreenPtr pScreen)
}
pScreen->CreateScreenResources = ms->createScreenResources;
-
+ pScreen->BlockHandler = ms->BlockHandler;
drmClose(ms->fd);
ms->fd = -1;
diff --git a/src/driver.h b/src/driver.h
index 255dede..beb5f8d 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -30,6 +30,7 @@
#include <errno.h>
#include <drm.h>
#include <xf86drm.h>
+#include <damage.h>
#include "drmmode_display.h"
#define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
@@ -68,10 +69,13 @@ typedef struct _modesettingRec
unsigned int SaveGeneration;
CreateScreenResourcesProcPtr createScreenResources;
-
+ ScreenBlockHandlerProcPtr BlockHandler;
void *driver;
drmmode_rec drmmode;
+
+ DamagePtr damage;
+ Bool dirty_enabled;
} modesettingRec, *modesettingPtr;
#define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))