Bug 1494062 - Part 2. Ensure blob image dirty rects are not clipped too small by containers. r=jrmuizel

If an item in a blob image gets a new parent container which clips it to
a smaller area than it was previously, we need to ensure the dirty rect
does not take into account the new clip when determining the old
intersection area. Instead now all old rects for an image are clipped to
the image bounds, rather than the image bounds clipped to the aggregate
of the ancestor containers.

Differential Revision: https://phabricator.services.mozilla.com/D16855
This commit is contained in:
Andrew Osmond 2019-01-17 07:56:12 -05:00
Родитель dbc1b3ebee
Коммит 42e20bac8f
1 изменённых файлов: 28 добавлений и 20 удалений

Просмотреть файл

@ -324,6 +324,9 @@ struct DIGroup {
// The current bounds of the blob image, relative to
// the top-left of the mLayerBounds.
IntRect mImageBounds;
// mImageBounds clipped to the container/parent of the
// current item being processed.
IntRect mClippedImageBounds;
Maybe<wr::BlobImageKey> mKey;
std::vector<RefPtr<SourceSurface>> mExternalSurfaces;
std::vector<RefPtr<ScaledFont>> mFonts;
@ -391,8 +394,9 @@ struct DIGroup {
LayoutDeviceIntPoint offset = RoundedToInt(bounds.TopLeft());
GP("\n");
GP("CGC offset %d %d\n", offset.x, offset.y);
GP("imageRect %d %d %d %d\n", mImageBounds.x, mImageBounds.y,
mImageBounds.width, mImageBounds.height);
GP("clippedImageRect %d %d %d %d\n", mClippedImageBounds.x,
mClippedImageBounds.y, mClippedImageBounds.width,
mClippedImageBounds.height);
/*if (aItem->IsReused() && aData->mGeometry) {
return;
}*/
@ -412,7 +416,7 @@ struct DIGroup {
IntRect transformedRect = ToDeviceSpace(
clippedBounds, aMatrix, appUnitsPerDevPixel, mLayerBounds.TopLeft());
aData->mRect = transformedRect.Intersect(mImageBounds);
aData->mRect = transformedRect.Intersect(mClippedImageBounds);
GP("CGC %s %d %d %d %d\n", aItem->Name(), clippedBounds.x,
clippedBounds.y, clippedBounds.width, clippedBounds.height);
GP("%d %d, %f %f\n", mLayerBounds.TopLeft().x, mLayerBounds.TopLeft().y,
@ -442,7 +446,7 @@ struct DIGroup {
// no transform
IntRect transformedRect = ToDeviceSpace(
clippedBounds, aMatrix, appUnitsPerDevPixel, mLayerBounds.TopLeft());
aData->mRect = transformedRect.Intersect(mImageBounds);
aData->mRect = transformedRect.Intersect(mClippedImageBounds);
InvalidateRect(aData->mRect);
GP("new rect: %d %d %d %d\n", aData->mRect.x, aData->mRect.y,
aData->mRect.width, aData->mRect.height);
@ -471,7 +475,7 @@ struct DIGroup {
IntRect transformedRect =
ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel,
mLayerBounds.TopLeft());
aData->mRect = transformedRect.Intersect(mImageBounds);
aData->mRect = transformedRect.Intersect(mClippedImageBounds);
InvalidateRect(aData->mRect);
// CGC invariant broken
@ -503,7 +507,7 @@ struct DIGroup {
ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel,
mLayerBounds.TopLeft());
InvalidateRect(aData->mRect.Intersect(mImageBounds));
aData->mRect = transformedRect.Intersect(mImageBounds);
aData->mRect = transformedRect.Intersect(mClippedImageBounds);
InvalidateRect(aData->mRect);
GP("ClipChange: %s %d %d %d %d\n", aItem->Name(), aData->mRect.x,
@ -533,7 +537,7 @@ struct DIGroup {
ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel,
mLayerBounds.TopLeft());
InvalidateRect(aData->mRect.Intersect(mImageBounds));
aData->mRect = transformedRect.Intersect(mImageBounds);
aData->mRect = transformedRect.Intersect(mClippedImageBounds);
InvalidateRect(aData->mRect);
GP("TransformChange: %s %d %d %d %d\n", aItem->Name(), aData->mRect.x,
@ -552,11 +556,11 @@ struct DIGroup {
ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel,
mLayerBounds.TopLeft());
InvalidateRect(aData->mRect.Intersect(mImageBounds));
aData->mRect = transformedRect.Intersect(mImageBounds);
aData->mRect = transformedRect.Intersect(mClippedImageBounds);
InvalidateRect(aData->mRect);
GP("UpdateContainerLayerPropertiesAndDetectChange change\n");
} else if (!aData->mImageRect.IsEqualEdges(mImageBounds)) {
// Make sure we update mRect for mImageBounds changes
} else if (!aData->mImageRect.IsEqualEdges(mClippedImageBounds)) {
// Make sure we update mRect for mClippedImageBounds changes
nsRect clippedBounds = clip.ApplyNonRoundedIntersection(
geometry->ComputeInvalidationRegion());
IntRect transformedRect =
@ -565,7 +569,7 @@ struct DIGroup {
// The invalid rect should contain the old rect and the new rect
// but may not because the parent may have been removed.
InvalidateRect(aData->mRect);
aData->mRect = transformedRect.Intersect(mImageBounds);
aData->mRect = transformedRect.Intersect(mClippedImageBounds);
InvalidateRect(aData->mRect);
GP("ContainerLayer image rect bounds change\n");
} else {
@ -575,14 +579,14 @@ struct DIGroup {
IntRect transformedRect =
ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel,
mLayerBounds.TopLeft());
auto rect = transformedRect.Intersect(mImageBounds);
auto rect = transformedRect.Intersect(mClippedImageBounds);
GP("Layer NoChange: %s %d %d %d %d\n", aItem->Name(),
aData->mRect.x, aData->mRect.y, aData->mRect.XMost(),
aData->mRect.YMost());
MOZ_RELEASE_ASSERT(rect.IsEqualEdges(aData->mRect));
}
} else if (!aData->mImageRect.IsEqualEdges(mImageBounds)) {
// Make sure we update mRect for mImageBounds changes
} else if (!aData->mImageRect.IsEqualEdges(mClippedImageBounds)) {
// Make sure we update mRect for mClippedImageBounds changes
UniquePtr<nsDisplayItemGeometry> geometry(
aItem->AllocateGeometry(aBuilder));
nsRect clippedBounds = clip.ApplyNonRoundedIntersection(
@ -593,7 +597,7 @@ struct DIGroup {
// The invalid rect should contain the old rect and the new rect
// but may not because the parent may have been removed.
InvalidateRect(aData->mRect);
aData->mRect = transformedRect.Intersect(mImageBounds);
aData->mRect = transformedRect.Intersect(mClippedImageBounds);
InvalidateRect(aData->mRect);
GP("image rect bounds change\n");
} else {
@ -605,7 +609,7 @@ struct DIGroup {
IntRect transformedRect =
ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel,
mLayerBounds.TopLeft());
auto rect = transformedRect.Intersect(mImageBounds);
auto rect = transformedRect.Intersect(mClippedImageBounds);
GP("NoChange: %s %d %d %d %d\n", aItem->Name(), aData->mRect.x,
aData->mRect.y, aData->mRect.XMost(), aData->mRect.YMost());
MOZ_RELEASE_ASSERT(rect.IsEqualEdges(aData->mRect));
@ -615,7 +619,7 @@ struct DIGroup {
aData->mClip = clip;
aData->mMatrix = aMatrix;
aData->mGroupOffset = mLayerBounds.TopLeft();
aData->mImageRect = mImageBounds;
aData->mImageRect = mClippedImageBounds;
GP("post mInvalidRect: %d %d %d %d\n", mInvalidRect.x, mInvalidRect.y,
mInvalidRect.width, mInvalidRect.height);
}
@ -1162,6 +1166,8 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
currentGroup->mAppUnitsPerDevPixel;
groupData->mFollowingGroup.mLayerBounds = currentGroup->mLayerBounds;
groupData->mFollowingGroup.mImageBounds = currentGroup->mImageBounds;
groupData->mFollowingGroup.mClippedImageBounds =
currentGroup->mClippedImageBounds;
groupData->mFollowingGroup.mScale = currentGroup->mScale;
groupData->mFollowingGroup.mResidualOffset =
currentGroup->mResidualOffset;
@ -1219,8 +1225,9 @@ void Grouper::ConstructItemInsideInactive(
// Temporarily restrict the image bounds to the bounds of the container so
// that clipped children within the container know about the clip.
IntRect oldImageBounds = aGroup->mImageBounds;
aGroup->mImageBounds = aGroup->mImageBounds.Intersect(data->mRect);
IntRect oldClippedImageBounds = aGroup->mClippedImageBounds;
aGroup->mClippedImageBounds =
aGroup->mClippedImageBounds.Intersect(data->mRect);
if (aItem->GetType() == DisplayItemType::TYPE_FILTER) {
gfx::Size scale(1, 1);
@ -1265,7 +1272,7 @@ void Grouper::ConstructItemInsideInactive(
}
GP("Including %s of %d\n", aItem->Name(), aGroup->mDisplayItems.Count());
aGroup->mImageBounds = oldImageBounds;
aGroup->mClippedImageBounds = oldClippedImageBounds;
}
/* This is just a copy of nsRect::ScaleToOutsidePixels with an offset added in.
@ -1373,6 +1380,7 @@ void WebRenderCommandBuilder::DoGroupingForDisplayList(
group.mAppUnitsPerDevPixel, residualOffset));
group.mImageBounds =
IntRect(0, 0, group.mLayerBounds.width, group.mLayerBounds.height);
group.mClippedImageBounds = group.mImageBounds;
group.mPaintRect =
LayerIntRect::FromUnknownRect(
ScaleToOutsidePixelsOffset(aWrappingItem->GetPaintRect(), scale.width,