aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix/pixmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/dix/pixmap.c')
-rw-r--r--xorg-server/dix/pixmap.c135
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;
+}