--- a/layout/painting/RetainedDisplayListBuilder.cpp
+++ b/layout/painting/RetainedDisplayListBuilder.cpp
@@ -665,53 +665,36 @@ GetFirstDisplayItemWithChildren(nsIFrame
for (nsDisplayItem* i : *items) {
if (i->GetChildren()) {
return i;
}
}
return nullptr;
}
-static nsIFrame*
-HandlePreserve3D(nsIFrame* aFrame, nsRect& aOverflow)
+static bool
+IsInPreserve3DContext(const nsIFrame* aFrame)
{
- // Preserve-3d frames don't have valid overflow areas, and they might
- // have singular transforms (despite still being visible when combined
- // with their ancestors). If we're at one, jump up to the root of the
- // preserve-3d context and use the whole overflow area.
- nsIFrame* last = aFrame;
- while (aFrame->Extend3DContext() ||
- aFrame->Combines3DTransformWithAncestors()) {
- last = aFrame;
- aFrame = aFrame->GetParent();
- }
- if (last != aFrame) {
- aOverflow = last->GetVisualOverflowRectRelativeToParent();
- CRR_LOG("HandlePreserve3D() Updated overflow rect to: %d %d %d %d\n",
- aOverflow.x, aOverflow.y, aOverflow.width, aOverflow.height);
- }
-
- return aFrame;
+ return aFrame->Extend3DContext() ||
+ aFrame->Combines3DTransformWithAncestors();
}
-static void
+static bool
ProcessFrameInternal(nsIFrame* aFrame, nsDisplayListBuilder& aBuilder,
AnimatedGeometryRoot** aAGR, nsRect& aOverflow,
nsIFrame* aStopAtFrame, nsTArray<nsIFrame*>& aOutFramesWithProps,
const bool aStopAtStackingContext)
{
nsIFrame* currentFrame = aFrame;
while (currentFrame != aStopAtFrame) {
CRR_LOG("currentFrame: %p (placeholder=%d), aOverflow: %d %d %d %d\n",
currentFrame, !aStopAtStackingContext,
aOverflow.x, aOverflow.y, aOverflow.width, aOverflow.height);
- currentFrame = HandlePreserve3D(currentFrame, aOverflow);
-
// If the current frame is an OOF frame, DisplayListBuildingData needs to be
// set on all the ancestor stacking contexts of the placeholder frame, up
// to the containing block of the OOF frame. This is done to ensure that the
// content that might be behind the OOF frame is built for merging.
nsIFrame* placeholder = currentFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)
? currentFrame->GetPlaceholderFrame()
: nullptr;
@@ -734,26 +717,33 @@ ProcessFrameInternal(nsIFrame* aFrame, n
// Find a common ancestor frame to handle frame continuations.
// TODO: It might be possible to write a more specific and efficient
// function for this.
nsIFrame* ancestor =
nsLayoutUtils::FindNearestCommonAncestorFrame(currentFrame->GetParent(),
placeholder->GetParent());
- ProcessFrameInternal(placeholder, aBuilder, &dummyAGR, placeholderOverflow,
- ancestor, aOutFramesWithProps, false);
+ if (!ProcessFrameInternal(placeholder, aBuilder, &dummyAGR,
+ placeholderOverflow, ancestor,
+ aOutFramesWithProps, false)) {
+ return false;
+ }
}
// Convert 'aOverflow' into the coordinate space of the nearest stacking context
// or display port ancestor and update 'currentFrame' to point to that frame.
aOverflow = nsLayoutUtils::TransformFrameRectToAncestor(currentFrame, aOverflow, aStopAtFrame,
nullptr, nullptr,
/* aStopAtStackingContextAndDisplayPortAndOOFFrame = */ true,
¤tFrame);
+ if (IsInPreserve3DContext(currentFrame)) {
+ return false;
+ }
+
MOZ_ASSERT(currentFrame);
if (nsLayoutUtils::FrameHasDisplayPort(currentFrame)) {
CRR_LOG("Frame belongs to displayport frame %p\n", currentFrame);
nsIScrollableFrame* sf = do_QueryFrame(currentFrame);
MOZ_ASSERT(sf);
nsRect displayPort;
DebugOnly<bool> hasDisplayPort =
@@ -851,16 +841,17 @@ ProcessFrameInternal(nsIFrame* aFrame, n
// Don't contribute to the root dirty area at all.
aOverflow.SetEmpty();
*aAGR = nullptr;
break;
}
}
+ return true;
}
bool
RetainedDisplayListBuilder::ProcessFrame(nsIFrame* aFrame, nsDisplayListBuilder& aBuilder,
nsIFrame* aStopAtFrame, nsTArray<nsIFrame*>& aOutFramesWithProps,
const bool aStopAtStackingContext,
nsRect* aOutDirty,
AnimatedGeometryRoot** aOutModifiedAGR)
@@ -891,18 +882,20 @@ RetainedDisplayListBuilder::ProcessFrame
// If the modified frame is also a caret frame, include the caret area.
// This is needed because some frames (for example text frames without text)
// might have an empty overflow rect.
if (aFrame == aBuilder.GetCaretFrame()) {
overflow.UnionRect(overflow, aBuilder.GetCaretRect());
}
- ProcessFrameInternal(aFrame, aBuilder, &agr, overflow, aStopAtFrame,
- aOutFramesWithProps, aStopAtStackingContext);
+ if (!ProcessFrameInternal(aFrame, aBuilder, &agr, overflow, aStopAtFrame,
+ aOutFramesWithProps, aStopAtStackingContext)) {
+ return false;
+ }
if (!overflow.IsEmpty()) {
aOutDirty->UnionRect(*aOutDirty, overflow);
CRR_LOG("Adding area to root draw area: %d %d %d %d\n",
overflow.x, overflow.y, overflow.width, overflow.height);
// If we get changed frames from multiple AGRS, then just give up as it gets really complex to
// track which items would need to be marked in MarkFramesForDifferentAGR.