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

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

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

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

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

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

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

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

@ -3204,8 +3204,7 @@ void ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange,
static Maybe<int32_t> MaxZIndexInList(nsDisplayList* aList,
nsDisplayListBuilder* aBuilder) {
Maybe<int32_t> maxZIndex = Nothing();
for (nsDisplayItem* item = aList->GetBottom(); item;
item = item->GetAbove()) {
for (nsDisplayItem* item : *aList) {
int32_t zIndex = item->ZIndex();
if (zIndex < 0) {
continue;
@ -3480,7 +3479,7 @@ static void ClipItemsExceptCaret(
const DisplayItemClipChain* aExtraClip,
nsTHashMap<nsPtrHashKey<const DisplayItemClipChain>,
const DisplayItemClipChain*>& aCache) {
for (nsDisplayItem* i = aList->GetBottom(); i; i = i->GetAbove()) {
for (nsDisplayItem* i : *aList) {
if (!ShouldBeClippedByFrame(aClipFrame, i->Frame())) {
continue;
}
@ -3575,8 +3574,7 @@ class MOZ_RAII AutoContainsBlendModeCapturer {
static int32_t MaxZIndexInListOfItemsContainedInFrame(nsDisplayList* aList,
nsIFrame* aFrame) {
int32_t maxZIndex = -1;
for (nsDisplayItem* item = aList->GetBottom(); item;
item = item->GetAbove()) {
for (nsDisplayItem* item : *aList) {
nsIFrame* itemFrame = item->Frame();
// Perspective items return the scroll frame as their Frame(), so consider
// 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
// to/from a wrap list without invalidating correctly.
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
// 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) {
for (nsDisplayItem* i = aList->GetBottom(); i != nullptr; i = i->GetAbove()) {
for (nsDisplayItem* i : *aList) {
if (!i->HasDeletedFrame() && i->CanBeReused() &&
!i->Frame()->IsFrameModified()) {
// If we have existing cached geometry for this item, then check that for
@ -758,8 +758,7 @@ class MergeState {
#ifdef DEBUG
void VerifyNotModified(nsDisplayList* aList) {
for (nsDisplayItem* item = aList->GetBottom(); item;
item = item->GetAbove()) {
for (nsDisplayItem* item : *aList) {
MOZ_ASSERT(!AnyContentAncestorModified(item->FrameForInvalidation()));
if (item->GetChildren()) {

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

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

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

@ -3319,40 +3319,75 @@ class nsDisplayList {
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layers::PaintedLayer PaintedLayer;
template <typename T>
class Iterator {
public:
Iterator() : mItem(nullptr) {}
constexpr Iterator() : mCurrent(nullptr), mEnd(nullptr) {}
~Iterator() = default;
Iterator(const Iterator& aOther) = default;
Iterator& operator=(const Iterator& aOther) = default;
explicit Iterator(const nsDisplayList* aList) : mItem(aList->GetBottom()) {}
explicit Iterator(const nsDisplayItem* aItem) : mItem(aItem) {}
explicit Iterator(const nsDisplayList* aList)
: mCurrent(aList->GetBottom()), mEnd(nullptr) {}
explicit Iterator(nsDisplayItem* aStart)
: mCurrent(aStart), mEnd(nullptr) {}
Iterator& operator++() {
mItem = mItem ? mItem->GetAbove() : mItem;
mCurrent = Next();
return *this;
}
nsDisplayItem* operator*() {
MOZ_ASSERT(mCurrent);
return mCurrent;
}
bool operator==(const Iterator& aOther) const {
return mItem == aOther.mItem;
return mCurrent == aOther.mCurrent;
}
bool operator!=(const Iterator& aOther) const {
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:
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); }
DisplayItemIterator end() const { return DisplayItemIterator(); }
Iterator begin() const { return Iterator(this); }
constexpr Iterator end() const { return Iterator(); }
/**
* Create an empty list.