diff options
author | win7-7 <win7-7@users.noreply.github.com> | 2020-02-25 00:17:54 +0200 |
---|---|---|
committer | win7-7 <win7-7@users.noreply.github.com> | 2020-02-25 00:17:54 +0200 |
commit | 44c47c50388f526c2d134e16d5debebe94a0faf8 (patch) | |
tree | 5c46b943a3463f67e379eebdbcc8e364eeca9a7c /layout/base | |
parent | 81089ff09437ca99eba3dacf901fdef0de533024 (diff) | |
download | UXP-44c47c50388f526c2d134e16d5debebe94a0faf8.tar UXP-44c47c50388f526c2d134e16d5debebe94a0faf8.tar.gz UXP-44c47c50388f526c2d134e16d5debebe94a0faf8.tar.lz UXP-44c47c50388f526c2d134e16d5debebe94a0faf8.tar.xz UXP-44c47c50388f526c2d134e16d5debebe94a0faf8.zip |
Issue #1355 - Better way to create display items for column backgrounds
Part 1: Remove current table item, as it's never set.
Part 2: Get rid of generic table painting code, and handle each class separately.
Part 4: Hoist outline skipping into col(group) frame code.
Part 5: Skip box-shadow for table column and column groups.
Part 6: Store column and column group backgrounds separately, and then append them before the rest of the table contents.
Part 7: Pass rects in display list coordinates to AppendBackgroundItemsToTop.
Part 8: Create column and column group background display items as part of the cell's BuildDisplayList.
Part 9: Used cached values instead of calling nsDisplayListBuilder::ToReferenceFrame when possible, since it can be expensive when the requested frame isn't the builder's current frame.
Part 10: Make sure we build display items for table parts where only the normal position is visible, since we may need to create background items for ancestors at that position.
Part 11: Create an AutoBuildingDisplayList when we create background items for table columns and column groups, so that we initialize the invalidation state correctly.
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) { |