diff options
Diffstat (limited to 'layout/generic')
50 files changed, 320 insertions, 258 deletions
diff --git a/layout/generic/nsBackdropFrame.cpp b/layout/generic/nsBackdropFrame.cpp index 687c5b2e3..ae847f460 100644 --- a/layout/generic/nsBackdropFrame.cpp +++ b/layout/generic/nsBackdropFrame.cpp @@ -39,7 +39,6 @@ nsBackdropFrame::GetParentStyleContext(nsIFrame** aProviderFrame) const /* virtual */ void nsBackdropFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { DO_GLOBAL_REFLOW_COUNT_DSP("nsBackdropFrame"); diff --git a/layout/generic/nsBackdropFrame.h b/layout/generic/nsBackdropFrame.h index 74d366bef..f3159da31 100644 --- a/layout/generic/nsBackdropFrame.h +++ b/layout/generic/nsBackdropFrame.h @@ -27,7 +27,6 @@ public: virtual nsStyleContext* GetParentStyleContext(nsIFrame** aProviderFrame) const override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual mozilla::LogicalSize ComputeAutoSize(nsRenderingContext* aRenderingContext, diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index a37bfc06b..93de79cef 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -6527,13 +6527,14 @@ static void DebugOutputDrawLine(int32_t aDepth, nsLineBox* aLine, bool aDrawn) { static void DisplayLine(nsDisplayListBuilder* aBuilder, const nsRect& aLineArea, - const nsRect& aDirtyRect, nsBlockFrame::LineIterator& aLine, + nsBlockFrame::LineIterator& aLine, int32_t aDepth, int32_t& aDrawnLines, const nsDisplayListSet& aLists, nsBlockFrame* aFrame, TextOverflow* aTextOverflow) { // If the line's combined area (which includes child frames that // stick outside of the line's bounding box or our bounding box) // intersects the dirty rect then paint the line. - bool intersect = aLineArea.Intersects(aDirtyRect); + bool intersect = aLineArea.Intersects(aBuilder->GetDirtyRect()); + bool visible = aLineArea.Intersects(aBuilder->GetVisibleRect()); #ifdef DEBUG if (nsBlockFrame::gLamePaintMetrics) { aDrawnLines++; @@ -6549,14 +6550,14 @@ DisplayLine(nsDisplayListBuilder* aBuilder, const nsRect& aLineArea, // frame in the line, it's also true for aFrame. bool lineInline = aLine->IsInline(); bool lineMayHaveTextOverflow = aTextOverflow && lineInline; - if (!intersect && !aBuilder->ShouldDescendIntoFrame(aFrame) && + if (!intersect && !aBuilder->ShouldDescendIntoFrame(aFrame, visible) && !lineMayHaveTextOverflow) return; // Collect our line's display items in a temporary nsDisplayListCollection, // so that we can apply any "text-overflow" clipping to the entire collection // without affecting previous lines. - nsDisplayListCollection collection; + nsDisplayListCollection collection(aBuilder); // Block-level child backgrounds go on the blockBorderBackgrounds list ... // Inline-level child backgrounds go on the regular child content list. @@ -6568,8 +6569,7 @@ DisplayLine(nsDisplayListBuilder* aBuilder, const nsRect& aLineArea, nsIFrame* kid = aLine->mFirstChild; int32_t n = aLine->GetChildCount(); while (--n >= 0) { - aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, - childLists, flags); + aFrame->BuildDisplayListForChild(aBuilder, kid, childLists, flags); kid = kid->GetNextSibling(); } @@ -6582,13 +6582,13 @@ DisplayLine(nsDisplayListBuilder* aBuilder, const nsRect& aLineArea, void nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { int32_t drawnLines; // Will only be used if set (gLamePaintMetrics). int32_t depth = 0; #ifdef DEBUG if (gNoisyDamageRepair) { + nsRect dirty = aBuilder->GetDirtyRect(); depth = GetDepth(); nsRect ca; ::ComputeVisualOverflowArea(mLines, mRect.width, mRect.height, ca); @@ -6596,7 +6596,7 @@ nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, ListTag(stdout); printf(": bounds=%d,%d,%d,%d dirty(absolute)=%d,%d,%d,%d ca=%d,%d,%d,%d\n", mRect.x, mRect.y, mRect.width, mRect.height, - aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height, + dirty.x, dirty.y, dirty.width, dirty.height, ca.x, ca.y, ca.width, ca.height); } PRTime start = 0; // Initialize these variables to silence the compiler. @@ -6609,21 +6609,21 @@ nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, DisplayBorderBackgroundOutline(aBuilder, aLists); if (GetPrevInFlow()) { - DisplayOverflowContainers(aBuilder, aDirtyRect, aLists); + DisplayOverflowContainers(aBuilder, aLists); for (nsIFrame* f : mFloats) { if (f->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT) - BuildDisplayListForChild(aBuilder, f, aDirtyRect, aLists); + BuildDisplayListForChild(aBuilder, f, aLists); } } - aBuilder->MarkFramesForDisplayList(this, mFloats, aDirtyRect); + aBuilder->MarkFramesForDisplayList(this, mFloats); // Prepare for text-overflow processing. UniquePtr<TextOverflow> textOverflow( TextOverflow::WillProcessLines(aBuilder, this)); // We'll collect our lines' display items here, & then append this to aLists. - nsDisplayListCollection linesDisplayListCollection; + nsDisplayListCollection linesDisplayListCollection(aBuilder); // Don't use the line cursor if we might have a descendant placeholder ... // it might skip lines that contain placeholders but don't themselves @@ -6632,8 +6632,8 @@ nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, // on all our child frames, but that might be expensive. So we // approximate it by checking it on |this|; if it's true for any // frame in our child list, it's also true for |this|. - nsLineBox* cursor = aBuilder->ShouldDescendIntoFrame(this) ? - nullptr : GetFirstLineContaining(aDirtyRect.y); + nsLineBox* cursor = (aBuilder->ShouldDescendIntoFrame(this, true)) ? + nullptr : GetFirstLineContaining(aBuilder->GetDirtyRect().y); LineIterator line_end = LinesEnd(); if (cursor) { @@ -6644,10 +6644,10 @@ nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, if (!lineArea.IsEmpty()) { // Because we have a cursor, the combinedArea.ys are non-decreasing. // Once we've passed aDirtyRect.YMost(), we can never see it again. - if (lineArea.y >= aDirtyRect.YMost()) { + if (lineArea.y >= aBuilder->GetDirtyRect().YMost()) { break; } - DisplayLine(aBuilder, lineArea, aDirtyRect, line, depth, drawnLines, + DisplayLine(aBuilder, lineArea, line, depth, drawnLines, linesDisplayListCollection, this, textOverflow.get()); } } @@ -6660,7 +6660,7 @@ nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, line != line_end; ++line) { nsRect lineArea = line->GetVisualOverflowArea(); - DisplayLine(aBuilder, lineArea, aDirtyRect, line, depth, drawnLines, + DisplayLine(aBuilder, lineArea, line, depth, drawnLines, linesDisplayListCollection, this, textOverflow.get()); if (!lineArea.IsEmpty()) { if (lineArea.y < lastY @@ -6690,7 +6690,7 @@ nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, if (HasOutsideBullet()) { // Display outside bullets manually nsIFrame* bullet = GetOutsideBullet(); - BuildDisplayListForChild(aBuilder, bullet, aDirtyRect, aLists); + BuildDisplayListForChild(aBuilder, bullet, aLists); } #ifdef DEBUG diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index f515cc26f..4775fa626 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -139,7 +139,6 @@ public: virtual nsSplittableType GetSplittableType() const override; virtual bool IsFloatContainingBlock() const override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual nsIAtom* GetType() const override; virtual bool IsFrameOfType(uint32_t aFlags) const override diff --git a/layout/generic/nsBulletFrame.cpp b/layout/generic/nsBulletFrame.cpp index f6595e8f6..db9a70aff 100644 --- a/layout/generic/nsBulletFrame.cpp +++ b/layout/generic/nsBulletFrame.cpp @@ -274,7 +274,6 @@ void nsDisplayBullet::Paint(nsDisplayListBuilder* aBuilder, void nsBulletFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (!IsVisibleForPainting(aBuilder)) diff --git a/layout/generic/nsBulletFrame.h b/layout/generic/nsBulletFrame.h index e35ed0923..30f4e23cd 100644 --- a/layout/generic/nsBulletFrame.h +++ b/layout/generic/nsBulletFrame.h @@ -68,7 +68,6 @@ public: // nsIFrame virtual void DestroyFrom(nsIFrame* aDestructRoot) override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual nsIAtom* GetType() const override; virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override; diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp index 1a8812fb7..31baa040c 100644 --- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -410,11 +410,10 @@ public: void nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (GetPrevInFlow()) { - DisplayOverflowContainers(aBuilder, aDirtyRect, aLists); + DisplayOverflowContainers(aBuilder, aLists); } // Force a background to be shown. We may have a background propagated to us, @@ -488,7 +487,7 @@ nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, for (nsIFrame* kid : PrincipalChildList()) { // Put our child into its own pseudo-stack. - BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists); + BuildDisplayListForChild(aBuilder, kid, aLists); } #ifdef DEBUG_CANVAS_FOCUS @@ -504,7 +503,7 @@ nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, docShell->GetHasFocus(&hasFocus); printf("%p - nsCanvasFrame::Paint R:%d,%d,%d,%d DR: %d,%d,%d,%d\n", this, mRect.x, mRect.y, mRect.width, mRect.height, - aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); + dirty.x, dirty.y, dirty.width, dirty.height); } printf("%p - Focus: %s c: %p DoPaint:%s\n", docShell.get(), hasFocus?"Y":"N", focusContent.get(), mDoPaintFocus?"Y":"N"); diff --git a/layout/generic/nsCanvasFrame.h b/layout/generic/nsCanvasFrame.h index 8bd9dbf79..8c59f18c0 100644 --- a/layout/generic/nsCanvasFrame.h +++ b/layout/generic/nsCanvasFrame.h @@ -107,7 +107,6 @@ public: NS_IMETHOD SetHasFocus(bool aHasFocus); virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; void PaintFocus(mozilla::gfx::DrawTarget* aRenderingContext, nsPoint aPt); diff --git a/layout/generic/nsColumnSetFrame.cpp b/layout/generic/nsColumnSetFrame.cpp index 6ea15d4d2..90d425ccf 100644 --- a/layout/generic/nsColumnSetFrame.cpp +++ b/layout/generic/nsColumnSetFrame.cpp @@ -1115,7 +1115,6 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext, void nsColumnSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { DisplayBorderBackgroundOutline(aBuilder, aLists); @@ -1128,7 +1127,7 @@ nsColumnSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, // Our children won't have backgrounds so it doesn't matter where we put them. for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { - BuildDisplayListForChild(aBuilder, e.get(), aDirtyRect, aLists); + BuildDisplayListForChild(aBuilder, e.get(), aLists); } } diff --git a/layout/generic/nsColumnSetFrame.h b/layout/generic/nsColumnSetFrame.h index db44183d6..4195742c2 100644 --- a/layout/generic/nsColumnSetFrame.h +++ b/layout/generic/nsColumnSetFrame.h @@ -67,7 +67,6 @@ public: } virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual nsIAtom* GetType() const override; diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index abf687c9b..162e64a3c 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -329,17 +329,15 @@ nsContainerFrame::GetChildLists(nsTArray<ChildList>* aLists) const void nsContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { DisplayBorderBackgroundOutline(aBuilder, aLists); - BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists); + BuildDisplayListForNonBlockChildren(aBuilder, aLists); } void nsContainerFrame::BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists, uint32_t aFlags) { @@ -348,7 +346,7 @@ nsContainerFrame::BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aB nsDisplayListSet set(aLists, aLists.Content()); // The children should be in content order while (kid) { - BuildDisplayListForChild(aBuilder, kid, aDirtyRect, set, aFlags); + BuildDisplayListForChild(aBuilder, kid, set, aFlags); kid = kid->GetNextSibling(); } } @@ -1336,13 +1334,12 @@ nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext* aPres void nsContainerFrame::DisplayOverflowContainers(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { nsFrameList* overflowconts = GetPropTableFrames(OverflowContainersProperty()); if (overflowconts) { for (nsIFrame* frame : *overflowconts) { - BuildDisplayListForChild(aBuilder, frame, aDirtyRect, aLists); + BuildDisplayListForChild(aBuilder, frame, aLists); } } } diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h index ddf993d91..e3cc54b0b 100644 --- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -437,7 +437,6 @@ public: * Add overflow containers to the display list */ void DisplayOverflowContainers(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists); /** @@ -450,7 +449,6 @@ public: * to emulate what nsContainerFrame::Paint did. */ virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; static void PlaceFrameView(nsIFrame* aFrame) @@ -576,7 +574,6 @@ protected: * display items) go into the Content() list. */ void BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists, uint32_t aFlags = 0); @@ -585,11 +582,9 @@ protected: * Intended as a convenience for derived classes. */ void BuildDisplayListForInline(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { DisplayBorderBackgroundOutline(aBuilder, aLists); - BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists, - DISPLAY_CHILD_INLINE); + BuildDisplayListForNonBlockChildren(aBuilder, aLists, DISPLAY_CHILD_INLINE); } diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index 980e1e9be..426e3caa7 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -50,10 +50,9 @@ nsFirstLetterFrame::GetType() const void nsFirstLetterFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { - BuildDisplayListForInline(aBuilder, aDirtyRect, aLists); + BuildDisplayListForInline(aBuilder, aLists); } void diff --git a/layout/generic/nsFirstLetterFrame.h b/layout/generic/nsFirstLetterFrame.h index 40e4ef0cf..c8d416a85 100644 --- a/layout/generic/nsFirstLetterFrame.h +++ b/layout/generic/nsFirstLetterFrame.h @@ -20,7 +20,6 @@ public: explicit nsFirstLetterFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {} virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual void Init(nsIContent* aContent, diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 94bce1e7a..69200117b 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -2433,7 +2433,6 @@ GetDisplayFlagsForFlexItem(nsIFrame* aFrame) void nsFlexContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { // XXXdholbert hacky temporary band-aid for bug 1059138: Trivially pass this @@ -2452,7 +2451,7 @@ nsFlexContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, // the BlockBorderBackgrounds list. nsDisplayListSet childLists(aLists, aLists.BlockBorderBackgrounds()); for (nsIFrame* childFrame : mFrames) { - BuildDisplayListForChild(aBuilder, childFrame, aDirtyRect, childLists, + BuildDisplayListForChild(aBuilder, childFrame, childLists, GetDisplayFlagsForFlexItem(childFrame)); } } diff --git a/layout/generic/nsFlexContainerFrame.h b/layout/generic/nsFlexContainerFrame.h index 459ae8e20..ac2cc72f6 100644 --- a/layout/generic/nsFlexContainerFrame.h +++ b/layout/generic/nsFlexContainerFrame.h @@ -64,7 +64,6 @@ public: nsIFrame* aPrevInFlow) override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; void MarkIntrinsicISizesDirty() override; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 8d4ea8754..ab264dd76 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1794,6 +1794,13 @@ void nsFrame::DisplayOutlineUnconditional(nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) { + // Per https://drafts.csswg.org/css-tables-3/#global-style-overrides: + // "All css properties of table-column and table-column-group boxes are + // ignored, except when explicitly specified by this specification." + // CSS outlines fall into this category, so we skip them on these boxes. + + MOZ_ASSERT(GetType() != nsGkAtoms::tableColGroupFrame && GetType() != nsGkAtoms::tableColFrame); + if (StyleOutline()->mOutlineStyle == NS_STYLE_BORDER_STYLE_NONE) { return; } @@ -1814,7 +1821,7 @@ nsFrame::DisplayOutline(nsDisplayListBuilder* aBuilder, void nsIFrame::DisplayCaret(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, nsDisplayList* aList) + nsDisplayList* aList) { if (!IsVisibleForPainting(aBuilder)) return; @@ -1840,7 +1847,9 @@ nsFrame::DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder, if (aBuilder->IsForEventDelivery() || aForceBackground || !StyleBackground()->IsTransparent() || StyleDisplay()->mAppearance) { return nsDisplayBackgroundImage::AppendBackgroundItemsToTop( - aBuilder, this, GetRectRelativeToSelf(), aLists.BorderBackground()); + aBuilder, this, + GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this), + aLists.BorderBackground()); } return false; } @@ -1873,7 +1882,9 @@ nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder, // If there's a themed background, we should not create a border item. // It won't be rendered. - if (!bgIsThemed && StyleBorder()->HasBorder()) { + // Don't paint borders for tables here, since they paint them in a different + // order. + if (!bgIsThemed && StyleBorder()->HasBorder() && GetType() != nsGkAtoms::tableFrame) { aLists.BorderBackground()->AppendNewToTop(new (aBuilder) nsDisplayBorder(aBuilder, this)); } @@ -2073,13 +2084,12 @@ ItemParticipatesIn3DContext(nsIFrame* aAncestor, nsDisplayItem* aItem) static void WrapSeparatorTransform(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - nsRect& aDirtyRect, nsDisplayList* aSource, nsDisplayList* aTarget, int aIndex) { if (!aSource->IsEmpty()) { nsDisplayTransform *sepIdItem = new (aBuilder) nsDisplayTransform(aBuilder, aFrame, aSource, - aDirtyRect, Matrix4x4(), aIndex); + aBuilder->GetDirtyRect(), Matrix4x4(), aIndex); sepIdItem->SetNoExtendContext(); aTarget->AppendToTop(sepIdItem); } @@ -2087,7 +2097,6 @@ WrapSeparatorTransform(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, void nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, nsDisplayList* aList) { if (GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE) return; @@ -2131,13 +2140,14 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, autoPreserves3DContext.emplace(aBuilder); // Save dirty rect on the builder to avoid being distorted for // multiple transforms along the chain. - aBuilder->SetPreserves3DDirtyRect(aDirtyRect); + aBuilder->SavePreserves3DRects(); } // For preserves3d, use the dirty rect already installed on the // builder, since aDirtyRect maybe distorted for transforms along // the chain. - nsRect dirtyRect = aDirtyRect; + nsRect visibleRect = aBuilder->GetVisibleRect(); + nsRect dirtyRect = aBuilder->GetDirtyRect(); bool inTransform = aBuilder->IsInTransform(); bool isTransformed = IsTransformed(); @@ -2148,7 +2158,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, AutoSaveRestoreContainsBlendMode autoRestoreBlendMode(*aBuilder); aBuilder->SetContainsBlendMode(false); - nsRect dirtyRectOutsideTransform = dirtyRect; + nsRect visibleRectOutsideTransform = visibleRect; if (isTransformed) { const nsRect overflow = GetVisualOverflowRectRelativeToSelf(); if (nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, @@ -2162,17 +2172,19 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, // If we're in preserve-3d then grab the dirty rect that was given to the root // and transform using the combined transform. if (Combines3DTransformWithAncestors()) { - dirtyRect = aBuilder->GetPreserves3DDirtyRect(this); + dirtyRect = aBuilder->GetPreserves3DRects(&visibleRect); } nsRect untransformedDirtyRect; if (nsDisplayTransform::UntransformRect(dirtyRect, overflow, this, &untransformedDirtyRect)) { dirtyRect = untransformedDirtyRect; + nsDisplayTransform::UntransformRect(visibleRect, overflow, this, &visibleRect); } else { NS_WARNING("Unable to untransform dirty rect!"); // This should only happen if the transform is singular, in which case nothing is visible anyway dirtyRect.SetEmpty(); + visibleRect.SetEmpty(); } } inTransform = true; @@ -2181,11 +2193,13 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, bool usingMask = nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(this); bool usingSVGEffects = usingFilter || usingMask; - nsRect dirtyRectOutsideSVGEffects = dirtyRect; + nsRect visibleRectOutsideSVGEffects = visibleRect; nsDisplayList hoistedScrollInfoItemsStorage; if (usingSVGEffects) { dirtyRect = nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect); + visibleRect = + nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, visibleRect); aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage); } @@ -2205,7 +2219,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, bool useFixedPosition = nsLayoutUtils::IsFixedPosFrameInDisplayPort(this); nsDisplayListBuilder::AutoBuildingDisplayList - buildingDisplayList(aBuilder, this, dirtyRect, true); + buildingDisplayList(aBuilder, this, visibleRect, dirtyRect, true); // Depending on the effects that are applied to this frame, we can create // multiple container display items and wrap them around our contents. @@ -2270,7 +2284,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, clipState.EnterStackingContextContents(clearClip); - nsDisplayListCollection set; + nsDisplayListCollection set(aBuilder); { DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder); nsDisplayListBuilder::AutoInTransformSetter @@ -2282,7 +2296,8 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, Maybe<nsRect> clipPropClip = GetClipPropClipRect(disp, effects, GetSize()); if (clipPropClip) { - dirtyRect.IntersectRect(dirtyRect, *clipPropClip); + aBuilder->IntersectDirtyRect(*clipPropClip); + aBuilder->IntersectVisibleRect(*clipPropClip); nestedClipState.ClipContentDescendants( *clipPropClip + aBuilder->ToReferenceFrame(this)); } @@ -2295,7 +2310,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, aBuilder->MarkPreserve3DFramesForDisplayList(this); } - MarkAbsoluteFramesForDisplayList(aBuilder, dirtyRect); + MarkAbsoluteFramesForDisplayList(aBuilder); nsDisplayLayerEventRegions* eventRegions = nullptr; if (aBuilder->IsBuildingLayerEventRegions()) { @@ -2304,7 +2319,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, aBuilder->SetLayerEventRegions(eventRegions); } aBuilder->AdjustWindowDraggingRegion(this); - BuildDisplayList(aBuilder, dirtyRect, set); + BuildDisplayList(aBuilder, set); if (eventRegions) { // If the event regions item ended up empty, throw it away rather than // adding it to the display list. @@ -2410,7 +2425,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, clipState.ExitStackingContextContents(&containerItemScrollClip); } // Revert to the post-filter dirty rect. - buildingDisplayList.SetDirtyRect(dirtyRectOutsideSVGEffects); + aBuilder->SetVisibleRect(visibleRectOutsideSVGEffects); // Skip all filter effects while generating glyph mask. if (usingFilter && !aBuilder->IsForGenerateGlyphMask()) { @@ -2443,7 +2458,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, /* If the list is non-empty and there is CSS group opacity without SVG * effects, wrap it up in an opacity item. */ - if (useOpacity && !resultList.IsEmpty()) { + if (useOpacity) { // Don't clip nsDisplayOpacity items. We clip their descendants instead. // The clip we would set on an element with opacity would clip // all descendant content, but some should not be clipped. @@ -2465,7 +2480,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, * We also traverse into sublists created by nsDisplayWrapList, so that we find all the * correct children. */ - if (isTransformed && !resultList.IsEmpty() && extend3DContext) { + if (isTransformed && extend3DContext) { // Install dummy nsDisplayTransform as a leaf containing // descendants not participating this 3D rendering context. nsDisplayList nonparticipants; @@ -2475,8 +2490,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, while (nsDisplayItem* item = resultList.RemoveBottom()) { if (ItemParticipatesIn3DContext(this, item) && !item->GetClip().HasClip()) { // The frame of this item participates the same 3D context. - WrapSeparatorTransform(aBuilder, this, dirtyRect, - &nonparticipants, &participants, index++); + WrapSeparatorTransform(aBuilder, this, &nonparticipants, &participants, index++); participants.AppendToTop(item); } else { // The frame of the item doesn't participate the current @@ -2489,19 +2503,18 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, nonparticipants.AppendToTop(item); } } - WrapSeparatorTransform(aBuilder, this, dirtyRect, - &nonparticipants, &participants, index++); + WrapSeparatorTransform(aBuilder, this, &nonparticipants, &participants, index++); resultList.AppendToTop(&participants); } - if (isTransformed && !resultList.IsEmpty()) { + if (isTransformed) { if (clipCapturedBy == ContainerItemType::eTransform) { // Restore clip state now so nsDisplayTransform is clipped properly. clipState.ExitStackingContextContents(&containerItemScrollClip); } // Revert to the dirtyrect coming in from the parent, without our transform // taken into account. - buildingDisplayList.SetDirtyRect(dirtyRectOutsideTransform); + aBuilder->SetVisibleRect(visibleRectOutsideTransform); // Revert to the outer reference frame and offset because all display // items we create from now on are outside the transform. nsPoint toOuterReferenceFrame; @@ -2514,10 +2527,10 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, GetOffsetToCrossDoc(outerReferenceFrame)); bool isFullyVisible = - dirtyRectOutsideSVGEffects.Contains(GetVisualOverflowRectRelativeToSelf()); + visibleRectOutsideSVGEffects.Contains(GetVisualOverflowRectRelativeToSelf()); nsDisplayTransform *transformItem = new (aBuilder) nsDisplayTransform(aBuilder, this, - &resultList, dirtyRect, 0, + &resultList, visibleRect, 0, isFullyVisible); resultList.AppendNewToTop(transformItem); @@ -2561,7 +2574,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, * not affected by foreground opacity (only background alpha). */ - if (useBlendMode && !resultList.IsEmpty()) { + if (useBlendMode) { DisplayListClipState::AutoSaveRestore mixBlendClipState(aBuilder); mixBlendClipState.Clear(); resultList.AppendNewToTop( @@ -2602,10 +2615,80 @@ WrapInWrapList(nsDisplayListBuilder* aBuilder, return item; } + static bool DescendIntoChild(nsDisplayListBuilder* aBuilder, + const nsIFrame* aChild, const nsRect& aVisible, + const nsRect& aDirty) { + if (aChild->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) { + return true; + } + // No need to descend into child to catch placeholders for visible + // positioned stuff. So see if we can short-circuit frame traversal here. + + // We can stop if child's frame subtree's intersection with the + // dirty area is empty. + // If the child is a scrollframe that we want to ignore, then we need + // to descend into it because its scrolled child may intersect the dirty + // area even if the scrollframe itself doesn't. + // There are cases where the "ignore scroll frame" on the builder is not set + // correctly, and so we additionally want to catch cases where the child is + // a root scrollframe and we are ignoring scrolling on the viewport. + + // If the child is a scrollframe that we want to ignore, then we need + // to descend into it because its scrolled child may intersect the dirty + // area even if the scrollframe itself doesn't. + if (aChild == aBuilder->GetIgnoreScrollFrame()) { + return true; + } + + + // There are cases where the "ignore scroll frame" on the builder is not set + // correctly, and so we additionally want to catch cases where the child is + // a root scrollframe and we are ignoring scrolling on the viewport. + if (aChild == aBuilder->GetPresShellIgnoreScrollFrame()) { + return true; + } + + const nsRect overflow = aChild->GetVisualOverflowRect(); + + if (aDirty.Intersects(overflow)) { + return true; + } + + if (aChild->ForceDescendIntoIfVisible() && aVisible.Intersects(overflow)) { + return true; + } + + if (aChild->IsFrameOfType(nsIFrame::eTablePart)) { + // Relative positioning and transforms can cause table parts to move, but we + // will still paint the backgrounds for their ancestor parts under them at + // their 'normal' position. That means that we must consider the overflow + // rects at both positions. + + // We convert the overflow rect into the nsTableFrame's coordinate + // space, applying the normal position offset at each step. Then we + // compare that against the builder's cached dirty rect in table + // coordinate space. + const nsIFrame* f = aChild; + nsRect normalPositionOverflowRelativeToTable = overflow; + + while (f->IsFrameOfType(nsIFrame::eTablePart)) { + normalPositionOverflowRelativeToTable += f->GetNormalPosition(); + f = f->GetParent(); + } + + nsDisplayTableBackgroundSet* tableBGs = aBuilder->GetTableBackgroundSet(); + if (tableBGs && + tableBGs->GetDirtyRect().Intersects(normalPositionOverflowRelativeToTable)) { + return true; + } + } + + return false; +} + void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, nsIFrame* aChild, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists, uint32_t aFlags) { // If painting is restricted to just the background of the top level frame, @@ -2638,12 +2721,16 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, pseudoStackingContext = true; } - // dirty rect in child-relative coordinates - nsRect dirty = aDirtyRect - child->GetOffsetTo(this); - nsIAtom* childType = child->GetType(); nsDisplayListBuilder::OutOfFlowDisplayData* savedOutOfFlowData = nullptr; bool isPlaceholder = false; + + // dirty rect in child-relative coordinates + NS_ASSERTION(aBuilder->GetCurrentFrame() == this, "Wrong coord space!"); + const nsPoint offset = child->GetOffsetTo(this); + nsRect visible = aBuilder->GetVisibleRect() - offset; + nsRect dirty = aBuilder->GetDirtyRect() - offset; + if (childType == nsGkAtoms::placeholderFrame) { isPlaceholder = true; nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(child); @@ -2673,15 +2760,25 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, return; savedOutOfFlowData = nsDisplayListBuilder::GetOutOfFlowData(child); if (savedOutOfFlowData) { + visible = savedOutOfFlowData->mVisibleRect; dirty = savedOutOfFlowData->mDirtyRect; } else { // The out-of-flow frame did not intersect the dirty area. We may still // need to traverse into it, since it may contain placeholders we need // to enter to reach other out-of-flow frames that are visible. + visible.SetEmpty(); dirty.SetEmpty(); } pseudoStackingContext = true; } + + if (aBuilder->GetIncludeAllOutOfFlows() && + (child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) { + visible = child->GetVisualOverflowRect(); + dirty = child->GetVisualOverflowRect(); + } else if (!DescendIntoChild(aBuilder, child, visible, dirty)) { + return; + } NS_ASSERTION(childType != nsGkAtoms::placeholderFrame, "Should have dealt with placeholders already"); @@ -2691,36 +2788,6 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, return; } - if (aBuilder->GetIncludeAllOutOfFlows() && - (child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) { - dirty = child->GetVisualOverflowRect(); - } else if (!(child->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) { - // No need to descend into child to catch placeholders for visible - // positioned stuff. So see if we can short-circuit frame traversal here. - - // We can stop if child's frame subtree's intersection with the - // dirty area is empty. - // If the child is a scrollframe that we want to ignore, then we need - // to descend into it because its scrolled child may intersect the dirty - // area even if the scrollframe itself doesn't. - // There are cases where the "ignore scroll frame" on the builder is not set - // correctly, and so we additionally want to catch cases where the child is - // a root scrollframe and we are ignoring scrolling on the viewport. - nsIPresShell* shell = PresContext()->PresShell(); - bool keepDescending = child == aBuilder->GetIgnoreScrollFrame() || - (shell->IgnoringViewportScrolling() && child == shell->GetRootScrollFrame()); - if (!keepDescending) { - nsRect childDirty; - if (!childDirty.IntersectRect(dirty, child->GetVisualOverflowRect())) - return; - // Usually we could set dirty to childDirty now but there's no - // benefit, and it can be confusing. It can especially confuse - // situations where we're going to ignore a scrollframe's clipping; - // we wouldn't want to clip the dirty area to the scrollframe's - // bounds in that case. - } - } - // XXX need to have inline-block and inline-table set pseudoStackingContext const nsStyleDisplay* ourDisp = StyleDisplay(); @@ -2771,7 +2838,8 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, "Stacking contexts must also be pseudo-stacking-contexts"); nsDisplayListBuilder::AutoBuildingDisplayList - buildingForChild(aBuilder, child, dirty, pseudoStackingContext); + buildingForChild(aBuilder, child, visible, dirty, pseudoStackingContext); + DisplayListClipState::AutoClipMultiple clipState(aBuilder); CheckForApzAwareEventHandlers(aBuilder, child); @@ -2784,7 +2852,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, savedOutOfFlowData->mContainingBlockScrollClip); } else if (GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO && isPlaceholder) { - NS_ASSERTION(dirty.IsEmpty(), "should have empty dirty rect"); + NS_ASSERTION(visible.IsEmpty(), "should have empty visible rect"); // Every item we build from now until we descent into an out of flow that // does have saved out of flow data should be invisible. This state gets // restored when AutoBuildingDisplayList gets out of scope. @@ -2820,18 +2888,19 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, // True stacking context. // For stacking contexts, BuildDisplayListForStackingContext handles // clipping and MarkAbsoluteFramesForDisplayList. - child->BuildDisplayListForStackingContext(aBuilder, dirty, &list); - aBuilder->DisplayCaret(child, dirty, &list); + child->BuildDisplayListForStackingContext(aBuilder, &list); + aBuilder->DisplayCaret(child, &list); } else { Maybe<nsRect> clipPropClip = child->GetClipPropClipRect(disp, effects, child->GetSize()); if (clipPropClip) { - dirty.IntersectRect(dirty, *clipPropClip); + aBuilder->IntersectVisibleRect(*clipPropClip); + aBuilder->IntersectDirtyRect(*clipPropClip); clipState.ClipContentDescendants( *clipPropClip + aBuilder->ToReferenceFrame(child)); } - child->MarkAbsoluteFramesForDisplayList(aBuilder, dirty); + child->MarkAbsoluteFramesForDisplayList(aBuilder); if (aBuilder->IsBuildingLayerEventRegions()) { // If this frame has a different animated geometry root than its parent, @@ -2863,8 +2932,8 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, // return early. aBuilder->AdjustWindowDraggingRegion(child); - child->BuildDisplayList(aBuilder, dirty, aLists); - aBuilder->DisplayCaret(child, dirty, aLists.Content()); + child->BuildDisplayList(aBuilder, aLists); + aBuilder->DisplayCaret(child, aLists.Content()); #ifdef DEBUG DisplayDebugBorders(aBuilder, child, aLists); #endif @@ -2875,10 +2944,10 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, // We allow positioned descendants of the child to escape to our parent // stacking context's positioned descendant list, because they might be // z-index:non-auto - nsDisplayListCollection pseudoStack; + nsDisplayListCollection pseudoStack(aBuilder); aBuilder->AdjustWindowDraggingRegion(child); - child->BuildDisplayList(aBuilder, dirty, pseudoStack); - aBuilder->DisplayCaret(child, dirty, pseudoStack.Content()); + child->BuildDisplayList(aBuilder, pseudoStack); + aBuilder->DisplayCaret(child, pseudoStack.Content()); list.AppendToTop(pseudoStack.BorderBackground()); list.AppendToTop(pseudoStack.BlockBorderBackgrounds()); @@ -2928,11 +2997,10 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, } void -nsIFrame::MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect) +nsIFrame::MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder) { if (IsAbsoluteContainer()) { - aBuilder->MarkFramesForDisplayList(this, GetAbsoluteContainingBlock()->GetChildList(), aDirtyRect); + aBuilder->MarkFramesForDisplayList(this, GetAbsoluteContainingBlock()->GetChildList()); } } diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index 87cb31fd0..4315b9b8a 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -100,7 +100,6 @@ public: nsIFrame::Cursor& aCursor) override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual void Reflow(nsPresContext* aPresContext, @@ -149,7 +148,6 @@ public: #endif virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual void Reflow(nsPresContext* aPresContext, @@ -672,10 +670,9 @@ nsHTMLFramesetFrame::GetCursor(const nsPoint& aPoint, void nsHTMLFramesetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { - BuildDisplayListForInline(aBuilder, aDirtyRect, aLists); + BuildDisplayListForInline(aBuilder, aLists); if (mDragger && aBuilder->IsForEventDelivery()) { aLists.Content()->AppendNewToTop( @@ -1429,7 +1426,6 @@ void nsDisplayFramesetBorder::Paint(nsDisplayListBuilder* aBuilder, void nsHTMLFramesetBorderFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { aLists.Content()->AppendNewToTop( @@ -1640,7 +1636,6 @@ void nsDisplayFramesetBlank::Paint(nsDisplayListBuilder* aBuilder, void nsHTMLFramesetBlankFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { aLists.Content()->AppendNewToTop( diff --git a/layout/generic/nsFrameSetFrame.h b/layout/generic/nsFrameSetFrame.h index ac6ab07ce..b97d10c58 100644 --- a/layout/generic/nsFrameSetFrame.h +++ b/layout/generic/nsFrameSetFrame.h @@ -97,7 +97,6 @@ public: nsIFrame::Cursor& aCursor) override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual void Reflow(nsPresContext* aPresContext, diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 3ed3b0bb3..fcd365edf 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -3031,7 +3031,6 @@ struct HoveredStateComparator void ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists, bool aCreateLayer, bool aPositioned) @@ -3091,25 +3090,30 @@ ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder, // include all of the scrollbars if we are in a RCD-RSF. We only do // this for the root scrollframe of the root content document, which is // zoomable, and where the scrollbar sizes are bounded by the widget. + nsRect visible = mIsRoot && mOuter->PresContext()->IsRootContentDocument() + ? scrollParts[i]->GetVisualOverflowRectRelativeToParent() + : aBuilder->GetVisibleRect(); nsRect dirty = mIsRoot && mOuter->PresContext()->IsRootContentDocument() ? scrollParts[i]->GetVisualOverflowRectRelativeToParent() - : aDirtyRect; - nsDisplayListBuilder::AutoBuildingDisplayList - buildingForChild(aBuilder, scrollParts[i], - dirty + mOuter->GetOffsetTo(scrollParts[i]), true); + : aBuilder->GetDirtyRect(); // Always create layers for overlay scrollbars so that we don't create a // giant layer covering the whole scrollport if both scrollbars are visible. bool isOverlayScrollbar = (flags != 0) && overlayScrollbars; bool createLayer = aCreateLayer || isOverlayScrollbar; - nsDisplayListBuilder::AutoCurrentScrollbarInfoSetter - infoSetter(aBuilder, scrollTargetId, flags, createLayer); - nsDisplayListCollection partList; - mOuter->BuildDisplayListForChild( - aBuilder, scrollParts[i], dirty, partList, - nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT); - + nsDisplayListCollection partList(aBuilder); + { + nsDisplayListBuilder::AutoBuildingDisplayList + buildingForChild(aBuilder, mOuter, + visible, dirty, true); + + nsDisplayListBuilder::AutoCurrentScrollbarInfoSetter + infoSetter(aBuilder, scrollTargetId, flags, createLayer); + mOuter->BuildDisplayListForChild( + aBuilder, scrollParts[i], partList, + nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT); + } if (createLayer) { appendToTopFlags |= APPEND_OWN_LAYER; } @@ -3117,11 +3121,19 @@ ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder, appendToTopFlags |= APPEND_POSITIONED; } + { + nsDisplayListBuilder::AutoBuildingDisplayList + buildingForChild(aBuilder, scrollParts[i], + visible + mOuter->GetOffsetTo(scrollParts[i]), + dirty + mOuter->GetOffsetTo(scrollParts[i]), true); + nsDisplayListBuilder::AutoCurrentScrollbarInfoSetter + infoSetter(aBuilder, scrollTargetId, flags, createLayer); // DISPLAY_CHILD_FORCE_STACKING_CONTEXT put everything into // partList.PositionedDescendants(). ::AppendToTop(aBuilder, aLists, partList.PositionedDescendants(), scrollParts[i], appendToTopFlags); + } } } @@ -3246,7 +3258,6 @@ ClipListsExceptCaret(nsDisplayListCollection* aLists, void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (aBuilder->IsForFrameVisibility()) { @@ -3283,12 +3294,15 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, // had dirty rects saved for them by their parent frames calling // MarkOutOfFlowChildrenForDisplayList, so it's safe to restrict our // dirty rect here. - nsRect dirtyRect = aDirtyRect; + nsRect visibleRect = aBuilder->GetVisibleRect(); + nsRect dirtyRect = aBuilder->GetDirtyRect(); if (!ignoringThisScrollFrame) { + visibleRect = visibleRect.Intersect(mScrollPort); dirtyRect = dirtyRect.Intersect(mScrollPort); } - Unused << DecideScrollableLayer(aBuilder, &dirtyRect, + bool usingDisplayPortInvalidRect = false; + Unused << DecideScrollableLayer(aBuilder, &visibleRect, &dirtyRect, /* aAllowCreateDisplayPort = */ !mIsRoot); bool usingDisplayPort = aBuilder->IsPaintingToWindow() && @@ -3300,6 +3314,7 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, // too much expansion in the presence of very large (bigger than the // viewport) scroll ports. dirtyRect = ExpandRectToNearlyVisible(dirtyRect); + visibleRect = dirtyRect; } // We put non-overlay scrollbars in their own layers when this is the root @@ -3325,20 +3340,20 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, if (addScrollBars) { // Add classic scrollbars. - AppendScrollPartsTo(aBuilder, aDirtyRect, aLists, - createLayersForScrollbars, false); + AppendScrollPartsTo(aBuilder, aLists, createLayersForScrollbars, false); } + nsDisplayListBuilder::AutoBuildingDisplayList + building(aBuilder, mOuter, visibleRect, dirtyRect, aBuilder->IsAtRootOfPseudoStackingContext()); + // Don't clip the scrolled child, and don't paint scrollbars/scrollcorner. // The scrolled frame shouldn't have its own background/border, so we // can just pass aLists directly. - mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, - dirtyRect, aLists); + mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, aLists); if (addScrollBars) { // Add overlay scrollbars. - AppendScrollPartsTo(aBuilder, aDirtyRect, aLists, - createLayersForScrollbars, true); + AppendScrollPartsTo(aBuilder, aLists, createLayersForScrollbars, true); } return; @@ -3376,8 +3391,7 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, // Note that this does not apply for overlay scrollbars; those are drawn // in the positioned-elements layer on top of everything else by the call // to AppendScrollPartsTo(..., true) further down. - AppendScrollPartsTo(aBuilder, aDirtyRect, aLists, - createLayersForScrollbars, false); + AppendScrollPartsTo(aBuilder, aLists, createLayersForScrollbars, false); const nsStyleDisplay* disp = mOuter->StyleDisplay(); if (disp && (disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_SCROLL)) { @@ -3414,7 +3428,7 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, nsIScrollableFrame* sf = do_QueryFrame(mOuter); MOZ_ASSERT(sf); - nsDisplayListCollection scrolledContent; + nsDisplayListCollection scrolledContent(aBuilder); { // Note that setting the current scroll parent id here means that positioned children // of this scroll info layer will pick up the scroll info layer as their scroll handoff @@ -3501,12 +3515,15 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, // pixels. // If there is no display port, we don't need this because the clip // from the scroll port is still applied. - scrolledRectClip = scrolledRectClip.Intersect(dirtyRect); + scrolledRectClip = scrolledRectClip.Intersect(visibleRect); } scrolledRectClipState.ClipContainingBlockDescendants( scrolledRectClip + aBuilder->ToReferenceFrame(mOuter)); - mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, scrolledContent); + nsDisplayListBuilder::AutoBuildingDisplayList + building(aBuilder, mOuter, visibleRect, dirtyRect, aBuilder->IsAtRootOfPseudoStackingContext()); + + mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, scrolledContent); } if (contentBoxClipForNonCaretContent) { @@ -3558,7 +3575,8 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, // recompute the current animated geometry root if needed. // It's too late to change the dirty rect so pass a copy. nsRect copyOfDirtyRect = dirtyRect; - Unused << DecideScrollableLayer(aBuilder, ©OfDirtyRect, + nsRect copyOfVisibleRect = visibleRect; + Unused << DecideScrollableLayer(aBuilder, ©OfVisibleRect, ©OfDirtyRect, /* aAllowCreateDisplayPort = */ false); } } @@ -3593,13 +3611,14 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, } } // Now display overlay scrollbars and the resizer, if we have one. - AppendScrollPartsTo(aBuilder, aDirtyRect, scrolledContent, - createLayersForScrollbars, true); + AppendScrollPartsTo(aBuilder, scrolledContent, createLayersForScrollbars, true); + scrolledContent.MoveTo(aLists); } bool ScrollFrameHelper::DecideScrollableLayer(nsDisplayListBuilder* aBuilder, + nsRect* aVisibleRect, nsRect* aDirtyRect, bool aAllowCreateDisplayPort) { @@ -3615,16 +3634,16 @@ ScrollFrameHelper::DecideScrollableLayer(nsDisplayListBuilder* aBuilder, if (aAllowCreateDisplayPort) { nsLayoutUtils::MaybeCreateDisplayPort(*aBuilder, mOuter); - nsRect displayportBase = *aDirtyRect; + nsRect displayportBase = *aVisibleRect; nsPresContext* pc = mOuter->PresContext(); if (mIsRoot && (pc->IsRootContentDocument() || !pc->GetParentPresContext())) { displayportBase = nsRect(nsPoint(0, 0), nsLayoutUtils::CalculateCompositionSizeForFrame(mOuter)); } else { - // Make the displayport base equal to the dirty rect restricted to + // Make the displayport base equal to the visible rect restricted to // the scrollport and the root composition bounds, relative to the // scrollport. - displayportBase = aDirtyRect->Intersect(mScrollPort); + displayportBase = aVisibleRect->Intersect(mScrollPort); // Only restrict to the root composition bounds if necessary, // as the required coordinate transformation is expensive. @@ -3687,12 +3706,15 @@ ScrollFrameHelper::DecideScrollableLayer(nsDisplayListBuilder* aBuilder, if (usingDisplayPort) { // Override the dirty rectangle if the displayport has been set. + *aVisibleRect = displayPort; *aDirtyRect = displayPort; } else if (mIsRoot) { // The displayPort getter takes care of adjusting for resolution. So if // we have resolution but no displayPort then we need to adjust for // resolution here. nsIPresShell* presShell = mOuter->PresContext()->PresShell(); + *aVisibleRect = aVisibleRect->RemoveResolution( + presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f); *aDirtyRect = aDirtyRect->RemoveResolution( presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f); } @@ -6175,3 +6197,4 @@ ScrollFrameHelper::UsesContainerScrolling() const } return false; } + diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 81bbb358f..8ad510d65 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -70,11 +70,9 @@ public: void Destroy(); void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists); void AppendScrollPartsTo(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists, bool aCreateLayer, bool aPositioned); @@ -404,6 +402,7 @@ public: ScrollSnapInfo GetScrollSnapInfo() const; bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder, + nsRect* aVisibleRect, nsRect* aDirtyRect, bool aAllowCreateDisplayPort); void NotifyApproximateFrameVisibilityUpdate(); @@ -687,9 +686,8 @@ public: } virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override { - mHelper.BuildDisplayList(aBuilder, aDirtyRect, aLists); + mHelper.BuildDisplayList(aBuilder, aLists); } bool TryLayout(ScrollReflowInput* aState, @@ -947,9 +945,10 @@ public: return mHelper.UsesContainerScrolling(); } virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder, + nsRect* aVisibleRect, nsRect* aDirtyRect, bool aAllowCreateDisplayPort) override { - return mHelper.DecideScrollableLayer(aBuilder, aDirtyRect, aAllowCreateDisplayPort); + return mHelper.DecideScrollableLayer(aBuilder, aVisibleRect, aDirtyRect, aAllowCreateDisplayPort); } virtual void NotifyApproximateFrameVisibilityUpdate() override { mHelper.NotifyApproximateFrameVisibilityUpdate(); @@ -1105,9 +1104,8 @@ public: bool aClipAllDescendants); virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override { - mHelper.BuildDisplayList(aBuilder, aDirtyRect, aLists); + mHelper.BuildDisplayList(aBuilder, aLists); } // XXXldb Is this actually used? @@ -1453,9 +1451,10 @@ public: mHelper.SetScrollsClipOnUnscrolledOutOfFlow(); } virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder, + nsRect* aVisibleRect, nsRect* aDirtyRect, bool aAllowCreateDisplayPort) override { - return mHelper.DecideScrollableLayer(aBuilder, aDirtyRect, aAllowCreateDisplayPort); + return mHelper.DecideScrollableLayer(aBuilder, aVisibleRect, aDirtyRect, aAllowCreateDisplayPort); } virtual void NotifyApproximateFrameVisibilityUpdate() override { mHelper.NotifyApproximateFrameVisibilityUpdate(); diff --git a/layout/generic/nsGridContainerFrame.cpp b/layout/generic/nsGridContainerFrame.cpp index 959061e33..baa554405 100644 --- a/layout/generic/nsGridContainerFrame.cpp +++ b/layout/generic/nsGridContainerFrame.cpp @@ -6643,12 +6643,11 @@ nsGridContainerFrame::GetType() const void nsGridContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { DisplayBorderBackgroundOutline(aBuilder, aLists); if (GetPrevInFlow()) { - DisplayOverflowContainers(aBuilder, aDirtyRect, aLists); + DisplayOverflowContainers(aBuilder, aLists); } // Our children are all grid-level boxes, which behave the same as @@ -6662,8 +6661,7 @@ nsGridContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, GridItemCSSOrderIterator::eIncludeAll, order); for (; !iter.AtEnd(); iter.Next()) { nsIFrame* child = *iter; - BuildDisplayListForChild(aBuilder, child, aDirtyRect, aLists, - ::GetDisplayFlagsForGridItem(child)); + BuildDisplayListForChild(aBuilder, child, aLists, ::GetDisplayFlagsForGridItem(child)); } } diff --git a/layout/generic/nsGridContainerFrame.h b/layout/generic/nsGridContainerFrame.h index 960558421..c9163b95c 100644 --- a/layout/generic/nsGridContainerFrame.h +++ b/layout/generic/nsGridContainerFrame.h @@ -98,7 +98,6 @@ public: } void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const override diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp index bad3a710f..f86ec1136 100644 --- a/layout/generic/nsHTMLCanvasFrame.cpp +++ b/layout/generic/nsHTMLCanvasFrame.cpp @@ -367,7 +367,6 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder, void nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (!IsVisibleForPainting(aBuilder)) diff --git a/layout/generic/nsHTMLCanvasFrame.h b/layout/generic/nsHTMLCanvasFrame.h index e4235deae..b2d159627 100644 --- a/layout/generic/nsHTMLCanvasFrame.h +++ b/layout/generic/nsHTMLCanvasFrame.h @@ -45,7 +45,6 @@ public: nsIFrame* aPrevInFlow) override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 93eb95099..90de72d8d 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -1435,21 +1435,14 @@ public: * BuildDisplayListForChild. * * See nsDisplayList.h for more information about display lists. - * - * @param aDirtyRect content outside this rectangle can be ignored; the - * rectangle is in frame coordinates */ virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) {} /** * Displays the caret onto the given display list builder. The caret is * painted on top of the rest of the display list items. - * - * @param aDirtyRect is the dirty rectangle that we're repainting. */ void DisplayCaret(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, nsDisplayList* aList); /** @@ -1483,11 +1476,8 @@ public: /** * Builds a display list for the content represented by this frame, * treating this frame as the root of a stacking context. - * @param aDirtyRect content outside this rectangle can be ignored; the - * rectangle is in frame coordinates */ void BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, nsDisplayList* aList); enum { @@ -1506,7 +1496,6 @@ public: */ void BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, nsIFrame* aChild, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists, uint32_t aFlags = 0); @@ -3530,13 +3519,23 @@ protected: nsRect mRect; nsIContent* mContent; nsStyleContext* mStyleContext; + /** + * This bit is used during BuildDisplayList to mark frames that need to + * have display items rebuilt. We will descend into them if they are + * currently visible, even if they don't intersect the dirty area. + */ + bool mForceDescendIntoIfVisible : 1; private: nsContainerFrame* mParent; nsIFrame* mNextSibling; // doubly-linked list of frames nsIFrame* mPrevSibling; // Do not touch outside SetNextSibling! - void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect); - + void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder); + public: + bool ForceDescendIntoIfVisible() const { return mForceDescendIntoIfVisible; } + void SetForceDescendIntoIfVisible(bool aForce) { + mForceDescendIntoIfVisible = aForce; + } static void DestroyPaintedPresShellList(nsTArray<nsWeakPtr>* list) { list->Clear(); delete list; diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index b7e3caf46..20a598452 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -440,13 +440,16 @@ public: /** * Determine if we should build a scrollable layer for this scroll frame and * return the result. It will also record this result on the scroll frame. + * Pass the visible rect in aVisibleRect. On return it will be set to the + * displayport if there is one. * Pass the dirty rect in aDirtyRect. On return it will be set to the - * displayport if there is one (ie the dirty rect that should be used). + * dirty rect inside the displayport (ie the dirty rect that should be used). * This function may create a display port where one did not exist before if * aAllowCreateDisplayPort is true. It is only allowed to be false if there * has been a call with it set to true before on the same paint. */ virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder, + nsRect* aVisibleRect, nsRect* aDirtyRect, bool aAllowCreateDisplayPort) = 0; diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index c64520f2e..342370050 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1730,7 +1730,6 @@ nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt, void nsImageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (!IsVisibleForPainting(aBuilder)) diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index 5bc59c042..fceecc43d 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -82,7 +82,6 @@ public: nsContainerFrame* aParent, nsIFrame* aPrevInFlow) override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override; diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 7e188c247..fb77422a3 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -243,10 +243,9 @@ nsInlineFrame::StealFrame(nsIFrame* aChild) void nsInlineFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { - BuildDisplayListForInline(aBuilder, aDirtyRect, aLists); + BuildDisplayListForInline(aBuilder, aLists); // The sole purpose of this is to trigger display of the selection // window for Named Anchors, which don't have any children and diff --git a/layout/generic/nsInlineFrame.h b/layout/generic/nsInlineFrame.h index 36df6be93..c1e0d7fe3 100644 --- a/layout/generic/nsInlineFrame.h +++ b/layout/generic/nsInlineFrame.h @@ -31,7 +31,6 @@ public: // nsIFrame overrides virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; #ifdef ACCESSIBILITY diff --git a/layout/generic/nsLeafFrame.h b/layout/generic/nsLeafFrame.h index 407f9846d..7087fb6cf 100644 --- a/layout/generic/nsLeafFrame.h +++ b/layout/generic/nsLeafFrame.h @@ -24,7 +24,6 @@ public: // nsIFrame replacements virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override { DO_GLOBAL_REFLOW_COUNT_DSP("nsLeafFrame"); DisplayBorderBackgroundOutline(aBuilder, aLists); diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp index ae3af6ef7..7ec90c051 100644 --- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -437,7 +437,7 @@ PruneDisplayListForExtraPage(nsDisplayListBuilder* aBuilder, static void BuildDisplayListForExtraPage(nsDisplayListBuilder* aBuilder, nsPageFrame* aPage, nsIFrame* aExtraPage, - const nsRect& aDirtyRect, nsDisplayList* aList) + nsDisplayList* aList) { // The only content in aExtraPage we care about is out-of-flow content whose // placeholders have occurred in aPage. If @@ -447,7 +447,7 @@ BuildDisplayListForExtraPage(nsDisplayListBuilder* aBuilder, return; } nsDisplayList list; - aExtraPage->BuildDisplayListForStackingContext(aBuilder, aDirtyRect, &list); + aExtraPage->BuildDisplayListForStackingContext(aBuilder, &list); PruneDisplayListForExtraPage(aBuilder, aPage, aExtraPage, &list); aList->AppendToTop(&list); } @@ -517,10 +517,9 @@ protected: //------------------------------------------------------------------------------ void nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { - nsDisplayListCollection set; + nsDisplayListCollection set(aBuilder); if (PresContext()->IsScreen()) { DisplayBorderBackgroundOutline(aBuilder, aLists); @@ -557,8 +556,11 @@ nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, clipState.Clear(); clipState.ClipContainingBlockDescendants(clipRect, nullptr); - nsRect dirtyRect = child->GetVisualOverflowRectRelativeToSelf(); - child->BuildDisplayListForStackingContext(aBuilder, dirtyRect, &content); + nsRect visibleRect = child->GetVisualOverflowRectRelativeToSelf(); + nsDisplayListBuilder::AutoBuildingDisplayList + buildingForChild(aBuilder, child, visibleRect, visibleRect, + aBuilder->IsAtRootOfPseudoStackingContext()); + child->BuildDisplayListForStackingContext(aBuilder, &content); // We may need to paint out-of-flow frames whose placeholders are // on other pages. Add those pages to our display list. Note that @@ -569,15 +571,19 @@ nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, // following placeholders to their out-of-flows) end up on the list. nsIFrame* page = child; while ((page = GetNextPage(page)) != nullptr) { - BuildDisplayListForExtraPage(aBuilder, this, page, - dirtyRect + child->GetOffsetTo(page), &content); + nsRect childVisible = visibleRect + child->GetOffsetTo(page); + + nsDisplayListBuilder::AutoBuildingDisplayList + buildingForChild(aBuilder, page, childVisible, childVisible, + aBuilder->IsAtRootOfPseudoStackingContext()); + BuildDisplayListForExtraPage(aBuilder, this, page, &content); } - // Invoke AutoBuildingDisplayList to ensure that the correct dirtyRect + // Invoke AutoBuildingDisplayList to ensure that the correct visibleRect // is used to compute the visible rect if AddCanvasBackgroundColorItem // creates a display item. nsDisplayListBuilder::AutoBuildingDisplayList - building(aBuilder, child, dirtyRect, true); + building(aBuilder, child, visibleRect, visibleRect, true); // Add the canvas background color to the bottom of the list. This // happens after we've built the list so that AddCanvasBackgroundColorItem diff --git a/layout/generic/nsPageFrame.h b/layout/generic/nsPageFrame.h index aab2ac7b8..86516fe73 100644 --- a/layout/generic/nsPageFrame.h +++ b/layout/generic/nsPageFrame.h @@ -29,7 +29,6 @@ public: nsReflowStatus& aStatus) override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; /** diff --git a/layout/generic/nsPlaceholderFrame.cpp b/layout/generic/nsPlaceholderFrame.cpp index bd380a2d9..f234b2f2d 100644 --- a/layout/generic/nsPlaceholderFrame.cpp +++ b/layout/generic/nsPlaceholderFrame.cpp @@ -240,7 +240,6 @@ PaintDebugPlaceholder(nsIFrame* aFrame, DrawTarget* aDrawTarget, void nsPlaceholderFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { DO_GLOBAL_REFLOW_COUNT_DSP("nsPlaceholderFrame"); diff --git a/layout/generic/nsPlaceholderFrame.h b/layout/generic/nsPlaceholderFrame.h index 0c23a4f75..11cb98592 100644 --- a/layout/generic/nsPlaceholderFrame.h +++ b/layout/generic/nsPlaceholderFrame.h @@ -107,7 +107,6 @@ public: #if defined(DEBUG) || (defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)) virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; #endif // DEBUG || (MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF) diff --git a/layout/generic/nsPluginFrame.cpp b/layout/generic/nsPluginFrame.cpp index 34ed12d44..6e9e072e7 100644 --- a/layout/generic/nsPluginFrame.cpp +++ b/layout/generic/nsPluginFrame.cpp @@ -1182,7 +1182,6 @@ nsPluginFrame::IsTransparentMode() const void nsPluginFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { // XXX why are we painting collapsed object frames? diff --git a/layout/generic/nsPluginFrame.h b/layout/generic/nsPluginFrame.h index 5d9f9f475..57db78acc 100644 --- a/layout/generic/nsPluginFrame.h +++ b/layout/generic/nsPluginFrame.h @@ -81,7 +81,6 @@ public: const ReflowInput* aReflowInput, nsDidReflowStatus aStatus) override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual nsresult HandleEvent(nsPresContext* aPresContext, diff --git a/layout/generic/nsRubyTextFrame.cpp b/layout/generic/nsRubyTextFrame.cpp index b4a26ff33..2848cb6fc 100644 --- a/layout/generic/nsRubyTextFrame.cpp +++ b/layout/generic/nsRubyTextFrame.cpp @@ -63,14 +63,13 @@ nsRubyTextFrame::GetFrameName(nsAString& aResult) const /* virtual */ void nsRubyTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (IsAutoHidden()) { return; } - nsRubyContentFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists); + nsRubyContentFrame::BuildDisplayList(aBuilder, aLists); } /* virtual */ void diff --git a/layout/generic/nsRubyTextFrame.h b/layout/generic/nsRubyTextFrame.h index 841b5081f..83c24d49d 100644 --- a/layout/generic/nsRubyTextFrame.h +++ b/layout/generic/nsRubyTextFrame.h @@ -34,7 +34,6 @@ public: #endif virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual void Reflow(nsPresContext* aPresContext, diff --git a/layout/generic/nsSimplePageSequenceFrame.cpp b/layout/generic/nsSimplePageSequenceFrame.cpp index 2e74afc3b..6dcb6ccc1 100644 --- a/layout/generic/nsSimplePageSequenceFrame.cpp +++ b/layout/generic/nsSimplePageSequenceFrame.cpp @@ -808,7 +808,6 @@ ComputePageSequenceTransform(nsIFrame* aFrame, float aAppUnitsPerPixel) void nsSimplePageSequenceFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { DisplayBorderBackgroundOutline(aBuilder, aLists); @@ -822,13 +821,17 @@ nsSimplePageSequenceFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, clipState.Clear(); nsIFrame* child = PrincipalChildList().FirstChild(); - nsRect dirty = aDirtyRect; - dirty.ScaleInverseRoundOut(PresContext()->GetPrintPreviewScale()); + nsRect visible = aBuilder->GetVisibleRect(); + visible.ScaleInverseRoundOut(PresContext()->GetPrintPreviewScale()); while (child) { - if (child->GetVisualOverflowRectRelativeToParent().Intersects(dirty)) { - child->BuildDisplayListForStackingContext(aBuilder, - dirty - child->GetPosition(), &content); + if (child->GetVisualOverflowRectRelativeToParent().Intersects(visible)) { + nsDisplayListBuilder::AutoBuildingDisplayList + buildingForChild(aBuilder, child, + visible - child->GetPosition(), + visible - child->GetPosition(), + aBuilder->IsAtRootOfPseudoStackingContext()); + child->BuildDisplayListForStackingContext(aBuilder, &content); aBuilder->ResetMarkedFramesForDisplayList(); } child = child->GetNextSibling(); diff --git a/layout/generic/nsSimplePageSequenceFrame.h b/layout/generic/nsSimplePageSequenceFrame.h index c4e1e84b6..4981c67a8 100644 --- a/layout/generic/nsSimplePageSequenceFrame.h +++ b/layout/generic/nsSimplePageSequenceFrame.h @@ -69,7 +69,6 @@ public: nsReflowStatus& aStatus) override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; // nsIPageSequenceFrame diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index 47026b73c..1c5ade583 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -327,7 +327,6 @@ WrapBackgroundColorInOwnLayer(nsDisplayListBuilder* aBuilder, void nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (!IsVisibleForPainting(aBuilder)) @@ -343,7 +342,7 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, bool pointerEventsNone = StyleUserInterface()->mPointerEvents == NS_STYLE_POINTER_EVENTS_NONE; if (!aBuilder->IsForEventDelivery() || !pointerEventsNone) { - nsDisplayListCollection decorations; + nsDisplayListCollection decorations(aBuilder); DisplayBorderBackgroundOutline(aBuilder, decorations); if (rfp) { // Wrap background colors of <iframe>s with remote subdocuments in their @@ -368,7 +367,7 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, } if (rfp) { - rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists); + rfp->BuildDisplayList(aBuilder, this, aLists); return; } @@ -387,23 +386,28 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, int32_t parentAPD = PresContext()->AppUnitsPerDevPixel(); int32_t subdocAPD = presContext->AppUnitsPerDevPixel(); + nsRect visible; nsRect dirty; bool haveDisplayPort = false; bool ignoreViewportScrolling = false; nsIFrame* savedIgnoreScrollFrame = nullptr; if (subdocRootFrame) { // get the dirty rect relative to the root frame of the subdoc - dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame); + visible = aBuilder->GetVisibleRect() + GetOffsetToCrossDoc(subdocRootFrame); + dirty = aBuilder->GetDirtyRect() + GetOffsetToCrossDoc(subdocRootFrame); // and convert into the appunits of the subdoc + visible = visible.ScaleToOtherAppUnitsRoundOut(parentAPD, subdocAPD); dirty = dirty.ScaleToOtherAppUnitsRoundOut(parentAPD, subdocAPD); if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) { nsIScrollableFrame* rootScrollableFrame = presShell->GetRootScrollFrameAsScrollable(); MOZ_ASSERT(rootScrollableFrame); - // Use a copy, so the dirty rect doesn't get modified to the display port. - nsRect copy = dirty; + // Use a copy, so the rects don't get modified. + nsRect copyOfDirty = dirty; + nsRect copyOfVisible = visible; haveDisplayPort = rootScrollableFrame->DecideScrollableLayer(aBuilder, - ©, /* aAllowCreateDisplayPort = */ true); + ©OfVisible, ©OfDirty, + /* aAllowCreateDisplayPort = */ true); if (!gfxPrefs::LayoutUseContainersForRootFrames()) { haveDisplayPort = false; } @@ -417,7 +421,8 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, aBuilder->EnterPresShell(subdocRootFrame, pointerEventsNone); } else { - dirty = aDirtyRect; + visible = aBuilder->GetVisibleRect(); + dirty = aBuilder->GetDirtyRect(); } DisplayListClipState::AutoSaveRestore clipState(aBuilder); @@ -456,6 +461,13 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, nestedClipState.EnterStackingContextContents(true); } + // Invoke AutoBuildingDisplayList to ensure that the correct dirty rect + // is used to compute the visible rect if AddCanvasBackgroundColorItem + // creates a display item. + nsIFrame* frame = subdocRootFrame ? subdocRootFrame : this; + nsDisplayListBuilder::AutoBuildingDisplayList + building(aBuilder, frame, visible, dirty, true); + if (subdocRootFrame) { nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame(); nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter( @@ -466,7 +478,7 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, aBuilder->SetAncestorHasApzAwareEventHandler(false); subdocRootFrame-> - BuildDisplayListForStackingContext(aBuilder, dirty, &childItems); + BuildDisplayListForStackingContext(aBuilder, &childItems); } if (!aBuilder->IsForEventDelivery()) { @@ -485,15 +497,8 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, // painted on the page itself. if (nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) { presShell->AddPrintPreviewBackgroundItem( - *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this, - bounds); + *aBuilder, childItems, frame, bounds); } else { - // Invoke AutoBuildingDisplayList to ensure that the correct dirty rect - // is used to compute the visible rect if AddCanvasBackgroundColorItem - // creates a display item. - nsIFrame* frame = subdocRootFrame ? subdocRootFrame : this; - nsDisplayListBuilder::AutoBuildingDisplayList - building(aBuilder, frame, dirty, true); // Add the canvas background color to the bottom of the list. This // happens after we've built the list so that AddCanvasBackgroundColorItem // can monkey with the contents if necessary. diff --git a/layout/generic/nsSubDocumentFrame.h b/layout/generic/nsSubDocumentFrame.h index 54f08d4fe..93d908dcc 100644 --- a/layout/generic/nsSubDocumentFrame.h +++ b/layout/generic/nsSubDocumentFrame.h @@ -79,7 +79,6 @@ public: nsReflowStatus& aStatus) override; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual nsresult AttributeChanged(int32_t aNameSpaceID, diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 59ef020ce..4bc542626 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -4998,7 +4998,6 @@ nsDisplayText::Paint(nsDisplayListBuilder* aBuilder, void nsTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (!IsVisibleForPainting(aBuilder)) diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 425dbb737..43a4f5f1c 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -65,7 +65,6 @@ public: // nsIFrame virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual void Init(nsIContent* aContent, diff --git a/layout/generic/nsVideoFrame.cpp b/layout/generic/nsVideoFrame.cpp index 9f27684a7..43383044b 100644 --- a/layout/generic/nsVideoFrame.cpp +++ b/layout/generic/nsVideoFrame.cpp @@ -446,7 +446,6 @@ public: void nsVideoFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (!IsVisibleForPainting(aBuilder)) @@ -482,14 +481,16 @@ nsVideoFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, // but only want to draw mPosterImage conditionally. Others we // always add to the display list. for (nsIFrame* child : mFrames) { - if (child->GetContent() != mPosterImage || shouldDisplayPoster) { - child->BuildDisplayListForStackingContext(aBuilder, - aDirtyRect - child->GetOffsetTo(this), - aLists.Content()); - } else if (child->GetType() == nsGkAtoms::boxFrame) { - child->BuildDisplayListForStackingContext(aBuilder, - aDirtyRect - child->GetOffsetTo(this), - aLists.Content()); + if (child->GetContent() != mPosterImage || shouldDisplayPoster || + child->GetType() == nsGkAtoms::boxFrame) { + + nsDisplayListBuilder::AutoBuildingDisplayList + buildingForChild(aBuilder, child, + aBuilder->GetVisibleRect() - child->GetOffsetTo(this), + aBuilder->GetDirtyRect() - child->GetOffsetTo(this), + aBuilder->IsAtRootOfPseudoStackingContext()); + + child->BuildDisplayListForStackingContext(aBuilder, aLists.Content()); } } } diff --git a/layout/generic/nsVideoFrame.h b/layout/generic/nsVideoFrame.h index 36e9f9ac3..d624ae6b9 100644 --- a/layout/generic/nsVideoFrame.h +++ b/layout/generic/nsVideoFrame.h @@ -45,7 +45,6 @@ public: NS_DECL_FRAMEARENA_HELPERS virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; virtual nsresult AttributeChanged(int32_t aNameSpaceID, diff --git a/layout/generic/nsViewportFrame.cpp b/layout/generic/nsViewportFrame.cpp index 39491a0ed..a7a8cd50c 100644 --- a/layout/generic/nsViewportFrame.cpp +++ b/layout/generic/nsViewportFrame.cpp @@ -48,7 +48,6 @@ ViewportFrame::Init(nsIContent* aContent, void ViewportFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { PROFILER_LABEL("ViewportFrame", "BuildDisplayList", @@ -58,7 +57,7 @@ ViewportFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, // make the kid's BorderBackground our own. This ensures that the canvas // frame's background becomes our own background and therefore appears // below negative z-index elements. - BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists); + BuildDisplayListForChild(aBuilder, kid, aLists); } nsDisplayList topLayerList; @@ -98,19 +97,25 @@ BuildDisplayListForTopLayerFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList) { + nsRect visible; nsRect dirty; DisplayListClipState::AutoClipMultiple clipState(aBuilder); nsDisplayListBuilder::OutOfFlowDisplayData* savedOutOfFlowData = nsDisplayListBuilder::GetOutOfFlowData(aFrame); if (savedOutOfFlowData) { + visible = savedOutOfFlowData->mVisibleRect; dirty = savedOutOfFlowData->mDirtyRect; clipState.SetClipForContainingBlockDescendants( &savedOutOfFlowData->mContainingBlockClip); clipState.SetScrollClipForContainingBlockDescendants( aBuilder, savedOutOfFlowData->mContainingBlockScrollClip); } + nsDisplayListBuilder::AutoBuildingDisplayList + buildingForChild(aBuilder, aFrame, visible, dirty, + aBuilder->IsAtRootOfPseudoStackingContext()); + nsDisplayList list; - aFrame->BuildDisplayListForStackingContext(aBuilder, dirty, &list); + aFrame->BuildDisplayListForStackingContext(aBuilder, &list); aList->AppendToTop(&list); } diff --git a/layout/generic/nsViewportFrame.h b/layout/generic/nsViewportFrame.h index 062de4054..3e5263093 100644 --- a/layout/generic/nsViewportFrame.h +++ b/layout/generic/nsViewportFrame.h @@ -56,7 +56,6 @@ public: #endif virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; void BuildDisplayListForTopLayer(nsDisplayListBuilder* aBuilder, |