Bug 1720711 - Remove most nsDisplayItem::GetAbove() calls r=mattwoodrow

Replaces direct linked list traversals with iterators.

Differential Revision: https://phabricator.services.mozilla.com/D119985
This commit is contained in:
Miko Mynttinen 2021-07-16 10:55:03 +00:00
Родитель af425d0b7a
Коммит 746fe9865a
9 изменённых файлов: 103 добавлений и 63 удалений

Просмотреть файл

@ -646,8 +646,8 @@ struct DIGroup {
// Reset mHitInfo, it will get updated inside PaintItemRange // Reset mHitInfo, it will get updated inside PaintItemRange
mHitInfo = CompositorHitTestInvisibleToHit; mHitInfo = CompositorHitTestInvisibleToHit;
PaintItemRange(aGrouper, aStartItem, aEndItem, context, recorder, PaintItemRange(aGrouper, nsDisplayList::Range(aStartItem, aEndItem),
rootManager, aResources); context, recorder, rootManager, aResources);
// XXX: set this correctly perhaps using // XXX: set this correctly perhaps using
// aItem->GetOpaqueRegion(aDisplayListBuilder, &snapped). // aItem->GetOpaqueRegion(aDisplayListBuilder, &snapped).
@ -743,14 +743,16 @@ struct DIGroup {
wr::AsImageKey(*mKey)); wr::AsImageKey(*mKey));
} }
void PaintItemRange(Grouper* aGrouper, nsDisplayItem* aStartItem, void PaintItemRange(Grouper* aGrouper, nsDisplayList::Iterator aIter,
nsDisplayItem* aEndItem, gfxContext* aContext, gfxContext* aContext,
WebRenderDrawEventRecorder* aRecorder, WebRenderDrawEventRecorder* aRecorder,
RenderRootStateManager* aRootManager, RenderRootStateManager* aRootManager,
wr::IpcResourceUpdateQueue& aResources) { wr::IpcResourceUpdateQueue& aResources) {
LayerIntSize size = mVisibleRect.Size(); LayerIntSize size = mVisibleRect.Size();
for (nsDisplayItem* item = aStartItem; item != aEndItem; while (aIter.HasNext()) {
item = item->GetAbove()) { nsDisplayItem* item = aIter.GetNext();
MOZ_ASSERT(item);
BlobItemData* data = GetBlobItemData(item); BlobItemData* data = GetBlobItemData(item);
IntRect bounds = data->mRect; IntRect bounds = data->mRect;
auto bottomRight = bounds.BottomRight(); auto bottomRight = bounds.BottomRight();
@ -915,8 +917,8 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
aContext->GetDrawTarget()->FlushItem(aItemBounds); aContext->GetDrawTarget()->FlushItem(aItemBounds);
} else { } else {
aContext->Multiply(ThebesMatrix(trans2d)); aContext->Multiply(ThebesMatrix(trans2d));
aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aContext, aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren),
aRecorder, aRootManager, aResources); aContext, aRecorder, aRootManager, aResources);
} }
if (currentClip.HasClip()) { if (currentClip.HasClip()) {
@ -938,7 +940,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
aItem->GetPerFrameKey()); aItem->GetPerFrameKey());
aContext->GetDrawTarget()->FlushItem(aItemBounds); aContext->GetDrawTarget()->FlushItem(aItemBounds);
aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aContext, aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren), aContext,
aRecorder, aRootManager, aResources); aRecorder, aRootManager, aResources);
aContext->GetDrawTarget()->PopLayer(); aContext->GetDrawTarget()->PopLayer();
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
@ -955,7 +957,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
aItem->GetPerFrameKey()); aItem->GetPerFrameKey());
aContext->GetDrawTarget()->FlushItem(aItemBounds); aContext->GetDrawTarget()->FlushItem(aItemBounds);
aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aContext, aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren), aContext,
aRecorder, aRootManager, aResources); aRecorder, aRootManager, aResources);
aContext->GetDrawTarget()->PopLayer(); aContext->GetDrawTarget()->PopLayer();
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
@ -969,7 +971,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
aItem->GetPerFrameKey()); aItem->GetPerFrameKey());
aContext->GetDrawTarget()->FlushItem(aItemBounds); aContext->GetDrawTarget()->FlushItem(aItemBounds);
aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aContext, aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren), aContext,
aRecorder, aRootManager, aResources); aRecorder, aRootManager, aResources);
aContext->GetDrawTarget()->PopLayer(); aContext->GetDrawTarget()->PopLayer();
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
@ -987,7 +989,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
aItem->GetPerFrameKey()); aItem->GetPerFrameKey());
aContext->GetDrawTarget()->FlushItem(aItemBounds); aContext->GetDrawTarget()->FlushItem(aItemBounds);
aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren),
aContext, aRecorder, aRootManager, aContext, aRecorder, aRootManager,
aResources); aResources);
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
@ -1020,7 +1022,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
} }
default: default:
aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aContext, aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren), aContext,
aRecorder, aRootManager, aResources); aRecorder, aRootManager, aResources);
break; break;
} }
@ -1052,8 +1054,8 @@ static bool HasActiveChildren(const nsDisplayList& aList,
const mozilla::layers::StackingContextHelper& aSc, const mozilla::layers::StackingContextHelper& aSc,
mozilla::layers::RenderRootStateManager* aManager, mozilla::layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) { nsDisplayListBuilder* aDisplayListBuilder) {
for (nsDisplayItem* i = aList.GetBottom(); i; i = i->GetAbove()) { for (nsDisplayItem* item : aList) {
if (IsItemProbablyActive(i, aBuilder, aResources, aSc, aManager, if (IsItemProbablyActive(item, aBuilder, aResources, aSc, aManager,
aDisplayListBuilder, false)) { aDisplayListBuilder, false)) {
return true; return true;
} }
@ -1143,15 +1145,20 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
wr::IpcResourceUpdateQueue& aResources, wr::IpcResourceUpdateQueue& aResources,
DIGroup* aGroup, nsDisplayList* aList, DIGroup* aGroup, nsDisplayList* aList,
const StackingContextHelper& aSc) { const StackingContextHelper& aSc) {
DIGroup* currentGroup = aGroup;
nsDisplayItem* item = aList->GetBottom();
nsDisplayItem* startOfCurrentGroup = item;
RenderRootStateManager* manager = RenderRootStateManager* manager =
aCommandBuilder->mManager->GetRenderRootStateManager(); aCommandBuilder->mManager->GetRenderRootStateManager();
nsDisplayItem* startOfCurrentGroup = nullptr;
DIGroup* currentGroup = aGroup;
// We need to track whether we have active siblings for mixed blend mode. // We need to track whether we have active siblings for mixed blend mode.
bool encounteredActiveItem = false; bool encounteredActiveItem = false;
while (item) {
for (nsDisplayItem* item : *aList) {
if (!startOfCurrentGroup) {
startOfCurrentGroup = item;
}
if (IsItemProbablyActive(item, aBuilder, aResources, aSc, manager, if (IsItemProbablyActive(item, aBuilder, aResources, aSc, manager,
mDisplayListBuilder, encounteredActiveItem)) { mDisplayListBuilder, encounteredActiveItem)) {
encounteredActiveItem = true; encounteredActiveItem = true;
@ -1225,15 +1232,12 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
sIndent--; sIndent--;
} }
startOfCurrentGroup = nullptr;
currentGroup = &groupData->mFollowingGroup; currentGroup = &groupData->mFollowingGroup;
startOfCurrentGroup = item->GetAbove();
} else { // inactive item } else { // inactive item
ConstructItemInsideInactive(aCommandBuilder, aBuilder, aResources, ConstructItemInsideInactive(aCommandBuilder, aBuilder, aResources,
currentGroup, item, aSc); currentGroup, item, aSc);
} }
item = item->GetAbove();
} }
currentGroup->EndGroup(aCommandBuilder->mManager, aDisplayListBuilder, currentGroup->EndGroup(aCommandBuilder->mManager, aDisplayListBuilder,
@ -1247,12 +1251,10 @@ bool Grouper::ConstructGroupInsideInactive(
WebRenderCommandBuilder* aCommandBuilder, wr::DisplayListBuilder& aBuilder, WebRenderCommandBuilder* aCommandBuilder, wr::DisplayListBuilder& aBuilder,
wr::IpcResourceUpdateQueue& aResources, DIGroup* aGroup, wr::IpcResourceUpdateQueue& aResources, DIGroup* aGroup,
nsDisplayList* aList, const StackingContextHelper& aSc) { nsDisplayList* aList, const StackingContextHelper& aSc) {
nsDisplayItem* item = aList->GetBottom();
bool invalidated = false; bool invalidated = false;
while (item) { for (nsDisplayItem* item : *aList) {
invalidated |= ConstructItemInsideInactive(aCommandBuilder, aBuilder, invalidated |= ConstructItemInsideInactive(aCommandBuilder, aBuilder,
aResources, aGroup, item, aSc); aResources, aGroup, item, aSc);
item = item->GetAbove();
} }
return invalidated; return invalidated;
} }

Просмотреть файл

@ -5160,7 +5160,7 @@ void PresShell::AddPrintPreviewBackgroundItem(nsDisplayListBuilder* aBuilder,
static bool AddCanvasBackgroundColor(const nsDisplayList* aList, static bool AddCanvasBackgroundColor(const nsDisplayList* aList,
nsIFrame* aCanvasFrame, nscolor aColor, nsIFrame* aCanvasFrame, nscolor aColor,
bool aCSSBackgroundColor) { bool aCSSBackgroundColor) {
for (nsDisplayItem* i = aList->GetBottom(); i; i = i->GetAbove()) { for (nsDisplayItem* i : *aList) {
const DisplayItemType type = i->GetType(); const DisplayItemType type = i->GetType();
if (i->Frame() == aCanvasFrame && if (i->Frame() == aCanvasFrame &&
@ -5803,7 +5803,7 @@ void PresShell::ProcessSynthMouseMoveEvent(bool aFromScroll) {
/* static */ /* static */
void PresShell::MarkFramesInListApproximatelyVisible( void PresShell::MarkFramesInListApproximatelyVisible(
const nsDisplayList& aList) { const nsDisplayList& aList) {
for (nsDisplayItem* item = aList.GetBottom(); item; item = item->GetAbove()) { for (nsDisplayItem* item : aList) {
nsDisplayList* sublist = item->GetChildren(); nsDisplayList* sublist = item->GetChildren();
if (sublist) { if (sublist) {
MarkFramesInListApproximatelyVisible(*sublist); MarkFramesInListApproximatelyVisible(*sublist);

Просмотреть файл

@ -179,7 +179,7 @@ static void PrintDisplayListTo(nsDisplayListBuilder* aBuilder,
aStream << "<ul>"; aStream << "<ul>";
} }
for (nsDisplayItem* i = aList.GetBottom(); i != nullptr; i = i->GetAbove()) { for (nsDisplayItem* i : aList) {
if (aDumpHtml) { if (aDumpHtml) {
aStream << "<li>"; aStream << "<li>";
} }

Просмотреть файл

@ -2953,7 +2953,7 @@ static RetainedDisplayListBuilder* GetOrCreateRetainedDisplayListBuilder(
void PrintHitTestInfoStatsInternal(nsDisplayList* aList, int& aTotal, void PrintHitTestInfoStatsInternal(nsDisplayList* aList, int& aTotal,
int& aHitTest, int& aVisible, int& aHitTest, int& aVisible,
int& aSpecial) { int& aSpecial) {
for (nsDisplayItem* i = aList->GetBottom(); i; i = i->GetAbove()) { for (nsDisplayItem* i : *aList) {
aTotal++; aTotal++;
if (i->GetChildren()) { if (i->GetChildren()) {

Просмотреть файл

@ -3204,8 +3204,7 @@ void ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange,
static Maybe<int32_t> MaxZIndexInList(nsDisplayList* aList, static Maybe<int32_t> MaxZIndexInList(nsDisplayList* aList,
nsDisplayListBuilder* aBuilder) { nsDisplayListBuilder* aBuilder) {
Maybe<int32_t> maxZIndex = Nothing(); Maybe<int32_t> maxZIndex = Nothing();
for (nsDisplayItem* item = aList->GetBottom(); item; for (nsDisplayItem* item : *aList) {
item = item->GetAbove()) {
int32_t zIndex = item->ZIndex(); int32_t zIndex = item->ZIndex();
if (zIndex < 0) { if (zIndex < 0) {
continue; continue;
@ -3480,7 +3479,7 @@ static void ClipItemsExceptCaret(
const DisplayItemClipChain* aExtraClip, const DisplayItemClipChain* aExtraClip,
nsTHashMap<nsPtrHashKey<const DisplayItemClipChain>, nsTHashMap<nsPtrHashKey<const DisplayItemClipChain>,
const DisplayItemClipChain*>& aCache) { const DisplayItemClipChain*>& aCache) {
for (nsDisplayItem* i = aList->GetBottom(); i; i = i->GetAbove()) { for (nsDisplayItem* i : *aList) {
if (!ShouldBeClippedByFrame(aClipFrame, i->Frame())) { if (!ShouldBeClippedByFrame(aClipFrame, i->Frame())) {
continue; continue;
} }
@ -3575,8 +3574,7 @@ class MOZ_RAII AutoContainsBlendModeCapturer {
static int32_t MaxZIndexInListOfItemsContainedInFrame(nsDisplayList* aList, static int32_t MaxZIndexInListOfItemsContainedInFrame(nsDisplayList* aList,
nsIFrame* aFrame) { nsIFrame* aFrame) {
int32_t maxZIndex = -1; int32_t maxZIndex = -1;
for (nsDisplayItem* item = aList->GetBottom(); item; for (nsDisplayItem* item : *aList) {
item = item->GetAbove()) {
nsIFrame* itemFrame = item->Frame(); nsIFrame* itemFrame = item->Frame();
// Perspective items return the scroll frame as their Frame(), so consider // Perspective items return the scroll frame as their Frame(), so consider
// their TransformFrame() instead. // their TransformFrame() instead.

Просмотреть файл

@ -3802,7 +3802,7 @@ static nsDisplayItem* WrapInWrapList(nsDisplayListBuilder* aBuilder,
// on which items we build, so we need to ensure that we don't transition // on which items we build, so we need to ensure that we don't transition
// to/from a wrap list without invalidating correctly. // to/from a wrap list without invalidating correctly.
bool needsWrapList = bool needsWrapList =
item->GetAbove() || item->Frame() != aFrame || item->GetChildren(); aList->Count() > 1 || item->Frame() != aFrame || item->GetChildren();
// If we have an explicit container item (that can't change without an // If we have an explicit container item (that can't change without an
// invalidation) or we're doing a full build and don't need a wrap list, then // invalidation) or we're doing a full build and don't need a wrap list, then

Просмотреть файл

@ -74,7 +74,7 @@ RetainedDisplayListData* GetOrSetRetainedDisplayListData(nsIFrame* aRootFrame) {
} }
static void MarkFramesWithItemsAndImagesModified(nsDisplayList* aList) { static void MarkFramesWithItemsAndImagesModified(nsDisplayList* aList) {
for (nsDisplayItem* i = aList->GetBottom(); i != nullptr; i = i->GetAbove()) { for (nsDisplayItem* i : *aList) {
if (!i->HasDeletedFrame() && i->CanBeReused() && if (!i->HasDeletedFrame() && i->CanBeReused() &&
!i->Frame()->IsFrameModified()) { !i->Frame()->IsFrameModified()) {
// If we have existing cached geometry for this item, then check that for // If we have existing cached geometry for this item, then check that for
@ -758,8 +758,7 @@ class MergeState {
#ifdef DEBUG #ifdef DEBUG
void VerifyNotModified(nsDisplayList* aList) { void VerifyNotModified(nsDisplayList* aList) {
for (nsDisplayItem* item = aList->GetBottom(); item; for (nsDisplayItem* item : *aList) {
item = item->GetAbove()) {
MOZ_ASSERT(!AnyContentAncestorModified(item->FrameForInvalidation())); MOZ_ASSERT(!AnyContentAncestorModified(item->FrameForInvalidation()));
if (item->GetChildren()) { if (item->GetChildren()) {

Просмотреть файл

@ -3970,14 +3970,20 @@ nsDisplayBackgroundImage::ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
} }
static void CheckForBorderItem(nsDisplayItem* aItem, uint32_t& aFlags) { static void CheckForBorderItem(nsDisplayItem* aItem, uint32_t& aFlags) {
nsDisplayItem* nextItem = aItem->GetAbove(); // TODO(miko): Iterating over the display list like this is suspicious.
while (nextItem && nextItem->GetType() == DisplayItemType::TYPE_BACKGROUND) { for (nsDisplayList::Iterator it(aItem); it.HasNext(); ++it) {
nextItem = nextItem->GetAbove(); nsDisplayItem* next = *it;
if (next->GetType() == DisplayItemType::TYPE_BACKGROUND) {
continue;
} }
if (nextItem && nextItem->Frame() == aItem->Frame() &&
nextItem->GetType() == DisplayItemType::TYPE_BORDER) { if (next->GetType() == DisplayItemType::TYPE_BORDER) {
aFlags |= nsCSSRendering::PAINTBG_WILL_PAINT_BORDER; aFlags |= nsCSSRendering::PAINTBG_WILL_PAINT_BORDER;
} }
break;
}
} }
LayerState nsDisplayBackgroundImage::GetLayerState( LayerState nsDisplayBackgroundImage::GetLayerState(
@ -5530,11 +5536,11 @@ nsDisplayWrapList::nsDisplayWrapList(
return; return;
} }
nsDisplayItem* i = mListPtr->GetBottom(); nsDisplayItem* item = mListPtr->GetBottom();
if (i && if (item && item->Frame() == mFrame &&
(!i->GetAbove() || i->GetType() == DisplayItemType::TYPE_TRANSFORM) && (mListPtr->Count() == 1 ||
i->Frame() == mFrame) { item->GetType() == DisplayItemType::TYPE_TRANSFORM)) {
MOZ_ASSERT(mReferenceFrame == i->ReferenceFrame()); MOZ_ASSERT(mReferenceFrame == item->ReferenceFrame());
} }
#endif #endif
} }

Просмотреть файл

@ -3319,40 +3319,75 @@ class nsDisplayList {
typedef mozilla::layers::LayerManager LayerManager; typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layers::PaintedLayer PaintedLayer; typedef mozilla::layers::PaintedLayer PaintedLayer;
template <typename T>
class Iterator { class Iterator {
public: public:
Iterator() : mItem(nullptr) {} constexpr Iterator() : mCurrent(nullptr), mEnd(nullptr) {}
~Iterator() = default; ~Iterator() = default;
Iterator(const Iterator& aOther) = default; Iterator(const Iterator& aOther) = default;
Iterator& operator=(const Iterator& aOther) = default; Iterator& operator=(const Iterator& aOther) = default;
explicit Iterator(const nsDisplayList* aList) : mItem(aList->GetBottom()) {} explicit Iterator(const nsDisplayList* aList)
explicit Iterator(const nsDisplayItem* aItem) : mItem(aItem) {} : mCurrent(aList->GetBottom()), mEnd(nullptr) {}
explicit Iterator(nsDisplayItem* aStart)
: mCurrent(aStart), mEnd(nullptr) {}
Iterator& operator++() { Iterator& operator++() {
mItem = mItem ? mItem->GetAbove() : mItem; mCurrent = Next();
return *this; return *this;
} }
nsDisplayItem* operator*() {
MOZ_ASSERT(mCurrent);
return mCurrent;
}
bool operator==(const Iterator& aOther) const { bool operator==(const Iterator& aOther) const {
return mItem == aOther.mItem; return mCurrent == aOther.mCurrent;
} }
bool operator!=(const Iterator& aOther) const { bool operator!=(const Iterator& aOther) const {
return !operator==(aOther); return !operator==(aOther);
} }
T* operator*() { return mItem; } bool HasNext() const { return mCurrent != nullptr; }
nsDisplayItem* GetNext() {
MOZ_ASSERT(HasNext());
auto* next = mCurrent;
operator++();
return next;
}
protected:
Iterator(nsDisplayItem* aStart, nsDisplayItem* aEnd)
: mCurrent(aStart), mEnd(aEnd) {}
nsDisplayItem* Next() const {
if (!mCurrent) {
return nullptr;
}
auto* next = mCurrent->GetAbove();
if (next == mEnd) {
return nullptr;
}
return next;
}
private: private:
T* mItem; nsDisplayItem* mCurrent;
nsDisplayItem* mEnd;
}; };
using DisplayItemIterator = Iterator<nsDisplayItem>; class Range final : public Iterator {
public:
Range(nsDisplayItem* aStart, nsDisplayItem* aEnd)
: Iterator(aStart, aEnd) {}
};
DisplayItemIterator begin() const { return DisplayItemIterator(this); } Iterator begin() const { return Iterator(this); }
DisplayItemIterator end() const { return DisplayItemIterator(); } constexpr Iterator end() const { return Iterator(); }
/** /**
* Create an empty list. * Create an empty list.