diff options
Diffstat (limited to 'xorg-server/dix/pixmap.c')
-rw-r--r-- | xorg-server/dix/pixmap.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/xorg-server/dix/pixmap.c b/xorg-server/dix/pixmap.c index 0c85c3fb1..9163e99eb 100644 --- a/xorg-server/dix/pixmap.c +++ b/xorg-server/dix/pixmap.c @@ -129,3 +129,138 @@ FreePixmap(PixmapPtr pPixmap) dixFiniPrivates(pPixmap, PRIVATE_PIXMAP); free(pPixmap); } + +PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave) +{ + PixmapPtr spix; + int ret; + void *handle; + ScreenPtr master = pixmap->drawable.pScreen; + int depth = pixmap->drawable.depth; + + ret = master->SharePixmapBacking(pixmap, slave, &handle); + if (ret == FALSE) + return NULL; + + spix = slave->CreatePixmap(slave, 0, 0, depth, + CREATE_PIXMAP_USAGE_SHARED); + slave->ModifyPixmapHeader(spix, pixmap->drawable.width, + pixmap->drawable.height, depth, 0, + pixmap->devKind, NULL); + + spix->master_pixmap = pixmap; + + ret = slave->SetSharedPixmapBacking(spix, handle); + if (ret == FALSE) { + slave->DestroyPixmap(spix); + return NULL; + } + + return spix; +} + +Bool +PixmapStartDirtyTracking(PixmapPtr src, + PixmapPtr slave_dst, + int x, int y) +{ + ScreenPtr screen = src->drawable.pScreen; + PixmapDirtyUpdatePtr dirty_update; + + dirty_update = calloc(1, sizeof(PixmapDirtyUpdateRec)); + if (!dirty_update) + return FALSE; + + dirty_update->src = src; + dirty_update->slave_dst = slave_dst; + dirty_update->x = x; + dirty_update->y = y; + + dirty_update->damage = DamageCreate(NULL, NULL, + DamageReportNone, + TRUE, src->drawable.pScreen, + src->drawable.pScreen); + if (!dirty_update->damage) { + free(dirty_update); + return FALSE; + } + + DamageRegister(&src->drawable, dirty_update->damage); + xorg_list_add(&dirty_update->ent, &screen->pixmap_dirty_list); + return TRUE; +} + +Bool +PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst) +{ + ScreenPtr screen = src->drawable.pScreen; + PixmapDirtyUpdatePtr ent, safe; + + xorg_list_for_each_entry_safe(ent, safe, &screen->pixmap_dirty_list, ent) { + if (ent->src == src && ent->slave_dst == slave_dst) { + DamageUnregister(&src->drawable, ent->damage); + DamageDestroy(ent->damage); + xorg_list_del(&ent->ent); + free(ent); + } + } + return TRUE; +} + +/* + * this function can possibly be improved and optimised, by clipping + * instead of iterating + */ +Bool PixmapSyncDirtyHelper(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; + + 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; +} |