diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 334db8181fdc..b8f23cbcdc5a 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -904,7 +904,7 @@ nsIFrame::AddDisplayItem(nsDisplayItem* aItem) items = new DisplayItemArray(); AddProperty(DisplayItems(), items); } - MOZ_ASSERT(!items->Contains(aItem)); + MOZ_DIAGNOSTIC_ASSERT(!items->Contains(aItem)); items->AppendElement(aItem); } diff --git a/layout/generic/nsSimplePageSequenceFrame.cpp b/layout/generic/nsSimplePageSequenceFrame.cpp index b21527132339..d9f8d320d0ad 100644 --- a/layout/generic/nsSimplePageSequenceFrame.cpp +++ b/layout/generic/nsSimplePageSequenceFrame.cpp @@ -720,6 +720,8 @@ void nsSimplePageSequenceFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) { + aBuilder->SetInPageSequence(true); + aBuilder->SetDisablePartialUpdates(true); DisplayBorderBackgroundOutline(aBuilder, aLists); nsDisplayList content; @@ -753,6 +755,7 @@ nsSimplePageSequenceFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, ::ComputePageSequenceTransform)); aLists.Content()->AppendToTop(&content); + aBuilder->SetInPageSequence(false); } //------------------------------------------------------------------------------ diff --git a/layout/painting/RetainedDisplayListBuilder.cpp b/layout/painting/RetainedDisplayListBuilder.cpp index 47e7e10828ea..70f12ed6cf0b 100644 --- a/layout/painting/RetainedDisplayListBuilder.cpp +++ b/layout/painting/RetainedDisplayListBuilder.cpp @@ -117,6 +117,11 @@ RetainedDisplayListBuilder::PreProcessDisplayList(RetainedDisplayList* aList, aList->mOldItems.SetCapacity(aList->Count()); MOZ_ASSERT(aList->mOldItems.IsEmpty()); while (nsDisplayItem* item = aList->RemoveBottom()) { +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED + item->mMergedItem = false; + item->mPreProcessedItem = true; +#endif + if (item->HasDeletedFrame() || !item->CanBeReused()) { size_t i = aList->mOldItems.Length(); aList->mOldItems.AppendElement(OldItemInfo(nullptr)); @@ -275,8 +280,10 @@ public: if (!HasModifiedFrame(aNewItem) && HasMatchingItemInOldList(aNewItem, &oldIndex)) { nsDisplayItem* oldItem = mOldItems[oldIndex.val].mItem; + MOZ_DIAGNOSTIC_ASSERT(oldItem->GetPerFrameKey() == aNewItem->GetPerFrameKey() && + oldItem->Frame() == aNewItem->Frame()); if (!mOldItems[oldIndex.val].IsChanged()) { - MOZ_ASSERT(!mOldItems[oldIndex.val].IsUsed()); + MOZ_DIAGNOSTIC_ASSERT(!mOldItems[oldIndex.val].IsUsed()); if (aNewItem->GetChildren()) { Maybe containerASRForChildren; if (mBuilder->MergeDisplayLists(aNewItem->GetChildren(), @@ -355,6 +362,20 @@ public: Span aDirectPredecessors, const Maybe& aExtraDirectPredecessor) { UpdateContainerASR(aItem); + +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED + nsIFrame::DisplayItemArray* items = aItem->Frame()->GetProperty(nsIFrame::DisplayItems()); + for (nsDisplayItem* i : *items) { + if (i->Frame() == aItem->Frame() && + i->GetPerFrameKey() == aItem->GetPerFrameKey()) { + MOZ_DIAGNOSTIC_ASSERT(!i->mMergedItem); + } + } + + aItem->mMergedItem = true; + aItem->mPreProcessedItem = false; +#endif + mMergedItems.AppendToTop(aItem); MergedListIndex newIndex = mMergedDAG.AddNode(aDirectPredecessors, aExtraDirectPredecessor); return newIndex; diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index 4776128bb9e2..9ad8dcb2716f 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -124,6 +124,26 @@ SpammyLayoutWarningsEnabled() } #endif +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED +void AssertUniqueItem(nsDisplayItem* aItem) { + nsIFrame::DisplayItemArray* items = aItem->Frame()->GetProperty(nsIFrame::DisplayItems()); + if (!items) { + return; + } + for (nsDisplayItem* i : *items) { + if (i != aItem && + !i->HasDeletedFrame() && + i->Frame() == aItem->Frame() && + i->GetPerFrameKey() == aItem->GetPerFrameKey()) { + if (i->mPreProcessedItem) { + continue; + } + MOZ_DIAGNOSTIC_ASSERT(false, "Duplicate display item!"); + } + } +} +#endif + /* static */ bool ActiveScrolledRoot::IsAncestor(const ActiveScrolledRoot* aAncestor, const ActiveScrolledRoot* aDescendant) @@ -996,6 +1016,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, mAllowMergingAndFlattening(true), mWillComputePluginGeometry(false), mInTransform(false), + mInPageSequence(false), mIsInChromePresContext(false), mSyncDecodeImages(false), mIsPaintingToWindow(false), @@ -3087,7 +3108,8 @@ nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) {} nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - const ActiveScrolledRoot* aActiveScrolledRoot) + const ActiveScrolledRoot* aActiveScrolledRoot, + bool aAnonymous) : mFrame(aFrame) , mActiveScrolledRoot(aActiveScrolledRoot) , mAnimatedGeometryRoot(nullptr) @@ -3100,7 +3122,7 @@ nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, #endif { MOZ_COUNT_CTOR(nsDisplayItem); - if (aBuilder->IsRetainingDisplayList()) { + if (aBuilder->IsRetainingDisplayList() && !aAnonymous) { mFrame->AddDisplayItem(this); } mReferenceFrame = aBuilder->FindReferenceFrameFor(aFrame, &mToReferenceFrame); @@ -6090,17 +6112,18 @@ nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder, } nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, - nsIFrame* aFrame, nsDisplayList* aList) + nsIFrame* aFrame, nsDisplayList* aList, bool aAnonymous) : nsDisplayWrapList(aBuilder, aFrame, aList, - aBuilder->CurrentActiveScrolledRoot()) + aBuilder->CurrentActiveScrolledRoot(), false, 0, aAnonymous) {} nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList, const ActiveScrolledRoot* aActiveScrolledRoot, bool aClearClipChain, - uint32_t aIndex) - : nsDisplayItem(aBuilder, aFrame, aActiveScrolledRoot) + uint32_t aIndex, + bool aAnonymous) + : nsDisplayItem(aBuilder, aFrame, aActiveScrolledRoot, aAnonymous) , mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot()) , mOverrideZIndex(0) , mIndex(aIndex) @@ -6143,8 +6166,8 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, } nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, - nsIFrame* aFrame, nsDisplayItem* aItem) - : nsDisplayItem(aBuilder, aFrame) + nsIFrame* aFrame, nsDisplayItem* aItem, bool aAnonymous) + : nsDisplayItem(aBuilder, aFrame, aBuilder->CurrentActiveScrolledRoot(), aAnonymous) , mOverrideZIndex(0) , mIndex(0) , mHasZIndexOverride(false) @@ -9141,7 +9164,7 @@ nsDisplayPerspective::nsDisplayPerspective(nsDisplayListBuilder* aBuilder, nsIFrame* aPerspectiveFrame, nsDisplayList* aList) : nsDisplayItem(aBuilder, aPerspectiveFrame) - , mList(aBuilder, aPerspectiveFrame, aList) + , mList(aBuilder, aPerspectiveFrame, aList, true) , mTransformFrame(aTransformFrame) , mIndex(aBuilder->AllocatePerspectiveItemIndex()) { diff --git a/layout/painting/nsDisplayList.h b/layout/painting/nsDisplayList.h index eb1e267fb4f3..ace8a4fae905 100644 --- a/layout/painting/nsDisplayList.h +++ b/layout/painting/nsDisplayList.h @@ -835,6 +835,9 @@ public: */ void SetInTransform(bool aInTransform) { mInTransform = aInTransform; } + bool IsInPageSequence() const { return mInPageSequence; } + void SetInPageSequence(bool aInPage) { mInPageSequence = aInPage; } + /** * Return true if we're currently building a display list for a * nested presshell. @@ -1979,6 +1982,7 @@ private: // True when we're building a display list that's directly or indirectly // under an nsDisplayTransform bool mInTransform; + bool mInPageSequence; bool mIsInChromePresContext; bool mSyncDecodeImages; bool mIsPaintingToWindow; @@ -2024,6 +2028,10 @@ protected: class nsDisplayWrapList; +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED +void AssertUniqueItem(nsDisplayItem* aItem); +#endif + template MOZ_ALWAYS_INLINE T* MakeDisplayItem(nsDisplayListBuilder* aBuilder, Args&&... aArgs) @@ -2042,6 +2050,14 @@ MakeDisplayItem(nsDisplayListBuilder* aBuilder, Args&&... aArgs) } } +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED + if (aBuilder->IsRetainingDisplayList() && + !aBuilder->IsInPageSequence() && + aBuilder->IsBuilding()) { + AssertUniqueItem(item); + } +#endif + return item; } @@ -2083,7 +2099,8 @@ public: // need to count constructors and destructors. nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame); nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - const ActiveScrolledRoot* aActiveScrolledRoot); + const ActiveScrolledRoot* aActiveScrolledRoot, + bool aAnonymous = false); /** * This constructor is only used in rare cases when we need to construct @@ -2833,12 +2850,18 @@ public: // used by RetainedDisplayListBuilder. void SetOldListIndex(nsDisplayList* aList, OldListIndex aIndex) { +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED mOldList = reinterpret_cast(aList); +#endif mOldListIndex = aIndex; } OldListIndex GetOldListIndex(nsDisplayList* aList) { - MOZ_ASSERT(mOldList == reinterpret_cast(aList)); +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED + if (mOldList != reinterpret_cast(aList)) { + MOZ_CRASH_UNSAFE_PRINTF("Item found was in the wrong list! type %d", GetPerFrameKey()); + } +#endif return mOldListIndex; } @@ -2867,7 +2890,13 @@ protected: // Guaranteed to be contained in GetBounds(). nsRect mVisibleRect; - mozilla::DebugOnly mOldList; +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED +public: + uintptr_t mOldList = 0; + bool mMergedItem = false; + bool mPreProcessedItem = false; +protected: +#endif OldListIndex mOldListIndex; bool mForceNotVisible; @@ -4994,14 +5023,15 @@ public: * Takes all the items from aList and puts them in our list. */ nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - nsDisplayList* aList); + nsDisplayList* aList, bool aAnonymous = false); nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList, const ActiveScrolledRoot* aActiveScrolledRoot, bool aClearClipChain = false, - uint32_t aIndex = 0); + uint32_t aIndex = 0, + bool aAnonymous = false); nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - nsDisplayItem* aItem); + nsDisplayItem* aItem, bool aAnonymous = false); nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) : nsDisplayItem(aBuilder, aFrame) , mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot()) @@ -6275,10 +6305,10 @@ class nsDisplayTransform: public nsDisplayItem public: StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList) : - nsDisplayWrapList(aBuilder, aFrame, aList) {} + nsDisplayWrapList(aBuilder, aFrame, aList, true) {} StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayItem* aItem) : - nsDisplayWrapList(aBuilder, aFrame, aItem) {} + nsDisplayWrapList(aBuilder, aFrame, aItem, true) {} virtual ~StoreList() {} virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override { @@ -6634,6 +6664,12 @@ public: mFrame->Combines3DTransformWithAncestors(); } + virtual void RemoveFrame(nsIFrame* aFrame) override + { + nsDisplayItem::RemoveFrame(aFrame); + mStoredList.RemoveFrame(aFrame); + } + private: void ComputeBounds(nsDisplayListBuilder* aBuilder); void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder); @@ -6808,6 +6844,7 @@ public: mTransformFrame = nullptr; } nsDisplayItem::RemoveFrame(aFrame); + mList.RemoveFrame(aFrame); } private: