summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2011-10-10 13:36:06 +0100
committerDave Airlie <airlied@redhat.com>2011-10-10 13:36:06 +0100
commit15d5d6f3543aa9d02835ec0306d0e6af262a5901 (patch)
tree5392b3174a91f6091d9deb641f136256608c4e55
parentd019ff571fa4ae27ac523dd44fce169cde696401 (diff)
add blockhandler for drv port
-rw-r--r--src/driver.c58
-rw-r--r--src/driver.h2
2 files changed, 60 insertions, 0 deletions
diff --git a/src/driver.c b/src/driver.c
index 32917e1..c77de31 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -352,6 +352,45 @@ DrvGetRec(DrvScrnInfoPtr pDrvScrn)
}
+static void drv_dispatch_dirty(DrvScrnInfoPtr scrn)
+{
+ modesettingPtr ms = modesettingPTR(scrn);
+ DrvScreenPtr drvscreen = scrn->pDrvScreen;
+ RegionPtr dirty = DrvDamageRegion(ms->drv_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->drmmodedrv.fb_id, clip, num_cliprects);
+ if (ret) {
+ if (ret == -EINVAL) {
+ ms->dirty_enabled = FALSE;
+ DrvDamageUnregister(drvscreen->screenPixmap, ms->drv_damage);
+ DrvDamageDestroy(ms->drv_damage);
+ ms->drv_damage = NULL;
+ xf86DrvV2Msg(scrn->drvScrnIndex, X_INFO, "Disabling kernel dirty updates, not required.\n");
+ return;
+ } else
+ ErrorF("%s: failed to send dirty (%i, %s)\n",
+ __func__, ret, strerror(-ret));
+ }
+
+ DrvDamageEmpty(ms->drv_damage);
+ }
+}
+
static void dispatch_dirty(ScreenPtr pScreen)
{
ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
@@ -404,6 +443,22 @@ static void msBlockHandler(int i, pointer blockData, pointer pTimeout,
dispatch_dirty(pScreen);
}
+static void msdrvBlockHandler(DrvScreenPtr pDrvScreen, pointer blockData, pointer pTimeout,
+ pointer pReadmask)
+{
+ DrvScrnInfoPtr pDrvScrn = dixLookupPrivate(&pDrvScreen->devPrivates, xf86DrvScreenKey);
+ modesettingPtr ms = modesettingPTR(pDrvScrn);
+
+ if (ms->DrvBlockHandler) {
+ pDrvScreen->BlockHandler = ms->DrvBlockHandler;
+ pDrvScreen->BlockHandler(pDrvScreen, blockData, pTimeout, pReadmask);
+ pDrvScreen->BlockHandler = msdrvBlockHandler;
+ }
+ if (ms->dirty_enabled)
+ drv_dispatch_dirty(pDrvScrn);
+}
+
+
static void
FreeRec(ScrnInfoPtr pScrn)
{
@@ -880,6 +935,9 @@ DrvScreenInit(DrvScrnInfoPtr drvscrn)
if (!xf86DrvCrtcScreenInit(pDrvScreen))
return FALSE;
+ ms->drvBlockHandler = pDrvScreen->BlockHandler;
+ pDrvScreen->BlockHandler = msdrvBlockHandler;
+
ms->drvcreateScreenResources = pDrvScreen->CreateScreenResources;
pDrvScreen->CreateScreenResources = drvCreateScreenResources;
diff --git a/src/driver.h b/src/driver.h
index 4a91409..4424932 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -70,6 +70,8 @@ typedef struct _modesettingRec
CreateScreenResourcesProcPtr createScreenResources;
ScreenBlockHandlerProcPtr BlockHandler;
+
+ DrvScreenBlockHandlerProcPtr DrvBlockHandler;
void *driver;
drmmode_rec drmmode;