Bug 1442190 - Part 2: Virtualize FlattenedDisplayItemIterator and move it to a more appropriate place
MozReview-Commit-ID: CW89yfHUeQA
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -3202,16 +3202,102 @@ private:
// is empty (i.e. everything that was visible is covered by some
// opaque content in this list).
bool mIsOpaque;
// 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;
};
+class FlattenedDisplayItemIterator
+{
+public:
+ FlattenedDisplayItemIterator(nsDisplayListBuilder* aBuilder,
+ nsDisplayList* aList,
+ const bool aResolveFlattening = true)
+ : mBuilder(aBuilder)
+ , mNext(aList->GetBottom())
+ {
+ if (aResolveFlattening) {
+ // This is done conditionally in case subclass overrides
+ // ShouldFlattenNextItem().
+ ResolveFlattening();
+ }
+ }
+
+ virtual ~FlattenedDisplayItemIterator()
+ {
+ MOZ_ASSERT(!HasNext());
+ }
+
+ nsDisplayItem* GetNext()
+ {
+ nsDisplayItem* next = mNext;
+
+ // Advance mNext to the following item
+ if (next) {
+ mNext = mNext->GetAbove();
+ ResolveFlattening();
+ }
+ return next;
+ }
+
+ bool HasNext() const
+ {
+ return mNext || !mStack.IsEmpty();
+ }
+
+ nsDisplayItem* PeekNext()
+ {
+ return mNext;
+ }
+
+protected:
+ bool AtEndOfNestedList() const
+ {
+ return !mNext && mStack.Length() > 0;
+ }
+
+ virtual bool ShouldFlattenNextItem() const
+ {
+ return mNext && mNext->ShouldFlattenAway(mBuilder);
+ }
+
+ void ResolveFlattening()
+ {
+ // Handle the case where we reach the end of a nested list, or the current
+ // item should start a new nested list. Repeat this until we find an actual
+ // item, or the very end of the outer list.
+ while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
+ if (AtEndOfNestedList()) {
+ // Pop the last item off the stack.
+ mNext = mStack.LastElement();
+ EndNested(mNext);
+ mStack.RemoveElementAt(mStack.Length() - 1);
+ // We stored the item that was flattened, so advance to the next.
+ mNext = mNext->GetAbove();
+ } else {
+ // This item wants to be flattened. Store the current item on the stack,
+ // and use the first item in the child list instead.
+ mStack.AppendElement(mNext);
+ StartNested(mNext);
+ nsDisplayList* childItems = mNext->GetSameCoordinateSystemChildren();
+ mNext = childItems->GetBottom();
+ }
+ }
+ }
+
+ virtual void EndNested(nsDisplayItem* aItem) {}
+ virtual void StartNested(nsDisplayItem* aItem) {}
+
+ nsDisplayListBuilder* mBuilder;
+ nsDisplayItem* mNext;
+ AutoTArray<nsDisplayItem*, 10> mStack;
+};
+
/**
* This is passed as a parameter to nsIFrame::BuildDisplayList. That method
* will put any generated items onto the appropriate list given here. It's
* basically just a collection with one list for each separate stacking layer.
* The lists themselves are external to this object and thus can be shared
* with others. Some of the list pointers may even refer to the same list.
*/
class nsDisplayListSet {
@@ -6773,82 +6859,16 @@ public:
// (i.e. left and right respectively in horizontal writing modes,
// regardless of bidi directionality; top and bottom in vertical modes).
nscoord mVisIStartEdge;
nscoord mVisIEndEdge;
// Cached result of mFrame->IsSelected(). Only initialized when needed.
mutable mozilla::Maybe<bool> mIsFrameSelected;
};
-class FlattenedDisplayItemIterator
-{
-public:
- FlattenedDisplayItemIterator(nsDisplayListBuilder* aBuilder,
- nsDisplayList* aList)
- : mBuilder(aBuilder)
- , mNext(aList->GetBottom())
- {
- ResolveFlattening();
- }
-
- nsDisplayItem* GetNext()
- {
- nsDisplayItem* next = mNext;
-
- // Advance mNext to the following item
- if (next) {
- mNext = mNext->GetAbove();
- ResolveFlattening();
- }
- return next;
- }
-
- nsDisplayItem* PeekNext()
- {
- return mNext;
- }
-
-private:
- bool AtEndOfNestedList()
- {
- return !mNext && mStack.Length() > 0;
- }
-
- bool ShouldFlattenNextItem()
- {
- return mNext && mNext->ShouldFlattenAway(mBuilder);
- }
-
- void ResolveFlattening()
- {
- // Handle the case where we reach the end of a nested list, or the current
- // item should start a new nested list. Repeat this until we find an actual
- // item, or the very end of the outer list.
- while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
- if (AtEndOfNestedList()) {
- // Pop the last item off the stack.
- mNext = mStack.PopLastElement();
- // We stored the item that was flattened, so advance to the next.
- mNext = mNext->GetAbove();
- } else {
- // This item wants to be flattened. Store the current item on the stack,
- // and use the first item in the child list instead.
- mStack.AppendElement(mNext);
- nsDisplayList* childItems = mNext->GetSameCoordinateSystemChildren();
- mNext = childItems->GetBottom();
- }
- }
- }
-
-
- nsDisplayListBuilder* mBuilder;
- nsDisplayItem* mNext;
- AutoTArray<nsDisplayItem*, 10> mStack;
-};
-
/**
* A display item that for webrender to handle SVG
*/
class nsDisplaySVGWrapper : public nsDisplayWrapList {
public:
NS_DISPLAY_DECL_NAME("SVGWrapper", TYPE_SVG_WRAPPER)
nsDisplaySVGWrapper(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,