diff options
| author | Dave Airlie <airlied@redhat.com> | 2011-10-10 13:36:06 +0100 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2011-10-10 13:36:06 +0100 |
| commit | 15d5d6f3543aa9d02835ec0306d0e6af262a5901 (patch) | |
| tree | 5392b3174a91f6091d9deb641f136256608c4e55 | |
| parent | d019ff571fa4ae27ac523dd44fce169cde696401 (diff) | |
add blockhandler for drv port
| -rw-r--r-- | src/driver.c | 58 | ||||
| -rw-r--r-- | src/driver.h | 2 |
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; |
