summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <daenzer@vmware.com>2009-02-15 17:44:51 +0100
committerMichel Dänzer <daenzer@vmware.com>2009-02-15 17:44:51 +0100
commit736b6fbd2c941b6276066cd1503523edebe7bf3d (patch)
tree4ad45635f063aa364b55497d8fd7e6b2c6ad365f
parent45e14f515337159e600a47ebf349692751552af8 (diff)
EXA: Try to prevent the valid regions from growing too many rects.
This helps contain region management overhead in some pathological cases, see e.g. http://bugs.freedesktop.org/show_bug.cgi?id=16647 . Signed-off-by: Michel Dänzer <daenzer@vmware.com>
-rw-r--r--exa/exa_migration.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/exa/exa_migration.c b/exa/exa_migration.c
index 8fb6d2f8d..861ff2363 100644
--- a/exa/exa_migration.c
+++ b/exa/exa_migration.c
@@ -173,7 +173,27 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
}
#endif
- REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, pending_damage);
+ /* Try to prevent destination valid region from growing too many
+ * rects by filling it up to the extents of the union of the
+ * destination valid region and the pending damage region.
+ */
+ if (REGION_NUM_RECTS(pValidDst) > 10) {
+ BoxRec box;
+ BoxPtr pValidExt, pDamageExt;
+ RegionRec closure;
+
+ pValidExt = REGION_EXTENTS(pScreen, pValidDst);
+ pDamageExt = REGION_EXTENTS(pScreen, pending_damage);
+
+ box.x1 = min(pValidExt->x1, pDamageExt->x1);
+ box.y1 = min(pValidExt->y1, pDamageExt->y1);
+ box.x2 = max(pValidExt->x2, pDamageExt->x2);
+ box.y2 = max(pValidExt->y2, pDamageExt->y2);
+
+ REGION_INIT(pScreen, &closure, &box, 0);
+ REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, &closure);
+ } else
+ REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, pending_damage);
}
/* The caller may provide a region to be subtracted from the calculated
@@ -237,6 +257,13 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
pExaPixmap->offscreen = save_offscreen;
pPixmap->devKind = save_pitch;
+ /* Try to prevent source valid region from growing too many rects by
+ * removing parts of it which are also in the destination valid region.
+ * Removing anything beyond that would lead to data loss.
+ */
+ if (REGION_NUM_RECTS(pValidSrc) > 10)
+ REGION_SUBTRACT(pScreen, pValidSrc, pValidSrc, pValidDst);
+
/* The copied bits are now valid in destination */
REGION_UNION(pScreen, pValidDst, pValidDst, &CopyReg);