diff options
Diffstat (limited to 'src/nv_driver.c')
-rw-r--r-- | src/nv_driver.c | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/src/nv_driver.c b/src/nv_driver.c index f14c847..5645f59 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -447,15 +447,78 @@ NVFlushCallback(CallbackListPtr *list, pointer user_data, pointer call_data) } #ifdef NOUVEAU_PIXMAP_SHARING +/* + * this function can possibly be improved and optimised, by clipping + * instead of iterating + */ +Bool nvPixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region) +{ + ScreenPtr pScreen = dirty->src->drawable.pScreen; + int n; + BoxPtr b; + RegionPtr region = DamageRegion(dirty->damage); + GCPtr pGC; + PixmapPtr dst; + SourceValidateProcPtr SourceValidate; + + /* + * SourceValidate is used by the software cursor code + * to pull the cursor off of the screen when reading + * bits from the frame buffer. Bypassing this function + * leaves the software cursor in place + */ + SourceValidate = pScreen->SourceValidate; + pScreen->SourceValidate = NULL; + + RegionTranslate(dirty_region, dirty->x, dirty->y); + RegionIntersect(dirty_region, dirty_region, region); + + if (RegionNil(dirty_region)) { + RegionUninit(dirty_region); + return FALSE; + } + + dst = dirty->slave_dst->master_pixmap; + if (dirty->slave_dst->drawable.pScreen == pScreen) + dst = dirty->slave_dst; + + RegionTranslate(dirty_region, -dirty->x, -dirty->y); + n = RegionNumRects(dirty_region); + b = RegionRects(dirty_region); + + pGC = GetScratchGC(dirty->src->drawable.depth, pScreen); + ValidateGC(&dst->drawable, pGC); + + while (n--) { + BoxRec dst_box; + int w, h; + + dst_box = *b; + w = dst_box.x2 - dst_box.x1; + h = dst_box.y2 - dst_box.y1; + + pGC->ops->CopyArea(&dirty->src->drawable, &dst->drawable, pGC, + dirty->x + dst_box.x1, dirty->y + dst_box.y1, w, h, dst_box.x1, dst_box.y1); + b++; + } + FreeScratchGC(pGC); + + pScreen->SourceValidate = SourceValidate; + return TRUE; +} + static void redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty) { RegionRec pixregion; - PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap); + if (dirty->slave_dst->drawable.pScreen == screen) + PixmapRegionInit(&pixregion, dirty->src); + else + PixmapRegionInit(&pixregion, dirty->slave_dst); DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion); - PixmapSyncDirtyHelper(dirty, &pixregion); + nvPixmapSyncDirtyHelper(dirty, &pixregion); DamageRegionProcessPending(&dirty->slave_dst->drawable); RegionUninit(&pixregion); @@ -676,7 +739,7 @@ nouveau_setup_capabilities(ScrnInfoPtr pScrn) if (value & DRM_PRIME_CAP_EXPORT) pScrn->capabilities |= RR_Capability_SourceOutput; if (value & DRM_PRIME_CAP_IMPORT) - pScrn->capabilities |= RR_Capability_SourceOffload; + pScrn->capabilities |= RR_Capability_SourceOffload | RR_Capability_SinkOutput; } #endif } |