Bug 1714584 - Part 1: Decouple nsDisplayList internal list from nsDisplayItems r=mstange

Differential Revision: https://phabricator.services.mozilla.com/D138152
This commit is contained in:
Miko Mynttinen 2022-02-22 23:42:18 +00:00
Родитель 5e97d6f437
Коммит ddec6eef59
23 изменённых файлов: 387 добавлений и 391 удалений

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

@ -558,7 +558,8 @@ struct DIGroup {
nsDisplayListBuilder* aDisplayListBuilder,
wr::DisplayListBuilder& aBuilder,
wr::IpcResourceUpdateQueue& aResources, Grouper* aGrouper,
nsDisplayItem* aStartItem, nsDisplayItem* aEndItem) {
nsDisplayList::iterator aStartItem,
nsDisplayList::iterator aEndItem) {
GP("\n\n");
GP("Begin EndGroup\n");
@ -654,6 +655,7 @@ struct DIGroup {
RenderRootStateManager* rootManager =
aWrManager->GetRenderRootStateManager();
bool empty = aStartItem == aEndItem;
if (empty) {
ClearImageKey(rootManager, true);
@ -663,8 +665,8 @@ struct DIGroup {
// Reset mHitInfo, it will get updated inside PaintItemRange
mHitInfo = CompositorHitTestInvisibleToHit;
PaintItemRange(aGrouper, nsDisplayList::Range(aStartItem, aEndItem),
context, recorder, rootManager, aResources);
PaintItemRange(aGrouper, aStartItem, aEndItem, context, recorder,
rootManager, aResources);
// XXX: set this correctly perhaps using
// aItem->GetOpaqueRegion(aDisplayListBuilder, &snapped).
@ -769,14 +771,14 @@ struct DIGroup {
SideBits::eNone);
}
void PaintItemRange(Grouper* aGrouper, nsDisplayList::Iterator aIter,
gfxContext* aContext,
void PaintItemRange(Grouper* aGrouper, nsDisplayList::iterator aStartItem,
nsDisplayList::iterator aEndItem, gfxContext* aContext,
WebRenderDrawEventRecorder* aRecorder,
RenderRootStateManager* aRootManager,
wr::IpcResourceUpdateQueue& aResources) {
LayerIntSize size = mVisibleRect.Size();
while (aIter.HasNext()) {
nsDisplayItem* item = aIter.GetNext();
for (auto it = aStartItem; it != aEndItem; ++it) {
nsDisplayItem* item = *it;
MOZ_ASSERT(item);
BlobItemData* data = GetBlobItemData(item);
@ -949,7 +951,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
aContext->GetDrawTarget()->FlushItem(aItemBounds);
} else {
aContext->Multiply(ThebesMatrix(trans2d));
aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren),
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
aContext, aRecorder, aRootManager, aResources);
}
@ -972,8 +974,8 @@ 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, nsDisplayList::Iterator(aChildren), aContext,
aRecorder, aRootManager, aResources);
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
aContext, aRecorder, aRootManager, aResources);
aContext->GetDrawTarget()->PopLayer();
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
aItem->GetPerFrameKey());
@ -989,8 +991,8 @@ 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, nsDisplayList::Iterator(aChildren), aContext,
aRecorder, aRootManager, aResources);
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
aContext, aRecorder, aRootManager, aResources);
aContext->GetDrawTarget()->PopLayer();
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
aItem->GetPerFrameKey());
@ -1003,8 +1005,8 @@ 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, nsDisplayList::Iterator(aChildren), aContext,
aRecorder, aRootManager, aResources);
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
aContext, aRecorder, aRootManager, aResources);
aContext->GetDrawTarget()->PopLayer();
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
aItem->GetPerFrameKey());
@ -1023,7 +1025,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, nsDisplayList::Iterator(aChildren),
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
aContext, aRecorder, aRootManager,
aResources);
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
@ -1061,8 +1063,8 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
}
default:
aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren), aContext,
aRecorder, aRootManager, aResources);
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
aContext, aRecorder, aRootManager, aResources);
break;
}
}
@ -1186,15 +1188,18 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
RenderRootStateManager* manager =
aCommandBuilder->mManager->GetRenderRootStateManager();
nsDisplayItem* startOfCurrentGroup = nullptr;
nsDisplayList::iterator startOfCurrentGroup = aList->end();
DIGroup* currentGroup = aGroup;
// We need to track whether we have active siblings for mixed blend mode.
bool encounteredActiveItem = false;
for (nsDisplayItem* item : *aList) {
if (!startOfCurrentGroup) {
startOfCurrentGroup = item;
for (auto it = aList->begin(); it != aList->end(); ++it) {
nsDisplayItem* item = *it;
MOZ_ASSERT(item);
if (startOfCurrentGroup == aList->end()) {
startOfCurrentGroup = it;
}
if (IsItemProbablyActive(item, aBuilder, aResources, aSc, manager,
@ -1250,7 +1255,7 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
currentGroup->EndGroup(aCommandBuilder->mManager, aDisplayListBuilder,
aBuilder, aResources, this, startOfCurrentGroup,
item);
it);
{
auto spaceAndClipChain =
@ -1270,7 +1275,7 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
sIndent--;
}
startOfCurrentGroup = nullptr;
startOfCurrentGroup = aList->end();
currentGroup = &groupData->mFollowingGroup;
} else { // inactive item
ConstructItemInsideInactive(aCommandBuilder, aBuilder, aResources,
@ -1280,7 +1285,7 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
currentGroup->EndGroup(aCommandBuilder->mManager, aDisplayListBuilder,
aBuilder, aResources, this, startOfCurrentGroup,
nullptr);
aList->end());
}
// This does a pass over the display lists and will join the display items

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

@ -234,7 +234,8 @@ struct RangePaintInfo {
RangePaintInfo(nsRange* aRange, nsIFrame* aFrame)
: mRange(aRange),
mBuilder(aFrame, nsDisplayListBuilderMode::Painting, false) {
mBuilder(aFrame, nsDisplayListBuilderMode::Painting, false),
mList(&mBuilder) {
MOZ_COUNT_CTOR(RangePaintInfo);
mBuilder.BeginFrame();
}
@ -4909,7 +4910,7 @@ UniquePtr<RangePaintInfo> PresShell::CreateRangePaintInfo(
ViewID zoomedId =
nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent());
nsDisplayList wrapped;
nsDisplayList wrapped(&info->mBuilder);
wrapped.AppendNewToTop<nsDisplayAsyncZoom>(&info->mBuilder, rootScrollFrame,
&info->mList, nullptr, zoomedId);
info->mList.AppendToTop(&wrapped);
@ -5215,8 +5216,13 @@ already_AddRefed<SourceSurface> PresShell::RenderSelection(
aScreenRect, aFlags);
}
void AddDisplayItemToBottom(nsDisplayList* aList, nsDisplayItem* aItem) {
nsDisplayList list;
void AddDisplayItemToBottom(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList, nsDisplayItem* aItem) {
if (!aItem) {
return;
}
nsDisplayList list(aBuilder);
list.AppendToTop(aItem);
list.AppendToTop(aList);
aList->AppendToTop(&list);
@ -5228,7 +5234,7 @@ void PresShell::AddPrintPreviewBackgroundItem(nsDisplayListBuilder* aBuilder,
const nsRect& aBounds) {
nsDisplayItem* item = MakeDisplayItem<nsDisplaySolidColor>(
aBuilder, aFrame, aBounds, NS_RGB(115, 115, 115));
AddDisplayItemToBottom(aList, item);
AddDisplayItemToBottom(aBuilder, aList, item);
}
static bool AddCanvasBackgroundColor(const nsDisplayList* aList,
@ -5308,7 +5314,7 @@ void PresShell::AddCanvasBackgroundColorItem(
if (!addedScrollingBackgroundColor || forceUnscrolledItem) {
nsDisplayItem* item = MakeDisplayItem<nsDisplaySolidColor>(
aBuilder, aFrame, aBounds, bgcolor);
AddDisplayItemToBottom(aList, item);
AddDisplayItemToBottom(aBuilder, aList, item);
}
}

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

@ -2521,7 +2521,7 @@ bool nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame,
nsDisplayListBuilderMode::TransformComputation,
false /*don't build caret*/);
builder.BeginFrame();
nsDisplayList list;
nsDisplayList list(&builder);
nsDisplayTransform* item =
MakeDisplayItem<nsDisplayTransform>(&builder, aFrame, &list, nsRect());
MOZ_ASSERT(item);
@ -2716,7 +2716,7 @@ nsresult nsLayoutUtils::GetFramesForArea(RelativeTo aRelativeTo,
nsDisplayListBuilder builder(frame, nsDisplayListBuilderMode::EventDelivery,
false);
builder.BeginFrame();
nsDisplayList list;
nsDisplayList list(&builder);
if (aOptions.mBits.contains(FrameForPointOption::IgnorePaintSuppression)) {
builder.IgnorePaintSuppression();
@ -3058,7 +3058,7 @@ struct TemporaryDisplayListBuilder {
TemporaryDisplayListBuilder(nsIFrame* aFrame,
nsDisplayListBuilderMode aBuilderMode,
const bool aBuildCaret)
: mBuilder(aFrame, aBuilderMode, aBuildCaret) {}
: mBuilder(aFrame, aBuilderMode, aBuildCaret), mList(&mBuilder) {}
~TemporaryDisplayListBuilder() { mList.DeleteAll(&mBuilder); }
@ -3354,7 +3354,6 @@ void nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
}
list->DeleteAll(builder);
list->RestoreState();
builder->ClearRetainedWindowRegions();
builder->ClearWillChangeBudgets();

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

@ -73,7 +73,7 @@ bool nsHTMLButtonControlFrame::ShouldClipPaintingToBorderBox() {
void nsHTMLButtonControlFrame::BuildDisplayList(
nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) {
nsDisplayList onTop;
nsDisplayList onTop(aBuilder);
if (IsVisibleForPainting()) {
// Clip the button itself to its border area for event hit testing.
Maybe<DisplayListClipState::AutoSaveRestore> eventClipState;

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

@ -285,6 +285,7 @@ TextOverflow::TextOverflow(nsDisplayListBuilder* aBuilder,
mBuilder(aBuilder),
mBlock(aBlockFrame),
mScrollableFrame(nsLayoutUtils::GetScrollableFrameFor(aBlockFrame)),
mMarkerList(aBuilder),
mBlockSize(aBlockFrame->GetSize()),
mBlockWM(aBlockFrame->GetWritingMode()),
mAdjustForPixelSnapping(false) {

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

@ -124,7 +124,7 @@ static void BuildDisplayListForTopLayerFrame(nsDisplayListBuilder* aBuilder,
nsDisplayListBuilder::AutoBuildingDisplayList buildingForChild(
aBuilder, aFrame, visible, dirty);
nsDisplayList list;
nsDisplayList list(aBuilder);
aFrame->BuildDisplayListForStackingContext(aBuilder, &list);
aList->AppendToTop(&list);
}
@ -135,7 +135,7 @@ static bool BackdropListIsOpaque(ViewportFrame* aFrame,
// The common case for ::backdrop elements on the top layer is a single
// fixed position container, holding an opaque background color covering
// the whole viewport.
if (aList->Count() != 1 ||
if (aList->Length() != 1 ||
aList->GetTop()->GetType() != DisplayItemType::TYPE_FIXED_POSITION) {
return false;
}
@ -168,7 +168,7 @@ static bool BackdropListIsOpaque(ViewportFrame* aFrame,
nsDisplayWrapList* ViewportFrame::BuildDisplayListForTopLayer(
nsDisplayListBuilder* aBuilder, bool* aIsOpaque) {
nsDisplayList topLayerList;
nsDisplayList topLayerList(aBuilder);
nsTArray<dom::Element*> topLayer = PresContext()->Document()->GetTopLayer();
for (dom::Element* elem : topLayer) {

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

@ -502,7 +502,7 @@ void nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
return false;
}();
nsDisplayList layerItems;
nsDisplayList layerItems(aBuilder);
// Create separate items for each background layer.
const nsStyleImageLayers& layers = bg->StyleBackground()->mImage;
@ -518,7 +518,7 @@ void nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this);
const ActiveScrolledRoot* thisItemASR = asr;
nsDisplayList thisItemList;
nsDisplayList thisItemList(aBuilder);
nsDisplayBackgroundImage::InitData bgData =
nsDisplayBackgroundImage::GetInitData(aBuilder, this, i, bgRect, bg);

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

@ -4132,7 +4132,7 @@ void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// Effectively we are double clipping to the viewport, at potentially
// different async scales.
nsDisplayList resultList;
nsDisplayList resultList(aBuilder);
set.SerializeWithCorrectZOrder(&resultList, mOuter->GetContent());
if (blendCapture.CaptureContainsBlendMode()) {

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

@ -2924,7 +2924,7 @@ static bool ItemParticipatesIn3DContext(nsIFrame* aAncestor,
const bool isContainer = type == DisplayItemType::TYPE_WRAP_LIST ||
type == DisplayItemType::TYPE_CONTAINER;
if (isContainer && aItem->GetChildren()->Count() == 1) {
if (isContainer && aItem->GetChildren()->Length() == 1) {
// If the wraplist has only one child item, use the type of that item.
type = aItem->GetChildren()->GetBottom()->GetType();
}
@ -3131,7 +3131,6 @@ bool TryToReuseStackingContextItem(nsDisplayListBuilder* aBuilder,
}
nsDisplayItem* container = *res;
MOZ_ASSERT(!container->GetAbove());
MOZ_ASSERT(container->Frame() == aFrame);
DL_LOGD("RDL - Found SC item %p (%s) (frame: %p)", container,
container->Name(), container->Frame());
@ -3341,7 +3340,7 @@ void nsIFrame::BuildDisplayListForStackingContext(
bool usingSVGEffects = usingFilter || usingMask;
nsRect visibleRectOutsideSVGEffects = visibleRect;
nsDisplayList hoistedScrollInfoItemsStorage;
nsDisplayList hoistedScrollInfoItemsStorage(aBuilder);
if (usingSVGEffects) {
dirtyRect =
SVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
@ -3570,7 +3569,7 @@ void nsIFrame::BuildDisplayListForStackingContext(
content = PresContext()->Document()->GetRootElement();
}
nsDisplayList resultList;
nsDisplayList resultList(aBuilder);
set.SerializeWithCorrectZOrder(&resultList, content);
#ifdef DEBUG
@ -3697,8 +3696,8 @@ void nsIFrame::BuildDisplayListForStackingContext(
if (isTransformed && extend3DContext) {
// Install dummy nsDisplayTransform as a leaf containing
// descendants not participating this 3D rendering context.
nsDisplayList nonparticipants;
nsDisplayList participants;
nsDisplayList nonparticipants(aBuilder);
nsDisplayList participants(aBuilder);
int index = 1;
nsDisplayItem* separator = nullptr;
@ -3880,7 +3879,7 @@ void nsIFrame::BuildDisplayListForStackingContext(
}
nsDisplayItem* container = resultList.GetBottom();
if (resultList.Count() > 1 || container->Frame() != this) {
if (resultList.Length() > 1 || container->Frame() != this) {
container = MakeDisplayItem<nsDisplayContainer>(
aBuilder, this, containerItemASR, &resultList);
} else {
@ -3918,7 +3917,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 =
aList->Count() > 1 || item->Frame() != aFrame || item->GetChildren();
aList->Length() > 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
@ -4340,8 +4339,8 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
awayFromCommonPath = true;
}
nsDisplayList list;
nsDisplayList extraPositionedDescendants;
nsDisplayList list(aBuilder);
nsDisplayList extraPositionedDescendants(aBuilder);
const ActiveScrolledRoot* wrapListASR;
bool builtContainerItem = false;
if (isStackingContext) {

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

@ -301,7 +301,7 @@ static void BuildDisplayListForExtraPage(nsDisplayListBuilder* aBuilder,
if (!aExtraPage->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
return;
}
nsDisplayList list;
nsDisplayList list(aBuilder);
aExtraPage->BuildDisplayListForStackingContext(aBuilder, &list);
PruneDisplayListForExtraPage(aBuilder, aPage, &list);
aList->AppendToTop(&list);
@ -332,7 +332,7 @@ void nsPageContentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsDisplayListCollection set(aBuilder);
nsDisplayList content;
nsDisplayList content(aBuilder);
{
const nsRect clipRect(aBuilder->ToReferenceFrame(this), GetSize());
DisplayListClipState::AutoSaveRestore clipState(aBuilder);

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

@ -585,7 +585,7 @@ nsSize nsPageFrame::ComputePageSize() const {
void nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) {
nsDisplayList content;
nsDisplayList content(aBuilder);
nsDisplayListSet set(&content, &content, &content, &content, &content,
&content);
{

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

@ -731,7 +731,7 @@ void nsPageSequenceFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
aBuilder->SetDisablePartialUpdates(true);
DisplayBorderBackgroundOutline(aBuilder, aLists);
nsDisplayList content;
nsDisplayList content(aBuilder);
{
// Clear clip state while we construct the children of the

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

@ -310,7 +310,7 @@ static void WrapBackgroundColorInOwnLayer(nsDisplayListBuilder* aBuilder,
nsDisplayItem* item;
while ((item = aList->RemoveBottom()) != nullptr) {
if (item->GetType() == DisplayItemType::TYPE_BACKGROUND_COLOR) {
nsDisplayList tmpList;
nsDisplayList tmpList(aBuilder);
tmpList.AppendToTop(item);
item = MakeDisplayItemWithIndex<nsDisplayOwnLayer>(
aBuilder, aFrame, /* aIndex = */ nsDisplayOwnLayer::OwnLayerForSubdoc,
@ -438,7 +438,7 @@ void nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
needsOwnLayer = true;
}
nsDisplayList childItems;
nsDisplayList childItems(aBuilder);
{
DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);

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

@ -193,7 +193,7 @@ bool RetainedDisplayListBuilder::PreProcessDisplayList(
// a merge.
const bool initializeOldItems = aList->mOldItems.IsEmpty();
if (initializeOldItems) {
aList->mOldItems.SetCapacity(aList->Count());
aList->mOldItems.SetCapacity(aList->Length());
} else {
MOZ_RELEASE_ASSERT(!initializeDAG);
}
@ -201,7 +201,7 @@ bool RetainedDisplayListBuilder::PreProcessDisplayList(
MOZ_RELEASE_ASSERT(
initializeDAG ||
aList->mDAG.Length() ==
(initializeOldItems ? aList->Count() : aList->mOldItems.Length()));
(initializeOldItems ? aList->Length() : aList->mOldItems.Length()));
nsDisplayList out;
@ -349,7 +349,6 @@ bool RetainedDisplayListBuilder::PreProcessDisplayList(
}
MOZ_RELEASE_ASSERT(aList->mOldItems.Length() == aList->mDAG.Length());
aList->RestoreState();
if (aKeepLinked) {
aList->AppendToTop(&out);
@ -462,6 +461,7 @@ class MergeState {
mOldDAG(
std::move(*reinterpret_cast<DirectedAcyclicGraph<OldListUnits>*>(
&aOldList.mDAG))),
mMergedItems(aBuilder->Builder()),
mOuterItem(aOuterItem),
mResultIsModified(false) {
mMergedDAG.EnsureCapacityFor(mOldDAG);
@ -538,7 +538,7 @@ class MergeState {
}
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
nsDisplayList empty;
nsDisplayList empty(mBuilder->Builder());
const bool modified = mBuilder->MergeDisplayLists(
aNewItem ? aNewItem->GetChildren() : &empty, aOldItem->GetChildren(),
aOutItem->GetChildren(), containerASRForChildren, aOutItem);
@ -636,10 +636,10 @@ class MergeState {
ProcessOldNode(OldListIndex(i), std::move(directPredecessors));
}
RetainedDisplayList result;
RetainedDisplayList result(mBuilder->Builder());
result.AppendToTop(&mMergedItems);
result.mDAG = std::move(mMergedDAG);
MOZ_RELEASE_ASSERT(result.mDAG.Length() == result.Count());
MOZ_RELEASE_ASSERT(result.mDAG.Length() == result.Length());
return result;
}
@ -1563,14 +1563,14 @@ void CollectStackingContextItems(nsDisplayListBuilder* aBuilder,
int aDepth = 0, bool aParentReused = false) {
nsDisplayList out;
while (nsDisplayItem* item = aList->RemoveBottom()) {
for (nsDisplayItem* item : *aList) {
if (DL_LOG_TEST(LogLevel::Debug)) {
DL_LOGD(
"%*s Preprocessing item %p (%s) (frame: %p) "
"(children: %d) (depth: %d) (parentReused: %d)",
"(children: %zu) (depth: %d) (parentReused: %d)",
aDepth, "", item, item->Name(),
item->HasDeletedFrame() ? nullptr : item->Frame(),
item->GetChildren() ? item->GetChildren()->Count() : 0, aDepth,
item->GetChildren() ? item->GetChildren()->Length() : 0, aDepth,
aParentReused);
}
@ -1616,8 +1616,8 @@ void CollectStackingContextItems(nsDisplayListBuilder* aBuilder,
}
}
aList->Clear();
aList->AppendToTop(&out);
aList->RestoreState();
}
} // namespace RDL
@ -1664,7 +1664,7 @@ PartialUpdateResult RetainedDisplayListBuilder::AttemptPartialUpdate(
}
nsRect modifiedDirty;
nsDisplayList modifiedDL;
nsDisplayList modifiedDL(&mBuilder);
nsIFrame* modifiedAGR = nullptr;
PartialUpdateResult result = PartialUpdateResult::NoChange;
const bool simpleUpdate =

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

@ -177,7 +177,7 @@ struct RetainedDisplayListMetrics {
struct RetainedDisplayListBuilder {
RetainedDisplayListBuilder(nsIFrame* aReferenceFrame,
nsDisplayListBuilderMode aMode, bool aBuildCaret)
: mBuilder(aReferenceFrame, aMode, aBuildCaret, true) {}
: mBuilder(aReferenceFrame, aMode, aBuildCaret, true), mList(&mBuilder) {}
~RetainedDisplayListBuilder() { mList.DeleteAll(&mBuilder); }
nsDisplayListBuilder* Builder() { return &mBuilder; }

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

@ -353,11 +353,12 @@ nsDisplayWrapper* nsDisplayWrapList::CreateShallowCopy(
}
nsDisplayWrapList* nsDisplayListBuilder::MergeItems(
nsTArray<nsDisplayWrapList*>& aItems) {
nsTArray<nsDisplayItem*>& aItems) {
// For merging, we create a temporary item by cloning the last item of the
// mergeable items list. This ensures that the temporary item will have the
// correct frame and bounds.
nsDisplayWrapList* last = aItems.PopLastElement();
nsDisplayWrapList* last = aItems.PopLastElement()->AsDisplayWrapList();
MOZ_ASSERT(last);
nsDisplayWrapList* merged = last->Clone(this);
MOZ_ASSERT(merged);
AddTemporaryItem(merged);
@ -365,11 +366,13 @@ nsDisplayWrapList* nsDisplayListBuilder::MergeItems(
// Create nsDisplayWrappers that point to the internal display lists of the
// items we are merging. These nsDisplayWrappers are added to the display list
// of the temporary item.
for (nsDisplayWrapList* item : Reversed(aItems)) {
for (nsDisplayItem* item : aItems) {
MOZ_ASSERT(item);
MOZ_ASSERT(merged->CanMerge(item));
merged->Merge(item);
merged->GetChildren()->AppendToTop(item->CreateShallowCopy(this));
MOZ_ASSERT(item->AsDisplayWrapList());
merged->GetChildren()->AppendToTop(
static_cast<nsDisplayWrapList*>(item)->CreateShallowCopy(this));
}
merged->GetChildren()->AppendToTop(last->CreateShallowCopy(this));
@ -2322,21 +2325,6 @@ void nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
}
}
nsDisplayItem* nsDisplayList::RemoveBottom() {
nsDisplayItem* item = mSentinel.mAbove;
if (!item) {
return nullptr;
}
mSentinel.mAbove = item->mAbove;
if (item == mTop) {
// must have been the only item
mTop = &mSentinel;
}
item->mAbove = nullptr;
mLength--;
return item;
}
void nsDisplayList::DeleteAll(nsDisplayListBuilder* aBuilder) {
nsDisplayItem* item;
while ((item = RemoveBottom()) != nullptr) {
@ -2696,7 +2684,8 @@ nsRect nsDisplayItem::GetClippedBounds(nsDisplayListBuilder* aBuilder) const {
nsDisplayContainer::nsDisplayContainer(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const ActiveScrolledRoot* aActiveScrolledRoot, nsDisplayList* aList)
: nsDisplayItem(aBuilder, aFrame, aActiveScrolledRoot) {
: nsDisplayItem(aBuilder, aFrame, aActiveScrolledRoot),
mChildren(aBuilder) {
MOZ_COUNT_CTOR(nsDisplayContainer);
mChildren.AppendToTop(aList);
UpdateBounds(aBuilder);
@ -3151,7 +3140,7 @@ AppendedBackgroundType nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
// 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
nsDisplayList bgItemList;
nsDisplayList bgItemList(aBuilder);
// Even if we don't actually have a background color to paint, we may still
// need to create an item for hit testing and we still need to create an item
// for background-color animations.
@ -3260,7 +3249,7 @@ AppendedBackgroundType nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
willPaintBorder);
}
nsDisplayList thisItemList;
nsDisplayList thisItemList(aBuilder);
nsDisplayBackgroundImage::InitData bgData =
nsDisplayBackgroundImage::GetInitData(aBuilder, aFrame, i, bgOriginRect,
bgSC);
@ -3388,23 +3377,6 @@ static bool RoundedRectContainsRect(const nsRect& aRoundedRect,
return rgn.Contains(aContainedRect);
}
static void CheckForBorderItem(nsDisplayItem* aItem, uint32_t& aFlags) {
// 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 (next->GetType() == DisplayItemType::TYPE_BORDER) {
aFlags |= nsCSSRendering::PAINTBG_WILL_PAINT_BORDER;
}
break;
}
}
bool nsDisplayBackgroundImage::CanApplyOpacity(
WebRenderLayerManager* aManager, nsDisplayListBuilder* aBuilder) const {
// Bug 1752919: WebRender does not properly handle opacity flattening for
@ -3440,7 +3412,6 @@ bool nsDisplayBackgroundImage::CreateWebRenderCommands(
uint32_t paintFlags = aDisplayListBuilder->GetBackgroundPaintFlags();
bool dummy;
CheckForBorderItem(this, paintFlags);
nsCSSRendering::PaintBGParams params =
nsCSSRendering::PaintBGParams::ForSingleLayer(
*StyleFrame()->PresContext(), GetBounds(aDisplayListBuilder, &dummy),
@ -4592,6 +4563,7 @@ nsDisplayWrapList::nsDisplayWrapList(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot, bool aClearClipChain)
: nsPaintedDisplayItem(aBuilder, aFrame, aActiveScrolledRoot),
mList(aBuilder),
mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot()),
mOverrideZIndex(0),
mHasZIndexOverride(false),
@ -4610,6 +4582,7 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayItem* aItem)
: nsPaintedDisplayItem(aBuilder, aFrame,
aBuilder->CurrentActiveScrolledRoot()),
mList(aBuilder),
mOverrideZIndex(0),
mHasZIndexOverride(false) {
MOZ_COUNT_CTOR(nsDisplayWrapList);
@ -4855,7 +4828,7 @@ static bool CollectItemsWithOpacity(WebRenderLayerManager* aManager,
nsDisplayListBuilder* aBuilder,
nsDisplayList* aList,
nsTArray<nsPaintedDisplayItem*>& aArray) {
if (aList->Count() > kOpacityMaxListSize) {
if (aList->Length() > kOpacityMaxListSize) {
// Exit early, since |aList| will likely contain more than
// |kOpacityMaxChildCount| items.
return false;
@ -4941,7 +4914,7 @@ bool nsDisplayOpacity::CanApplyToChildren(WebRenderLayerManager* aManager,
* opacity. In this case the opacity item can be optimized away.
*/
bool nsDisplayOpacity::ApplyToMask() {
if (mList.Count() != 1) {
if (mList.Length() != 1) {
return false;
}
@ -5454,7 +5427,7 @@ nsDisplayFixedPosition* nsDisplayFixedPosition::CreateForFixedBackground(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsIFrame* aSecondaryFrame,
nsDisplayBackgroundImage* aImage, const uint16_t aIndex,
const ActiveScrolledRoot* aScrollTargetASR) {
nsDisplayList temp;
nsDisplayList temp(aBuilder);
temp.AppendToTop(aImage);
if (aSecondaryFrame) {
@ -6027,6 +6000,7 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
const nsRect& aChildrenBuildingRect)
: nsPaintedDisplayItem(aBuilder, aFrame),
mChildren(aBuilder),
mTransform(Some(Matrix4x4())),
mChildrenBuildingRect(aChildrenBuildingRect),
mPrerenderDecision(PrerenderDecision::No),
@ -6043,6 +6017,7 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
const nsRect& aChildrenBuildingRect,
PrerenderDecision aPrerenderDecision)
: nsPaintedDisplayItem(aBuilder, aFrame),
mChildren(aBuilder),
mChildrenBuildingRect(aChildrenBuildingRect),
mPrerenderDecision(aPrerenderDecision),
mIsTransformSeparator(false),
@ -6059,6 +6034,7 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
const nsRect& aChildrenBuildingRect,
decltype(WithTransformGetter))
: nsPaintedDisplayItem(aBuilder, aFrame),
mChildren(aBuilder),
mChildrenBuildingRect(aChildrenBuildingRect),
mPrerenderDecision(PrerenderDecision::No),
mIsTransformSeparator(false),
@ -6773,7 +6749,8 @@ void nsDisplayTransform::Collect3DTransformLeaves(
}
FlattenedDisplayListIterator iter(aBuilder, &mChildren);
while (nsDisplayItem* item = iter.GetNextItem()) {
while (iter.HasNext()) {
nsDisplayItem* item = iter.GetNextItem();
if (item->GetType() == DisplayItemType::TYPE_PERSPECTIVE) {
auto* perspective = static_cast<nsDisplayPerspective*>(item);
if (!perspective->GetChildren()->GetTop()) {
@ -7349,9 +7326,9 @@ void nsDisplayTransform::WriteDebugInfo(std::stringstream& aStream) {
nsDisplayPerspective::nsDisplayPerspective(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
nsDisplayList* aList)
: nsPaintedDisplayItem(aBuilder, aFrame) {
: nsPaintedDisplayItem(aBuilder, aFrame), mList(aBuilder) {
mList.AppendToTop(aList);
MOZ_ASSERT(mList.Count() == 1);
MOZ_ASSERT(mList.Length() == 1);
MOZ_ASSERT(mList.GetTop()->GetType() == DisplayItemType::TYPE_TRANSFORM);
}
@ -7816,8 +7793,8 @@ static void ComputeMaskGeometry(PaintFramesParams& aParams) {
auto cssToDevScale = frame->PresContext()->CSSToDevPixelScale();
int32_t appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
gfxPoint devPixelOffsetToUserSpace = nsLayoutUtils::PointToGfxPoint(
offsetToUserSpace, appUnitsPerDevPixel);
gfxPoint devPixelOffsetToUserSpace =
nsLayoutUtils::PointToGfxPoint(offsetToUserSpace, appUnitsPerDevPixel);
gfxContextMatrixAutoSaveRestore matSR(&ctx);
ctx.SetMatrixDouble(

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

@ -24,6 +24,7 @@
#include "gfxContext.h"
#include "mozilla/ArenaAllocator.h"
#include "mozilla/Array.h"
#include "mozilla/ArrayIterator.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h"
@ -257,11 +258,17 @@ enum class nsDisplayListBuilderMode : uint8_t {
GenerateGlyph,
};
using ListArenaAllocator = ArenaAllocator<4096, 8>;
class nsDisplayItem;
class nsPaintedDisplayItem;
class nsDisplayList;
class nsDisplayWrapList;
class nsDisplayTableBackgroundSet;
class nsDisplayTableItem;
class RetainedDisplayList;
/**
* This manages a display list and is passed as a parameter to
* nsIFrame::BuildDisplayList.
@ -958,7 +965,7 @@ class nsDisplayListBuilder {
* display item.
* The display items in |aMergedItems| have to be mergeable with each other.
*/
nsDisplayWrapList* MergeItems(nsTArray<nsDisplayWrapList*>& aItems);
nsDisplayWrapList* MergeItems(nsTArray<nsDisplayItem*>& aItems);
/**
* A helper class used to temporarily set nsDisplayListBuilder properties for
@ -1723,6 +1730,8 @@ class nsDisplayListBuilder {
*/
void ReuseDisplayItem(nsDisplayItem* aItem);
ListArenaAllocator& GetListAllocator() { return mListPool; }
private:
bool MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
const nsRect& aVisibleRect,
@ -1921,12 +1930,9 @@ class nsDisplayListBuilder {
// Stores reusable items collected during display list preprocessing.
nsTHashSet<nsDisplayItem*> mReuseableItems;
};
class nsDisplayItem;
class nsPaintedDisplayItem;
class nsDisplayList;
class RetainedDisplayList;
ArenaAllocator<4096, 8> mListPool;
};
// All types are defined in nsDisplayItemTypes.h
#define NS_DISPLAY_DECL_NAME(n, e) \
@ -2047,23 +2053,6 @@ MOZ_ALWAYS_INLINE T* MakeDisplayItem(nsDisplayListBuilder* aBuilder, F* aFrame,
std::forward<Args>(aArgs)...);
}
/**
* nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
* nsDisplayItemLink holds the link. The lists are linked from lowest to
* highest in z-order.
*/
class nsDisplayItemLink {
// This is never instantiated directly, so no need to count constructors and
// destructors.
protected:
nsDisplayItemLink() : mAbove(nullptr) {}
nsDisplayItemLink(const nsDisplayItemLink&) : mAbove(nullptr) {}
~nsDisplayItemLink() { MOZ_RELEASE_ASSERT(!mAbove); }
nsDisplayItem* mAbove;
friend class nsDisplayList;
};
/*
* nsDisplayItemBase is a base-class for all display items. It is mainly
* responsible for handling the frame-display item 1:n relationship, as well as
@ -2077,7 +2066,7 @@ class nsDisplayItemLink {
* Display items belong to a list at all times (except temporarily as they
* move from one list to another).
*/
class nsDisplayItem : public nsDisplayItemLink {
class nsDisplayItem {
public:
using Layer = layers::Layer;
using LayerManager = layers::LayerManager;
@ -2106,6 +2095,12 @@ class nsDisplayItem : public nsDisplayItemLink {
return nullptr;
}
/**
* Checks if the given display item can be merged with this item.
* @return true if the merging is possible, otherwise false.
*/
virtual bool CanMerge(const nsDisplayItem* aItem) const { return false; }
/**
* Frees the memory allocated for this display item.
* The given display list builder must have allocated this display item.
@ -2706,8 +2701,6 @@ class nsDisplayItem : public nsDisplayItemLink {
virtual void WriteDebugInfo(std::stringstream& aStream) {}
nsDisplayItem* GetAbove() { return mAbove; }
/**
* Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
*/
@ -2989,147 +2982,134 @@ class nsPaintedDisplayItem : public nsDisplayItem {
Maybe<uint16_t> mCacheIndex;
};
template <typename T>
struct MOZ_HEAP_CLASS LinkedListNode {
explicit LinkedListNode(T aValue) : mNext(nullptr), mValue(aValue) {}
LinkedListNode* mNext;
T mValue;
};
template <typename T>
struct LinkedListIterator {
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
using Node = LinkedListNode<T>;
explicit LinkedListIterator(Node* aNode = nullptr) : mNode(aNode) {}
LinkedListIterator<T>& operator++() {
MOZ_ASSERT(mNode);
mNode = mNode->mNext;
return *this;
}
bool operator==(const LinkedListIterator<T>& aOther) const {
return mNode == aOther.mNode;
}
bool operator!=(const LinkedListIterator<T>& aOther) const {
return mNode != aOther.mNode;
}
const T operator*() const {
MOZ_ASSERT(mNode);
return mNode->mValue;
}
T operator*() {
MOZ_ASSERT(mNode);
return mNode->mValue;
}
Node* mNode;
};
/**
* Manages a singly-linked list of display list items.
*
* mSentinel is the sentinel list value, the first value in the null-terminated
* linked list of items. mTop is the last item in the list (whose 'above'
* pointer is null). This class has no virtual methods. So list objects are just
* two pointers.
*
* Stepping upward through this list is very fast. Stepping downward is very
* slow so we don't support it. The methods that need to step downward
* (HitTest()) internally build a temporary array of all
* the items while they do the downward traversal, so overall they're still
* linear time. We have optimized for efficient AppendToTop() of both
* items and lists, with minimal codesize.
*
* Internal linked list nodes are allocated using arena allocator.
* */
class nsDisplayList {
public:
class Iterator {
public:
constexpr Iterator() : mCurrent(nullptr), mEnd(nullptr) {}
~Iterator() = default;
Iterator(const Iterator& aOther) = default;
Iterator& operator=(const Iterator& aOther) = default;
using Node = LinkedListNode<nsDisplayItem*>;
using iterator = LinkedListIterator<nsDisplayItem*>;
using const_iterator = iterator;
explicit Iterator(const nsDisplayList* aList)
: mCurrent(aList->GetBottom()), mEnd(nullptr) {}
explicit Iterator(nsDisplayItem* aStart)
: mCurrent(aStart), mEnd(nullptr) {}
iterator begin() { return iterator(mBottom); }
iterator end() { return iterator(nullptr); }
const_iterator begin() const { return iterator(mBottom); }
const_iterator end() const { return iterator(nullptr); }
Iterator& operator++() {
mCurrent = Next();
return *this;
}
explicit nsDisplayList(nsDisplayListBuilder* aBuilder)
: mPool(aBuilder->GetListAllocator()) {}
nsDisplayItem* operator*() {
MOZ_ASSERT(mCurrent);
return mCurrent;
}
bool operator==(const Iterator& aOther) const {
return mCurrent == aOther.mCurrent;
}
bool operator!=(const Iterator& aOther) const {
return !operator==(aOther);
}
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:
nsDisplayItem* mCurrent;
nsDisplayItem* mEnd;
};
class Range final : public Iterator {
public:
Range(nsDisplayItem* aStart, nsDisplayItem* aEnd)
: Iterator(aStart, aEnd) {}
};
Iterator begin() const { return Iterator(this); }
constexpr Iterator end() const { return Iterator(); }
/**
* Create an empty list.
*/
nsDisplayList() : mLength(0), mForceTransparentSurface(false) {
mTop = &mSentinel;
mSentinel.mAbove = nullptr;
}
nsDisplayList() = delete;
nsDisplayList(const nsDisplayList&) = delete;
nsDisplayList& operator=(const nsDisplayList&) = delete;
virtual ~nsDisplayList() {
MOZ_RELEASE_ASSERT(!mSentinel.mAbove, "Nonempty list left over?");
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
if (!mAllowNonEmptyDestruction) {
MOZ_RELEASE_ASSERT(IsEmpty(), "Nonempty list left over?");
}
#endif
Clear();
}
nsDisplayList(nsDisplayList&& aOther) {
mForceTransparentSurface = aOther.mForceTransparentSurface;
if (aOther.mSentinel.mAbove) {
AppendToTop(&aOther);
} else {
mTop = &mSentinel;
mLength = 0;
}
nsDisplayList(nsDisplayList&& aOther)
: mBottom(aOther.mBottom),
mTop(aOther.mTop),
mLength(aOther.mLength),
mPool(aOther.mPool) {
aOther.SetEmpty();
}
nsDisplayList& operator=(nsDisplayList&& aOther) {
MOZ_RELEASE_ASSERT(&mPool == &aOther.mPool);
if (this != &aOther) {
if (aOther.mSentinel.mAbove) {
nsDisplayList tmp;
tmp.AppendToTop(&aOther);
aOther.AppendToTop(this);
AppendToTop(&tmp);
} else {
mTop = &mSentinel;
mLength = 0;
}
mForceTransparentSurface = aOther.mForceTransparentSurface;
MOZ_RELEASE_ASSERT(IsEmpty());
mBottom = std::move(aOther.mBottom);
mTop = std::move(aOther.mTop);
mLength = std::move(aOther.mLength);
aOther.SetEmpty();
}
return *this;
}
nsDisplayList(const nsDisplayList&) = delete;
nsDisplayList& operator=(const nsDisplayList& aOther) = delete;
/**
* Append an item to the top of the list. The item must not currently
* be in a list and cannot be null.
*/
* Append an item to the top of the list.
**/
void AppendToTop(nsDisplayItem* aItem) {
if (!aItem) {
return;
}
MOZ_ASSERT(!aItem->mAbove, "Already in a list!");
mTop->mAbove = aItem;
mTop = aItem;
auto* next = Allocate(aItem);
MOZ_ASSERT(next);
if (IsEmpty()) {
mBottom = next;
mTop = next;
} else {
mTop->mNext = next;
mTop = next;
}
mLength++;
MOZ_ASSERT(mBottom && mTop);
MOZ_ASSERT(mTop->mNext == nullptr);
}
template <typename T, typename F, typename... Args>
@ -3144,61 +3124,84 @@ class nsDisplayList {
const uint16_t aIndex, Args&&... aArgs) {
nsDisplayItem* item = MakeDisplayItemWithIndex<T>(
aBuilder, aFrame, aIndex, std::forward<Args>(aArgs)...);
if (item) {
AppendToTop(item);
}
AppendToTop(item);
}
/**
* Removes all items from aList and appends them to the top of this list
* Removes all items from aList and appends them to the top of this list.
*/
void AppendToTop(nsDisplayList* aList) {
if (aList->mSentinel.mAbove) {
mTop->mAbove = aList->mSentinel.mAbove;
MOZ_ASSERT(aList != this);
MOZ_RELEASE_ASSERT(&mPool == &aList->mPool);
if (aList->IsEmpty()) {
return;
}
if (IsEmpty()) {
std::swap(mBottom, aList->mBottom);
std::swap(mTop, aList->mTop);
std::swap(mLength, aList->mLength);
} else {
MOZ_ASSERT(mTop && mTop->mNext == nullptr);
mTop->mNext = aList->mBottom;
mTop = aList->mTop;
aList->mTop = &aList->mSentinel;
aList->mSentinel.mAbove = nullptr;
mLength += aList->mLength;
aList->mLength = 0;
aList->SetEmpty();
}
}
/**
* Remove an item from the bottom of the list and return it.
* Clears the display list.
*/
nsDisplayItem* RemoveBottom();
void Clear() {
Node* current = mBottom;
Node* next = nullptr;
while (current) {
next = current->mNext;
Deallocate(current);
current = next;
}
SetEmpty();
}
/**
* Remove all items from the list and call their destructors.
*/
virtual void DeleteAll(nsDisplayListBuilder* aBuilder);
/**
* @return the item at the top of the list, or null if the list is empty
*/
nsDisplayItem* GetTop() const {
return mTop != &mSentinel ? static_cast<nsDisplayItem*>(mTop) : nullptr;
}
/**
* @return the item at the bottom of the list, or null if the list is empty
*/
nsDisplayItem* GetBottom() const { return mSentinel.mAbove; }
bool IsEmpty() const { return mTop == &mSentinel; }
nsDisplayItem* GetBottom() const {
return mBottom ? mBottom->mValue : nullptr;
}
/**
* @return the item at the top of the list, or null if the list is empty
*/
nsDisplayItem* GetTop() const { return mTop ? mTop->mValue : nullptr; }
bool IsEmpty() const { return mBottom == nullptr; }
/**
* @return the number of items in the list
*/
uint32_t Count() const { return mLength; }
size_t Length() const { return mLength; }
/**
* Stable sort the list by the z-order of GetUnderlyingFrame() on
* Stable sort the list by the z-order of Frame() on
* each item. 'auto' is counted as zero.
* It is assumed that the list is already in content document order.
*/
void SortByZOrder();
/**
* Stable sort the list by the tree order of the content of
* GetUnderlyingFrame() on each item. z-index is ignored.
* Frame() on each item. z-index is ignored.
* @param aCommonAncestor a common ancestor of all the content elements
* associated with the display items, for speeding up tree order
* checks, or nullptr if not known; it's only a hint, if it is not an
@ -3207,15 +3210,14 @@ class nsDisplayList {
void SortByContentOrder(nsIContent* aCommonAncestor);
/**
* Sort the display list using a stable sort. Take care, because some of the
* items might be nsDisplayLists themselves.
* Sort the display list using a stable sort.
* aComparator(Item item1, Item item2) should return true if item1 should go
* before item2.
* We sort the items into increasing order.
*/
template <typename Item, typename Comparator>
void Sort(const Comparator& aComparator) {
if (Count() < 2) {
if (Length() < 2) {
// Only sort lists with more than one item.
return;
}
@ -3225,7 +3227,7 @@ class nsDisplayList {
// here.
AutoTArray<Item, 20> items;
while (nsDisplayItem* item = RemoveBottom()) {
for (nsDisplayItem* item : TakeItems()) {
items.AppendElement(Item(item));
}
@ -3236,10 +3238,14 @@ class nsDisplayList {
}
}
/**
* Returns true if any display item requires the surface to be transparent.
*/
bool NeedsTransparentSurface() const { return mForceTransparentSurface; }
nsDisplayList TakeItems() {
nsDisplayList list = std::move(*this);
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
list.mAllowNonEmptyDestruction = true;
#endif
return list;
}
/**
* Paint the list to the rendering context. We assume that (0,0) in aCtx
* corresponds to the origin of the reference frame. For best results,
@ -3335,19 +3341,32 @@ class nsDisplayList {
*/
nsRect GetBuildingRect() const;
void SetNeedsTransparentSurface() { mForceTransparentSurface = true; }
void RestoreState() { mForceTransparentSurface = false; }
private:
nsDisplayItemLink mSentinel;
nsDisplayItemLink* mTop;
inline Node* Allocate(nsDisplayItem* aItem) {
void* ptr = mPool.Allocate(sizeof(Node));
return new (ptr) Node(aItem);
}
uint32_t mLength;
inline void Deallocate(Node* aNode) {
aNode->~Node();
// Memory remains reserved by the arena allocator.
}
// This is set to true by FrameLayerBuilder if any display item in this
// list needs to force the surface containing this list to be transparent.
bool mForceTransparentSurface;
void SetEmpty() {
mBottom = nullptr;
mTop = nullptr;
mLength = 0;
}
Node* mBottom = nullptr;
Node* mTop = nullptr;
size_t mLength = 0;
ListArenaAllocator& mPool;
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
// This checks that the invariant of display lists owning their items is held.
bool mAllowNonEmptyDestruction = false;
#endif
};
/**
@ -3453,13 +3472,17 @@ class nsDisplayListSet {
struct nsDisplayListCollection : public nsDisplayListSet {
explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder)
: nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3],
&mLists[4], &mLists[5]) {}
&mLists[4], &mLists[5]),
mLists{nsDisplayList{aBuilder}, nsDisplayList{aBuilder},
nsDisplayList{aBuilder}, nsDisplayList{aBuilder},
nsDisplayList{aBuilder}, nsDisplayList{aBuilder}} {}
/*
explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder,
nsDisplayList* aBorderBackground)
: nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3],
&mLists[4], &mLists[5]) {}
*/
/**
* Sort all lists by content order.
*/
@ -3497,29 +3520,33 @@ struct nsDisplayListCollection : public nsDisplayListSet {
*/
class RetainedDisplayList : public nsDisplayList {
public:
RetainedDisplayList() = default;
RetainedDisplayList(RetainedDisplayList&& aOther) {
AppendToTop(&aOther);
mDAG = std::move(aOther.mDAG);
}
explicit RetainedDisplayList(nsDisplayListBuilder* aBuilder)
: nsDisplayList(aBuilder) {}
RetainedDisplayList(RetainedDisplayList&& aOther)
: nsDisplayList(std::move(aOther)), mDAG(std::move(aOther.mDAG)) {}
RetainedDisplayList(const RetainedDisplayList&) = delete;
RetainedDisplayList& operator=(const RetainedDisplayList&) = delete;
~RetainedDisplayList() override {
MOZ_ASSERT(mOldItems.IsEmpty(), "Must empty list before destroying");
}
RetainedDisplayList& operator=(RetainedDisplayList&& aOther) {
MOZ_ASSERT(!Count(), "Can only move into an empty list!");
MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
MOZ_ASSERT(mOldItems.IsEmpty(), "Can only move into an empty list!");
AppendToTop(&aOther);
nsDisplayList::operator=(std::move(aOther));
mDAG = std::move(aOther.mDAG);
mOldItems = std::move(aOther.mOldItems);
return *this;
}
RetainedDisplayList& operator=(nsDisplayList&& aOther) {
MOZ_ASSERT(!Count(), "Can only move into an empty list!");
MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
MOZ_ASSERT(mOldItems.IsEmpty(), "Can only move into an empty list!");
AppendToTop(&aOther);
nsDisplayList::operator=(std::move(aOther));
return *this;
}
@ -4721,6 +4748,7 @@ class nsDisplayWrapList : public nsPaintedDisplayItem {
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsPaintedDisplayItem(aBuilder, aFrame),
mList(aBuilder),
mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot()),
mOverrideZIndex(0),
mHasZIndexOverride(false) {
@ -4740,6 +4768,7 @@ class nsDisplayWrapList : public nsPaintedDisplayItem {
nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
const nsDisplayWrapList& aOther)
: nsPaintedDisplayItem(aBuilder, aOther),
mList(aBuilder),
mListPtr(&mList),
mFrameActiveScrolledRoot(aOther.mFrameActiveScrolledRoot),
mMergedFrames(aOther.mMergedFrames.Clone()),
@ -4813,12 +4842,6 @@ class nsDisplayWrapList : public nsPaintedDisplayItem {
bool* aSnap) const override;
Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
/**
* Checks if the given display item can be merged with this item.
* @return true if the merging is possible, otherwise false.
*/
virtual bool CanMerge(const nsDisplayItem* aItem) const { return false; }
/**
* Try to merge with the other item (which is below us in the display
* list). This gets used by nsDisplayClip to coalesce clipping operations
@ -6390,12 +6413,12 @@ class nsDisplayTransform : public nsPaintedDisplayItem {
void CollectSorted3DTransformLeaves(nsDisplayListBuilder* aBuilder,
nsTArray<TransformPolygon>& aLeaves);
mutable RetainedDisplayList mChildren;
mutable Maybe<Matrix4x4Flagged> mTransform;
mutable Maybe<Matrix4x4Flagged> mInverseTransform;
// Accumulated transform of ancestors on the preserves-3d chain.
UniquePtr<Matrix4x4> mTransformPreserves3D;
nsRect mChildrenBuildingRect;
mutable RetainedDisplayList mChildren;
// The untransformed bounds of |mChildren|.
nsRect mChildBounds;
@ -6693,50 +6716,58 @@ class FlattenedDisplayListIterator {
public:
FlattenedDisplayListIterator(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList)
: FlattenedDisplayListIterator(aBuilder, aList, true) {}
: mBuilder(aBuilder), mStart(aList->begin()), mEnd(aList->end()) {
ResolveFlattening();
}
virtual bool HasNext() const { return mNext || !mStack.IsEmpty(); }
bool HasNext() const { return !AtEndOfCurrentList(); }
nsDisplayItem* GetNextItem() {
if (!mNext) {
return nullptr;
}
MOZ_ASSERT(HasNext());
nsDisplayItem* next = mNext;
mNext = next->GetAbove();
nsDisplayItem* current = NextItem();
Advance();
if (mNext && next->HasChildren() && mNext->HasChildren()) {
// Since |next| and |mNext| are container items in the same list,
// merging them might be possible.
next = TryMergingFrom(next);
if (!AtEndOfCurrentList() && current->CanMerge(NextItem())) {
// Since we can merge at least two display items, create an array and
// collect mergeable display items there.
AutoTArray<nsDisplayItem*, 2> willMerge{current};
auto it = mStart;
while (it != mEnd) {
nsDisplayItem* next = *it;
if (current->CanMerge(next)) {
willMerge.AppendElement(next);
++it;
} else {
break;
}
}
mStart = it;
current = mBuilder->MergeItems(willMerge);
}
ResolveFlattening();
return next;
return current;
}
nsDisplayItem* PeekNext() { return mNext; }
protected:
FlattenedDisplayListIterator(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList,
const bool aResolveFlattening)
: mBuilder(aBuilder), mNext(aList->GetBottom()) {
if (aResolveFlattening) {
// This is done conditionally in case subclass overrides
// ShouldFlattenNextItem().
ResolveFlattening();
}
void Advance() { ++mStart; }
bool AtEndOfNestedList() const {
return AtEndOfCurrentList() && mStack.Length() > 0;
}
virtual void EnterChildList(nsDisplayItem* aContainerItem) {}
virtual void ExitChildList() {}
bool AtEndOfCurrentList() const { return mStart == mEnd; }
bool AtEndOfNestedList() const { return !mNext && mStack.Length() > 0; }
nsDisplayItem* NextItem() {
MOZ_ASSERT(HasNext());
return *mStart;
}
virtual bool ShouldFlattenNextItem() {
return mNext && mNext->ShouldFlattenAway(mBuilder);
bool ShouldFlattenNextItem() {
return HasNext() && NextItem()->ShouldFlattenAway(mBuilder);
}
void ResolveFlattening() {
@ -6745,60 +6776,36 @@ class FlattenedDisplayListIterator {
// item, or the very end of the outer list.
while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
if (AtEndOfNestedList()) {
ExitChildList();
// We reached the end of the list, pop the next item from the stack.
mNext = mStack.PopLastElement();
// We reached the end of the list, pop the next list from the stack.
std::tie(mStart, mEnd) = mStack.PopLastElement();
} else {
EnterChildList(mNext);
// The next item wants to be flattened. This means that we will skip the
// flattened item and directly iterate over its sublist.
MOZ_ASSERT(ShouldFlattenNextItem());
// This item wants to be flattened. Store the next item on the stack,
// and use the first item in the child list instead.
mStack.AppendElement(mNext->GetAbove());
mNext = mNext->GetChildren()->GetBottom();
nsDisplayList* sublist = NextItem()->GetChildren();
MOZ_ASSERT(sublist);
// Skip the flattened item.
Advance();
// Store the current position on the stack.
if (!AtEndOfCurrentList()) {
mStack.AppendElement(std::make_pair(mStart, mEnd));
}
// Iterate over the sublist.
mStart = sublist->begin();
mEnd = sublist->end();
}
}
}
/**
* Tries to merge display items starting from |aCurrent|.
* Updates the internal pointer to the next display item.
*/
nsDisplayItem* TryMergingFrom(nsDisplayItem* aCurrent) {
MOZ_ASSERT(aCurrent);
MOZ_ASSERT(aCurrent->GetAbove());
nsDisplayWrapList* current = aCurrent->AsDisplayWrapList();
nsDisplayWrapList* next = mNext->AsDisplayWrapList();
if (!current || !next) {
// Either the current or the next item do not support merging.
return aCurrent;
}
// Attempt to merge |next| with |current|.
if (current->CanMerge(next)) {
// Merging is possible, collect all the successive mergeable items.
AutoTArray<nsDisplayWrapList*, 2> willMerge{current};
do {
willMerge.AppendElement(next);
mNext = next->GetAbove();
next = mNext ? mNext->AsDisplayWrapList() : nullptr;
} while (next && current->CanMerge(next));
current = mBuilder->MergeItems(willMerge);
}
// Here |mNext| will be either the first item that could not be merged with
// |current|, or nullptr.
return current;
}
private:
nsDisplayListBuilder* mBuilder;
nsDisplayItem* mNext;
AutoTArray<nsDisplayItem*, 16> mStack;
nsDisplayList::iterator mStart;
nsDisplayList::iterator mEnd;
nsTArray<std::pair<nsDisplayList::iterator, nsDisplayList::iterator>> mStack;
};
class PaintTelemetry {

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

@ -154,7 +154,7 @@ void SVGForeignObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
if (!static_cast<const SVGElement*>(GetContent())->HasValidDimensions()) {
return;
}
nsDisplayList newList;
nsDisplayList newList(aBuilder);
nsDisplayListSet set(&newList, &newList, &newList, &newList, &newList,
&newList);
DisplayOutline(aBuilder, set);

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

@ -997,7 +997,7 @@ void SVGOuterSVGAnonChildFrame::BuildDisplayList(
// inside the nsDisplayTransform for our viewbox transform. The
// nsDisplaySVGWrapper's reference frame is this frame, because this frame
// always returns true from IsSVGTransformed.
nsDisplayList newList;
nsDisplayList newList(aBuilder);
nsDisplayListSet set(&newList, &newList, &newList, &newList, &newList,
&newList);
BuildDisplayListForNonBlockChildren(aBuilder, set);

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

@ -7520,7 +7520,9 @@ void nsDisplayTableItem::ComputeInvalidationRegion(
nsDisplayTableBackgroundSet::nsDisplayTableBackgroundSet(
nsDisplayListBuilder* aBuilder, nsIFrame* aTable)
: mBuilder(aBuilder) {
: mBuilder(aBuilder),
mColGroupBackgrounds(aBuilder),
mColBackgrounds(aBuilder) {
mPrevTableBackgroundSet = mBuilder->SetTableBackgroundSet(this);
mozilla::DebugOnly<const nsIFrame*> reference =
mBuilder->FindReferenceFrameFor(aTable, &mToReferenceFrame);

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

@ -961,7 +961,7 @@ void nsBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// and merge them into a single Content() list. This can cause us
// to violate CSS stacking order, but forceLayer is a magic
// XUL-only extension anyway.
nsDisplayList masterList;
nsDisplayList masterList(aBuilder);
masterList.AppendToTop(tempLists.BorderBackground());
masterList.AppendToTop(tempLists.BlockBorderBackgrounds());
masterList.AppendToTop(tempLists.Floats());

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

@ -330,7 +330,7 @@ void nsImageBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox clip(
aBuilder, this, clipFlags);
nsDisplayList list;
nsDisplayList list(aBuilder);
list.AppendNewToTop<nsDisplayXULImage>(aBuilder, this);
CreateOwnLayerIfNeeded(aBuilder, &list,

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

@ -500,7 +500,7 @@ void nsSliderFrame::BuildDisplayListForChildren(
// This is a bit of a hack. Collect up all descendant display items
// and merge them into a single Content() list.
nsDisplayList masterList;
nsDisplayList masterList(aBuilder);
masterList.AppendToTop(tempLists.BorderBackground());
masterList.AppendToTop(tempLists.BlockBorderBackgrounds());
masterList.AppendToTop(tempLists.Floats());