diff --git a/exa/exa_migration.c b/exa/exa_migration.c index 3c79f68..9c22178 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -152,42 +152,45 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, REGION_NULL(pScreen, &CopyReg); REGION_SUBTRACT(pScreen, &CopyReg, pValidSrc, pValidDst); - if (migrate->as_dst) { - ExaScreenPriv (pPixmap->drawable.pScreen); - - /* XXX: The pending damage region will be marked as damaged after the - * operation, so it should serve as an upper bound for the region that - * needs to be synchronized for the operation. Unfortunately, this - * causes corruption in some cases, e.g. when starting compiz. See - * https://bugs.freedesktop.org/show_bug.cgi?id=12916 . - */ - if (pExaScr->optimize_migration) { - RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); - - if (REGION_NIL(pending_damage)) { - static Bool firsttime = TRUE; - - if (firsttime) { - ErrorF("%s: Pending damage region empty!\n", __func__); - firsttime = FALSE; + /* Try to prevent destination valid region from growing too many rects */ + if (REGION_NUM_RECTS(pValidDst) < 10) { + if (migrate->as_dst) { + ExaScreenPriv (pPixmap->drawable.pScreen); + + /* XXX: The pending damage region will be marked as damaged after the + * operation, so it should serve as an upper bound for the region that + * needs to be synchronized for the operation. Unfortunately, this + * causes corruption in some cases, e.g. when starting compiz. See + * https://bugs.freedesktop.org/show_bug.cgi?id=12916 . + */ + if (pExaScr->optimize_migration) { + RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); + + if (REGION_NIL(pending_damage)) { + static Bool firsttime = TRUE; + + if (firsttime) { + ErrorF("%s: Pending damage region empty!\n", __func__); + firsttime = FALSE; + } } + + REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, pending_damage); } - REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, pending_damage); + /* The caller may provide a region to be subtracted from the calculated + * dirty region. This is to avoid migration of bits that don't + * contribute to the result of the operation. + */ + if (migrate->pReg) + REGION_SUBTRACT(pScreen, &CopyReg, &CopyReg, migrate->pReg); + } else { + /* The caller may restrict the region to be migrated for source pixmaps + * to what's relevant for the operation. + */ + if (migrate->pReg) + REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, migrate->pReg); } - - /* The caller may provide a region to be subtracted from the calculated - * dirty region. This is to avoid migration of bits that don't - * contribute to the result of the operation. - */ - if (migrate->pReg) - REGION_SUBTRACT(pScreen, &CopyReg, &CopyReg, migrate->pReg); - } else { - /* The caller may restrict the region to be migrated for source pixmaps - * to what's relevant for the operation. - */ - if (migrate->pReg) - REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, migrate->pReg); } pBox = REGION_RECTS(&CopyReg); @@ -239,6 +242,10 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, /* The copied bits are now valid in destination */ REGION_UNION(pScreen, pValidDst, pValidDst, &CopyReg); + /* Try to prevent source valid region from growing too many rects */ + if (REGION_NUM_RECTS(pValidSrc) > 10) + REGION_SUBTRACT(pScreen, pValidSrc, pValidSrc, pValidDst); + REGION_UNINIT(pScreen, &CopyReg); }