summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dix/dispatch.c1
-rw-r--r--dix/pixmap.c106
-rw-r--r--include/pixmap.h16
-rw-r--r--include/pixmapstr.h8
-rw-r--r--include/scrnintstr.h2
5 files changed, 133 insertions, 0 deletions
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 29ac5a45a..bc803d78f 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3742,6 +3742,7 @@ static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
pScreen->CreateScreenResources = 0;
+ xorg_list_init(&pScreen->pixmap_dirty_list);
xorg_list_init(&pScreen->unattached_list);
xorg_list_init(&pScreen->output_slave_list);
diff --git a/dix/pixmap.c b/dix/pixmap.c
index 11b1b049e..9163e99eb 100644
--- a/dix/pixmap.c
+++ b/dix/pixmap.c
@@ -158,3 +158,109 @@ PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave)
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;
+}
diff --git a/include/pixmap.h b/include/pixmap.h
index 8c523bdd9..921a94d1e 100644
--- a/include/pixmap.h
+++ b/include/pixmap.h
@@ -49,6 +49,7 @@ SOFTWARE.
#include "misc.h"
#include "screenint.h"
+#include "regionstr.h"
/* types for Drawable */
#define DRAWABLE_WINDOW 0
@@ -73,6 +74,8 @@ SOFTWARE.
typedef struct _Drawable *DrawablePtr;
typedef struct _Pixmap *PixmapPtr;
+typedef struct _PixmapDirtyUpdate *PixmapDirtyUpdatePtr;
+
typedef union _PixUnion {
PixmapPtr pixmap;
unsigned long pixel;
@@ -112,4 +115,17 @@ extern _X_EXPORT void FreePixmap(PixmapPtr /*pPixmap */ );
extern _X_EXPORT PixmapPtr
PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave);
+extern _X_EXPORT Bool
+PixmapStartDirtyTracking(PixmapPtr src,
+ PixmapPtr slave_dst,
+ int x, int y);
+
+extern _X_EXPORT Bool
+PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst);
+
+/* helper function, drivers can do this themselves if they can do it more
+ efficently */
+extern _X_EXPORT Bool
+PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region);
+
#endif /* PIXMAP_H */
diff --git a/include/pixmapstr.h b/include/pixmapstr.h
index 40af5c4a3..2a1ef9b85 100644
--- a/include/pixmapstr.h
+++ b/include/pixmapstr.h
@@ -50,6 +50,7 @@ SOFTWARE.
#include "screenint.h"
#include "regionstr.h"
#include "privates.h"
+#include "damage.h"
typedef struct _Drawable {
unsigned char type; /* DRAWABLE_<type> */
@@ -84,6 +85,13 @@ typedef struct _Pixmap {
PixmapPtr master_pixmap; /* pointer to master copy of pixmap for pixmap sharing */
} PixmapRec;
+typedef struct _PixmapDirtyUpdate {
+ PixmapPtr src, slave_dst;
+ int x, y;
+ DamagePtr damage;
+ struct xorg_list ent;
+} PixmapDirtyUpdateRec;
+
static inline void
PixmapBox(BoxPtr box, PixmapPtr pixmap)
{
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 3a738d3b0..5ef37ed9a 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -505,6 +505,8 @@ typedef struct _Screen {
StartPixmapTrackingProcPtr StartPixmapTracking;
StopPixmapTrackingProcPtr StopPixmapTracking;
+
+ struct xorg_list pixmap_dirty_list;
} ScreenRec;
static inline RegionPtr