diff options
Diffstat (limited to 'layout/base')
-rw-r--r-- | layout/base/nsDisplayList.cpp | 120 | ||||
-rw-r--r-- | layout/base/nsDisplayList.h | 95 | ||||
-rw-r--r-- | layout/base/nsLayoutUtils.cpp | 15 | ||||
-rw-r--r-- | layout/base/nsPresShell.cpp | 5 |
4 files changed, 159 insertions, 76 deletions
diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 8a34d108f..f870c6d97 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -721,7 +721,6 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, : mReferenceFrame(aReferenceFrame), mIgnoreScrollFrame(nullptr), mLayerEventRegions(nullptr), - mCurrentTableItem(nullptr), mCurrentFrame(aReferenceFrame), mCurrentReferenceFrame(aReferenceFrame), mCurrentAGR(&mRootAGR), @@ -731,6 +730,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, mGlassDisplayItem(nullptr), mScrollInfoItemsForHoisting(nullptr), mMode(aMode), + mTableBackgroundSet(nullptr), mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID), mCurrentScrollbarTarget(FrameMetrics::NULL_SCROLL_ID), mCurrentScrollbarFlags(0), @@ -783,7 +783,10 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, "Check nsDisplayItem::TYPE_MAX should not overflow"); } -static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) { +void +nsDisplayListBuilder::MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) +{ + mFramesMarkedForDisplay.AppendElement(aFrame); for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) { if (f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) @@ -796,6 +799,22 @@ static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) { } } +void +nsDisplayListBuilder::MarkFrameForDisplayIfVisible(nsIFrame* aFrame, nsIFrame* aStopAtFrame) +{ + mFramesMarkedForDisplay.AppendElement(aFrame); + for (nsIFrame* f = aFrame; f; + f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) { + if (f->ForceDescendIntoIfVisible()) + return; + f->SetForceDescendIntoIfVisible(true); + if (f == aStopAtFrame) { + // we've reached a frame that we know will be painted, so we can stop. + break; + } + } +} + bool nsDisplayListBuilder::NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem) { return aItem == mGlassDisplayItem || aItem->ClearsBackground(); @@ -864,10 +883,10 @@ nsDisplayListBuilder::FindAnimatedGeometryRootFor(nsDisplayItem* aItem) void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, - nsIFrame* aFrame, - const nsRect& aDirtyRect) + nsIFrame* aFrame) { - nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect; + nsRect visible = GetVisibleRect(); + nsRect dirtyRectRelativeToDirtyFrame = GetDirtyRect(); if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) && IsPaintingToWindow()) { NS_ASSERTION(aDirtyFrame == aFrame->GetParent(), "Dirty frame should be viewport frame"); @@ -881,8 +900,14 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, } else { dirtyRectRelativeToDirtyFrame.SizeTo(aDirtyFrame->GetSize()); } + // TODO: We probably don't want visible and dirty to be the same here, figure + // out what to do. + visible = dirtyRectRelativeToDirtyFrame; } - nsRect dirty = dirtyRectRelativeToDirtyFrame - aFrame->GetOffsetTo(aDirtyFrame); + + nsPoint offset = aFrame->GetOffsetTo(aDirtyFrame); + visible -= offset; + nsRect dirty = dirtyRectRelativeToDirtyFrame - offset; nsRect overflowRect = aFrame->GetVisualOverflowRect(); if (aFrame->IsTransformed() && @@ -895,15 +920,18 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, */ overflowRect.Inflate(nsPresContext::CSSPixelsToAppUnits(32)); } - - if (!dirty.IntersectRect(dirty, overflowRect) && - !(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) { + visible.IntersectRect(visible, overflowRect); + dirty.IntersectRect(dirty, overflowRect); + if (!(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) && + dirty.IsEmpty() && + (!aFrame->ForceDescendIntoIfVisible() || + visible.IsEmpty())) { return; } const DisplayItemClip* oldClip = mClipState.GetClipForContainingBlockDescendants(); const DisplayItemScrollClip* sc = mClipState.GetCurrentInnermostScrollClip(); - OutOfFlowDisplayData* data = new OutOfFlowDisplayData(oldClip, sc, dirty); + OutOfFlowDisplayData* data = new OutOfFlowDisplayData(oldClip, sc, visible, dirty); aFrame->SetProperty(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data); MarkFrameForDisplay(aFrame, aDirtyFrame); @@ -914,9 +942,11 @@ static void UnmarkFrameForDisplay(nsIFrame* aFrame) { for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) { - if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) + if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) && + !f->ForceDescendIntoIfVisible()) return; f->RemoveStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO); + f->SetForceDescendIntoIfVisible(false); } } @@ -925,7 +955,6 @@ nsDisplayListBuilder::~nsDisplayListBuilder() { "All frames should have been unmarked"); NS_ASSERTION(mPresShellStates.Length() == 0, "All presshells should have been exited"); - NS_ASSERTION(!mCurrentTableItem, "No table item should be active"); nsCSSRendering::EndFrameTreesLocked(); @@ -1008,22 +1037,27 @@ nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame, } state->mInsidePointerEventsNoneDoc = pointerEventsNone; + state->mPresShellIgnoreScrollFrame = + state->mPresShell->IgnoringViewportScrolling() + ? state->mPresShell->GetRootScrollFrame() + : nullptr; + + nsPresContext* pc = aReferenceFrame->PresContext(); + nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell(); + if (docShell) { + docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed); + } + + mIsInChromePresContext = pc->IsChrome(); + if (!buildCaret) return; RefPtr<nsCaret> caret = state->mPresShell->GetCaret(); state->mCaretFrame = caret->GetPaintGeometry(&state->mCaretRect); if (state->mCaretFrame) { - mFramesMarkedForDisplay.AppendElement(state->mCaretFrame); MarkFrameForDisplay(state->mCaretFrame, nullptr); } - - nsPresContext* pc = aReferenceFrame->PresContext(); - nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell(); - if (docShell) { - docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed); - } - mIsInChromePresContext = pc->IsChrome(); } // A non-blank paint is a paint that does not just contain the canvas background. @@ -1094,8 +1128,7 @@ nsDisplayListBuilder::ResetMarkedFramesForDisplayList() void nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame, - const nsFrameList& aFrames, - const nsRect& aDirtyRect) { + const nsFrameList& aFrames) { for (nsIFrame* e : aFrames) { // Skip the AccessibleCaret frame when building no caret. if (!IsBuildingCaret()) { @@ -1108,8 +1141,7 @@ nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame, } } - mFramesMarkedForDisplay.AppendElement(e); - MarkOutOfFlowFrameForDisplay(aDirtyFrame, e, aDirtyRect); + MarkOutOfFlowFrameForDisplay(aDirtyFrame, e); } } @@ -1132,7 +1164,6 @@ nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame) for (; !childFrames.AtEnd(); childFrames.Next()) { nsIFrame *child = childFrames.get(); if (child->Combines3DTransformWithAncestors()) { - mFramesMarkedForDisplay.AppendElement(child); MarkFrameForDisplay(child, aDirtyFrame); } } @@ -2318,11 +2349,11 @@ nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(aFrame); MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(aBuilder->RootReferenceFrame(), *mAnimatedGeometryRoot), "Bad"); - NS_ASSERTION(aBuilder->GetDirtyRect().width >= 0 || - !aBuilder->IsForPainting(), "dirty rect not set"); - // The dirty rect is for mCurrentFrame, so we have to use + NS_ASSERTION(aBuilder->GetVisibleRect().width >= 0 || + !aBuilder->IsForPainting(), "visible rect not set"); + // The visible rect is for mCurrentFrame, so we have to use // mCurrentOffsetToReferenceFrame - mVisibleRect = aBuilder->GetDirtyRect() + + mVisibleRect = aBuilder->GetVisibleRect() + aBuilder->GetCurrentFrameOffsetToReferenceFrame(); } @@ -2573,8 +2604,7 @@ static nsStyleContext* GetBackgroundStyleContext(nsIFrame* aFrame) /* static */ void SetBackgroundClipRegion(DisplayListClipState::AutoSaveRestore& aClipState, - nsIFrame* aFrame, const nsPoint& aToReferenceFrame, - const nsStyleImageLayers::Layer& aLayer, + nsIFrame* aFrame, const nsStyleImageLayers::Layer& aLayer, const nsRect& aBackgroundRect, bool aWillPaintBorder) { @@ -2626,7 +2656,6 @@ SpecialCutoutRegionCase(nsDisplayListBuilder* aBuilder, return true; } - /*static*/ bool nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, @@ -2635,14 +2664,16 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil bool aAllowWillPaintBorderOptimization, nsStyleContext* aStyleContext, const nsRect& aBackgroundOriginRect, - nsIFrame* aSecondaryReferenceFrame) + nsIFrame* aSecondaryReferenceFrame, + Maybe<nsDisplayListBuilder::AutoBuildingDisplayList>* + aAutoBuildingDisplayList) { nsStyleContext* bgSC = aStyleContext; const nsStyleBackground* bg = nullptr; - nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame); + nsRect bgRect = aBackgroundRect; nsRect bgOriginRect = bgRect; if (!aBackgroundOriginRect.IsEmpty()) { - bgOriginRect = aBackgroundOriginRect + aBuilder->ToReferenceFrame(aFrame); + bgOriginRect = aBackgroundOriginRect; } nsPresContext* presContext = aFrame->PresContext(); bool isThemed = aFrame->IsThemed(); @@ -2678,8 +2709,6 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil !isThemed && !hasInsetShadow && borderStyle->HasBorder(); - nsPoint toRef = aBuilder->ToReferenceFrame(aFrame); - // An auxiliary list is necessary in case we have background blending; if that // is the case, background items need to be wrapped by a blend container to // isolate blending to the background @@ -2688,6 +2717,9 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil // to create an item for hit testing. if ((drawBackgroundColor && color != NS_RGBA(0,0,0,0)) || aBuilder->IsForEventDelivery()) { + if (aAutoBuildingDisplayList && !*aAutoBuildingDisplayList) { + aAutoBuildingDisplayList->emplace(aBuilder, aFrame); + } DisplayListClipState::AutoSaveRestore clipState(aBuilder); if (bg && !aBuilder->IsForEventDelivery()) { // Disable the will-paint-border optimization for background @@ -2699,7 +2731,7 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil // artifacts along the rounded corners. bool useWillPaintBorderOptimization = willPaintBorder && nsLayoutUtils::HasNonZeroCorner(borderStyle->mBorderRadius); - SetBackgroundClipRegion(clipState, aFrame, toRef, + SetBackgroundClipRegion(clipState, aFrame, bg->BottomLayer(), bgRect, useWillPaintBorderOptimization); } @@ -2752,6 +2784,10 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil continue; } + if (aAutoBuildingDisplayList && !*aAutoBuildingDisplayList) { + aAutoBuildingDisplayList->emplace(aBuilder, aFrame); + } + if (bg->mImage.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) { needBlendContainer = true; } @@ -2759,8 +2795,8 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil DisplayListClipState::AutoSaveRestore clipState(aBuilder); if (!aBuilder->IsForEventDelivery()) { const nsStyleImageLayers::Layer& layer = bg->mImage.mLayers[i]; - SetBackgroundClipRegion(clipState, aFrame, toRef, - layer, bgRect, willPaintBorder); + SetBackgroundClipRegion(clipState, aFrame, layer, bgRect, + willPaintBorder); } nsDisplayList thisItemList; @@ -4342,7 +4378,7 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, mReferenceFrame = i->ReferenceFrame(); mToReferenceFrame = i->ToReferenceFrame(); } - mVisibleRect = aBuilder->GetDirtyRect() + + mVisibleRect = aBuilder->GetVisibleRect() + aBuilder->GetCurrentFrameOffsetToReferenceFrame(); } @@ -4368,7 +4404,7 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, mReferenceFrame = aItem->ReferenceFrame(); mToReferenceFrame = aItem->ToReferenceFrame(); } - mVisibleRect = aBuilder->GetDirtyRect() + + mVisibleRect = aBuilder->GetVisibleRect() + aBuilder->GetCurrentFrameOffsetToReferenceFrame(); } diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 9cee7b517..9ae76e2ac 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -48,6 +48,7 @@ class nsISelection; class nsIScrollableFrame; class nsDisplayLayerEventRegions; class nsDisplayScrollInfoLayer; +class nsDisplayTableBackgroundSet; class nsCaret; namespace mozilla { @@ -202,6 +203,7 @@ class nsDisplayListBuilder { : mAccumulatedTransform() , mAccumulatedRect() , mAccumulatedRectLevels(0) + , mVisibleRect(aOther.mVisibleRect) , mDirtyRect(aOther.mDirtyRect) {} // Accmulate transforms of ancestors on the preserves-3d chain. @@ -210,6 +212,7 @@ class nsDisplayListBuilder { nsRect mAccumulatedRect; // How far this frame is from the root of the current 3d context. int mAccumulatedRectLevels; + nsRect mVisibleRect; nsRect mDirtyRect; }; @@ -443,7 +446,14 @@ public: * Get dirty rect relative to current frame (the frame that we're calling * BuildDisplayList on right now). */ + const nsRect& GetVisibleRect() { return mVisibleRect; } const nsRect& GetDirtyRect() { return mDirtyRect; } + + void SetVisibleRect(const nsRect& aVisibleRect) { mVisibleRect = aVisibleRect; } + void IntersectVisibleRect(const nsRect& aVisibleRect) { mVisibleRect.IntersectRect(mVisibleRect, aVisibleRect); } + void SetDirtyRect(const nsRect& aDirtyRect) { mDirtyRect = aDirtyRect; } + void IntersectDirtyRect(const nsRect& aDirtyRect) { mDirtyRect.IntersectRect(mDirtyRect, aDirtyRect); } + const nsIFrame* GetCurrentFrame() { return mCurrentFrame; } const nsIFrame* GetCurrentReferenceFrame() { return mCurrentReferenceFrame; } const nsPoint& GetCurrentFrameOffsetToReferenceFrame() { return mCurrentOffsetToReferenceFrame; } @@ -493,11 +503,10 @@ public: /** * Display the caret if needed. */ - void DisplayCaret(nsIFrame* aFrame, const nsRect& aDirtyRect, - nsDisplayList* aList) { + void DisplayCaret(nsIFrame* aFrame, nsDisplayList* aList) { nsIFrame* frame = GetCaretFrame(); if (aFrame == frame) { - frame->DisplayCaret(this, aDirtyRect, aList); + frame->DisplayCaret(this, aList); } } /** @@ -517,6 +526,15 @@ public: * Get the caret associated with the current presshell. */ nsCaret* GetCaret(); + + /** + * Returns the root scroll frame for the current PresShell, if the PresShell + * is ignoring viewport scrolling. + */ + nsIFrame* GetPresShellIgnoreScrollFrame() { + return CurrentPresShellState()->mPresShellIgnoreScrollFrame; + } + /** * Notify the display list builder that we're entering a presshell. * aReferenceFrame should be a frame in the new presshell. @@ -577,6 +595,16 @@ public: mSyncDecodeImages = aSyncDecodeImages; } + nsDisplayTableBackgroundSet* SetTableBackgroundSet( + nsDisplayTableBackgroundSet* aTableSet) { + nsDisplayTableBackgroundSet* old = mTableBackgroundSet; + mTableBackgroundSet = aTableSet; + return old; + } + nsDisplayTableBackgroundSet* GetTableBackgroundSet() const { + return mTableBackgroundSet; + } + /** * Helper method to generate background painting flags based on the * information available in the display list builder. Currently only @@ -602,8 +630,9 @@ public: * destroyed. */ void MarkFramesForDisplayList(nsIFrame* aDirtyFrame, - const nsFrameList& aFrames, - const nsRect& aDirtyRect); + const nsFrameList& aFrames); + void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame = nullptr); + void MarkFrameForDisplayIfVisible(nsIFrame* aFrame, nsIFrame* aStopAtFrame = nullptr); /** * Mark all child frames that Preserve3D() as needing display. * Because these frames include transforms set on their parent, dirty rects @@ -618,9 +647,10 @@ public: * the display list, even though it doesn't intersect the dirty * rect, because it may have out-of-flows that do so. */ - bool ShouldDescendIntoFrame(nsIFrame* aFrame) const { + bool ShouldDescendIntoFrame(nsIFrame* aFrame, bool aVisible) const { return (aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) || + (aVisible && aFrame->ForceDescendIntoIfVisible()) || GetIncludeAllOutOfFlows(); } @@ -700,14 +730,20 @@ public: friend class AutoBuildingDisplayList; class AutoBuildingDisplayList { public: - AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, - nsIFrame* aForChild, + AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild) + : AutoBuildingDisplayList( + aBuilder, aForChild, aBuilder->GetVisibleRect(), + aBuilder->GetDirtyRect(), aForChild->IsTransformed()){} + + AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild, + const nsRect& aVisibleRect, const nsRect& aDirtyRect, bool aIsRoot) : mBuilder(aBuilder), mPrevFrame(aBuilder->mCurrentFrame), mPrevReferenceFrame(aBuilder->mCurrentReferenceFrame), mPrevLayerEventRegions(aBuilder->mLayerEventRegions), mPrevOffset(aBuilder->mCurrentOffsetToReferenceFrame), + mPrevVisibleRect(aBuilder->mVisibleRect), mPrevDirtyRect(aBuilder->mDirtyRect), mPrevAGR(aBuilder->mCurrentAGR), mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext), @@ -733,12 +769,10 @@ public: } MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(aBuilder->RootReferenceFrame(), *aBuilder->mCurrentAGR)); aBuilder->mCurrentFrame = aForChild; + aBuilder->mVisibleRect = aVisibleRect; aBuilder->mDirtyRect = aDirtyRect; aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot; } - void SetDirtyRect(const nsRect& aRect) { - mBuilder->mDirtyRect = aRect; - } void SetReferenceFrameAndCurrentOffset(const nsIFrame* aFrame, const nsPoint& aOffset) { mBuilder->mCurrentReferenceFrame = aFrame; mBuilder->mCurrentOffsetToReferenceFrame = aOffset; @@ -760,6 +794,7 @@ public: mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame; mBuilder->mLayerEventRegions = mPrevLayerEventRegions; mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset; + mBuilder->mVisibleRect = mPrevVisibleRect; mBuilder->mDirtyRect = mPrevDirtyRect; mBuilder->mCurrentAGR = mPrevAGR; mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext; @@ -773,6 +808,7 @@ public: nsIFrame* mPrevAnimatedGeometryRoot; nsDisplayLayerEventRegions* mPrevLayerEventRegions; nsPoint mPrevOffset; + nsRect mPrevVisibleRect; nsRect mPrevDirtyRect; AnimatedGeometryRoot* mPrevAGR; bool mPrevIsAtRootOfPseudoStackingContext; @@ -981,20 +1017,19 @@ public: return mPreserves3DCtx.mAccumulatedRectLevels; } - // Helpers for tables - nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; } - void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; } - struct OutOfFlowDisplayData { OutOfFlowDisplayData(const DisplayItemClip* aContainingBlockClip, const DisplayItemScrollClip* aContainingBlockScrollClip, + const nsRect &aVisibleRect, const nsRect &aDirtyRect) : mContainingBlockClip(aContainingBlockClip ? *aContainingBlockClip : DisplayItemClip()) , mContainingBlockScrollClip(aContainingBlockScrollClip) + , mVisibleRect(aVisibleRect) , mDirtyRect(aDirtyRect) {} DisplayItemClip mContainingBlockClip; const DisplayItemScrollClip* mContainingBlockScrollClip; + nsRect mVisibleRect; nsRect mDirtyRect; }; @@ -1120,11 +1155,13 @@ public: Preserves3DContext mSavedCtx; }; - const nsRect GetPreserves3DDirtyRect(const nsIFrame *aFrame) const { + const nsRect GetPreserves3DRects(nsRect* aOutVisibleRect) const { + *aOutVisibleRect = mPreserves3DCtx.mVisibleRect; return mPreserves3DCtx.mDirtyRect; } - void SetPreserves3DDirtyRect(const nsRect &aDirtyRect) { - mPreserves3DCtx.mDirtyRect = aDirtyRect; + void SavePreserves3DRects() { + mPreserves3DCtx.mVisibleRect = mVisibleRect; + mPreserves3DCtx.mDirtyRect = mDirtyRect; } bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems; } @@ -1133,8 +1170,7 @@ public: } private: - void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame, - const nsRect& aDirtyRect); + void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame); /** * Returns whether a frame acts as an animated geometry root, optionally @@ -1174,6 +1210,7 @@ private: nsRect mCaretRect; uint32_t mFirstFrameMarkedForDisplay; bool mIsBackgroundOnly; + nsIFrame* mPresShellIgnoreScrollFrame; // This is a per-document flag turning off event handling for all content // in the document, and is set when we enter a subdocument for a pointer- // events:none frame. @@ -1202,7 +1239,6 @@ private: AutoTArray<PresShellState,8> mPresShellStates; AutoTArray<nsIFrame*,400> mFramesMarkedForDisplay; AutoTArray<ThemeGeometry,2> mThemeGeometries; - nsDisplayTableItem* mCurrentTableItem; DisplayListClipState mClipState; // mCurrentFrame is the frame that we're currently calling (or about to call) // BuildDisplayList on. @@ -1229,6 +1265,7 @@ private: nsTHashtable<nsPtrHashKey<nsIFrame> > mAGRBudgetSet; // Relative to mCurrentFrame. + nsRect mVisibleRect; nsRect mDirtyRect; nsRegion mWindowExcludeGlassRegion; nsRegion mWindowOpaqueRegion; @@ -1245,6 +1282,7 @@ private: nsTArray<DisplayItemScrollClip*> mScrollClipsToDestroy; nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy; nsDisplayListBuilderMode mMode; + nsDisplayTableBackgroundSet* mTableBackgroundSet; ViewID mCurrentScrollParentId; ViewID mCurrentScrollbarTarget; uint32_t mCurrentScrollbarFlags; @@ -2287,12 +2325,13 @@ protected: * to the object, and all distinct. */ struct nsDisplayListCollection : public nsDisplayListSet { - nsDisplayListCollection() : - nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4], - &mLists[5]) {} - explicit nsDisplayListCollection(nsDisplayList* aBorderBackground) : - nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4], + explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder) + : nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4], &mLists[5]) {} + explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder, + nsDisplayList* aBorderBackground) + : nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4], + &mLists[5]) {} /** * Sort all lists by content order. @@ -2739,7 +2778,9 @@ public: bool aAllowWillPaintBorderOptimization = true, nsStyleContext* aStyleContext = nullptr, const nsRect& aBackgroundOriginRect = nsRect(), - nsIFrame* aSecondaryReferenceFrame = nullptr); + nsIFrame* aSecondaryReferenceFrame = nullptr, + mozilla::Maybe<nsDisplayListBuilder::AutoBuildingDisplayList>* + aAutoBuildingDisplayList = nullptr); virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 21d20c69f..39bef4d56 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3189,7 +3189,9 @@ nsLayoutUtils::GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect, } builder.EnterPresShell(aFrame); - aFrame->BuildDisplayListForStackingContext(&builder, aRect, &list); + builder.SetVisibleRect(aRect); + builder.SetDirtyRect(aRect); + aFrame->BuildDisplayListForStackingContext(&builder, &list); builder.LeavePresShell(aFrame, nullptr); #ifdef MOZ_DUMP_PAINTING @@ -3448,7 +3450,8 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram nsIScrollableFrame* rootScrollableFrame = presShell->GetRootScrollFrameAsScrollable(); MOZ_ASSERT(rootScrollableFrame); nsRect displayPortBase = aFrame->GetVisualOverflowRectRelativeToSelf(); - Unused << rootScrollableFrame->DecideScrollableLayer(&builder, &displayPortBase, + nsRect temp = displayPortBase; + Unused << rootScrollableFrame->DecideScrollableLayer(&builder, &displayPortBase, &temp, /* aAllowCreateDisplayPort = */ true); } @@ -3538,7 +3541,9 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram PROFILER_LABEL("nsLayoutUtils", "PaintFrame::BuildDisplayList", js::ProfileEntry::Category::GRAPHICS); - aFrame->BuildDisplayListForStackingContext(&builder, dirtyRect, &list); + builder.SetDirtyRect(dirtyRect); + builder.SetVisibleRect(dirtyRect); + aFrame->BuildDisplayListForStackingContext(&builder, &list); } nsIAtom* frameType = aFrame->GetType(); @@ -3550,7 +3555,7 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram nsRect bounds = nsRect(builder.ToReferenceFrame(aFrame), aFrame->GetSize()); nsDisplayListBuilder::AutoBuildingDisplayList - buildingDisplayList(&builder, aFrame, bounds, false); + buildingDisplayList(&builder, aFrame, bounds, bounds, false); presShell->AddPrintPreviewBackgroundItem(builder, list, aFrame, bounds); } else if (frameType != nsGkAtoms::pageFrame) { // For printing, this function is first called on an nsPageFrame, which @@ -3564,7 +3569,7 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram // can monkey with the contents if necessary. canvasArea.IntersectRect(canvasArea, visibleRegion.GetBounds()); nsDisplayListBuilder::AutoBuildingDisplayList - buildingDisplayList(&builder, aFrame, canvasArea, false); + buildingDisplayList(&builder, aFrame, canvasArea, canvasArea, false); presShell->AddCanvasBackgroundColorItem( builder, list, aFrame, canvasArea, aBackstop); } diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 264b52b18..222428a89 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -4894,8 +4894,9 @@ PresShell::CreateRangePaintInfo(nsIDOMRange* aRange, nsIFrame* frame = aNode->AsContent()->GetPrimaryFrame(); // XXX deal with frame being null due to display:contents for (; frame; frame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame)) { - frame->BuildDisplayListForStackingContext(&info->mBuilder, - frame->GetVisualOverflowRect(), &info->mList); + info->mBuilder.SetVisibleRect(frame->GetVisualOverflowRect()); + info->mBuilder.SetDirtyRect(frame->GetVisualOverflowRect()); + frame->BuildDisplayListForStackingContext(&info->mBuilder, &info->mList); } }; if (startParent->NodeType() == nsIDOMNode::TEXT_NODE) { |