1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6  */
7 
8 /*
9  * structures that represent things to be painted (ordered in z-order),
10  * used during painting and hit testing
11  */
12 
13 #ifndef NSDISPLAYLIST_H_
14 #define NSDISPLAYLIST_H_
15 
16 #include "DisplayItemClipChain.h"
17 #include "DisplayListClipState.h"
18 #include "FrameMetrics.h"
19 #include "HitTestInfo.h"
20 #include "ImgDrawResult.h"
21 #include "LayerState.h"
22 #include "RetainedDisplayListHelpers.h"
23 #include "Units.h"
24 #include "gfxContext.h"
25 #include "mozilla/ArenaAllocator.h"
26 #include "mozilla/Array.h"
27 #include "mozilla/ArrayIterator.h"
28 #include "mozilla/Assertions.h"
29 #include "mozilla/Attributes.h"
30 #include "mozilla/DebugOnly.h"
31 #include "mozilla/EffectCompositor.h"
32 #include "mozilla/EnumSet.h"
33 #include "mozilla/EnumeratedArray.h"
34 #include "mozilla/Logging.h"
35 #include "mozilla/Maybe.h"
36 #include "mozilla/MotionPathUtils.h"
37 #include "mozilla/RefPtr.h"
38 #include "mozilla/TemplateLib.h"
39 #include "mozilla/TimeStamp.h"
40 #include "mozilla/UniquePtr.h"
41 #include "mozilla/dom/EffectsInfo.h"
42 #include "mozilla/gfx/UserData.h"
43 #include "mozilla/layers/BSPTree.h"
44 #include "mozilla/layers/LayerAttributes.h"
45 #include "mozilla/layers/ScrollableLayerGuid.h"
46 #include "nsAutoLayoutPhase.h"
47 #include "nsCOMPtr.h"
48 #include "nsCSSRenderingBorders.h"
49 #include "nsContainerFrame.h"
50 #include "nsDisplayItemTypes.h"
51 #include "nsDisplayListInvalidation.h"
52 #include "nsPoint.h"
53 #include "nsPresArena.h"
54 #include "nsRect.h"
55 #include "nsRegion.h"
56 #include "nsClassHashtable.h"
57 #include "nsTHashSet.h"
58 #include "nsTHashMap.h"
59 
60 #include <algorithm>
61 #include <unordered_set>
62 
63 // XXX Includes that could be avoided by moving function implementations to the
64 // cpp file.
65 #include "gfxPlatform.h"
66 
67 class gfxContext;
68 class nsIContent;
69 class nsIScrollableFrame;
70 class nsSubDocumentFrame;
71 class nsCaret;
72 struct WrFiltersHolder;
73 
74 namespace nsStyleTransformMatrix {
75 class TransformReferenceBox;
76 }
77 
78 namespace mozilla {
79 
80 enum class nsDisplayOwnLayerFlags;
81 class nsDisplayCompositorHitTestInfo;
82 class nsDisplayScrollInfoLayer;
83 class PresShell;
84 class StickyScrollContainer;
85 
86 namespace layers {
87 struct FrameMetrics;
88 class RenderRootStateManager;
89 class Layer;
90 class ImageContainer;
91 class StackingContextHelper;
92 class WebRenderScrollData;
93 class WebRenderLayerScrollData;
94 class WebRenderLayerManager;
95 }  // namespace layers
96 
97 namespace wr {
98 class DisplayListBuilder;
99 }  // namespace wr
100 
101 namespace dom {
102 class RemoteBrowser;
103 class Selection;
104 }  // namespace dom
105 
106 enum class DisplayListArenaObjectId {
107 #define DISPLAY_LIST_ARENA_OBJECT(name_) name_,
108 #include "nsDisplayListArenaTypes.h"
109 #undef DISPLAY_LIST_ARENA_OBJECT
110   COUNT
111 };
112 
113 extern LazyLogModule sDisplayListLog;
114 #define DL_LOG(lvl, ...) MOZ_LOG(sDisplayListLog, lvl, (__VA_ARGS__))
115 #define DL_LOGI(...) DL_LOG(LogLevel::Info, __VA_ARGS__)
116 #define DL_LOGD(...) DL_LOG(LogLevel::Debug, __VA_ARGS__)
117 #define DL_LOGV(...) DL_LOG(LogLevel::Verbose, __VA_ARGS__)
118 #define DL_LOG_TEST(lvl) MOZ_LOG_TEST(sDisplayListLog, lvl)
119 
120 /*
121  * An nsIFrame can have many different visual parts. For example an image frame
122  * can have a background, border, and outline, the image itself, and a
123  * translucent selection overlay. In general these parts can be drawn at
124  * discontiguous z-levels; see CSS2.1 appendix E:
125  * http://www.w3.org/TR/CSS21/zindex.html
126  *
127  * We construct a display list for a frame tree that contains one item
128  * for each visual part. The display list is itself a tree since some items
129  * are containers for other items; however, its structure does not match
130  * the structure of its source frame tree. The display list items are sorted
131  * by z-order. A display list can be used to paint the frames, to determine
132  * which frame is the target of a mouse event, and to determine what areas
133  * need to be repainted when scrolling. The display lists built for each task
134  * may be different for efficiency; in particular some frames need special
135  * display list items only for event handling, and do not create these items
136  * when the display list will be used for painting (the common case). For
137  * example, when painting we avoid creating nsDisplayBackground items for
138  * frames that don't display a visible background, but for event handling
139  * we need those backgrounds because they are not transparent to events.
140  *
141  * We could avoid constructing an explicit display list by traversing the
142  * frame tree multiple times in clever ways. However, reifying the display list
143  * reduces code complexity and reduces the number of times each frame must be
144  * traversed to one, which seems to be good for performance. It also means
145  * we can share code for painting, event handling and scroll analysis.
146  *
147  * Display lists are short-lived; content and frame trees cannot change
148  * between a display list being created and destroyed. Display lists should
149  * not be created during reflow because the frame tree may be in an
150  * inconsistent state (e.g., a frame's stored overflow-area may not include
151  * the bounds of all its children). However, it should be fine to create
152  * a display list while a reflow is pending, before it starts.
153  *
154  * A display list covers the "extended" frame tree; the display list for
155  * a frame tree containing FRAME/IFRAME elements can include frames from
156  * the subdocuments.
157  *
158  * Display item's coordinates are relative to their nearest reference frame
159  * ancestor. Both the display root and any frame with a transform act as a
160  * reference frame for their frame subtrees.
161  */
162 
163 /**
164  * An active scrolled root (ASR) is similar to an animated geometry root (AGR).
165  * The differences are:
166  *  - ASRs are only created for async-scrollable scroll frames. This is a
167  *    (hopefully) temporary restriction. In the future we will want to create
168  *    ASRs for all the things that are currently creating AGRs, and then
169  *    replace AGRs with ASRs and rename them from "active scrolled root" to
170  *    "animated geometry root".
171  *  - ASR objects are created during display list construction by the nsIFrames
172  *    that induce ASRs. This is done using AutoCurrentActiveScrolledRootSetter.
173  *    The current ASR is returned by
174  *    nsDisplayListBuilder::CurrentActiveScrolledRoot().
175  *  - There is no way to go from an nsIFrame pointer to the ASR of that frame.
176  *    If you need to look up an ASR after display list construction, you need
177  *    to store it while the AutoCurrentActiveScrolledRootSetter that creates it
178  *    is on the stack.
179  */
180 struct ActiveScrolledRoot {
181   static already_AddRefed<ActiveScrolledRoot> CreateASRForFrame(
182       const ActiveScrolledRoot* aParent, nsIScrollableFrame* aScrollableFrame,
183       bool aIsRetained);
184 
PickAncestorActiveScrolledRoot185   static const ActiveScrolledRoot* PickAncestor(
186       const ActiveScrolledRoot* aOne, const ActiveScrolledRoot* aTwo) {
187     MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
188     return Depth(aOne) <= Depth(aTwo) ? aOne : aTwo;
189   }
190 
PickDescendantActiveScrolledRoot191   static const ActiveScrolledRoot* PickDescendant(
192       const ActiveScrolledRoot* aOne, const ActiveScrolledRoot* aTwo) {
193     MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
194     return Depth(aOne) >= Depth(aTwo) ? aOne : aTwo;
195   }
196 
197   static bool IsAncestor(const ActiveScrolledRoot* aAncestor,
198                          const ActiveScrolledRoot* aDescendant);
199   static bool IsProperAncestor(const ActiveScrolledRoot* aAncestor,
200                                const ActiveScrolledRoot* aDescendant);
201 
202   static nsCString ToString(const ActiveScrolledRoot* aActiveScrolledRoot);
203 
204   // Call this when inserting an ancestor.
IncrementDepthActiveScrolledRoot205   void IncrementDepth() { mDepth++; }
206 
207   /**
208    * Find the view ID (or generate a new one) for the content element
209    * corresponding to the ASR.
210    */
GetViewIdActiveScrolledRoot211   layers::ScrollableLayerGuid::ViewID GetViewId() const {
212     if (!mViewId.isSome()) {
213       mViewId = Some(ComputeViewId());
214     }
215     return *mViewId;
216   }
217 
218   RefPtr<const ActiveScrolledRoot> mParent;
219   nsIScrollableFrame* mScrollableFrame;
220 
NS_INLINE_DECL_REFCOUNTINGActiveScrolledRoot221   NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot)
222 
223  private:
224   ActiveScrolledRoot()
225       : mScrollableFrame(nullptr), mDepth(0), mRetained(false) {}
226 
227   ~ActiveScrolledRoot();
228 
DetachASRActiveScrolledRoot229   static void DetachASR(ActiveScrolledRoot* aASR) {
230     aASR->mParent = nullptr;
231     aASR->mScrollableFrame = nullptr;
232     NS_RELEASE(aASR);
233   }
NS_DECLARE_FRAME_PROPERTY_WITH_DTORActiveScrolledRoot234   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache,
235                                       ActiveScrolledRoot, DetachASR)
236 
237   static uint32_t Depth(const ActiveScrolledRoot* aActiveScrolledRoot) {
238     return aActiveScrolledRoot ? aActiveScrolledRoot->mDepth : 0;
239   }
240 
241   layers::ScrollableLayerGuid::ViewID ComputeViewId() const;
242 
243   // This field is lazily populated in GetViewId(). We don't want to do the
244   // work of populating if webrender is disabled, because it is often not
245   // needed.
246   mutable Maybe<layers::ScrollableLayerGuid::ViewID> mViewId;
247 
248   uint32_t mDepth;
249   bool mRetained;
250 };
251 
252 enum class nsDisplayListBuilderMode : uint8_t {
253   Painting,
254   PaintForPrinting,
255   EventDelivery,
256   FrameVisibility,
257   TransformComputation,
258   GenerateGlyph,
259 };
260 
261 using ListArenaAllocator = ArenaAllocator<4096, 8>;
262 
263 class nsDisplayItem;
264 class nsPaintedDisplayItem;
265 class nsDisplayList;
266 class nsDisplayWrapList;
267 class nsDisplayTableBackgroundSet;
268 class nsDisplayTableItem;
269 
270 class RetainedDisplayList;
271 
272 /**
273  * This manages a display list and is passed as a parameter to
274  * nsIFrame::BuildDisplayList.
275  * It contains the parameters that don't change from frame to frame and manages
276  * the display list memory using an arena. It also establishes the reference
277  * coordinate system for all display list items. Some of the parameters are
278  * available from the prescontext/presshell, but we copy them into the builder
279  * for faster/more convenient access.
280  */
281 class nsDisplayListBuilder {
282   /**
283    * This manages status of a 3d context to collect visible rects of
284    * descendants and passing a dirty rect.
285    *
286    * Since some transforms maybe singular, passing visible rects or
287    * the dirty rect level by level from parent to children may get a
288    * wrong result, being different from the result of appling with
289    * effective transform directly.
290    *
291    * nsIFrame::BuildDisplayListForStackingContext() uses
292    * AutoPreserves3DContext to install an instance on the builder.
293    *
294    * \see AutoAccumulateTransform, AutoAccumulateRect,
295    *      AutoPreserves3DContext, Accumulate, GetCurrentTransform,
296    *      StartRoot.
297    */
298   class Preserves3DContext {
299    public:
Preserves3DContext()300     Preserves3DContext()
301         : mAccumulatedRectLevels(0), mAllowAsyncAnimation(true) {}
302 
Preserves3DContext(const Preserves3DContext & aOther)303     Preserves3DContext(const Preserves3DContext& aOther)
304         : mAccumulatedTransform(),
305           mAccumulatedRect(),
306           mAccumulatedRectLevels(0),
307           mVisibleRect(aOther.mVisibleRect),
308           mAllowAsyncAnimation(aOther.mAllowAsyncAnimation) {}
309 
310     // Accmulate transforms of ancestors on the preserves-3d chain.
311     gfx::Matrix4x4 mAccumulatedTransform;
312     // Accmulate visible rect of descendants in the preserves-3d context.
313     nsRect mAccumulatedRect;
314     // How far this frame is from the root of the current 3d context.
315     int mAccumulatedRectLevels;
316     nsRect mVisibleRect;
317     // Allow async animation for this 3D context.
318     bool mAllowAsyncAnimation;
319   };
320 
321  public:
322   using ViewID = layers::ScrollableLayerGuid::ViewID;
323 
324   /**
325    * @param aReferenceFrame the frame at the root of the subtree; its origin
326    * is the origin of the reference coordinate system for this display list
327    * @param aMode encodes what the builder is being used for.
328    * @param aBuildCaret whether or not we should include the caret in any
329    * display lists that we make.
330    */
331   nsDisplayListBuilder(nsIFrame* aReferenceFrame,
332                        nsDisplayListBuilderMode aMode, bool aBuildCaret,
333                        bool aRetainingDisplayList = false);
334   ~nsDisplayListBuilder();
335 
336   void BeginFrame();
337   void EndFrame();
338 
AddTemporaryItem(nsDisplayItem * aItem)339   void AddTemporaryItem(nsDisplayItem* aItem) {
340     mTemporaryItems.AppendElement(aItem);
341   }
342 
343   WindowRenderer* GetWidgetWindowRenderer(nsView** aView = nullptr);
344   layers::WebRenderLayerManager* GetWidgetLayerManager(
345       nsView** aView = nullptr);
346 
347   /**
348    * @return true if the display is being built in order to determine which
349    * frame is under the mouse position.
350    */
IsForEventDelivery()351   bool IsForEventDelivery() const {
352     return mMode == nsDisplayListBuilderMode::EventDelivery;
353   }
354 
355   /**
356    * @return true if the display list is being built for painting. This
357    * includes both painting to a window or other buffer and painting to
358    * a print/pdf destination.
359    */
IsForPainting()360   bool IsForPainting() const {
361     return mMode == nsDisplayListBuilderMode::Painting ||
362            mMode == nsDisplayListBuilderMode::PaintForPrinting;
363   }
364 
365   /**
366    * @return true if the display list is being built specifically for printing.
367    */
IsForPrinting()368   bool IsForPrinting() const {
369     return mMode == nsDisplayListBuilderMode::PaintForPrinting;
370   }
371 
372   /**
373    * @return true if the display list is being built for determining frame
374    * visibility.
375    */
IsForFrameVisibility()376   bool IsForFrameVisibility() const {
377     return mMode == nsDisplayListBuilderMode::FrameVisibility;
378   }
379 
380   /**
381    * @return true if the display list is being built for creating the glyph
382    * mask from text items.
383    */
IsForGenerateGlyphMask()384   bool IsForGenerateGlyphMask() const {
385     return mMode == nsDisplayListBuilderMode::GenerateGlyph;
386   }
387 
IsForContent()388   bool IsForContent() const { return mIsForContent; }
389 
BuildCompositorHitTestInfo()390   bool BuildCompositorHitTestInfo() const {
391     return mBuildCompositorHitTestInfo;
392   }
393 
394   /**
395    * @return true if "painting is suppressed" during page load and we
396    * should paint only the background of the document.
397    */
IsBackgroundOnly()398   bool IsBackgroundOnly() {
399     NS_ASSERTION(mPresShellStates.Length() > 0,
400                  "don't call this if we're not in a presshell");
401     return CurrentPresShellState()->mIsBackgroundOnly;
402   }
403 
404   /**
405    * @return the root of given frame's (sub)tree, whose origin
406    * establishes the coordinate system for the child display items.
407    */
408   const nsIFrame* FindReferenceFrameFor(const nsIFrame* aFrame,
409                                         nsPoint* aOffset = nullptr) const;
410 
AdditionalOffset()411   const Maybe<nsPoint>& AdditionalOffset() const { return mAdditionalOffset; }
412 
413   /**
414    * @return the root of the display list's frame (sub)tree, whose origin
415    * establishes the coordinate system for the display list
416    */
RootReferenceFrame()417   nsIFrame* RootReferenceFrame() const { return mReferenceFrame; }
418 
419   /**
420    * @return a point pt such that adding pt to a coordinate relative to aFrame
421    * makes it relative to ReferenceFrame(), i.e., returns
422    * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
423    * the appunits of aFrame.
424    */
ToReferenceFrame(const nsIFrame * aFrame)425   const nsPoint ToReferenceFrame(const nsIFrame* aFrame) const {
426     nsPoint result;
427     FindReferenceFrameFor(aFrame, &result);
428     return result;
429   }
430   /**
431    * When building the display list, the scrollframe aFrame will be "ignored"
432    * for the purposes of clipping, and its scrollbars will be hidden. We use
433    * this to allow RenderOffscreen to render a whole document without beign
434    * clipped by the viewport or drawing the viewport scrollbars.
435    */
SetIgnoreScrollFrame(nsIFrame * aFrame)436   void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
437   /**
438    * Get the scrollframe to ignore, if any.
439    */
GetIgnoreScrollFrame()440   nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
441   void SetIsRelativeToLayoutViewport();
IsRelativeToLayoutViewport()442   bool IsRelativeToLayoutViewport() const {
443     return mIsRelativeToLayoutViewport;
444   }
445   /**
446    * Get the ViewID of the nearest scrolling ancestor frame.
447    */
GetCurrentScrollParentId()448   ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; }
449   /**
450    * Get and set the flag that indicates if scroll parents should have layers
451    * forcibly created. This flag is set when a deeply nested scrollframe has
452    * a displayport, and for scroll handoff to work properly the ancestor
453    * scrollframes should also get their own scrollable layers.
454    */
ForceLayerForScrollParent()455   void ForceLayerForScrollParent() { mForceLayerForScrollParent = true; }
456   /**
457    * Set the flag that indicates there is a non-minimal display port in the
458    * current subtree. This is used to determine display port expiry.
459    */
SetContainsNonMinimalDisplayPort()460   void SetContainsNonMinimalDisplayPort() {
461     mContainsNonMinimalDisplayPort = true;
462   }
463   /**
464    * Get the ViewID and the scrollbar flags corresponding to the scrollbar for
465    * which we are building display items at the moment.
466    */
GetCurrentScrollbarTarget()467   ViewID GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget; }
GetCurrentScrollbarDirection()468   Maybe<layers::ScrollDirection> GetCurrentScrollbarDirection() const {
469     return mCurrentScrollbarDirection;
470   }
471   /**
472    * Returns true if building a scrollbar, and the scrollbar will not be
473    * layerized.
474    */
IsBuildingNonLayerizedScrollbar()475   bool IsBuildingNonLayerizedScrollbar() const {
476     return mIsBuildingScrollbar && !mCurrentScrollbarWillHaveLayer;
477   }
478   /**
479    * Calling this setter makes us include all out-of-flow descendant
480    * frames in the display list, wherever they may be positioned (even
481    * outside the dirty rects).
482    */
SetIncludeAllOutOfFlows()483   void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
GetIncludeAllOutOfFlows()484   bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
485   /**
486    * Calling this setter makes us exclude all leaf frames that aren't
487    * selected.
488    */
SetSelectedFramesOnly()489   void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
GetSelectedFramesOnly()490   bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
491   /**
492    * @return Returns true if we should include the caret in any display lists
493    * that we make.
494    */
IsBuildingCaret()495   bool IsBuildingCaret() const { return mBuildCaret; }
496 
IsRetainingDisplayList()497   bool IsRetainingDisplayList() const { return mRetainingDisplayList; }
498 
IsPartialUpdate()499   bool IsPartialUpdate() const { return mPartialUpdate; }
SetPartialUpdate(bool aPartial)500   void SetPartialUpdate(bool aPartial) { mPartialUpdate = aPartial; }
501 
IsBuilding()502   bool IsBuilding() const { return mIsBuilding; }
SetIsBuilding(bool aIsBuilding)503   void SetIsBuilding(bool aIsBuilding) { mIsBuilding = aIsBuilding; }
504 
InInvalidSubtree()505   bool InInvalidSubtree() const { return mInInvalidSubtree; }
506 
507   /**
508    * Allows callers to selectively override the regular paint suppression
509    * checks, so that methods like GetFrameForPoint work when painting is
510    * suppressed.
511    */
IgnorePaintSuppression()512   void IgnorePaintSuppression() { mIgnoreSuppression = true; }
513   /**
514    * @return Returns if this builder will ignore paint suppression.
515    */
IsIgnoringPaintSuppression()516   bool IsIgnoringPaintSuppression() { return mIgnoreSuppression; }
517   /**
518    * Call this if we're doing normal painting to the window.
519    */
SetPaintingToWindow(bool aToWindow)520   void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
IsPaintingToWindow()521   bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
522   /**
523    * Call this if we're using high quality scaling for image decoding.
524    * It is also implied by IsPaintingToWindow.
525    */
SetUseHighQualityScaling(bool aUseHighQualityScaling)526   void SetUseHighQualityScaling(bool aUseHighQualityScaling) {
527     mUseHighQualityScaling = aUseHighQualityScaling;
528   }
UseHighQualityScaling()529   bool UseHighQualityScaling() const {
530     return mIsPaintingToWindow || mUseHighQualityScaling;
531   }
532   /**
533    * Call this if we're doing painting for WebRender
534    */
SetPaintingForWebRender(bool aForWebRender)535   void SetPaintingForWebRender(bool aForWebRender) {
536     mIsPaintingForWebRender = true;
537   }
IsPaintingForWebRender()538   bool IsPaintingForWebRender() const { return mIsPaintingForWebRender; }
539   /**
540    * Call this to prevent descending into subdocuments.
541    */
SetDescendIntoSubdocuments(bool aDescend)542   void SetDescendIntoSubdocuments(bool aDescend) {
543     mDescendIntoSubdocuments = aDescend;
544   }
545 
GetDescendIntoSubdocuments()546   bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; }
547 
548   /**
549    * Get dirty rect relative to current frame (the frame that we're calling
550    * BuildDisplayList on right now).
551    */
GetVisibleRect()552   const nsRect& GetVisibleRect() { return mVisibleRect; }
GetDirtyRect()553   const nsRect& GetDirtyRect() { return mDirtyRect; }
554 
SetVisibleRect(const nsRect & aVisibleRect)555   void SetVisibleRect(const nsRect& aVisibleRect) {
556     mVisibleRect = aVisibleRect;
557   }
558 
IntersectVisibleRect(const nsRect & aVisibleRect)559   void IntersectVisibleRect(const nsRect& aVisibleRect) {
560     mVisibleRect.IntersectRect(mVisibleRect, aVisibleRect);
561   }
562 
SetDirtyRect(const nsRect & aDirtyRect)563   void SetDirtyRect(const nsRect& aDirtyRect) { mDirtyRect = aDirtyRect; }
564 
IntersectDirtyRect(const nsRect & aDirtyRect)565   void IntersectDirtyRect(const nsRect& aDirtyRect) {
566     mDirtyRect.IntersectRect(mDirtyRect, aDirtyRect);
567   }
568 
GetCurrentFrame()569   const nsIFrame* GetCurrentFrame() { return mCurrentFrame; }
GetCurrentReferenceFrame()570   const nsIFrame* GetCurrentReferenceFrame() { return mCurrentReferenceFrame; }
571 
GetCurrentFrameOffsetToReferenceFrame()572   const nsPoint& GetCurrentFrameOffsetToReferenceFrame() const {
573     return mCurrentOffsetToReferenceFrame;
574   }
575 
Check()576   void Check() { mPool.Check(); }
577 
578   /**
579    * Returns true if merging and flattening of display lists should be
580    * performed while computing visibility.
581    */
AllowMergingAndFlattening()582   bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening; }
SetAllowMergingAndFlattening(bool aAllow)583   void SetAllowMergingAndFlattening(bool aAllow) {
584     mAllowMergingAndFlattening = aAllow;
585   }
586 
SetCompositorHitTestInfo(const gfx::CompositorHitTestInfo & aInfo)587   void SetCompositorHitTestInfo(const gfx::CompositorHitTestInfo& aInfo) {
588     mCompositorHitTestInfo = aInfo;
589   }
590 
GetCompositorHitTestInfo()591   const gfx::CompositorHitTestInfo& GetCompositorHitTestInfo() const {
592     return mCompositorHitTestInfo;
593   }
594 
595   /**
596    * Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
597    * needed, and adds it to the top of |aList|.
598    */
599   void BuildCompositorHitTestInfoIfNeeded(nsIFrame* aFrame,
600                                           nsDisplayList* aList);
601 
IsInsidePointerEventsNoneDoc()602   bool IsInsidePointerEventsNoneDoc() {
603     return CurrentPresShellState()->mInsidePointerEventsNoneDoc;
604   }
605 
IsTouchEventPrefEnabledDoc()606   bool IsTouchEventPrefEnabledDoc() {
607     return CurrentPresShellState()->mTouchEventPrefEnabledDoc;
608   }
609 
GetAncestorHasApzAwareEventHandler()610   bool GetAncestorHasApzAwareEventHandler() const {
611     return mAncestorHasApzAwareEventHandler;
612   }
613 
SetAncestorHasApzAwareEventHandler(bool aValue)614   void SetAncestorHasApzAwareEventHandler(bool aValue) {
615     mAncestorHasApzAwareEventHandler = aValue;
616   }
617 
HaveScrollableDisplayPort()618   bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort; }
SetHaveScrollableDisplayPort()619   void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = true; }
ClearHaveScrollableDisplayPort()620   void ClearHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = false; }
621 
SetIsCompositingCheap(bool aCompositingCheap)622   bool SetIsCompositingCheap(bool aCompositingCheap) {
623     bool temp = mIsCompositingCheap;
624     mIsCompositingCheap = aCompositingCheap;
625     return temp;
626   }
627 
IsCompositingCheap()628   bool IsCompositingCheap() const { return mIsCompositingCheap; }
629   /**
630    * Display the caret if needed.
631    */
DisplayCaret(nsIFrame * aFrame,nsDisplayList * aList)632   bool DisplayCaret(nsIFrame* aFrame, nsDisplayList* aList) {
633     nsIFrame* frame = GetCaretFrame();
634     if (aFrame == frame && !IsBackgroundOnly()) {
635       frame->DisplayCaret(this, aList);
636       return true;
637     }
638     return false;
639   }
640   /**
641    * Get the frame that the caret is supposed to draw in.
642    * If the caret is currently invisible, this will be null.
643    */
GetCaretFrame()644   nsIFrame* GetCaretFrame() { return mCaretFrame; }
645   /**
646    * Get the rectangle we're supposed to draw the caret into.
647    */
GetCaretRect()648   const nsRect& GetCaretRect() { return mCaretRect; }
649   /**
650    * Get the caret associated with the current presshell.
651    */
652   nsCaret* GetCaret();
653 
654   /**
655    * Returns the root scroll frame for the current PresShell, if the PresShell
656    * is ignoring viewport scrolling.
657    */
GetPresShellIgnoreScrollFrame()658   nsIFrame* GetPresShellIgnoreScrollFrame() {
659     return CurrentPresShellState()->mPresShellIgnoreScrollFrame;
660   }
661 
662   /**
663    * Notify the display list builder that we're entering a presshell.
664    * aReferenceFrame should be a frame in the new presshell.
665    * aPointerEventsNoneDoc should be set to true if the frame generating this
666    * document is pointer-events:none.
667    */
668   void EnterPresShell(const nsIFrame* aReferenceFrame,
669                       bool aPointerEventsNoneDoc = false);
670   /**
671    * For print-preview documents, we sometimes need to build display items for
672    * the same frames multiple times in the same presentation, with different
673    * clipping. Between each such batch of items, call
674    * ResetMarkedFramesForDisplayList to make sure that the results of
675    * MarkFramesForDisplayList do not carry over between batches.
676    */
677   void ResetMarkedFramesForDisplayList(const nsIFrame* aReferenceFrame);
678   /**
679    * Notify the display list builder that we're leaving a presshell.
680    */
681   void LeavePresShell(const nsIFrame* aReferenceFrame,
682                       nsDisplayList* aPaintedContents);
683 
684   void IncrementPresShellPaintCount(PresShell* aPresShell);
685 
686   /**
687    * Returns true if we're currently building a display list that's
688    * directly or indirectly under an nsDisplayTransform.
689    */
IsInTransform()690   bool IsInTransform() const { return mInTransform; }
691 
InEventsOnly()692   bool InEventsOnly() const { return mInEventsOnly; }
693   /**
694    * Indicate whether or not we're directly or indirectly under and
695    * nsDisplayTransform or SVG foreignObject.
696    */
SetInTransform(bool aInTransform)697   void SetInTransform(bool aInTransform) { mInTransform = aInTransform; }
698 
699   /**
700    * Returns true if we're currently building a display list that's
701    * under an nsDisplayFilters.
702    */
IsInFilter()703   bool IsInFilter() const { return mInFilter; }
704 
705   /**
706    * Return true if we're currently building a display list for a
707    * nested presshell.
708    */
IsInSubdocument()709   bool IsInSubdocument() const { return mPresShellStates.Length() > 1; }
710 
SetDisablePartialUpdates(bool aDisable)711   void SetDisablePartialUpdates(bool aDisable) {
712     mDisablePartialUpdates = aDisable;
713   }
DisablePartialUpdates()714   bool DisablePartialUpdates() const { return mDisablePartialUpdates; }
715 
SetPartialBuildFailed(bool aFailed)716   void SetPartialBuildFailed(bool aFailed) { mPartialBuildFailed = aFailed; }
PartialBuildFailed()717   bool PartialBuildFailed() const { return mPartialBuildFailed; }
718 
IsInActiveDocShell()719   bool IsInActiveDocShell() const { return mIsInActiveDocShell; }
SetInActiveDocShell(bool aActive)720   void SetInActiveDocShell(bool aActive) { mIsInActiveDocShell = aActive; }
721 
722   /**
723    * Return true if we're currently building a display list for the presshell
724    * of a chrome document, or if we're building the display list for a popup.
725    */
IsInChromeDocumentOrPopup()726   bool IsInChromeDocumentOrPopup() const {
727     return mIsInChromePresContext || mIsBuildingForPopup;
728   }
729 
730   /**
731    * @return true if images have been set to decode synchronously.
732    */
ShouldSyncDecodeImages()733   bool ShouldSyncDecodeImages() const { return mSyncDecodeImages; }
734 
735   /**
736    * Indicates whether we should synchronously decode images. If true, we decode
737    * and draw whatever image data has been loaded. If false, we just draw
738    * whatever has already been decoded.
739    */
SetSyncDecodeImages(bool aSyncDecodeImages)740   void SetSyncDecodeImages(bool aSyncDecodeImages) {
741     mSyncDecodeImages = aSyncDecodeImages;
742   }
743 
SetTableBackgroundSet(nsDisplayTableBackgroundSet * aTableSet)744   nsDisplayTableBackgroundSet* SetTableBackgroundSet(
745       nsDisplayTableBackgroundSet* aTableSet) {
746     nsDisplayTableBackgroundSet* old = mTableBackgroundSet;
747     mTableBackgroundSet = aTableSet;
748     return old;
749   }
GetTableBackgroundSet()750   nsDisplayTableBackgroundSet* GetTableBackgroundSet() const {
751     return mTableBackgroundSet;
752   }
753 
754   void FreeClipChains();
755 
756   /*
757    * Frees the temporary display items created during merging.
758    */
759   void FreeTemporaryItems();
760 
761   /**
762    * Helper method to generate background painting flags based on the
763    * information available in the display list builder.
764    */
765   uint32_t GetBackgroundPaintFlags();
766 
767   /**
768    * Helper method to generate nsImageRenderer flags based on the information
769    * available in the display list builder.
770    */
771   uint32_t GetImageRendererFlags() const;
772 
773   /**
774    * Helper method to generate image decoding flags based on the
775    * information available in the display list builder.
776    */
777   uint32_t GetImageDecodeFlags() const;
778 
779   /**
780    * Subtracts aRegion from *aVisibleRegion. We avoid letting
781    * aVisibleRegion become overcomplex by simplifying it if necessary.
782    */
783   void SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
784                                  const nsRegion& aRegion);
785 
786   /**
787    * Mark the frames in aFrames to be displayed if they intersect aDirtyRect
788    * (which is relative to aDirtyFrame). If the frames have placeholders
789    * that might not be displayed, we mark the placeholders and their ancestors
790    * to ensure that display list construction descends into them
791    * anyway. nsDisplayListBuilder will take care of unmarking them when it is
792    * destroyed.
793    */
794   void MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
795                                 const nsFrameList& aFrames);
796   void MarkFrameForDisplay(nsIFrame* aFrame, const nsIFrame* aStopAtFrame);
797   void MarkFrameForDisplayIfVisible(nsIFrame* aFrame,
798                                     const nsIFrame* aStopAtFrame);
799   void AddFrameMarkedForDisplayIfVisible(nsIFrame* aFrame);
800 
801   void ClearFixedBackgroundDisplayData();
802   /**
803    * Mark all child frames that Preserve3D() as needing display.
804    * Because these frames include transforms set on their parent, dirty rects
805    * for intermediate frames may be empty, yet child frames could still be
806    * visible.
807    */
808   void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame);
809 
810   /**
811    * Returns true if we need to descend into this frame when building
812    * the display list, even though it doesn't intersect the dirty
813    * rect, because it may have out-of-flows that do so.
814    */
ShouldDescendIntoFrame(nsIFrame * aFrame,bool aVisible)815   bool ShouldDescendIntoFrame(nsIFrame* aFrame, bool aVisible) const {
816     return aFrame->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
817            (aVisible && aFrame->ForceDescendIntoIfVisible()) ||
818            GetIncludeAllOutOfFlows();
819   }
820 
821   /**
822    * Returns the list of registered theme geometries.
823    */
GetThemeGeometries()824   nsTArray<nsIWidget::ThemeGeometry> GetThemeGeometries() const {
825     nsTArray<nsIWidget::ThemeGeometry> geometries;
826 
827     for (const auto& data : mThemeGeometries.Values()) {
828       geometries.AppendElements(*data);
829     }
830 
831     return geometries;
832   }
833 
834   /**
835    * Notifies the builder that a particular themed widget exists
836    * at the given rectangle within the currently built display list.
837    * For certain appearance values (currently only StyleAppearance::Toolbar and
838    * StyleAppearance::WindowTitlebar) this gets called during every display list
839    * construction, for every themed widget of the right type within the
840    * display list, except for themed widgets which are transformed or have
841    * effects applied to them (e.g. CSS opacity or filters).
842    *
843    * @param aWidgetType the -moz-appearance value for the themed widget
844    * @param aItem the item associated with the theme geometry
845    * @param aRect the device-pixel rect relative to the widget's displayRoot
846    * for the themed widget
847    */
RegisterThemeGeometry(uint8_t aWidgetType,nsDisplayItem * aItem,const LayoutDeviceIntRect & aRect)848   void RegisterThemeGeometry(uint8_t aWidgetType, nsDisplayItem* aItem,
849                              const LayoutDeviceIntRect& aRect) {
850     if (!mIsPaintingToWindow) {
851       return;
852     }
853 
854     nsTArray<nsIWidget::ThemeGeometry>* geometries =
855         mThemeGeometries.GetOrInsertNew(aItem);
856     geometries->AppendElement(nsIWidget::ThemeGeometry(aWidgetType, aRect));
857   }
858 
859   /**
860    * Removes theme geometries associated with the given display item |aItem|.
861    */
UnregisterThemeGeometry(nsDisplayItem * aItem)862   void UnregisterThemeGeometry(nsDisplayItem* aItem) {
863     mThemeGeometries.Remove(aItem);
864   }
865 
866   /**
867    * Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
868    * -moz-window-dragging value is |drag|, its border box is added to the
869    * collected dragging region; if the value is |no-drag|, the border box is
870    * subtracted from the region; if the value is |default|, that frame does
871    * not influence the window dragging region.
872    */
873   void AdjustWindowDraggingRegion(nsIFrame* aFrame);
874 
875   LayoutDeviceIntRegion GetWindowDraggingRegion() const;
876 
877   void RemoveModifiedWindowRegions();
878   void ClearRetainedWindowRegions();
879 
880   const nsTHashMap<nsPtrHashKey<dom::RemoteBrowser>, dom::EffectsInfo>&
GetEffectUpdates()881   GetEffectUpdates() const {
882     return mEffectsUpdates;
883   }
884 
885   void AddEffectUpdate(dom::RemoteBrowser* aBrowser,
886                        const dom::EffectsInfo& aUpdate);
887 
888   /**
889    * Allocate memory in our arena. It will only be freed when this display list
890    * builder is destroyed. This memory holds nsDisplayItems and
891    * DisplayItemClipChain objects.
892    *
893    * Destructors are called as soon as the item is no longer used.
894    */
Allocate(size_t aSize,DisplayListArenaObjectId aId)895   void* Allocate(size_t aSize, DisplayListArenaObjectId aId) {
896     return mPool.Allocate(aId, aSize);
897   }
Allocate(size_t aSize,DisplayItemType aType)898   void* Allocate(size_t aSize, DisplayItemType aType) {
899 #define DECLARE_DISPLAY_ITEM_TYPE(name_, ...)                \
900   static_assert(size_t(DisplayItemType::TYPE_##name_) ==     \
901                     size_t(DisplayListArenaObjectId::name_), \
902                 "");
903 #include "nsDisplayItemTypesList.h"
904     static_assert(size_t(DisplayItemType::TYPE_MAX) ==
905                       size_t(DisplayListArenaObjectId::CLIPCHAIN),
906                   "");
907     static_assert(size_t(DisplayItemType::TYPE_MAX) + 1 ==
908                       size_t(DisplayListArenaObjectId::LISTNODE),
909                   "");
910 #undef DECLARE_DISPLAY_ITEM_TYPE
911     return Allocate(aSize, DisplayListArenaObjectId(size_t(aType)));
912   }
913 
Destroy(DisplayListArenaObjectId aId,void * aPtr)914   void Destroy(DisplayListArenaObjectId aId, void* aPtr) {
915     return mPool.Free(aId, aPtr);
916   }
Destroy(DisplayItemType aType,void * aPtr)917   void Destroy(DisplayItemType aType, void* aPtr) {
918     return Destroy(DisplayListArenaObjectId(size_t(aType)), aPtr);
919   }
920 
921   /**
922    * Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
923    * automatically when the arena goes away.
924    */
925   ActiveScrolledRoot* AllocateActiveScrolledRoot(
926       const ActiveScrolledRoot* aParent, nsIScrollableFrame* aScrollableFrame);
927 
928   /**
929    * Allocate a new DisplayItemClipChain object in the arena. Will be cleaned
930    * up automatically when the arena goes away.
931    */
932   const DisplayItemClipChain* AllocateDisplayItemClipChain(
933       const DisplayItemClip& aClip, const ActiveScrolledRoot* aASR,
934       const DisplayItemClipChain* aParent);
935 
936   /**
937    * Intersect two clip chains, allocating the new clip chain items in this
938    * builder's arena. The result is parented to aAncestor, and no intersections
939    * happen past aAncestor's ASR.
940    * That means aAncestor has to be living in this builder's arena already.
941    * aLeafClip1 and aLeafClip2 only need to outlive the call to this function,
942    * their values are copied into the newly-allocated intersected clip chain
943    * and this function does not hold on to any pointers to them.
944    */
945   const DisplayItemClipChain* CreateClipChainIntersection(
946       const DisplayItemClipChain* aAncestor,
947       const DisplayItemClipChain* aLeafClip1,
948       const DisplayItemClipChain* aLeafClip2);
949 
950   /**
951    * Same as above, except aAncestor is computed as the nearest common
952    * ancestor of the two provided clips.
953    */
954   const DisplayItemClipChain* CreateClipChainIntersection(
955       const DisplayItemClipChain* aLeafClip1,
956       const DisplayItemClipChain* aLeafClip2);
957 
958   /**
959    * Clone the supplied clip chain's chain items into this builder's arena.
960    */
961   const DisplayItemClipChain* CopyWholeChain(
962       const DisplayItemClipChain* aClipChain);
963 
GetFilterASR()964   const ActiveScrolledRoot* GetFilterASR() const { return mFilterASR; }
965 
966   /**
967    * Merges the display items in |aMergedItems| and returns a new temporary
968    * display item.
969    * The display items in |aMergedItems| have to be mergeable with each other.
970    */
971   nsDisplayWrapList* MergeItems(nsTArray<nsDisplayItem*>& aItems);
972 
973   /**
974    * A helper class used to temporarily set nsDisplayListBuilder properties for
975    * building display items.
976    * aVisibleRect and aDirtyRect are relative to aForChild.
977    */
978   class AutoBuildingDisplayList {
979    public:
AutoBuildingDisplayList(nsDisplayListBuilder * aBuilder,nsIFrame * aForChild,const nsRect & aVisibleRect,const nsRect & aDirtyRect)980     AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild,
981                             const nsRect& aVisibleRect,
982                             const nsRect& aDirtyRect)
983         : AutoBuildingDisplayList(aBuilder, aForChild, aVisibleRect, aDirtyRect,
984                                   aForChild->IsTransformed()) {}
985 
986     AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild,
987                             const nsRect& aVisibleRect,
988                             const nsRect& aDirtyRect,
989                             const bool aIsTransformed);
990 
SetReferenceFrameAndCurrentOffset(const nsIFrame * aFrame,const nsPoint & aOffset)991     void SetReferenceFrameAndCurrentOffset(const nsIFrame* aFrame,
992                                            const nsPoint& aOffset) {
993       mBuilder->mCurrentReferenceFrame = aFrame;
994       mBuilder->mCurrentOffsetToReferenceFrame = aOffset;
995     }
996 
SetAdditionalOffset(const nsPoint & aOffset)997     void SetAdditionalOffset(const nsPoint& aOffset) {
998       MOZ_ASSERT(!mBuilder->mAdditionalOffset);
999       mBuilder->mAdditionalOffset = Some(aOffset);
1000 
1001       mBuilder->mCurrentOffsetToReferenceFrame += aOffset;
1002     }
1003 
RestoreBuildingInvisibleItemsValue()1004     void RestoreBuildingInvisibleItemsValue() {
1005       mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
1006     }
1007 
~AutoBuildingDisplayList()1008     ~AutoBuildingDisplayList() {
1009       mBuilder->mCurrentFrame = mPrevFrame;
1010       mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame;
1011       mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset;
1012       mBuilder->mVisibleRect = mPrevVisibleRect;
1013       mBuilder->mDirtyRect = mPrevDirtyRect;
1014       mBuilder->mAncestorHasApzAwareEventHandler =
1015           mPrevAncestorHasApzAwareEventHandler;
1016       mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
1017       mBuilder->mInInvalidSubtree = mPrevInInvalidSubtree;
1018       mBuilder->mAdditionalOffset = mPrevAdditionalOffset;
1019       mBuilder->mCompositorHitTestInfo = mPrevCompositorHitTestInfo;
1020     }
1021 
1022    private:
1023     nsDisplayListBuilder* mBuilder;
1024     const nsIFrame* mPrevFrame;
1025     const nsIFrame* mPrevReferenceFrame;
1026     nsPoint mPrevOffset;
1027     Maybe<nsPoint> mPrevAdditionalOffset;
1028     nsRect mPrevVisibleRect;
1029     nsRect mPrevDirtyRect;
1030     gfx::CompositorHitTestInfo mPrevCompositorHitTestInfo;
1031     bool mPrevAncestorHasApzAwareEventHandler;
1032     bool mPrevBuildingInvisibleItems;
1033     bool mPrevInInvalidSubtree;
1034   };
1035 
1036   /**
1037    * A helper class to temporarily set the value of mInTransform.
1038    */
1039   class AutoInTransformSetter {
1040    public:
AutoInTransformSetter(nsDisplayListBuilder * aBuilder,bool aInTransform)1041     AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform)
1042         : mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) {
1043       aBuilder->mInTransform = aInTransform;
1044     }
1045 
~AutoInTransformSetter()1046     ~AutoInTransformSetter() { mBuilder->mInTransform = mOldValue; }
1047 
1048    private:
1049     nsDisplayListBuilder* mBuilder;
1050     bool mOldValue;
1051   };
1052 
1053   class AutoInEventsOnly {
1054    public:
AutoInEventsOnly(nsDisplayListBuilder * aBuilder,bool aInEventsOnly)1055     AutoInEventsOnly(nsDisplayListBuilder* aBuilder, bool aInEventsOnly)
1056         : mBuilder(aBuilder), mOldValue(aBuilder->mInEventsOnly) {
1057       aBuilder->mInEventsOnly |= aInEventsOnly;
1058     }
1059 
~AutoInEventsOnly()1060     ~AutoInEventsOnly() { mBuilder->mInEventsOnly = mOldValue; }
1061 
1062    private:
1063     nsDisplayListBuilder* mBuilder;
1064     bool mOldValue;
1065   };
1066 
1067   /**
1068    * A helper class to temporarily set the value of mFilterASR and
1069    * mInFilter.
1070    */
1071   class AutoEnterFilter {
1072    public:
AutoEnterFilter(nsDisplayListBuilder * aBuilder,bool aUsingFilter)1073     AutoEnterFilter(nsDisplayListBuilder* aBuilder, bool aUsingFilter)
1074         : mBuilder(aBuilder),
1075           mOldValue(aBuilder->mFilterASR),
1076           mOldInFilter(aBuilder->mInFilter) {
1077       if (!aBuilder->mFilterASR && aUsingFilter) {
1078         aBuilder->mFilterASR = aBuilder->CurrentActiveScrolledRoot();
1079         aBuilder->mInFilter = true;
1080       }
1081     }
1082 
~AutoEnterFilter()1083     ~AutoEnterFilter() {
1084       mBuilder->mFilterASR = mOldValue;
1085       mBuilder->mInFilter = mOldInFilter;
1086     }
1087 
1088    private:
1089     nsDisplayListBuilder* mBuilder;
1090     const ActiveScrolledRoot* mOldValue;
1091     bool mOldInFilter;
1092   };
1093 
1094   /**
1095    * A helper class to temporarily set the value of mCurrentScrollParentId.
1096    */
1097   class AutoCurrentScrollParentIdSetter {
1098    public:
AutoCurrentScrollParentIdSetter(nsDisplayListBuilder * aBuilder,ViewID aScrollId)1099     AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder,
1100                                     ViewID aScrollId)
1101         : mBuilder(aBuilder),
1102           mOldValue(aBuilder->mCurrentScrollParentId),
1103           mOldForceLayer(aBuilder->mForceLayerForScrollParent),
1104           mOldContainsNonMinimalDisplayPort(
1105               mBuilder->mContainsNonMinimalDisplayPort) {
1106       // If this AutoCurrentScrollParentIdSetter has the same scrollId as the
1107       // previous one on the stack, then that means the scrollframe that
1108       // created this isn't actually scrollable and cannot participate in
1109       // scroll handoff. We set mCanBeScrollParent to false to indicate this.
1110       mCanBeScrollParent = (mOldValue != aScrollId);
1111       aBuilder->mCurrentScrollParentId = aScrollId;
1112       aBuilder->mForceLayerForScrollParent = false;
1113       aBuilder->mContainsNonMinimalDisplayPort = false;
1114     }
1115 
ShouldForceLayerForScrollParent()1116     bool ShouldForceLayerForScrollParent() const {
1117       // Only scrollframes participating in scroll handoff can be forced to
1118       // layerize
1119       return mCanBeScrollParent && mBuilder->mForceLayerForScrollParent;
1120     }
1121 
GetContainsNonMinimalDisplayPort()1122     bool GetContainsNonMinimalDisplayPort() const {
1123       // Only for scrollframes participating in scroll handoff can we return
1124       // true.
1125       return mCanBeScrollParent && mBuilder->mContainsNonMinimalDisplayPort;
1126     }
1127 
~AutoCurrentScrollParentIdSetter()1128     ~AutoCurrentScrollParentIdSetter() {
1129       mBuilder->mCurrentScrollParentId = mOldValue;
1130       if (mCanBeScrollParent) {
1131         // If this flag is set, caller code is responsible for having dealt
1132         // with the current value of mBuilder->mForceLayerForScrollParent, so
1133         // we can just restore the old value.
1134         mBuilder->mForceLayerForScrollParent = mOldForceLayer;
1135       } else {
1136         // Otherwise we need to keep propagating the force-layerization flag
1137         // upwards to the next ancestor scrollframe that does participate in
1138         // scroll handoff.
1139         mBuilder->mForceLayerForScrollParent |= mOldForceLayer;
1140       }
1141       mBuilder->mContainsNonMinimalDisplayPort |=
1142           mOldContainsNonMinimalDisplayPort;
1143     }
1144 
1145    private:
1146     nsDisplayListBuilder* mBuilder;
1147     ViewID mOldValue;
1148     bool mOldForceLayer;
1149     bool mOldContainsNonMinimalDisplayPort;
1150     bool mCanBeScrollParent;
1151   };
1152 
1153   /**
1154    * Used to update the current active scrolled root on the display list
1155    * builder, and to create new active scrolled roots.
1156    */
1157   class AutoCurrentActiveScrolledRootSetter {
1158    public:
AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder * aBuilder)1159     explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder* aBuilder)
1160         : mBuilder(aBuilder),
1161           mSavedActiveScrolledRoot(aBuilder->mCurrentActiveScrolledRoot),
1162           mContentClipASR(aBuilder->ClipState().GetContentClipASR()),
1163           mDescendantsStartIndex(aBuilder->mActiveScrolledRoots.Length()),
1164           mUsed(false) {}
1165 
~AutoCurrentActiveScrolledRootSetter()1166     ~AutoCurrentActiveScrolledRootSetter() {
1167       mBuilder->mCurrentActiveScrolledRoot = mSavedActiveScrolledRoot;
1168     }
1169 
1170     void SetCurrentActiveScrolledRoot(
1171         const ActiveScrolledRoot* aActiveScrolledRoot);
1172 
EnterScrollFrame(nsIScrollableFrame * aScrollableFrame)1173     void EnterScrollFrame(nsIScrollableFrame* aScrollableFrame) {
1174       MOZ_ASSERT(!mUsed);
1175       ActiveScrolledRoot* asr = mBuilder->AllocateActiveScrolledRoot(
1176           mBuilder->mCurrentActiveScrolledRoot, aScrollableFrame);
1177       mBuilder->mCurrentActiveScrolledRoot = asr;
1178       mUsed = true;
1179     }
1180 
1181     void InsertScrollFrame(nsIScrollableFrame* aScrollableFrame);
1182 
1183    private:
1184     nsDisplayListBuilder* mBuilder;
1185     /**
1186      * The builder's mCurrentActiveScrolledRoot at construction time which
1187      * needs to be restored at destruction time.
1188      */
1189     const ActiveScrolledRoot* mSavedActiveScrolledRoot;
1190     /**
1191      * If there's a content clip on the builder at construction time, then
1192      * mContentClipASR is that content clip's ASR, otherwise null. The
1193      * assumption is that the content clip doesn't get relaxed while this
1194      * object is on the stack.
1195      */
1196     const ActiveScrolledRoot* mContentClipASR;
1197     /**
1198      * InsertScrollFrame needs to mutate existing ASRs (those that were
1199      * created while this object was on the stack), and mDescendantsStartIndex
1200      * makes it easier to skip ASRs that were created in the past.
1201      */
1202     size_t mDescendantsStartIndex;
1203     /**
1204      * Flag to make sure that only one of SetCurrentActiveScrolledRoot /
1205      * EnterScrollFrame / InsertScrollFrame is called per instance of this
1206      * class.
1207      */
1208     bool mUsed;
1209   };
1210 
1211   /**
1212    * Keeps track of the innermost ASR that can be used as the ASR for a
1213    * container item that wraps all items that were created while this
1214    * object was on the stack.
1215    * The rule is: all child items of the container item need to have
1216    * clipped bounds with respect to the container ASR.
1217    */
1218   class AutoContainerASRTracker {
1219    public:
1220     explicit AutoContainerASRTracker(nsDisplayListBuilder* aBuilder);
1221 
GetContainerASR()1222     const ActiveScrolledRoot* GetContainerASR() {
1223       return mBuilder->mCurrentContainerASR;
1224     }
1225 
~AutoContainerASRTracker()1226     ~AutoContainerASRTracker() {
1227       mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickAncestor(
1228           mBuilder->mCurrentContainerASR, mSavedContainerASR);
1229     }
1230 
1231    private:
1232     nsDisplayListBuilder* mBuilder;
1233     const ActiveScrolledRoot* mSavedContainerASR;
1234   };
1235 
1236   /**
1237    * A helper class to temporarily set the value of mCurrentScrollbarTarget
1238    * and mCurrentScrollbarFlags.
1239    */
1240   class AutoCurrentScrollbarInfoSetter {
1241    public:
AutoCurrentScrollbarInfoSetter(nsDisplayListBuilder * aBuilder,ViewID aScrollTargetID,const Maybe<layers::ScrollDirection> & aScrollbarDirection,bool aWillHaveLayer)1242     AutoCurrentScrollbarInfoSetter(
1243         nsDisplayListBuilder* aBuilder, ViewID aScrollTargetID,
1244         const Maybe<layers::ScrollDirection>& aScrollbarDirection,
1245         bool aWillHaveLayer)
1246         : mBuilder(aBuilder) {
1247       aBuilder->mIsBuildingScrollbar = true;
1248       aBuilder->mCurrentScrollbarTarget = aScrollTargetID;
1249       aBuilder->mCurrentScrollbarDirection = aScrollbarDirection;
1250       aBuilder->mCurrentScrollbarWillHaveLayer = aWillHaveLayer;
1251     }
1252 
~AutoCurrentScrollbarInfoSetter()1253     ~AutoCurrentScrollbarInfoSetter() {
1254       // No need to restore old values because scrollbars cannot be nested.
1255       mBuilder->mIsBuildingScrollbar = false;
1256       mBuilder->mCurrentScrollbarTarget =
1257           layers::ScrollableLayerGuid::NULL_SCROLL_ID;
1258       mBuilder->mCurrentScrollbarDirection.reset();
1259       mBuilder->mCurrentScrollbarWillHaveLayer = false;
1260     }
1261 
1262    private:
1263     nsDisplayListBuilder* mBuilder;
1264   };
1265 
1266   /**
1267    * A helper class to temporarily set mBuildingExtraPagesForPageNum.
1268    */
1269   class MOZ_RAII AutoPageNumberSetter {
1270    public:
AutoPageNumberSetter(nsDisplayListBuilder * aBuilder,const uint8_t aPageNum)1271     AutoPageNumberSetter(nsDisplayListBuilder* aBuilder, const uint8_t aPageNum)
1272         : mBuilder(aBuilder),
1273           mOldPageNum(aBuilder->GetBuildingExtraPagesForPageNum()) {
1274       mBuilder->SetBuildingExtraPagesForPageNum(aPageNum);
1275     }
~AutoPageNumberSetter()1276     ~AutoPageNumberSetter() {
1277       mBuilder->SetBuildingExtraPagesForPageNum(mOldPageNum);
1278     }
1279 
1280    private:
1281     nsDisplayListBuilder* mBuilder;
1282     uint8_t mOldPageNum;
1283   };
1284 
1285   /**
1286    * A helper class to track current effective transform for items.
1287    *
1288    * For frames that is Combines3DTransformWithAncestors(), we need to
1289    * apply all transforms of ancestors on the same preserves3D chain
1290    * on the bounds of current frame to the coordination of the 3D
1291    * context root.  The 3D context root computes it's bounds from
1292    * these transformed bounds.
1293    */
1294   class AutoAccumulateTransform {
1295    public:
AutoAccumulateTransform(nsDisplayListBuilder * aBuilder)1296     explicit AutoAccumulateTransform(nsDisplayListBuilder* aBuilder)
1297         : mBuilder(aBuilder),
1298           mSavedTransform(aBuilder->mPreserves3DCtx.mAccumulatedTransform) {}
1299 
~AutoAccumulateTransform()1300     ~AutoAccumulateTransform() {
1301       mBuilder->mPreserves3DCtx.mAccumulatedTransform = mSavedTransform;
1302     }
1303 
Accumulate(const gfx::Matrix4x4 & aTransform)1304     void Accumulate(const gfx::Matrix4x4& aTransform) {
1305       mBuilder->mPreserves3DCtx.mAccumulatedTransform =
1306           aTransform * mBuilder->mPreserves3DCtx.mAccumulatedTransform;
1307     }
1308 
GetCurrentTransform()1309     const gfx::Matrix4x4& GetCurrentTransform() {
1310       return mBuilder->mPreserves3DCtx.mAccumulatedTransform;
1311     }
1312 
StartRoot()1313     void StartRoot() {
1314       mBuilder->mPreserves3DCtx.mAccumulatedTransform = gfx::Matrix4x4();
1315     }
1316 
1317    private:
1318     nsDisplayListBuilder* mBuilder;
1319     gfx::Matrix4x4 mSavedTransform;
1320   };
1321 
1322   /**
1323    * A helper class to collect bounds rects of descendants.
1324    *
1325    * For a 3D context root, it's bounds is computed from the bounds of
1326    * descendants.  If we transform bounds frame by frame applying
1327    * transforms, the bounds may turn to empty for any singular
1328    * transform on the path, but it is not empty for the accumulated
1329    * transform.
1330    */
1331   class AutoAccumulateRect {
1332    public:
AutoAccumulateRect(nsDisplayListBuilder * aBuilder)1333     explicit AutoAccumulateRect(nsDisplayListBuilder* aBuilder)
1334         : mBuilder(aBuilder),
1335           mSavedRect(aBuilder->mPreserves3DCtx.mAccumulatedRect) {
1336       aBuilder->mPreserves3DCtx.mAccumulatedRect = nsRect();
1337       aBuilder->mPreserves3DCtx.mAccumulatedRectLevels++;
1338     }
1339 
~AutoAccumulateRect()1340     ~AutoAccumulateRect() {
1341       mBuilder->mPreserves3DCtx.mAccumulatedRect = mSavedRect;
1342       mBuilder->mPreserves3DCtx.mAccumulatedRectLevels--;
1343     }
1344 
1345    private:
1346     nsDisplayListBuilder* mBuilder;
1347     nsRect mSavedRect;
1348   };
1349 
AccumulateRect(const nsRect & aRect)1350   void AccumulateRect(const nsRect& aRect) {
1351     mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect,
1352                                                aRect);
1353   }
1354 
GetAccumulatedRect()1355   const nsRect& GetAccumulatedRect() {
1356     return mPreserves3DCtx.mAccumulatedRect;
1357   }
1358 
1359   /**
1360    * The level is increased by one for items establishing 3D rendering
1361    * context and starting a new accumulation.
1362    */
GetAccumulatedRectLevels()1363   int GetAccumulatedRectLevels() {
1364     return mPreserves3DCtx.mAccumulatedRectLevels;
1365   }
1366 
1367   struct OutOfFlowDisplayData {
OutOfFlowDisplayDataOutOfFlowDisplayData1368     OutOfFlowDisplayData(
1369         const DisplayItemClipChain* aContainingBlockClipChain,
1370         const DisplayItemClipChain* aCombinedClipChain,
1371         const ActiveScrolledRoot* aContainingBlockActiveScrolledRoot,
1372         const nsRect& aVisibleRect, const nsRect& aDirtyRect)
1373         : mContainingBlockClipChain(aContainingBlockClipChain),
1374           mCombinedClipChain(aCombinedClipChain),
1375           mContainingBlockActiveScrolledRoot(
1376               aContainingBlockActiveScrolledRoot),
1377           mVisibleRect(aVisibleRect),
1378           mDirtyRect(aDirtyRect) {}
1379     const DisplayItemClipChain* mContainingBlockClipChain;
1380     const DisplayItemClipChain*
1381         mCombinedClipChain;  // only necessary for the special case of top layer
1382     const ActiveScrolledRoot* mContainingBlockActiveScrolledRoot;
1383 
1384     // If this OutOfFlowDisplayData is associated with the ViewportFrame
1385     // of a document that has a resolution (creating separate visual and
1386     // layout viewports with their own coordinate spaces), these rects
1387     // are in layout coordinates. Similarly, GetVisibleRectForFrame() in
1388     // such a case returns a quantity in layout coordinates.
1389     nsRect mVisibleRect;
1390     nsRect mDirtyRect;
1391 
1392     static nsRect ComputeVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
1393                                              nsIFrame* aFrame,
1394                                              const nsRect& aVisibleRect,
1395                                              const nsRect& aDirtyRect,
1396                                              nsRect* aOutDirtyRect);
1397 
GetVisibleRectForFrameOutOfFlowDisplayData1398     nsRect GetVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
1399                                   nsIFrame* aFrame, nsRect* aDirtyRect) {
1400       return ComputeVisibleRectForFrame(aBuilder, aFrame, mVisibleRect,
1401                                         mDirtyRect, aDirtyRect);
1402     }
1403   };
1404 
1405   NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty,
1406                                       OutOfFlowDisplayData)
1407 
1408   struct DisplayListBuildingData {
1409     nsIFrame* mModifiedAGR = nullptr;
1410     nsRect mDirtyRect;
1411   };
NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect,DisplayListBuildingData)1412   NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect,
1413                                       DisplayListBuildingData)
1414 
1415   NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect,
1416                                       nsRect)
1417 
1418   static OutOfFlowDisplayData* GetOutOfFlowData(nsIFrame* aFrame) {
1419     if (!aFrame->GetParent()) {
1420       return nullptr;
1421     }
1422     return aFrame->GetParent()->GetProperty(OutOfFlowDisplayDataProperty());
1423   }
1424 
1425   nsPresContext* CurrentPresContext();
1426 
GetCurrentFixedBackgroundDisplayData()1427   OutOfFlowDisplayData* GetCurrentFixedBackgroundDisplayData() {
1428     auto& displayData = CurrentPresShellState()->mFixedBackgroundDisplayData;
1429     return displayData ? displayData.ptr() : nullptr;
1430   }
1431 
1432   /**
1433    * Accumulates the bounds of box frames that have moz-appearance
1434    * -moz-win-exclude-glass style. Used in setting glass margins on
1435    * Windows.
1436    *
1437    * We set the window opaque region (from which glass margins are computed)
1438    * to the intersection of the glass region specified here and the opaque
1439    * region computed during painting. So the excluded glass region actually
1440    * *limits* the extent of the opaque area reported to Windows. We limit it
1441    * so that changes to the computed opaque region (which can vary based on
1442    * region optimizations and the placement of UI elements) outside the
1443    * -moz-win-exclude-glass area don't affect the glass margins reported to
1444    * Windows; changing those margins willy-nilly can cause the Windows 7 glass
1445    * haze effect to jump around disconcertingly.
1446    */
AddWindowExcludeGlassRegion(nsIFrame * aFrame,const nsRect & aBounds)1447   void AddWindowExcludeGlassRegion(nsIFrame* aFrame, const nsRect& aBounds) {
1448     mWindowExcludeGlassRegion.Add(aFrame, aBounds);
1449   }
1450 
1451   /**
1452    * Returns the window exclude glass region.
1453    */
GetWindowExcludeGlassRegion()1454   nsRegion GetWindowExcludeGlassRegion() const {
1455     return mWindowExcludeGlassRegion.ToRegion();
1456   }
1457 
1458   /**
1459    * Accumulates opaque stuff into the window opaque region.
1460    */
AddWindowOpaqueRegion(nsIFrame * aFrame,const nsRect & aBounds)1461   void AddWindowOpaqueRegion(nsIFrame* aFrame, const nsRect& aBounds) {
1462     if (IsRetainingDisplayList()) {
1463       mRetainedWindowOpaqueRegion.Add(aFrame, aBounds);
1464       return;
1465     }
1466     mWindowOpaqueRegion.Or(mWindowOpaqueRegion, aBounds);
1467   }
1468   /**
1469    * Returns the window opaque region built so far. This may be incomplete
1470    * since the opaque region is built during layer construction.
1471    */
GetWindowOpaqueRegion()1472   const nsRegion GetWindowOpaqueRegion() {
1473     return IsRetainingDisplayList() ? mRetainedWindowOpaqueRegion.ToRegion()
1474                                     : mWindowOpaqueRegion;
1475   }
1476 
1477   void SetGlassDisplayItem(nsDisplayItem* aItem);
ClearGlassDisplayItem()1478   void ClearGlassDisplayItem() { mGlassDisplayItem = nullptr; }
GetGlassDisplayItem()1479   nsDisplayItem* GetGlassDisplayItem() { return mGlassDisplayItem; }
1480 
1481   bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem);
1482 
1483   /**
1484    * mContainsBlendMode is true if we processed a display item that
1485    * has a blend mode attached. We do this so we can insert a
1486    * nsDisplayBlendContainer in the parent stacking context.
1487    */
SetContainsBlendMode(bool aContainsBlendMode)1488   void SetContainsBlendMode(bool aContainsBlendMode) {
1489     mContainsBlendMode = aContainsBlendMode;
1490   }
ContainsBlendMode()1491   bool ContainsBlendMode() const { return mContainsBlendMode; }
1492 
1493   /**
1494    * mContainsBackdropFilter is true if we proccessed a display item that
1495    * has a backdrop filter set. We track this so we can insert a
1496    * nsDisplayBackdropRootContainer in the stacking context of the nearest
1497    * ancestor that forms a backdrop root.
1498    */
SetContainsBackdropFilter(bool aContainsBackdropFilter)1499   void SetContainsBackdropFilter(bool aContainsBackdropFilter) {
1500     mContainsBackdropFilter = aContainsBackdropFilter;
1501   }
ContainsBackdropFilter()1502   bool ContainsBackdropFilter() const { return mContainsBackdropFilter; }
1503 
ClipState()1504   DisplayListClipState& ClipState() { return mClipState; }
CurrentActiveScrolledRoot()1505   const ActiveScrolledRoot* CurrentActiveScrolledRoot() {
1506     return mCurrentActiveScrolledRoot;
1507   }
CurrentAncestorASRStackingContextContents()1508   const ActiveScrolledRoot* CurrentAncestorASRStackingContextContents() {
1509     return mCurrentContainerASR;
1510   }
1511 
1512   /**
1513    * Add the current frame to the will-change budget if possible and
1514    * remeber the outcome. Subsequent calls to IsInWillChangeBudget
1515    * will return the same value as return here.
1516    */
1517   bool AddToWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
1518 
1519   /**
1520    * This will add the current frame to the will-change budget the first
1521    * time it is seen. On subsequent calls this will return the same
1522    * answer. This effectively implements a first-come, first-served
1523    * allocation of the will-change budget.
1524    */
1525   bool IsInWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
1526 
1527   /**
1528    * Clears the will-change budget status for the given |aFrame|.
1529    * This will also remove the frame from will-change budgets.
1530    */
1531   void ClearWillChangeBudgetStatus(nsIFrame* aFrame);
1532 
1533   /**
1534    * Removes the given |aFrame| from will-change budgets.
1535    */
1536   void RemoveFromWillChangeBudgets(const nsIFrame* aFrame);
1537 
1538   /**
1539    * Clears the will-change budgets.
1540    */
1541   void ClearWillChangeBudgets();
1542 
1543   void EnterSVGEffectsContents(nsIFrame* aEffectsFrame,
1544                                nsDisplayList* aHoistedItemsStorage);
1545   void ExitSVGEffectsContents();
1546 
1547   bool ShouldBuildScrollInfoItemsForHoisting() const;
1548 
1549   void AppendNewScrollInfoItemForHoisting(
1550       nsDisplayScrollInfoLayer* aScrollInfoItem);
1551 
1552   /**
1553    * A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
1554    *
1555    * mPreserves3DCtx is used by class AutoAccumulateTransform &
1556    * AutoAccumulateRect to passing data between frames in the 3D
1557    * context.  If a frame create a new 3D context, it should restore
1558    * the value of mPreserves3DCtx before returning back to the parent.
1559    * This class do it for the users.
1560    */
1561   class AutoPreserves3DContext {
1562    public:
AutoPreserves3DContext(nsDisplayListBuilder * aBuilder)1563     explicit AutoPreserves3DContext(nsDisplayListBuilder* aBuilder)
1564         : mBuilder(aBuilder), mSavedCtx(aBuilder->mPreserves3DCtx) {}
1565 
~AutoPreserves3DContext()1566     ~AutoPreserves3DContext() { mBuilder->mPreserves3DCtx = mSavedCtx; }
1567 
1568    private:
1569     nsDisplayListBuilder* mBuilder;
1570     Preserves3DContext mSavedCtx;
1571   };
1572 
GetPreserves3DRect()1573   const nsRect GetPreserves3DRect() const {
1574     return mPreserves3DCtx.mVisibleRect;
1575   }
1576 
SavePreserves3DRect()1577   void SavePreserves3DRect() { mPreserves3DCtx.mVisibleRect = mVisibleRect; }
1578 
SavePreserves3DAllowAsyncAnimation(bool aValue)1579   void SavePreserves3DAllowAsyncAnimation(bool aValue) {
1580     mPreserves3DCtx.mAllowAsyncAnimation = aValue;
1581   }
1582 
GetPreserves3DAllowAsyncAnimation()1583   bool GetPreserves3DAllowAsyncAnimation() const {
1584     return mPreserves3DCtx.mAllowAsyncAnimation;
1585   }
1586 
IsBuildingInvisibleItems()1587   bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems; }
1588 
SetBuildingInvisibleItems(bool aBuildingInvisibleItems)1589   void SetBuildingInvisibleItems(bool aBuildingInvisibleItems) {
1590     mBuildingInvisibleItems = aBuildingInvisibleItems;
1591   }
1592 
SetBuildingExtraPagesForPageNum(uint8_t aPageNum)1593   void SetBuildingExtraPagesForPageNum(uint8_t aPageNum) {
1594     mBuildingExtraPagesForPageNum = aPageNum;
1595   }
GetBuildingExtraPagesForPageNum()1596   uint8_t GetBuildingExtraPagesForPageNum() const {
1597     return mBuildingExtraPagesForPageNum;
1598   }
1599 
HitTestIsForVisibility()1600   bool HitTestIsForVisibility() const { return mVisibleThreshold.isSome(); }
1601 
VisibilityThreshold()1602   float VisibilityThreshold() const {
1603     MOZ_DIAGNOSTIC_ASSERT(HitTestIsForVisibility());
1604     return mVisibleThreshold.valueOr(1.0f);
1605   }
1606 
SetHitTestIsForVisibility(float aVisibleThreshold)1607   void SetHitTestIsForVisibility(float aVisibleThreshold) {
1608     mVisibleThreshold = Some(aVisibleThreshold);
1609   }
1610 
ShouldBuildAsyncZoomContainer()1611   bool ShouldBuildAsyncZoomContainer() const {
1612     return mBuildAsyncZoomContainer;
1613   }
1614   void UpdateShouldBuildAsyncZoomContainer();
1615 
1616   void UpdateShouldBuildBackdropRootContainer();
1617 
1618   bool ShouldRebuildDisplayListDueToPrefChange();
1619 
1620   /**
1621    * Represents a region composed of frame/rect pairs.
1622    * WeakFrames are used to track whether a rect still belongs to the region.
1623    * Modified frames and rects are removed and re-added to the region if needed.
1624    */
1625   struct WeakFrameRegion {
1626     /**
1627      * A wrapper to store WeakFrame and the pointer to the underlying frame.
1628      * This is needed because WeakFrame does not store the frame pointer after
1629      * the frame has been deleted.
1630      */
1631     struct WeakFrameWrapper {
WeakFrameWrapperWeakFrameRegion::WeakFrameWrapper1632       explicit WeakFrameWrapper(nsIFrame* aFrame)
1633           : mWeakFrame(new WeakFrame(aFrame)), mFrame(aFrame) {}
1634 
1635       UniquePtr<WeakFrame> mWeakFrame;
1636       void* mFrame;
1637     };
1638 
1639     nsTHashSet<void*> mFrameSet;
1640     nsTArray<WeakFrameWrapper> mFrames;
1641     nsTArray<pixman_box32_t> mRects;
1642 
1643     template <typename RectType>
AddWeakFrameRegion1644     void Add(nsIFrame* aFrame, const RectType& aRect) {
1645       if (mFrameSet.Contains(aFrame)) {
1646         return;
1647       }
1648 
1649       mFrameSet.Insert(aFrame);
1650       mFrames.AppendElement(WeakFrameWrapper(aFrame));
1651       mRects.AppendElement(nsRegion::RectToBox(aRect));
1652     }
1653 
ClearWeakFrameRegion1654     void Clear() {
1655       mFrameSet.Clear();
1656       mFrames.Clear();
1657       mRects.Clear();
1658     }
1659 
1660     void RemoveModifiedFramesAndRects();
1661 
1662     size_t SizeOfExcludingThis(MallocSizeOf) const;
1663 
1664     typedef gfx::ArrayView<pixman_box32_t> BoxArrayView;
1665 
ToRegionWeakFrameRegion1666     nsRegion ToRegion() const { return nsRegion(BoxArrayView(mRects)); }
1667 
ToLayoutDeviceIntRegionWeakFrameRegion1668     LayoutDeviceIntRegion ToLayoutDeviceIntRegion() const {
1669       return LayoutDeviceIntRegion(BoxArrayView(mRects));
1670     }
1671   };
1672 
1673   void AddScrollFrameToNotify(nsIScrollableFrame* aScrollFrame);
1674   void NotifyAndClearScrollFrames();
1675 
1676   // Helper class to find what link spec (if any) to associate with a frame,
1677   // recording it in the builder, and generate the corresponding DisplayItem.
1678   // This also takes care of generating a named destination for internal links
1679   // if the element has an id or name attribute.
1680   class Linkifier {
1681    public:
1682     Linkifier(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1683               nsDisplayList* aList);
1684 
~Linkifier()1685     ~Linkifier() {
1686       if (mBuilderToReset) {
1687         mBuilderToReset->mLinkSpec.Truncate(0);
1688       }
1689     }
1690 
1691     void MaybeAppendLink(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
1692 
1693    private:
1694     nsDisplayListBuilder* mBuilderToReset = nullptr;
1695     nsDisplayList* mList;
1696   };
1697 
1698   /**
1699    * Returns the nearest ancestor frame to aFrame that is considered to have
1700    * (or will have) animated geometry. This can return aFrame.
1701    */
1702   nsIFrame* FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame);
1703 
1704   /**
1705    * Returns true if this is a retained builder and reuse stacking contexts
1706    * mode is enabled by pref.
1707    */
IsReusingStackingContextItems()1708   bool IsReusingStackingContextItems() const {
1709     return mIsReusingStackingContextItems;
1710   }
1711 
1712   /**
1713    * Adds display item |aItem| to the reuseable display items set.
1714    */
1715   void AddReusableDisplayItem(nsDisplayItem* aItem);
1716 
1717   /**
1718    * Removes display item |aItem| from the reuseable display items set.
1719    * This is needed because display items are sometimes deleted during
1720    * display list building.
1721    * Called by |nsDisplayItem::Destroy()| when the item has been reused.
1722    */
1723   void RemoveReusedDisplayItem(nsDisplayItem* aItem);
1724 
1725   /**
1726    * Clears the reuseable display items set.
1727    */
1728   void ClearReuseableDisplayItems();
1729 
1730   /**
1731    * Marks the given display item |aItem| as reused, and updates the necessary
1732    * display list builder state.
1733    */
1734   void ReuseDisplayItem(nsDisplayItem* aItem);
1735 
1736  private:
1737   bool MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
1738                                     const nsRect& aVisibleRect,
1739                                     const nsRect& aDirtyRect);
1740 
1741   friend class nsDisplayBackgroundImage;
1742   friend struct RetainedDisplayListBuilder;
1743 
1744   /**
1745    * Returns whether a frame acts as an animated geometry root, optionally
1746    * returning the next ancestor to check.
1747    */
1748   bool IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParent = nullptr);
1749 
1750   struct PresShellState {
1751     PresShell* mPresShell;
1752 #ifdef DEBUG
1753     Maybe<nsAutoLayoutPhase> mAutoLayoutPhase;
1754 #endif
1755     Maybe<OutOfFlowDisplayData> mFixedBackgroundDisplayData;
1756     uint32_t mFirstFrameMarkedForDisplay;
1757     uint32_t mFirstFrameWithOOFData;
1758     bool mIsBackgroundOnly;
1759     // This is a per-document flag turning off event handling for all content
1760     // in the document, and is set when we enter a subdocument for a pointer-
1761     // events:none frame.
1762     bool mInsidePointerEventsNoneDoc;
1763     bool mTouchEventPrefEnabledDoc;
1764     nsIFrame* mPresShellIgnoreScrollFrame;
1765   };
1766 
CurrentPresShellState()1767   PresShellState* CurrentPresShellState() {
1768     NS_ASSERTION(mPresShellStates.Length() > 0,
1769                  "Someone forgot to enter a presshell");
1770     return &mPresShellStates[mPresShellStates.Length() - 1];
1771   }
1772 
1773   void AddSizeOfExcludingThis(nsWindowSizes&) const;
1774 
1775   struct FrameWillChangeBudget {
FrameWillChangeBudgetFrameWillChangeBudget1776     FrameWillChangeBudget() : mPresContext(nullptr), mUsage(0) {}
1777 
FrameWillChangeBudgetFrameWillChangeBudget1778     FrameWillChangeBudget(const nsPresContext* aPresContext, uint32_t aUsage)
1779         : mPresContext(aPresContext), mUsage(aUsage) {}
1780 
1781     const nsPresContext* mPresContext;
1782     uint32_t mUsage;
1783   };
1784 
1785   nsIFrame* const mReferenceFrame;
1786   nsIFrame* mIgnoreScrollFrame;
1787 
1788   using Arena = nsPresArena<32768, DisplayListArenaObjectId,
1789                             size_t(DisplayListArenaObjectId::COUNT)>;
1790   Arena mPool;
1791 
1792   AutoTArray<PresShellState, 8> mPresShellStates;
1793   AutoTArray<nsIFrame*, 400> mFramesMarkedForDisplay;
1794   AutoTArray<nsIFrame*, 40> mFramesMarkedForDisplayIfVisible;
1795   AutoTArray<nsIFrame*, 20> mFramesWithOOFData;
1796   nsClassHashtable<nsPtrHashKey<nsDisplayItem>,
1797                    nsTArray<nsIWidget::ThemeGeometry>>
1798       mThemeGeometries;
1799   DisplayListClipState mClipState;
1800   const ActiveScrolledRoot* mCurrentActiveScrolledRoot;
1801   const ActiveScrolledRoot* mCurrentContainerASR;
1802   // mCurrentFrame is the frame that we're currently calling (or about to call)
1803   // BuildDisplayList on.
1804   const nsIFrame* mCurrentFrame;
1805   // The reference frame for mCurrentFrame.
1806   const nsIFrame* mCurrentReferenceFrame;
1807   // The offset from mCurrentFrame to mCurrentReferenceFrame.
1808   nsPoint mCurrentOffsetToReferenceFrame;
1809 
1810   Maybe<nsPoint> mAdditionalOffset;
1811 
1812   // will-change budget tracker
1813   typedef uint32_t DocumentWillChangeBudget;
1814   nsTHashMap<nsPtrHashKey<const nsPresContext>, DocumentWillChangeBudget>
1815       mDocumentWillChangeBudgets;
1816 
1817   // Any frame listed in this set is already counted in the budget
1818   // and thus is in-budget.
1819   nsTHashMap<nsPtrHashKey<const nsIFrame>, FrameWillChangeBudget>
1820       mFrameWillChangeBudgets;
1821 
1822   uint8_t mBuildingExtraPagesForPageNum;
1823 
1824   nsTHashMap<nsPtrHashKey<dom::RemoteBrowser>, dom::EffectsInfo>
1825       mEffectsUpdates;
1826 
1827   // Relative to mCurrentFrame.
1828   nsRect mVisibleRect;
1829   nsRect mDirtyRect;
1830 
1831   // Tracked regions used for retained display list.
1832   WeakFrameRegion mWindowExcludeGlassRegion;
1833   WeakFrameRegion mRetainedWindowDraggingRegion;
1834   WeakFrameRegion mRetainedWindowNoDraggingRegion;
1835 
1836   // Window opaque region is calculated during layer building.
1837   WeakFrameRegion mRetainedWindowOpaqueRegion;
1838 
1839   // Optimized versions for non-retained display list.
1840   LayoutDeviceIntRegion mWindowDraggingRegion;
1841   LayoutDeviceIntRegion mWindowNoDraggingRegion;
1842   nsRegion mWindowOpaqueRegion;
1843 
1844   // The display item for the Windows window glass background, if any
1845   // Set during full display list builds or during display list merging only,
1846   // partial display list builds don't touch this.
1847   nsDisplayItem* mGlassDisplayItem;
1848   // If we've encountered a glass item yet, only used during partial display
1849   // list builds.
1850   bool mHasGlassItemDuringPartial;
1851 
1852   nsIFrame* mCaretFrame;
1853   nsRect mCaretRect;
1854 
1855   // A temporary list that we append scroll info items to while building
1856   // display items for the contents of frames with SVG effects.
1857   // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
1858   // This is a pointer and not a real nsDisplayList value because the
1859   // nsDisplayList class is defined below this class, so we can't use it here.
1860   nsDisplayList* mScrollInfoItemsForHoisting;
1861   nsTArray<RefPtr<ActiveScrolledRoot>> mActiveScrolledRoots;
1862   std::unordered_set<const DisplayItemClipChain*, DisplayItemClipChainHasher,
1863                      DisplayItemClipChainEqualer>
1864       mClipDeduplicator;
1865   DisplayItemClipChain* mFirstClipChainToDestroy;
1866   nsTArray<nsDisplayItem*> mTemporaryItems;
1867   nsDisplayListBuilderMode mMode;
1868   nsDisplayTableBackgroundSet* mTableBackgroundSet;
1869   ViewID mCurrentScrollParentId;
1870   ViewID mCurrentScrollbarTarget;
1871   Maybe<layers::ScrollDirection> mCurrentScrollbarDirection;
1872   Preserves3DContext mPreserves3DCtx;
1873   nsTArray<nsIFrame*> mSVGEffectsFrames;
1874   // When we are inside a filter, the current ASR at the time we entered the
1875   // filter. Otherwise nullptr.
1876   const ActiveScrolledRoot* mFilterASR;
1877   std::unordered_set<nsIScrollableFrame*> mScrollFramesToNotify;
1878   nsCString mLinkSpec;  // Destination of link currently being emitted, if any.
1879   nsTHashSet<nsCString> mDestinations;  // Destination names emitted.
1880   bool mContainsBlendMode;
1881   bool mIsBuildingScrollbar;
1882   bool mCurrentScrollbarWillHaveLayer;
1883   bool mBuildCaret;
1884   bool mRetainingDisplayList;
1885   bool mPartialUpdate;
1886   bool mIgnoreSuppression;
1887   bool mIncludeAllOutOfFlows;
1888   bool mDescendIntoSubdocuments;
1889   bool mSelectedFramesOnly;
1890   bool mAllowMergingAndFlattening;
1891   // True when we're building a display list that's directly or indirectly
1892   // under an nsDisplayTransform
1893   bool mInTransform;
1894   bool mInEventsOnly;
1895   bool mInFilter;
1896   bool mInPageSequence;
1897   bool mIsInChromePresContext;
1898   bool mSyncDecodeImages;
1899   bool mIsPaintingToWindow;
1900   bool mUseHighQualityScaling;
1901   bool mIsPaintingForWebRender;
1902   bool mIsCompositingCheap;
1903   bool mAncestorHasApzAwareEventHandler;
1904   // True when the first async-scrollable scroll frame for which we build a
1905   // display list has a display port. An async-scrollable scroll frame is one
1906   // which WantsAsyncScroll().
1907   bool mHaveScrollableDisplayPort;
1908   bool mWindowDraggingAllowed;
1909   bool mIsBuildingForPopup;
1910   bool mForceLayerForScrollParent;
1911   bool mContainsNonMinimalDisplayPort;
1912   bool mAsyncPanZoomEnabled;
1913   bool mBuildingInvisibleItems;
1914   bool mIsBuilding;
1915   bool mInInvalidSubtree;
1916   bool mBuildCompositorHitTestInfo;
1917   bool mDisablePartialUpdates;
1918   bool mPartialBuildFailed;
1919   bool mIsInActiveDocShell;
1920   bool mBuildAsyncZoomContainer;
1921   bool mContainsBackdropFilter;
1922   bool mIsRelativeToLayoutViewport;
1923   bool mUseOverlayScrollbars;
1924   bool mAlwaysLayerizeScrollbars;
1925 
1926   Maybe<float> mVisibleThreshold;
1927   gfx::CompositorHitTestInfo mCompositorHitTestInfo;
1928 
1929   bool mIsForContent;
1930   bool mIsReusingStackingContextItems;
1931 
1932   // Stores reusable items collected during display list preprocessing.
1933   nsTHashSet<nsDisplayItem*> mReuseableItems;
1934 };
1935 
1936 // All types are defined in nsDisplayItemTypes.h
1937 #define NS_DISPLAY_DECL_NAME(n, e)                                           \
1938   const char* Name() const override { return n; }                            \
1939   constexpr static DisplayItemType ItemType() { return DisplayItemType::e; } \
1940                                                                              \
1941  private:                                                                    \
1942   void* operator new(size_t aSize, nsDisplayListBuilder* aBuilder) {         \
1943     return aBuilder->Allocate(aSize, DisplayItemType::e);                    \
1944   }                                                                          \
1945                                                                              \
1946   template <typename T, typename F, typename... Args>                        \
1947   friend T* mozilla::MakeDisplayItemWithIndex(                               \
1948       nsDisplayListBuilder* aBuilder, F* aFrame, const uint16_t aIndex,      \
1949       Args&&... aArgs);                                                      \
1950                                                                              \
1951  public:
1952 
1953 #define NS_DISPLAY_ALLOW_CLONING()                                          \
1954   template <typename T>                                                     \
1955   friend T* mozilla::MakeClone(nsDisplayListBuilder* aBuilder,              \
1956                                const T* aItem);                             \
1957                                                                             \
1958   nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override { \
1959     return MakeClone(aBuilder, this);                                       \
1960   }
1961 
1962 template <typename T>
MakeClone(nsDisplayListBuilder * aBuilder,const T * aItem)1963 MOZ_ALWAYS_INLINE T* MakeClone(nsDisplayListBuilder* aBuilder, const T* aItem) {
1964   static_assert(std::is_base_of<nsDisplayWrapList, T>::value,
1965                 "Display item type should be derived from nsDisplayWrapList");
1966   T* item = new (aBuilder) T(aBuilder, *aItem);
1967   item->SetType(T::ItemType());
1968   return item;
1969 }
1970 
1971 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1972 void AssertUniqueItem(nsDisplayItem* aItem);
1973 #endif
1974 
1975 /**
1976  * Returns true, if a display item of given |aType| needs to be built within
1977  * opacity:0 container.
1978  */
1979 bool ShouldBuildItemForEvents(const DisplayItemType aType);
1980 
1981 /**
1982  * Initializes the hit test information of |aItem| if the item type supports it.
1983  */
1984 void InitializeHitTestInfo(nsDisplayListBuilder* aBuilder,
1985                            nsPaintedDisplayItem* aItem,
1986                            const DisplayItemType aType);
1987 
1988 template <typename T, typename F, typename... Args>
MakeDisplayItemWithIndex(nsDisplayListBuilder * aBuilder,F * aFrame,const uint16_t aIndex,Args &&...aArgs)1989 MOZ_ALWAYS_INLINE T* MakeDisplayItemWithIndex(nsDisplayListBuilder* aBuilder,
1990                                               F* aFrame, const uint16_t aIndex,
1991                                               Args&&... aArgs) {
1992   static_assert(std::is_base_of<nsDisplayItem, T>::value,
1993                 "Display item type should be derived from nsDisplayItem");
1994   static_assert(std::is_base_of<nsIFrame, F>::value,
1995                 "Frame type should be derived from nsIFrame");
1996 
1997   const DisplayItemType type = T::ItemType();
1998   if (aBuilder->InEventsOnly() && !ShouldBuildItemForEvents(type)) {
1999     // This item is not needed for events.
2000     return nullptr;
2001   }
2002 
2003   T* item = new (aBuilder) T(aBuilder, aFrame, std::forward<Args>(aArgs)...);
2004 
2005   if (type != DisplayItemType::TYPE_GENERIC) {
2006     item->SetType(type);
2007   }
2008 
2009   item->SetPerFrameIndex(aIndex);
2010   item->SetExtraPageForPageNum(aBuilder->GetBuildingExtraPagesForPageNum());
2011 
2012   nsPaintedDisplayItem* paintedItem = item->AsPaintedDisplayItem();
2013   if (paintedItem) {
2014     InitializeHitTestInfo(aBuilder, paintedItem, type);
2015   }
2016 
2017   if (aBuilder->InInvalidSubtree() ||
2018       item->FrameForInvalidation()->IsFrameModified()) {
2019     item->SetModifiedFrame(true);
2020   }
2021 
2022 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2023   if (aBuilder->IsRetainingDisplayList() && aBuilder->IsBuilding()) {
2024     AssertUniqueItem(item);
2025   }
2026 
2027   // Verify that InInvalidSubtree matches invalidation frame's modified state.
2028   if (aBuilder->InInvalidSubtree()) {
2029     MOZ_DIAGNOSTIC_ASSERT(
2030         AnyContentAncestorModified(item->FrameForInvalidation()));
2031   }
2032 
2033   DebugOnly<bool> isContainerType =
2034       (GetDisplayItemFlagsForType(type) & TYPE_IS_CONTAINER);
2035 
2036   MOZ_ASSERT(item->HasChildren() == isContainerType,
2037              "Container items must have container display item flag set.");
2038 #endif
2039 
2040   if (aBuilder->IsForPainting() && aBuilder->IsForContent()) {
2041     DL_LOGV("Created display item %p (%s) (frame: %p)", item, item->Name(),
2042             aFrame);
2043   }
2044 
2045   return item;
2046 }
2047 
2048 template <typename T, typename F, typename... Args>
MakeDisplayItem(nsDisplayListBuilder * aBuilder,F * aFrame,Args &&...aArgs)2049 MOZ_ALWAYS_INLINE T* MakeDisplayItem(nsDisplayListBuilder* aBuilder, F* aFrame,
2050                                      Args&&... aArgs) {
2051   return MakeDisplayItemWithIndex<T>(aBuilder, aFrame, 0,
2052                                      std::forward<Args>(aArgs)...);
2053 }
2054 
2055 /*
2056  * nsDisplayItemBase is a base-class for all display items. It is mainly
2057  * responsible for handling the frame-display item 1:n relationship, as well as
2058  * storing the state needed for display list merging.
2059  *
2060  * Display items are arena-allocated during display list construction.
2061  *
2062  * Display items can be containers --- i.e., they can perform hit testing
2063  * and painting by recursively traversing a list of child items.
2064  *
2065  * Display items belong to a list at all times (except temporarily as they
2066  * move from one list to another).
2067  */
2068 class nsDisplayItem {
2069  public:
2070   using Layer = layers::Layer;
2071   using LayerManager = layers::LayerManager;
2072   using WebRenderLayerManager = layers::WebRenderLayerManager;
2073   using StackingContextHelper = layers::StackingContextHelper;
2074   using ViewID = layers::ScrollableLayerGuid::ViewID;
2075 
2076   /**
2077    * Downcasts this item to nsPaintedDisplayItem, if possible.
2078    */
AsPaintedDisplayItem()2079   virtual nsPaintedDisplayItem* AsPaintedDisplayItem() { return nullptr; }
AsPaintedDisplayItem()2080   virtual const nsPaintedDisplayItem* AsPaintedDisplayItem() const {
2081     return nullptr;
2082   }
2083 
2084   /**
2085    * Downcasts this item to nsDisplayWrapList, if possible.
2086    */
AsDisplayWrapList()2087   virtual nsDisplayWrapList* AsDisplayWrapList() { return nullptr; }
AsDisplayWrapList()2088   virtual const nsDisplayWrapList* AsDisplayWrapList() const { return nullptr; }
2089 
2090   /**
2091    * Create a clone of this item.
2092    */
Clone(nsDisplayListBuilder * aBuilder)2093   virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const {
2094     return nullptr;
2095   }
2096 
2097   /**
2098    * Checks if the given display item can be merged with this item.
2099    * @return true if the merging is possible, otherwise false.
2100    */
CanMerge(const nsDisplayItem * aItem)2101   virtual bool CanMerge(const nsDisplayItem* aItem) const { return false; }
2102 
2103   /**
2104    * Frees the memory allocated for this display item.
2105    * The given display list builder must have allocated this display item.
2106    */
Destroy(nsDisplayListBuilder * aBuilder)2107   virtual void Destroy(nsDisplayListBuilder* aBuilder) {
2108     const DisplayItemType type = GetType();
2109     if (aBuilder->IsForPainting() && aBuilder->IsForContent()) {
2110       DL_LOGV("Destroying display item %p (%s)", this, Name());
2111     }
2112 
2113     if (IsReusedItem()) {
2114       aBuilder->RemoveReusedDisplayItem(this);
2115     }
2116 
2117     this->~nsDisplayItem();
2118     aBuilder->Destroy(type, this);
2119   }
2120 
2121   /**
2122    * Returns the frame that this display item was created for.
2123    * Never returns null.
2124    */
Frame()2125   inline nsIFrame* Frame() const {
2126     MOZ_ASSERT(mFrame, "Trying to use display item after deletion!");
2127     return mFrame;
2128   }
2129 
2130   /**
2131    * Called when the display item is prepared for deletion. The display item
2132    * should not be used after calling this function.
2133    */
RemoveFrame(nsIFrame * aFrame)2134   virtual void RemoveFrame(nsIFrame* aFrame) {
2135     MOZ_ASSERT(aFrame);
2136 
2137     if (mFrame && aFrame == mFrame) {
2138       mFrame = nullptr;
2139       SetDeletedFrame();
2140     }
2141   }
2142 
2143   /**
2144    * A display item can depend on multiple different frames for invalidation.
2145    */
GetDependentFrame()2146   virtual nsIFrame* GetDependentFrame() { return nullptr; }
2147 
2148   /**
2149    * Returns the frame that provides the style data, and should
2150    * be checked when deciding if this display item can be reused.
2151    */
FrameForInvalidation()2152   virtual nsIFrame* FrameForInvalidation() const { return Frame(); }
2153 
2154   /**
2155    * Display items can override this to communicate that they won't
2156    * contribute any visual information (for example fully transparent).
2157    */
IsInvisible()2158   virtual bool IsInvisible() const { return false; }
2159 
2160   /**
2161    * Returns the printable name of this display item.
2162    */
2163   virtual const char* Name() const = 0;
2164 
2165   /**
2166    * Some consecutive items should be rendered together as a unit, e.g.,
2167    * outlines for the same element. For this, we need a way for items to
2168    * identify their type. We use the type for other purposes too.
2169    */
GetType()2170   DisplayItemType GetType() const {
2171     MOZ_ASSERT(mType != DisplayItemType::TYPE_ZERO,
2172                "Display item should have a valid type!");
2173     return mType;
2174   }
2175 
2176   /**
2177    * Pairing this with the Frame() pointer gives a key that
2178    * uniquely identifies this display item in the display item tree.
2179    */
GetPerFrameKey()2180   uint32_t GetPerFrameKey() const {
2181     // The top 8 bits are the page index
2182     // The middle 16 bits of the per frame key uniquely identify the display
2183     // item when there are more than one item of the same type for a frame.
2184     // The low 8 bits are the display item type.
2185     return (static_cast<uint32_t>(mExtraPageForPageNum)
2186             << (TYPE_BITS + (sizeof(mPerFrameIndex) * 8))) |
2187            (static_cast<uint32_t>(mPerFrameIndex) << TYPE_BITS) |
2188            static_cast<uint32_t>(mType);
2189   }
2190 
2191   /**
2192    * Returns true if this item was reused during display list merging.
2193    */
IsReused()2194   bool IsReused() const { return mItemFlags.contains(ItemFlag::ReusedItem); }
2195 
SetReused(bool aReused)2196   void SetReused(bool aReused) { SetItemFlag(ItemFlag::ReusedItem, aReused); }
2197 
2198   /**
2199    * Returns true if this item can be reused during display list merging.
2200    */
CanBeReused()2201   bool CanBeReused() const {
2202     return !mItemFlags.contains(ItemFlag::CantBeReused);
2203   }
2204 
SetCantBeReused()2205   void SetCantBeReused() { mItemFlags += ItemFlag::CantBeReused; }
2206 
CanBeCached()2207   bool CanBeCached() const {
2208     return !mItemFlags.contains(ItemFlag::CantBeCached);
2209   }
2210 
SetCantBeCached()2211   void SetCantBeCached() { mItemFlags += ItemFlag::CantBeCached; }
2212 
IsOldItem()2213   bool IsOldItem() const { return !!mOldList; }
2214 
2215   /**
2216    * Returns true if the frame of this display item is in a modified subtree.
2217    */
HasModifiedFrame()2218   bool HasModifiedFrame() const {
2219     return mItemFlags.contains(ItemFlag::ModifiedFrame);
2220   }
2221 
SetModifiedFrame(bool aModified)2222   void SetModifiedFrame(bool aModified) {
2223     SetItemFlag(ItemFlag::ModifiedFrame, aModified);
2224   }
2225 
2226   bool HasDeletedFrame() const;
2227 
2228   /**
2229    * Set the nsDisplayList that this item belongs to, and what index it is
2230    * within that list.
2231    * Temporary state for merging used by RetainedDisplayListBuilder.
2232    */
SetOldListIndex(nsDisplayList * aList,OldListIndex aIndex,uint32_t aListKey,uint32_t aNestingDepth)2233   void SetOldListIndex(nsDisplayList* aList, OldListIndex aIndex,
2234                        uint32_t aListKey, uint32_t aNestingDepth) {
2235 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2236     mOldListKey = aListKey;
2237     mOldNestingDepth = aNestingDepth;
2238 #endif
2239     mOldList = reinterpret_cast<uintptr_t>(aList);
2240     mOldListIndex = aIndex;
2241   }
2242 
GetOldListIndex(nsDisplayList * aList,uint32_t aListKey,OldListIndex * aOutIndex)2243   bool GetOldListIndex(nsDisplayList* aList, uint32_t aListKey,
2244                        OldListIndex* aOutIndex) {
2245     if (mOldList != reinterpret_cast<uintptr_t>(aList)) {
2246 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2247       MOZ_CRASH_UNSAFE_PRINTF(
2248           "Item found was in the wrong list! type %d "
2249           "(outer type was %d at depth %d, now is %d)",
2250           GetPerFrameKey(), mOldListKey, mOldNestingDepth, aListKey);
2251 #endif
2252       return false;
2253     }
2254     *aOutIndex = mOldListIndex;
2255     return true;
2256   }
2257 
2258   /**
2259    * Returns the display list containing the children of this display item.
2260    * The children may be in a different coordinate system than this item.
2261    */
GetChildren()2262   virtual RetainedDisplayList* GetChildren() const { return nullptr; }
HasChildren()2263   bool HasChildren() const { return GetChildren(); }
2264 
2265   /**
2266    * Display items with children may return true here. This causes the
2267    * display list iterator to descend into the child display list.
2268    */
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)2269   virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
2270     return false;
2271   }
2272 
CreatesStackingContextHelper()2273   virtual bool CreatesStackingContextHelper() { return false; }
2274 
2275   /**
2276    * Returns true if this item can be moved asynchronously on the compositor,
2277    * see RetainedDisplayListBuilder.cpp comments.
2278    */
CanMoveAsync()2279   virtual bool CanMoveAsync() { return false; }
2280 
2281  protected:
2282   // This is never instantiated directly (it has pure virtual methods), so no
2283   // need to count constructors and destructors.
2284   nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
2285   nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2286                 const ActiveScrolledRoot* aActiveScrolledRoot);
2287 
2288   /**
2289    * The custom copy-constructor is implemented to prevent copying the saved
2290    * state of the item.
2291    * This is currently only used when creating temporary items for merging.
2292    */
nsDisplayItem(nsDisplayListBuilder * aBuilder,const nsDisplayItem & aOther)2293   nsDisplayItem(nsDisplayListBuilder* aBuilder, const nsDisplayItem& aOther)
2294       : mFrame(aOther.mFrame),
2295         mItemFlags(aOther.mItemFlags),
2296         mType(aOther.mType),
2297         mExtraPageForPageNum(aOther.mExtraPageForPageNum),
2298         mPerFrameIndex(aOther.mPerFrameIndex),
2299         mBuildingRect(aOther.mBuildingRect),
2300         mToReferenceFrame(aOther.mToReferenceFrame),
2301         mActiveScrolledRoot(aOther.mActiveScrolledRoot),
2302         mClipChain(aOther.mClipChain) {
2303     MOZ_COUNT_CTOR(nsDisplayItem);
2304     // TODO: It might be better to remove the flags that aren't copied.
2305     if (aOther.ForceNotVisible()) {
2306       mItemFlags += ItemFlag::ForceNotVisible;
2307     }
2308     if (mFrame->In3DContextAndBackfaceIsHidden()) {
2309       mItemFlags += ItemFlag::BackfaceHidden;
2310     }
2311     if (aOther.Combines3DTransformWithAncestors()) {
2312       mItemFlags += ItemFlag::Combines3DTransformWithAncestors;
2313     }
2314   }
2315 
~nsDisplayItem()2316   virtual ~nsDisplayItem() {
2317     MOZ_COUNT_DTOR(nsDisplayItem);
2318     if (mFrame) {
2319       mFrame->RemoveDisplayItem(this);
2320     }
2321   }
2322 
SetType(const DisplayItemType aType)2323   void SetType(const DisplayItemType aType) { mType = aType; }
2324 
SetPerFrameIndex(const uint16_t aIndex)2325   void SetPerFrameIndex(const uint16_t aIndex) { mPerFrameIndex = aIndex; }
2326 
2327   // Display list building for printing can build duplicate
2328   // container display items when they contain a mixture of
2329   // OOF and normal content that is spread across multiple
2330   // pages. We include the page number for the duplicates
2331   // to make our GetPerFrameKey unique.
SetExtraPageForPageNum(const uint8_t aPageNum)2332   void SetExtraPageForPageNum(const uint8_t aPageNum) {
2333     mExtraPageForPageNum = aPageNum;
2334   }
2335 
2336   void SetDeletedFrame();
2337 
2338  public:
2339   nsDisplayItem() = delete;
2340   nsDisplayItem(const nsDisplayItem&) = delete;
2341 
2342   /**
2343    * Invalidate cached information that depends on this node's contents, after
2344    * a mutation of those contents.
2345    *
2346    * Specifically, if you mutate an |nsDisplayItem| in a way that would change
2347    * the WebRender display list items generated for it, you should call this
2348    * method.
2349    *
2350    * If a |RestoreState| method exists to restore some piece of state, that's a
2351    * good indication that modifications to said state should be accompanied by a
2352    * call to this method. Opacity flattening's effects on
2353    * |nsDisplayBackgroundColor| items are one example.
2354    */
InvalidateItemCacheEntry()2355   virtual void InvalidateItemCacheEntry() {}
2356 
2357   struct HitTestState {
2358     explicit HitTestState() = default;
2359 
~HitTestStateHitTestState2360     ~HitTestState() {
2361       NS_ASSERTION(mItemBuffer.Length() == 0,
2362                    "mItemBuffer should have been cleared");
2363     }
2364 
2365     // Handling transform items for preserve 3D frames.
2366     bool mInPreserves3D = false;
2367     // When hit-testing for visibility, we may hit an fully opaque item in a
2368     // nested display list. We want to stop at that point, without looking
2369     // further on other items.
2370     bool mHitOccludingItem = false;
2371 
2372     float mCurrentOpacity = 1.0f;
2373 
2374     AutoTArray<nsDisplayItem*, 100> mItemBuffer;
2375   };
2376 
GetFlags()2377   uint8_t GetFlags() const { return GetDisplayItemFlagsForType(GetType()); }
2378 
IsContentful()2379   virtual bool IsContentful() const { return GetFlags() & TYPE_IS_CONTENTFUL; }
2380 
2381   /**
2382    * This is called after we've constructed a display list for event handling.
2383    * When this is called, we've already ensured that aRect intersects the
2384    * item's bounds and that clipping has been taking into account.
2385    *
2386    * @param aRect the point or rect being tested, relative to the reference
2387    * frame. If the width and height are both 1 app unit, it indicates we're
2388    * hit testing a point, not a rect.
2389    * @param aState must point to a HitTestState. If you don't have one,
2390    * just create one with the default constructor and pass it in.
2391    * @param aOutFrames each item appends the frame(s) in this display item that
2392    * the rect is considered over (if any) to aOutFrames.
2393    */
HitTest(nsDisplayListBuilder * aBuilder,const nsRect & aRect,HitTestState * aState,nsTArray<nsIFrame * > * aOutFrames)2394   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2395                        HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) {}
2396 
StyleFrame()2397   virtual nsIFrame* StyleFrame() const { return mFrame; }
2398 
2399   /**
2400    * Compute the used z-index of our frame; returns zero for elements to which
2401    * z-index does not apply, and for z-index:auto.
2402    * @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex.
2403    */
2404   virtual int32_t ZIndex() const;
2405   /**
2406    * The default bounds is the frame border rect.
2407    * @param aSnap *aSnap is set to true if the returned rect will be
2408    * snapped to nearest device pixel edges during actual drawing.
2409    * It might be set to false and snap anyway, so code computing the set of
2410    * pixels affected by this display item needs to round outwards to pixel
2411    * boundaries when *aSnap is set to false.
2412    * This does not take the item's clipping into account.
2413    * @return a rectangle relative to aBuilder->ReferenceFrame() that
2414    * contains the area drawn by this display item
2415    */
GetBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)2416   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const {
2417     *aSnap = false;
2418     return nsRect(ToReferenceFrame(), Frame()->GetSize());
2419   }
2420 
2421   /**
2422    * Returns the untransformed bounds of this display item.
2423    */
GetUntransformedBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)2424   virtual nsRect GetUntransformedBounds(nsDisplayListBuilder* aBuilder,
2425                                         bool* aSnap) const {
2426     return GetBounds(aBuilder, aSnap);
2427   }
2428 
GetTightBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)2429   virtual nsRegion GetTightBounds(nsDisplayListBuilder* aBuilder,
2430                                   bool* aSnap) const {
2431     *aSnap = false;
2432     return nsRegion();
2433   }
2434 
2435   /**
2436    * Returns true if nothing will be rendered inside aRect, false if uncertain.
2437    * aRect is assumed to be contained in this item's bounds.
2438    */
IsInvisibleInRect(const nsRect & aRect)2439   virtual bool IsInvisibleInRect(const nsRect& aRect) const { return false; }
2440 
2441   /**
2442    * Returns the result of GetBounds intersected with the item's clip.
2443    * The intersection is approximate since rounded corners are not taking into
2444    * account.
2445    */
2446   nsRect GetClippedBounds(nsDisplayListBuilder* aBuilder) const;
2447 
GetBorderRect()2448   nsRect GetBorderRect() const {
2449     return nsRect(ToReferenceFrame(), Frame()->GetSize());
2450   }
2451 
GetPaddingRect()2452   nsRect GetPaddingRect() const {
2453     return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
2454   }
2455 
GetContentRect()2456   nsRect GetContentRect() const {
2457     return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
2458   }
2459 
2460   /**
2461    * Checks if the frame(s) owning this display item have been marked as
2462    * invalid, and needing repainting.
2463    */
IsInvalid(nsRect & aRect)2464   virtual bool IsInvalid(nsRect& aRect) const {
2465     bool result = mFrame ? mFrame->IsInvalid(aRect) : false;
2466     aRect += ToReferenceFrame();
2467     return result;
2468   }
2469 
2470   /**
2471    * Creates and initializes an nsDisplayItemGeometry object that retains the
2472    * current areas covered by this display item. These need to retain enough
2473    * information such that they can be compared against a future nsDisplayItem
2474    * of the same type, and determine if repainting needs to happen.
2475    *
2476    * Subclasses wishing to store more information need to override both this
2477    * and ComputeInvalidationRegion, as well as implementing an
2478    * nsDisplayItemGeometry subclass.
2479    *
2480    * The default implementation tracks both the display item bounds, and the
2481    * frame's border rect.
2482    */
AllocateGeometry(nsDisplayListBuilder * aBuilder)2483   virtual nsDisplayItemGeometry* AllocateGeometry(
2484       nsDisplayListBuilder* aBuilder) {
2485     return new nsDisplayItemGenericGeometry(this, aBuilder);
2486   }
2487 
2488   /**
2489    * Compares an nsDisplayItemGeometry object from a previous paint against the
2490    * current item. Computes if the geometry of the item has changed, and the
2491    * invalidation area required for correct repainting.
2492    *
2493    * The existing geometry will have been created from a display item with a
2494    * matching GetPerFrameKey()/mFrame pair to the current item.
2495    *
2496    * The default implementation compares the display item bounds, and the
2497    * frame's border rect, and invalidates the entire bounds if either rect
2498    * changes.
2499    *
2500    * @param aGeometry The geometry of the matching display item from the
2501    * previous paint.
2502    * @param aInvalidRegion Output param, the region to invalidate, or
2503    * unchanged if none.
2504    */
ComputeInvalidationRegion(nsDisplayListBuilder * aBuilder,const nsDisplayItemGeometry * aGeometry,nsRegion * aInvalidRegion)2505   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2506                                          const nsDisplayItemGeometry* aGeometry,
2507                                          nsRegion* aInvalidRegion) const {
2508     const nsDisplayItemGenericGeometry* geometry =
2509         static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
2510     bool snap;
2511     if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
2512         !geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
2513       aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
2514     }
2515   }
2516 
2517   /**
2518    * An alternative default implementation of ComputeInvalidationRegion,
2519    * that instead invalidates only the changed area between the two items.
2520    */
ComputeInvalidationRegionDifference(nsDisplayListBuilder * aBuilder,const nsDisplayItemBoundsGeometry * aGeometry,nsRegion * aInvalidRegion)2521   void ComputeInvalidationRegionDifference(
2522       nsDisplayListBuilder* aBuilder,
2523       const nsDisplayItemBoundsGeometry* aGeometry,
2524       nsRegion* aInvalidRegion) const {
2525     bool snap;
2526     nsRect bounds = GetBounds(aBuilder, &snap);
2527 
2528     if (!aGeometry->mBounds.IsEqualInterior(bounds)) {
2529       nscoord radii[8];
2530       if (aGeometry->mHasRoundedCorners || Frame()->GetBorderRadii(radii)) {
2531         aInvalidRegion->Or(aGeometry->mBounds, bounds);
2532       } else {
2533         aInvalidRegion->Xor(aGeometry->mBounds, bounds);
2534       }
2535     }
2536   }
2537 
2538   /**
2539    * This function is called when an item's list of children has been modified
2540    * by RetainedDisplayListBuilder.
2541    */
InvalidateCachedChildInfo(nsDisplayListBuilder * aBuilder)2542   virtual void InvalidateCachedChildInfo(nsDisplayListBuilder* aBuilder) {}
2543 
AddSizeOfExcludingThis(nsWindowSizes &)2544   virtual void AddSizeOfExcludingThis(nsWindowSizes&) const {}
2545 
2546   /**
2547    * @param aSnap set to true if the edges of the rectangles of the opaque
2548    * region would be snapped to device pixels when drawing
2549    * @return a region of the item that is opaque --- that is, every pixel
2550    * that is visible is painted with an opaque
2551    * color. This is useful for determining when one piece
2552    * of content completely obscures another so that we can do occlusion
2553    * culling.
2554    * This does not take clipping into account.
2555    * This must return a simple region (1 rect) for painting display lists.
2556    * It is only allowed to be a complex region for hit testing.
2557    */
GetOpaqueRegion(nsDisplayListBuilder * aBuilder,bool * aSnap)2558   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2559                                    bool* aSnap) const {
2560     *aSnap = false;
2561     return nsRegion();
2562   }
2563   /**
2564    * @return Some(nscolor) if the item is guaranteed to paint every pixel in its
2565    * bounds with the same (possibly translucent) color
2566    */
IsUniform(nsDisplayListBuilder * aBuilder)2567   virtual Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const {
2568     return Nothing();
2569   }
2570 
2571   /**
2572    * @return true if the contents of this item are rendered fixed relative
2573    * to the nearest viewport.
2574    */
ShouldFixToViewport(nsDisplayListBuilder * aBuilder)2575   virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const {
2576     return false;
2577   }
2578 
2579   /**
2580    * Returns true if all layers that can be active should be forced to be
2581    * active. Requires setting the pref layers.force-active=true.
2582    */
2583   static bool ForceActiveLayers();
2584 
2585 #ifdef MOZ_DUMP_PAINTING
2586   /**
2587    * Mark this display item as being painted via
2588    * FrameLayerBuilder::DrawPaintedLayer.
2589    */
Painted()2590   bool Painted() const { return mItemFlags.contains(ItemFlag::Painted); }
2591 
2592   /**
2593    * Check if this display item has been painted.
2594    */
SetPainted()2595   void SetPainted() { mItemFlags += ItemFlag::Painted; }
2596 #endif
2597 
SetIsGlassItem()2598   void SetIsGlassItem() { mItemFlags += ItemFlag::IsGlassItem; }
IsGlassItem()2599   bool IsGlassItem() { return mItemFlags.contains(ItemFlag::IsGlassItem); }
2600 
2601   /**
2602    * Function to create the WebRenderCommands.
2603    * We should check if the layer state is
2604    * active first and have an early return if the layer state is
2605    * not active.
2606    *
2607    * @return true if successfully creating webrender commands.
2608    */
CreateWebRenderCommands(wr::DisplayListBuilder & aBuilder,wr::IpcResourceUpdateQueue & aResources,const StackingContextHelper & aSc,layers::RenderRootStateManager * aManager,nsDisplayListBuilder * aDisplayListBuilder)2609   virtual bool CreateWebRenderCommands(
2610       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
2611       const StackingContextHelper& aSc,
2612       layers::RenderRootStateManager* aManager,
2613       nsDisplayListBuilder* aDisplayListBuilder) {
2614     return false;
2615   }
2616 
2617   /**
2618    * Updates the provided aLayerData with any APZ-relevant scroll data
2619    * that is specific to this display item. This is stuff that would normally
2620    * be put on the layer during BuildLayer, but this is only called in
2621    * layers-free webrender mode, where we don't have layers.
2622    *
2623    * This function returns true if and only if it has APZ-relevant scroll data
2624    * to provide. Note that the arguments passed in may be nullptr, in which case
2625    * the function should still return true if and only if it has APZ-relevant
2626    * scroll data, but obviously in this case it can't actually put the
2627    * data onto aLayerData, because there isn't one.
2628    *
2629    * This function assumes that aData and aLayerData will either both be null,
2630    * or will both be non-null. The caller is responsible for enforcing this.
2631    */
UpdateScrollData(layers::WebRenderScrollData * aData,layers::WebRenderLayerScrollData * aLayerData)2632   virtual bool UpdateScrollData(layers::WebRenderScrollData* aData,
2633                                 layers::WebRenderLayerScrollData* aLayerData) {
2634     return false;
2635   }
2636 
2637   /**
2638    * Returns true if this item needs to have its geometry updated, despite
2639    * returning empty invalidation region.
2640    */
NeedsGeometryUpdates()2641   virtual bool NeedsGeometryUpdates() const { return false; }
2642 
2643   /**
2644    * Some items such as those calling into the native themed widget machinery
2645    * have to be painted on the content process. In this case it is best to avoid
2646    * allocating layers that serializes and forwards the work to the compositor.
2647    */
MustPaintOnContentSide()2648   virtual bool MustPaintOnContentSide() const { return false; }
2649 
2650   /**
2651    * If this has a child list where the children are in the same coordinate
2652    * system as this item (i.e., they have the same reference frame),
2653    * return the list.
2654    */
GetSameCoordinateSystemChildren()2655   virtual RetainedDisplayList* GetSameCoordinateSystemChildren() const {
2656     return nullptr;
2657   }
2658 
UpdateBounds(nsDisplayListBuilder * aBuilder)2659   virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) {}
2660   /**
2661    * Do UpdateBounds() for items with frames establishing or extending
2662    * 3D rendering context.
2663    *
2664    * This function is called by UpdateBoundsFor3D() of
2665    * nsDisplayTransform(), and it is called by
2666    * BuildDisplayListForStackingContext() on transform items
2667    * establishing 3D rendering context.
2668    *
2669    * The bounds of a transform item with the frame establishing 3D
2670    * rendering context should be computed by calling
2671    * DoUpdateBoundsPreserves3D() on all descendants that participate
2672    * the same 3d rendering context.
2673    */
DoUpdateBoundsPreserves3D(nsDisplayListBuilder * aBuilder)2674   virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) {}
2675 
2676   /**
2677    * Returns the building rectangle used by nsDisplayListBuilder when
2678    * this item was constructed.
2679    */
GetBuildingRect()2680   const nsRect& GetBuildingRect() const { return mBuildingRect; }
2681 
SetBuildingRect(const nsRect & aBuildingRect)2682   void SetBuildingRect(const nsRect& aBuildingRect) {
2683     if (aBuildingRect == mBuildingRect) {
2684       // Avoid unnecessary paint rect recompution when the
2685       // building rect is staying the same.
2686       return;
2687     }
2688     mBuildingRect = aBuildingRect;
2689   }
2690 
2691   /**
2692    * Returns the building rect for the children, relative to their
2693    * reference frame. Can be different from mBuildingRect for
2694    * nsDisplayTransform, since the reference frame for the children is different
2695    * from the reference frame for the item itself.
2696    */
GetBuildingRectForChildren()2697   virtual const nsRect& GetBuildingRectForChildren() const {
2698     return mBuildingRect;
2699   }
2700 
WriteDebugInfo(std::stringstream & aStream)2701   virtual void WriteDebugInfo(std::stringstream& aStream) {}
2702 
2703   /**
2704    * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
2705    */
ToReferenceFrame()2706   const nsPoint& ToReferenceFrame() const {
2707     NS_ASSERTION(mFrame, "No frame?");
2708     return mToReferenceFrame;
2709   }
2710 
2711   /**
2712    * Returns the reference frame for display item children of this item.
2713    */
ReferenceFrameForChildren()2714   virtual const nsIFrame* ReferenceFrameForChildren() const { return nullptr; }
2715 
2716   /**
2717    * Checks if this display item (or any children) contains content that might
2718    * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
2719    * bounds of the area that needs component alpha, or an empty rect if nothing
2720    * in the item does.
2721    */
GetComponentAlphaBounds(nsDisplayListBuilder * aBuilder)2722   virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const {
2723     return nsRect();
2724   }
2725 
2726   /**
2727    * Check if we can add async animations to the layer for this display item.
2728    */
CanUseAsyncAnimations(nsDisplayListBuilder * aBuilder)2729   virtual bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
2730     return false;
2731   }
2732 
SupportsOptimizingToImage()2733   virtual bool SupportsOptimizingToImage() const { return false; }
2734 
2735   virtual const DisplayItemClip& GetClip() const;
2736   void IntersectClip(nsDisplayListBuilder* aBuilder,
2737                      const DisplayItemClipChain* aOther, bool aStore);
2738 
SetActiveScrolledRoot(const ActiveScrolledRoot * aActiveScrolledRoot)2739   virtual void SetActiveScrolledRoot(
2740       const ActiveScrolledRoot* aActiveScrolledRoot) {
2741     mActiveScrolledRoot = aActiveScrolledRoot;
2742   }
GetActiveScrolledRoot()2743   const ActiveScrolledRoot* GetActiveScrolledRoot() const {
2744     return mActiveScrolledRoot;
2745   }
2746 
2747   virtual void SetClipChain(const DisplayItemClipChain* aClipChain,
2748                             bool aStore);
GetClipChain()2749   const DisplayItemClipChain* GetClipChain() const { return mClipChain; }
2750 
BackfaceIsHidden()2751   bool BackfaceIsHidden() const {
2752     return mItemFlags.contains(ItemFlag::BackfaceHidden);
2753   }
2754 
Combines3DTransformWithAncestors()2755   bool Combines3DTransformWithAncestors() const {
2756     return mItemFlags.contains(ItemFlag::Combines3DTransformWithAncestors);
2757   }
2758 
ForceNotVisible()2759   bool ForceNotVisible() const {
2760     return mItemFlags.contains(ItemFlag::ForceNotVisible);
2761   }
2762 
In3DContextAndBackfaceIsHidden()2763   bool In3DContextAndBackfaceIsHidden() const {
2764     return mItemFlags.contains(ItemFlag::BackfaceHidden) &&
2765            mItemFlags.contains(ItemFlag::Combines3DTransformWithAncestors);
2766   }
2767 
HasDifferentFrame(const nsDisplayItem * aOther)2768   bool HasDifferentFrame(const nsDisplayItem* aOther) const {
2769     return mFrame != aOther->mFrame;
2770   }
2771 
HasHitTestInfo()2772   bool HasHitTestInfo() const {
2773     return mItemFlags.contains(ItemFlag::HasHitTestInfo);
2774   }
2775 
HasSameTypeAndClip(const nsDisplayItem * aOther)2776   bool HasSameTypeAndClip(const nsDisplayItem* aOther) const {
2777     return GetPerFrameKey() == aOther->GetPerFrameKey() &&
2778            GetClipChain() == aOther->GetClipChain();
2779   }
2780 
HasSameContent(const nsDisplayItem * aOther)2781   bool HasSameContent(const nsDisplayItem* aOther) const {
2782     return mFrame->GetContent() == aOther->Frame()->GetContent();
2783   }
2784 
NotifyUsed(nsDisplayListBuilder * aBuilder)2785   virtual void NotifyUsed(nsDisplayListBuilder* aBuilder) {}
2786 
2787   virtual Maybe<nsRect> GetClipWithRespectToASR(
2788       nsDisplayListBuilder* aBuilder, const ActiveScrolledRoot* aASR) const;
2789 
GetUntransformedPaintRect()2790   virtual const nsRect& GetUntransformedPaintRect() const {
2791     return GetBuildingRect();
2792   }
2793 
2794   nsRect GetPaintRect(nsDisplayListBuilder* aBuilder, gfxContext* aCtx);
2795 
GetHitTestInfo()2796   virtual const HitTestInfo& GetHitTestInfo() { return HitTestInfo::Empty(); }
2797 
2798   enum class ReuseState : uint8_t {
2799     None,
2800     // Set during display list building.
2801     Reusable,
2802     // Set during display list preprocessing.
2803     PreProcessed,
2804     // Set during partial display list build.
2805     Reused,
2806   };
2807 
SetReusable()2808   void SetReusable() {
2809     MOZ_ASSERT(mReuseState == ReuseState::None ||
2810                mReuseState == ReuseState::Reused);
2811     mReuseState = ReuseState::Reusable;
2812   }
2813 
IsReusable()2814   bool IsReusable() const { return mReuseState == ReuseState::Reusable; }
2815 
SetPreProcessed()2816   void SetPreProcessed() {
2817     MOZ_ASSERT(mReuseState == ReuseState::Reusable);
2818     mReuseState = ReuseState::PreProcessed;
2819   }
2820 
IsPreProcessed()2821   bool IsPreProcessed() const {
2822     return mReuseState == ReuseState::PreProcessed;
2823   }
2824 
SetReusedItem()2825   void SetReusedItem() {
2826     MOZ_ASSERT(mReuseState == ReuseState::PreProcessed);
2827     mReuseState = ReuseState::Reused;
2828   }
2829 
IsReusedItem()2830   bool IsReusedItem() const { return mReuseState == ReuseState::Reused; }
2831 
ResetReuseState()2832   void ResetReuseState() { mReuseState = ReuseState::None; }
2833 
GetReuseState()2834   ReuseState GetReuseState() const { return mReuseState; }
2835 
2836   nsIFrame* mFrame;  // 8
2837 
2838  private:
2839   enum class ItemFlag : uint16_t {
2840     CantBeReused,
2841     CantBeCached,
2842     DeletedFrame,
2843     ModifiedFrame,
2844     ReusedItem,
2845 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2846     MergedItem,
2847     PreProcessedItem,
2848 #endif
2849     BackfaceHidden,
2850     Combines3DTransformWithAncestors,
2851     ForceNotVisible,
2852     HasHitTestInfo,
2853     IsGlassItem,
2854 #ifdef MOZ_DUMP_PAINTING
2855     // True if this frame has been painted.
2856     Painted,
2857 #endif
2858   };
2859 
2860   EnumSet<ItemFlag, uint16_t> mItemFlags;              // 2
2861   DisplayItemType mType = DisplayItemType::TYPE_ZERO;  // 1
2862   uint8_t mExtraPageForPageNum = 0;                    // 1
2863   uint16_t mPerFrameIndex = 0;                         // 2
2864   ReuseState mReuseState = ReuseState::None;
2865   OldListIndex mOldListIndex;  // 4
2866   uintptr_t mOldList = 0;      // 8
2867 
2868   // This is the rectangle that nsDisplayListBuilder was using as the visible
2869   // rect to decide which items to construct.
2870   nsRect mBuildingRect;
2871 
2872  protected:
SetItemFlag(ItemFlag aFlag,const bool aValue)2873   void SetItemFlag(ItemFlag aFlag, const bool aValue) {
2874     if (aValue) {
2875       mItemFlags += aFlag;
2876     } else {
2877       mItemFlags -= aFlag;
2878     }
2879   }
2880 
SetHasHitTestInfo()2881   void SetHasHitTestInfo() { mItemFlags += ItemFlag::HasHitTestInfo; }
2882 
2883   // Result of ToReferenceFrame(mFrame), if mFrame is non-null
2884   nsPoint mToReferenceFrame;
2885 
2886   RefPtr<const ActiveScrolledRoot> mActiveScrolledRoot;
2887   RefPtr<const DisplayItemClipChain> mClipChain;
2888 
2889 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2890  public:
IsMergedItem()2891   bool IsMergedItem() const {
2892     return mItemFlags.contains(ItemFlag::MergedItem);
2893   }
2894 
IsPreProcessedItem()2895   bool IsPreProcessedItem() const {
2896     return mItemFlags.contains(ItemFlag::PreProcessedItem);
2897   }
2898 
SetMergedPreProcessed(bool aMerged,bool aPreProcessed)2899   void SetMergedPreProcessed(bool aMerged, bool aPreProcessed) {
2900     SetItemFlag(ItemFlag::MergedItem, aMerged);
2901     SetItemFlag(ItemFlag::PreProcessedItem, aPreProcessed);
2902   }
2903 
2904   uint32_t mOldListKey = 0;
2905   uint32_t mOldNestingDepth = 0;
2906 #endif
2907 };
2908 
2909 class nsPaintedDisplayItem : public nsDisplayItem {
2910  public:
AsPaintedDisplayItem()2911   nsPaintedDisplayItem* AsPaintedDisplayItem() final { return this; }
AsPaintedDisplayItem()2912   const nsPaintedDisplayItem* AsPaintedDisplayItem() const final {
2913     return this;
2914   }
2915 
2916   /**
2917    * Returns true if this display item would return true from ApplyOpacity
2918    * without actually applying the opacity. Otherwise returns false.
2919    */
CanApplyOpacity(WebRenderLayerManager * aManager,nsDisplayListBuilder * aBuilder)2920   virtual bool CanApplyOpacity(WebRenderLayerManager* aManager,
2921                                nsDisplayListBuilder* aBuilder) const {
2922     return false;
2923   }
2924 
2925   /**
2926    * Returns true if this item supports PaintWithClip, where the clipping
2927    * is used directly as the primitive geometry instead of needing an explicit
2928    * clip.
2929    */
CanPaintWithClip(const DisplayItemClip & aClip)2930   virtual bool CanPaintWithClip(const DisplayItemClip& aClip) { return false; }
2931 
2932   /**
2933    * Same as |Paint()|, except provides a clip to use the geometry to draw with.
2934    * Must not be called unless |CanPaintWithClip()| returned true.
2935    */
PaintWithClip(nsDisplayListBuilder * aBuilder,gfxContext * aCtx,const DisplayItemClip & aClip)2936   virtual void PaintWithClip(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
2937                              const DisplayItemClip& aClip) {
2938     MOZ_ASSERT_UNREACHABLE("PaintWithClip() is not implemented!");
2939   }
2940 
2941   /**
2942    * Paint this item to some rendering context.
2943    */
2944   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) = 0;
2945 
2946   /**
2947    * External storage used by |DisplayItemCache| to avoid hashmap lookups.
2948    * If an item is reused and has the cache index set, it means that
2949    * |DisplayItemCache| has assigned a cache slot for the item.
2950    */
CacheIndex()2951   Maybe<uint16_t>& CacheIndex() { return mCacheIndex; }
2952 
InvalidateItemCacheEntry()2953   void InvalidateItemCacheEntry() override {
2954     // |nsPaintedDisplayItem|s may have |DisplayItemCache| entries
2955     // that no longer match after a mutation. The cache will notice
2956     // on its own that the entry is no longer in use, and free it.
2957     mCacheIndex = Nothing();
2958   }
2959 
GetHitTestInfo()2960   const HitTestInfo& GetHitTestInfo() final { return mHitTestInfo; }
InitializeHitTestInfo(nsDisplayListBuilder * aBuilder)2961   void InitializeHitTestInfo(nsDisplayListBuilder* aBuilder) {
2962     mHitTestInfo.Initialize(aBuilder, Frame());
2963     SetHasHitTestInfo();
2964   }
2965 
2966  protected:
nsPaintedDisplayItem(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)2967   nsPaintedDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
2968       : nsPaintedDisplayItem(aBuilder, aFrame,
2969                              aBuilder->CurrentActiveScrolledRoot()) {}
2970 
nsPaintedDisplayItem(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,const ActiveScrolledRoot * aActiveScrolledRoot)2971   nsPaintedDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2972                        const ActiveScrolledRoot* aActiveScrolledRoot)
2973       : nsDisplayItem(aBuilder, aFrame, aActiveScrolledRoot) {}
2974 
nsPaintedDisplayItem(nsDisplayListBuilder * aBuilder,const nsPaintedDisplayItem & aOther)2975   nsPaintedDisplayItem(nsDisplayListBuilder* aBuilder,
2976                        const nsPaintedDisplayItem& aOther)
2977       : nsDisplayItem(aBuilder, aOther), mHitTestInfo(aOther.mHitTestInfo) {}
2978 
2979  protected:
2980   HitTestInfo mHitTestInfo;
2981   Maybe<uint16_t> mCacheIndex;
2982 };
2983 
2984 template <typename T>
2985 struct MOZ_HEAP_CLASS LinkedListNode {
LinkedListNodeLinkedListNode2986   explicit LinkedListNode(T aValue) : mNext(nullptr), mValue(aValue) {}
2987   LinkedListNode* mNext;
2988   T mValue;
2989 };
2990 
2991 template <typename T>
2992 struct LinkedListIterator {
2993   using iterator_category = std::forward_iterator_tag;
2994   using difference_type = std::ptrdiff_t;
2995   using value_type = T;
2996   using pointer = T*;
2997   using reference = T&;
2998   using Node = LinkedListNode<T>;
2999 
mNodeLinkedListIterator3000   explicit LinkedListIterator(Node* aNode = nullptr) : mNode(aNode) {}
3001 
3002   LinkedListIterator<T>& operator++() {
3003     MOZ_ASSERT(mNode);
3004     mNode = mNode->mNext;
3005     return *this;
3006   }
3007 
3008   bool operator==(const LinkedListIterator<T>& aOther) const {
3009     return mNode == aOther.mNode;
3010   }
3011 
3012   bool operator!=(const LinkedListIterator<T>& aOther) const {
3013     return mNode != aOther.mNode;
3014   }
3015 
3016   const T operator*() const {
3017     MOZ_ASSERT(mNode);
3018     return mNode->mValue;
3019   }
3020 
3021   T operator*() {
3022     MOZ_ASSERT(mNode);
3023     return mNode->mValue;
3024   }
3025 
3026   Node* mNode;
3027 };
3028 
3029 /**
3030  * Manages a singly-linked list of display list items.
3031  *
3032  * Stepping upward through this list is very fast. Stepping downward is very
3033  * slow so we don't support it. The methods that need to step downward
3034  * (HitTest()) internally build a temporary array of all
3035  * the items while they do the downward traversal, so overall they're still
3036  * linear time. We have optimized for efficient AppendToTop() of both
3037  * items and lists, with minimal codesize.
3038  *
3039  * Internal linked list nodes are allocated using arena allocator.
3040  * */
3041 class nsDisplayList {
3042  public:
3043   using Node = LinkedListNode<nsDisplayItem*>;
3044   using iterator = LinkedListIterator<nsDisplayItem*>;
3045   using const_iterator = iterator;
3046 
begin()3047   iterator begin() { return iterator(mBottom); }
end()3048   iterator end() { return iterator(nullptr); }
begin()3049   const_iterator begin() const { return iterator(mBottom); }
end()3050   const_iterator end() const { return iterator(nullptr); }
3051 
nsDisplayList(nsDisplayListBuilder * aBuilder)3052   explicit nsDisplayList(nsDisplayListBuilder* aBuilder) : mBuilder(aBuilder) {}
3053 
3054   nsDisplayList() = delete;
3055   nsDisplayList(const nsDisplayList&) = delete;
3056   nsDisplayList& operator=(const nsDisplayList&) = delete;
3057 
~nsDisplayList()3058   virtual ~nsDisplayList() {
3059 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3060     if (!mAllowNonEmptyDestruction) {
3061       MOZ_RELEASE_ASSERT(IsEmpty(), "Nonempty list left over?");
3062     }
3063 #endif
3064     Clear();
3065   }
3066 
nsDisplayList(nsDisplayList && aOther)3067   nsDisplayList(nsDisplayList&& aOther)
3068       : mBottom(aOther.mBottom),
3069         mTop(aOther.mTop),
3070         mLength(aOther.mLength),
3071         mBuilder(aOther.mBuilder) {
3072     aOther.SetEmpty();
3073   }
3074 
3075   nsDisplayList& operator=(nsDisplayList&& aOther) {
3076     MOZ_RELEASE_ASSERT(mBuilder == aOther.mBuilder);
3077 
3078     if (this != &aOther) {
3079       MOZ_RELEASE_ASSERT(IsEmpty());
3080       mBottom = std::move(aOther.mBottom);
3081       mTop = std::move(aOther.mTop);
3082       mLength = std::move(aOther.mLength);
3083       aOther.SetEmpty();
3084     }
3085     return *this;
3086   }
3087 
3088   /**
3089    * Append an item to the top of the list.
3090    **/
AppendToTop(nsDisplayItem * aItem)3091   void AppendToTop(nsDisplayItem* aItem) {
3092     if (!aItem) {
3093       return;
3094     }
3095 
3096     auto* next = Allocate(aItem);
3097     MOZ_ASSERT(next);
3098 
3099     if (IsEmpty()) {
3100       mBottom = next;
3101       mTop = next;
3102     } else {
3103       mTop->mNext = next;
3104       mTop = next;
3105     }
3106 
3107     mLength++;
3108 
3109     MOZ_ASSERT(mBottom && mTop);
3110     MOZ_ASSERT(mTop->mNext == nullptr);
3111   }
3112 
3113   template <typename T, typename F, typename... Args>
AppendNewToTop(nsDisplayListBuilder * aBuilder,F * aFrame,Args &&...aArgs)3114   void AppendNewToTop(nsDisplayListBuilder* aBuilder, F* aFrame,
3115                       Args&&... aArgs) {
3116     AppendNewToTopWithIndex<T>(aBuilder, aFrame, 0,
3117                                std::forward<Args>(aArgs)...);
3118   }
3119 
3120   template <typename T, typename F, typename... Args>
AppendNewToTopWithIndex(nsDisplayListBuilder * aBuilder,F * aFrame,const uint16_t aIndex,Args &&...aArgs)3121   void AppendNewToTopWithIndex(nsDisplayListBuilder* aBuilder, F* aFrame,
3122                                const uint16_t aIndex, Args&&... aArgs) {
3123     nsDisplayItem* item = MakeDisplayItemWithIndex<T>(
3124         aBuilder, aFrame, aIndex, std::forward<Args>(aArgs)...);
3125     AppendToTop(item);
3126   }
3127 
3128   /**
3129    * Removes all items from aList and appends them to the top of this list.
3130    */
AppendToTop(nsDisplayList * aList)3131   void AppendToTop(nsDisplayList* aList) {
3132     MOZ_ASSERT(aList != this);
3133     MOZ_RELEASE_ASSERT(mBuilder == aList->mBuilder);
3134 
3135     if (aList->IsEmpty()) {
3136       return;
3137     }
3138 
3139     if (IsEmpty()) {
3140       std::swap(mBottom, aList->mBottom);
3141       std::swap(mTop, aList->mTop);
3142       std::swap(mLength, aList->mLength);
3143     } else {
3144       MOZ_ASSERT(mTop && mTop->mNext == nullptr);
3145       mTop->mNext = aList->mBottom;
3146       mTop = aList->mTop;
3147       mLength += aList->mLength;
3148 
3149       aList->SetEmpty();
3150     }
3151   }
3152 
3153   /**
3154    * Clears the display list.
3155    */
Clear()3156   void Clear() {
3157     Node* current = mBottom;
3158     Node* next = nullptr;
3159 
3160     while (current) {
3161       next = current->mNext;
3162       Deallocate(current);
3163       current = next;
3164     }
3165 
3166     SetEmpty();
3167   }
3168 
3169   /**
3170    * Remove all items from the list and call their destructors.
3171    */
3172   virtual void DeleteAll(nsDisplayListBuilder* aBuilder);
3173 
3174   /**
3175    * @return the item at the bottom of the list, or null if the list is empty
3176    */
GetBottom()3177   nsDisplayItem* GetBottom() const {
3178     return mBottom ? mBottom->mValue : nullptr;
3179   }
3180 
3181   /**
3182    * @return the item at the top of the list, or null if the list is empty
3183    */
GetTop()3184   nsDisplayItem* GetTop() const { return mTop ? mTop->mValue : nullptr; }
3185 
IsEmpty()3186   bool IsEmpty() const { return mBottom == nullptr; }
3187 
3188   /**
3189    * @return the number of items in the list
3190    */
Length()3191   size_t Length() const { return mLength; }
3192 
3193   /**
3194    * Stable sort the list by the z-order of Frame() on
3195    * each item. 'auto' is counted as zero.
3196    * It is assumed that the list is already in content document order.
3197    */
3198   void SortByZOrder();
3199 
3200   /**
3201    * Stable sort the list by the tree order of the content of
3202    * Frame() on each item. z-index is ignored.
3203    * @param aCommonAncestor a common ancestor of all the content elements
3204    * associated with the display items, for speeding up tree order
3205    * checks, or nullptr if not known; it's only a hint, if it is not an
3206    * ancestor of some elements, then we lose performance but not correctness
3207    */
3208   void SortByContentOrder(nsIContent* aCommonAncestor);
3209 
3210   /**
3211    * Sort the display list using a stable sort.
3212    * aComparator(Item item1, Item item2) should return true if item1 should go
3213    * before item2.
3214    * We sort the items into increasing order.
3215    */
3216   template <typename Item, typename Comparator>
Sort(const Comparator & aComparator)3217   void Sort(const Comparator& aComparator) {
3218     if (Length() < 2) {
3219       // Only sort lists with more than one item.
3220       return;
3221     }
3222 
3223     // Some casual local browsing testing suggests that a local preallocated
3224     // array of 20 items should be able to avoid a lot of dynamic allocations
3225     // here.
3226     AutoTArray<Item, 20> items;
3227 
3228     for (nsDisplayItem* item : TakeItems()) {
3229       items.AppendElement(Item(item));
3230     }
3231 
3232     std::stable_sort(items.begin(), items.end(), aComparator);
3233 
3234     for (Item& item : items) {
3235       AppendToTop(item);
3236     }
3237   }
3238 
TakeItems()3239   nsDisplayList TakeItems() {
3240     nsDisplayList list = std::move(*this);
3241 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3242     list.mAllowNonEmptyDestruction = true;
3243 #endif
3244     return list;
3245   }
3246 
RemoveBottom()3247   nsDisplayItem* RemoveBottom() {
3248     if (!mBottom) {
3249       return nullptr;
3250     }
3251 
3252     nsDisplayItem* bottom = mBottom->mValue;
3253 
3254     auto next = mBottom->mNext;
3255     Deallocate(mBottom);
3256     mBottom = next;
3257 
3258     if (!mBottom) {
3259       // No bottom item means no items at all.
3260       mTop = nullptr;
3261     }
3262 
3263     MOZ_ASSERT(mLength > 0);
3264     mLength--;
3265 
3266     return bottom;
3267   }
3268 
3269   /**
3270    * Paint the list to the rendering context. We assume that (0,0) in aCtx
3271    * corresponds to the origin of the reference frame. For best results,
3272    * aCtx's current transform should make (0,0) pixel-aligned. The
3273    * rectangle in aDirtyRect is painted, which *must* be contained in the
3274    * dirty rect used to construct the display list.
3275    *
3276    * If aFlags contains PAINT_USE_WIDGET_LAYERS and
3277    * ShouldUseWidgetLayerManager() is set, then we will paint using
3278    * the reference frame's widget's layer manager (and ctx may be null),
3279    * otherwise we will use a temporary BasicLayerManager and ctx must
3280    * not be null.
3281    *
3282    * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
3283    * layer manager has already had BeginTransaction() called on it and
3284    * we should not call it again.
3285    *
3286    * This must only be called on the root display list of the display list
3287    * tree.
3288    *
3289    * We return the layer manager used for painting --- mainly so that
3290    * callers can dump its layer tree if necessary.
3291    */
3292   enum {
3293     PAINT_DEFAULT = 0,
3294     PAINT_USE_WIDGET_LAYERS = 0x01,
3295     PAINT_EXISTING_TRANSACTION = 0x04,
3296     PAINT_IDENTICAL_DISPLAY_LIST = 0x08
3297   };
3298   void PaintRoot(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
3299                  uint32_t aFlags, Maybe<double> aDisplayListBuildTime);
3300 
3301   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
3302              int32_t aAppUnitsPerDevPixel);
3303 
3304   /**
3305    * Get the bounds. Takes the union of the bounds of all children.
3306    * The result is not cached.
3307    */
3308   nsRect GetClippedBounds(nsDisplayListBuilder* aBuilder) const;
3309 
3310   /**
3311    * Get this list's bounds, respecting clips relative to aASR. The result is
3312    * the union of each item's clipped bounds with respect to aASR. That means
3313    * that if an item can move asynchronously with an ASR that is a descendant
3314    * of aASR, then the clipped bounds with respect to aASR will be the clip of
3315    * that item for aASR, because the item can move anywhere inside that clip.
3316    * If there is an item in this list which is not bounded with respect to
3317    * aASR (i.e. which does not have "finite bounds" with respect to aASR),
3318    * then this method trigger an assertion failure.
3319    * The optional aBuildingRect out argument can be set to non-null if the
3320    * caller is also interested to know the building rect.  This can be used
3321    * to get the visible rect efficiently without traversing the display list
3322    * twice.
3323    */
3324   nsRect GetClippedBoundsWithRespectToASR(
3325       nsDisplayListBuilder* aBuilder, const ActiveScrolledRoot* aASR,
3326       nsRect* aBuildingRect = nullptr) const;
3327 
3328   /**
3329    * Returns the opaque region of this display list.
3330    */
GetOpaqueRegion(nsDisplayListBuilder * aBuilder)3331   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder) {
3332     nsRegion result;
3333     bool snap;
3334     for (nsDisplayItem* item : *this) {
3335       result.OrWith(item->GetOpaqueRegion(aBuilder, &snap));
3336     }
3337     return result;
3338   }
3339 
3340   /**
3341    * Returns the bounds of the area that needs component alpha.
3342    */
GetComponentAlphaBounds(nsDisplayListBuilder * aBuilder)3343   nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const {
3344     nsRect bounds;
3345     for (nsDisplayItem* item : *this) {
3346       bounds.UnionRect(bounds, item->GetComponentAlphaBounds(aBuilder));
3347     }
3348     return bounds;
3349   }
3350 
3351   /**
3352    * Find the topmost display item that returns a non-null frame, and return
3353    * the frame.
3354    */
3355   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
3356                nsDisplayItem::HitTestState* aState,
3357                nsTArray<nsIFrame*>* aOutFrames) const;
3358   /**
3359    * Compute the union of the visible rects of the items in the list. The
3360    * result is not cached.
3361    */
3362   nsRect GetBuildingRect() const;
3363 
3364  private:
Allocate(nsDisplayItem * aItem)3365   inline Node* Allocate(nsDisplayItem* aItem) {
3366     void* ptr =
3367         mBuilder->Allocate(sizeof(Node), DisplayListArenaObjectId::LISTNODE);
3368     return new (ptr) Node(aItem);
3369   }
3370 
Deallocate(Node * aNode)3371   inline void Deallocate(Node* aNode) {
3372     aNode->~Node();
3373     mBuilder->Destroy(DisplayListArenaObjectId::LISTNODE, aNode);
3374   }
3375 
SetEmpty()3376   void SetEmpty() {
3377     mBottom = nullptr;
3378     mTop = nullptr;
3379     mLength = 0;
3380   }
3381 
3382   Node* mBottom = nullptr;
3383   Node* mTop = nullptr;
3384   size_t mLength = 0;
3385   nsDisplayListBuilder* mBuilder = nullptr;
3386 
3387 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3388   // This checks that the invariant of display lists owning their items is held.
3389   bool mAllowNonEmptyDestruction = false;
3390 #endif
3391 };
3392 
3393 /**
3394  * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
3395  * will put any generated items onto the appropriate list given here. It's
3396  * basically just a collection with one list for each separate stacking layer.
3397  * The lists themselves are external to this object and thus can be shared
3398  * with others. Some of the list pointers may even refer to the same list.
3399  */
3400 class nsDisplayListSet {
3401  public:
3402   /**
3403    * @return a list where one should place the border and/or background for
3404    * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
3405    */
BorderBackground()3406   nsDisplayList* BorderBackground() const { return mBorderBackground; }
3407   /**
3408    * @return a list where one should place the borders and/or backgrounds for
3409    * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
3410    */
BlockBorderBackgrounds()3411   nsDisplayList* BlockBorderBackgrounds() const {
3412     return mBlockBorderBackgrounds;
3413   }
3414   /**
3415    * @return a list where one should place descendant floats (step 5 of
3416    * CSS 2.1 appendix E)
3417    */
Floats()3418   nsDisplayList* Floats() const { return mFloats; }
3419   /**
3420    * @return a list where one should place the (pseudo) stacking contexts
3421    * for descendants of this frame (everything from steps 3, 7 and 8
3422    * of CSS 2.1 appendix E)
3423    */
PositionedDescendants()3424   nsDisplayList* PositionedDescendants() const { return mPositioned; }
3425   /**
3426    * @return a list where one should place the outlines
3427    * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
3428    */
Outlines()3429   nsDisplayList* Outlines() const { return mOutlines; }
3430   /**
3431    * @return a list where one should place all other content
3432    */
Content()3433   nsDisplayList* Content() const { return mContent; }
3434 
DeleteAll(nsDisplayListBuilder * aBuilder)3435   void DeleteAll(nsDisplayListBuilder* aBuilder) {
3436     BorderBackground()->DeleteAll(aBuilder);
3437     BlockBorderBackgrounds()->DeleteAll(aBuilder);
3438     Floats()->DeleteAll(aBuilder);
3439     PositionedDescendants()->DeleteAll(aBuilder);
3440     Outlines()->DeleteAll(aBuilder);
3441     Content()->DeleteAll(aBuilder);
3442   }
3443 
nsDisplayListSet(nsDisplayList * aBorderBackground,nsDisplayList * aBlockBorderBackgrounds,nsDisplayList * aFloats,nsDisplayList * aContent,nsDisplayList * aPositionedDescendants,nsDisplayList * aOutlines)3444   nsDisplayListSet(nsDisplayList* aBorderBackground,
3445                    nsDisplayList* aBlockBorderBackgrounds,
3446                    nsDisplayList* aFloats, nsDisplayList* aContent,
3447                    nsDisplayList* aPositionedDescendants,
3448                    nsDisplayList* aOutlines)
3449       : mBorderBackground(aBorderBackground),
3450         mBlockBorderBackgrounds(aBlockBorderBackgrounds),
3451         mFloats(aFloats),
3452         mContent(aContent),
3453         mPositioned(aPositionedDescendants),
3454         mOutlines(aOutlines) {}
3455 
3456   /**
3457    * A copy constructor that lets the caller override the BorderBackground
3458    * list.
3459    */
nsDisplayListSet(const nsDisplayListSet & aLists,nsDisplayList * aBorderBackground)3460   nsDisplayListSet(const nsDisplayListSet& aLists,
3461                    nsDisplayList* aBorderBackground)
3462       : mBorderBackground(aBorderBackground),
3463         mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()),
3464         mFloats(aLists.Floats()),
3465         mContent(aLists.Content()),
3466         mPositioned(aLists.PositionedDescendants()),
3467         mOutlines(aLists.Outlines()) {}
3468 
3469   /**
3470    * Move all display items in our lists to top of the corresponding lists in
3471    * the destination.
3472    */
3473   void MoveTo(const nsDisplayListSet& aDestination) const;
3474 
3475  private:
3476   // This class is only used on stack, so we don't have to worry about leaking
3477   // it.  Don't let us be heap-allocated!
3478   void* operator new(size_t sz) noexcept(true);
3479 
3480  protected:
3481   nsDisplayList* mBorderBackground;
3482   nsDisplayList* mBlockBorderBackgrounds;
3483   nsDisplayList* mFloats;
3484   nsDisplayList* mContent;
3485   nsDisplayList* mPositioned;
3486   nsDisplayList* mOutlines;
3487 };
3488 
3489 /**
3490  * A specialization of nsDisplayListSet where the lists are actually internal
3491  * to the object, and all distinct.
3492  */
3493 struct nsDisplayListCollection : public nsDisplayListSet {
nsDisplayListCollectionnsDisplayListCollection3494   explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder)
3495       : nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3],
3496                          &mLists[4], &mLists[5]),
3497         mLists{nsDisplayList{aBuilder}, nsDisplayList{aBuilder},
3498                nsDisplayList{aBuilder}, nsDisplayList{aBuilder},
3499                nsDisplayList{aBuilder}, nsDisplayList{aBuilder}} {}
3500 
3501   /*
3502   explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder,
3503                                    nsDisplayList* aBorderBackground)
3504       : nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3],
3505                          &mLists[4], &mLists[5]) {}
3506 */
3507   /**
3508    * Sort all lists by content order.
3509    */
SortAllByContentOrdernsDisplayListCollection3510   void SortAllByContentOrder(nsIContent* aCommonAncestor) {
3511     for (auto& mList : mLists) {
3512       mList.SortByContentOrder(aCommonAncestor);
3513     }
3514   }
3515 
3516   /**
3517    * Serialize this display list collection into a display list with the items
3518    * in the correct Z order.
3519    * @param aOutList the result display list
3520    * @param aContent the content element to use for content ordering
3521    */
3522   void SerializeWithCorrectZOrder(nsDisplayList* aOutResultList,
3523                                   nsIContent* aContent);
3524 
3525  private:
3526   // This class is only used on stack, so we don't have to worry about leaking
3527   // it.  Don't let us be heap-allocated!
3528   void* operator new(size_t sz) noexcept(true);
3529 
3530   nsDisplayList mLists[6];
3531 };
3532 
3533 /**
3534  * A display list that also retains the partial build
3535  * information (in the form of a DAG) used to create it.
3536  *
3537  * Display lists built from a partial list aren't necessarily
3538  * in the same order as a full build, and the DAG retains
3539  * the information needing to interpret the current
3540  * order correctly.
3541  */
3542 class RetainedDisplayList : public nsDisplayList {
3543  public:
RetainedDisplayList(nsDisplayListBuilder * aBuilder)3544   explicit RetainedDisplayList(nsDisplayListBuilder* aBuilder)
3545       : nsDisplayList(aBuilder) {}
3546 
RetainedDisplayList(RetainedDisplayList && aOther)3547   RetainedDisplayList(RetainedDisplayList&& aOther)
3548       : nsDisplayList(std::move(aOther)), mDAG(std::move(aOther.mDAG)) {}
3549 
3550   RetainedDisplayList(const RetainedDisplayList&) = delete;
3551   RetainedDisplayList& operator=(const RetainedDisplayList&) = delete;
3552 
~RetainedDisplayList()3553   ~RetainedDisplayList() override {
3554     MOZ_ASSERT(mOldItems.IsEmpty(), "Must empty list before destroying");
3555   }
3556 
3557   RetainedDisplayList& operator=(RetainedDisplayList&& aOther) {
3558     MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
3559     MOZ_ASSERT(mOldItems.IsEmpty(), "Can only move into an empty list!");
3560 
3561     nsDisplayList::operator=(std::move(aOther));
3562     mDAG = std::move(aOther.mDAG);
3563     mOldItems = std::move(aOther.mOldItems);
3564     return *this;
3565   }
3566 
3567   RetainedDisplayList& operator=(nsDisplayList&& aOther) {
3568     MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
3569     MOZ_ASSERT(mOldItems.IsEmpty(), "Can only move into an empty list!");
3570     nsDisplayList::operator=(std::move(aOther));
3571     return *this;
3572   }
3573 
DeleteAll(nsDisplayListBuilder * aBuilder)3574   void DeleteAll(nsDisplayListBuilder* aBuilder) override {
3575     for (OldItemInfo& i : mOldItems) {
3576       if (i.mItem && i.mOwnsItem) {
3577         i.mItem->Destroy(aBuilder);
3578         MOZ_ASSERT(!GetBottom(),
3579                    "mOldItems should not be owning items if we also have items "
3580                    "in the normal list");
3581       }
3582     }
3583     mOldItems.Clear();
3584     mDAG.Clear();
3585     nsDisplayList::DeleteAll(aBuilder);
3586   }
3587 
3588   void AddSizeOfExcludingThis(nsWindowSizes&) const;
3589 
3590   DirectedAcyclicGraph<MergedListUnits> mDAG;
3591 
3592   // Temporary state initialized during the preprocess pass
3593   // of RetainedDisplayListBuilder and then used during merging.
3594   nsTArray<OldItemInfo> mOldItems;
3595 };
3596 
3597 class nsDisplayContainer final : public nsDisplayItem {
3598  public:
3599   nsDisplayContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3600                      const ActiveScrolledRoot* aActiveScrolledRoot,
3601                      nsDisplayList* aList);
3602 
~nsDisplayContainer()3603   ~nsDisplayContainer() override { MOZ_COUNT_DTOR(nsDisplayContainer); }
3604 
3605   NS_DISPLAY_DECL_NAME("nsDisplayContainer", TYPE_CONTAINER)
3606 
Destroy(nsDisplayListBuilder * aBuilder)3607   void Destroy(nsDisplayListBuilder* aBuilder) override {
3608     mChildren.DeleteAll(aBuilder);
3609     nsDisplayItem::Destroy(aBuilder);
3610   }
3611 
3612   bool CreateWebRenderCommands(
3613       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
3614       const StackingContextHelper& aSc,
3615       layers::RenderRootStateManager* aManager,
3616       nsDisplayListBuilder* aDisplayListBuilder) override;
3617 
3618   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
3619 
3620   nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override;
3621 
3622   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
3623                            bool* aSnap) const override;
3624 
IsUniform(nsDisplayListBuilder * aBuilder)3625   Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override {
3626     return Nothing();
3627   }
3628 
GetChildren()3629   RetainedDisplayList* GetChildren() const override { return &mChildren; }
GetSameCoordinateSystemChildren()3630   RetainedDisplayList* GetSameCoordinateSystemChildren() const override {
3631     return GetChildren();
3632   }
3633 
3634   Maybe<nsRect> GetClipWithRespectToASR(
3635       nsDisplayListBuilder* aBuilder,
3636       const ActiveScrolledRoot* aASR) const override;
3637 
3638   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
3639                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
3640 
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)3641   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
3642     return true;
3643   }
3644 
SetClipChain(const DisplayItemClipChain * aClipChain,bool aStore)3645   void SetClipChain(const DisplayItemClipChain* aClipChain,
3646                     bool aStore) override {
3647     MOZ_ASSERT_UNREACHABLE("nsDisplayContainer does not support clipping");
3648   }
3649 
3650   void UpdateBounds(nsDisplayListBuilder* aBuilder) override;
3651 
3652  private:
3653   mutable RetainedDisplayList mChildren;
3654   nsRect mBounds;
3655 };
3656 
3657 /**
3658  * Use this class to implement not-very-frequently-used display items
3659  * that are not opaque, do not receive events, and are bounded by a frame's
3660  * border-rect.
3661  *
3662  * This should not be used for display items which are created frequently,
3663  * because each item is one or two pointers bigger than an item from a
3664  * custom display item class could be, and fractionally slower. However it does
3665  * save code size. We use this for infrequently-used item types.
3666  */
3667 class nsDisplayGeneric : public nsPaintedDisplayItem {
3668  public:
3669   typedef void (*PaintCallback)(nsIFrame* aFrame, gfx::DrawTarget* aDrawTarget,
3670                                 const nsRect& aDirtyRect, nsPoint aFramePt);
3671 
3672   // XXX: should be removed eventually
3673   typedef void (*OldPaintCallback)(nsIFrame* aFrame, gfxContext* aCtx,
3674                                    const nsRect& aDirtyRect, nsPoint aFramePt);
3675 
nsDisplayGeneric(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,PaintCallback aPaint,const char * aName,DisplayItemType aType)3676   nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3677                    PaintCallback aPaint, const char* aName,
3678                    DisplayItemType aType)
3679       : nsPaintedDisplayItem(aBuilder, aFrame),
3680         mPaint(aPaint),
3681         mOldPaint(nullptr),
3682         mName(aName) {
3683     MOZ_COUNT_CTOR(nsDisplayGeneric);
3684     SetType(aType);
3685   }
3686 
3687   // XXX: should be removed eventually
nsDisplayGeneric(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,OldPaintCallback aOldPaint,const char * aName,DisplayItemType aType)3688   nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3689                    OldPaintCallback aOldPaint, const char* aName,
3690                    DisplayItemType aType)
3691       : nsPaintedDisplayItem(aBuilder, aFrame),
3692         mPaint(nullptr),
3693         mOldPaint(aOldPaint),
3694         mName(aName) {
3695     MOZ_COUNT_CTOR(nsDisplayGeneric);
3696     SetType(aType);
3697   }
3698 
ItemType()3699   constexpr static DisplayItemType ItemType() {
3700     return DisplayItemType::TYPE_GENERIC;
3701   }
3702 
MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayGeneric)3703   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayGeneric)
3704 
3705   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
3706     MOZ_ASSERT(!!mPaint != !!mOldPaint);
3707     if (mPaint) {
3708       mPaint(mFrame, aCtx->GetDrawTarget(), GetPaintRect(aBuilder, aCtx),
3709              ToReferenceFrame());
3710     } else {
3711       mOldPaint(mFrame, aCtx, GetPaintRect(aBuilder, aCtx), ToReferenceFrame());
3712     }
3713   }
3714 
Name()3715   const char* Name() const override { return mName; }
3716 
3717   // This override is needed because GetType() for nsDisplayGeneric subclasses
3718   // does not match TYPE_GENERIC that was used to allocate the object.
Destroy(nsDisplayListBuilder * aBuilder)3719   void Destroy(nsDisplayListBuilder* aBuilder) override {
3720     this->~nsDisplayGeneric();
3721     aBuilder->Destroy(DisplayItemType::TYPE_GENERIC, this);
3722   }
3723 
3724  protected:
new(size_t aSize,nsDisplayListBuilder * aBuilder)3725   void* operator new(size_t aSize, nsDisplayListBuilder* aBuilder) {
3726     return aBuilder->Allocate(aSize, DisplayItemType::TYPE_GENERIC);
3727   }
3728 
3729   template <typename T, typename F, typename... Args>
3730   friend T* MakeDisplayItemWithIndex(nsDisplayListBuilder* aBuilder, F* aFrame,
3731                                      const uint16_t aIndex, Args&&... aArgs);
3732 
3733   PaintCallback mPaint;
3734   OldPaintCallback mOldPaint;  // XXX: should be removed eventually
3735   const char* mName;
3736 };
3737 
3738 #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
3739 /**
3740  * This class implements painting of reflow counts.  Ideally, we would simply
3741  * make all the frame names be those returned by nsIFrame::GetFrameName
3742  * (except that tosses in the content tag name!)  and support only one color
3743  * and eliminate this class altogether in favor of nsDisplayGeneric, but for
3744  * the time being we can't pass args to a PaintCallback, so just have a
3745  * separate class to do the right thing.  Sadly, this alsmo means we need to
3746  * hack all leaf frame classes to handle this.
3747  *
3748  * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
3749  * here...  I could switch it all to nscolor, but why bother?
3750  */
3751 class nsDisplayReflowCount : public nsPaintedDisplayItem {
3752  public:
3753   nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3754                        const char* aFrameName, uint32_t aColor = 0)
nsPaintedDisplayItem(aBuilder,aFrame)3755       : nsPaintedDisplayItem(aBuilder, aFrame),
3756         mFrameName(aFrameName),
3757         mColor(aColor) {
3758     MOZ_COUNT_CTOR(nsDisplayReflowCount);
3759   }
3760 
3761   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayReflowCount)
3762 
3763   NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT)
3764 
3765   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3766 
3767  protected:
3768   const char* mFrameName;
3769   nscolor mColor;
3770 };
3771 
3772 #  define DO_GLOBAL_REFLOW_COUNT_DSP(_name)                                 \
3773     PR_BEGIN_MACRO                                                          \
3774     if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
3775         PresShell()->IsPaintingFrameCounts()) {                             \
3776       aLists.Outlines()->AppendNewToTop<mozilla::nsDisplayReflowCount>(     \
3777           aBuilder, this, _name);                                           \
3778     }                                                                       \
3779     PR_END_MACRO
3780 
3781 #  define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)                   \
3782     PR_BEGIN_MACRO                                                          \
3783     if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
3784         PresShell()->IsPaintingFrameCounts()) {                             \
3785       aLists.Outlines()->AppendNewToTop<mozilla::nsDisplayReflowCount>(     \
3786           aBuilder, this, _name, _color);                                   \
3787     }                                                                       \
3788     PR_END_MACRO
3789 
3790 /*
3791   Macro to be used for classes that don't actually implement BuildDisplayList
3792  */
3793 #  define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)     \
3794     void BuildDisplayList(nsDisplayListBuilder* aBuilder,     \
3795                           const nsRect& aDirtyRect,           \
3796                           const nsDisplayListSet& aLists) {   \
3797       DO_GLOBAL_REFLOW_COUNT_DSP(#_class);                    \
3798       _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
3799     }
3800 
3801 #else  // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
3802 
3803 #  define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
3804 #  define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
3805 #  define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
3806 
3807 #endif  // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
3808 
3809 class nsDisplayCaret : public nsPaintedDisplayItem {
3810  public:
3811   nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame);
3812 
3813 #ifdef NS_BUILD_REFCNT_LOGGING
3814   ~nsDisplayCaret() override;
3815 #endif
3816 
3817   NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET)
3818 
3819   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
3820   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3821   bool CreateWebRenderCommands(
3822       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
3823       const StackingContextHelper& aSc,
3824       layers::RenderRootStateManager* aManager,
3825       nsDisplayListBuilder* aDisplayListBuilder) override;
3826 
3827  protected:
3828   RefPtr<nsCaret> mCaret;
3829   nsRect mBounds;
3830 };
3831 
3832 /**
3833  * The standard display item to paint the CSS borders of a frame.
3834  */
3835 class nsDisplayBorder : public nsPaintedDisplayItem {
3836  public:
3837   nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
3838 
3839   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBorder)
3840 
3841   NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
3842 
3843   bool IsInvisibleInRect(const nsRect& aRect) const override;
3844   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
3845   bool CreateWebRenderCommands(
3846       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
3847       const StackingContextHelper& aSc,
3848       layers::RenderRootStateManager* aManager,
3849       nsDisplayListBuilder* aDisplayListBuilder) override;
3850   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3851   nsDisplayItemGeometry* AllocateGeometry(
3852       nsDisplayListBuilder* aBuilder) override;
3853   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3854                                  const nsDisplayItemGeometry* aGeometry,
3855                                  nsRegion* aInvalidRegion) const override;
3856 
GetTightBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)3857   nsRegion GetTightBounds(nsDisplayListBuilder* aBuilder,
3858                           bool* aSnap) const override {
3859     *aSnap = true;
3860     return CalculateBounds<nsRegion>(*mFrame->StyleBorder());
3861   }
3862 
3863  protected:
3864   template <typename T>
CalculateBounds(const nsStyleBorder & aStyleBorder)3865   T CalculateBounds(const nsStyleBorder& aStyleBorder) const {
3866     nsRect borderBounds(ToReferenceFrame(), mFrame->GetSize());
3867     if (aStyleBorder.IsBorderImageSizeAvailable()) {
3868       borderBounds.Inflate(aStyleBorder.GetImageOutset());
3869       return borderBounds;
3870     }
3871 
3872     nsMargin border = aStyleBorder.GetComputedBorder();
3873     T result;
3874     if (border.top > 0) {
3875       result = nsRect(borderBounds.X(), borderBounds.Y(), borderBounds.Width(),
3876                       border.top);
3877     }
3878     if (border.right > 0) {
3879       result.OrWith(nsRect(borderBounds.XMost() - border.right,
3880                            borderBounds.Y(), border.right,
3881                            borderBounds.Height()));
3882     }
3883     if (border.bottom > 0) {
3884       result.OrWith(nsRect(borderBounds.X(),
3885                            borderBounds.YMost() - border.bottom,
3886                            borderBounds.Width(), border.bottom));
3887     }
3888     if (border.left > 0) {
3889       result.OrWith(nsRect(borderBounds.X(), borderBounds.Y(), border.left,
3890                            borderBounds.Height()));
3891     }
3892 
3893     nscoord radii[8];
3894     if (mFrame->GetBorderRadii(radii)) {
3895       if (border.left > 0 || border.top > 0) {
3896         nsSize cornerSize(radii[eCornerTopLeftX], radii[eCornerTopLeftY]);
3897         result.OrWith(nsRect(borderBounds.TopLeft(), cornerSize));
3898       }
3899       if (border.top > 0 || border.right > 0) {
3900         nsSize cornerSize(radii[eCornerTopRightX], radii[eCornerTopRightY]);
3901         result.OrWith(
3902             nsRect(borderBounds.TopRight() - nsPoint(cornerSize.width, 0),
3903                    cornerSize));
3904       }
3905       if (border.right > 0 || border.bottom > 0) {
3906         nsSize cornerSize(radii[eCornerBottomRightX],
3907                           radii[eCornerBottomRightY]);
3908         result.OrWith(nsRect(borderBounds.BottomRight() -
3909                                  nsPoint(cornerSize.width, cornerSize.height),
3910                              cornerSize));
3911       }
3912       if (border.bottom > 0 || border.left > 0) {
3913         nsSize cornerSize(radii[eCornerBottomLeftX], radii[eCornerBottomLeftY]);
3914         result.OrWith(
3915             nsRect(borderBounds.BottomLeft() - nsPoint(0, cornerSize.height),
3916                    cornerSize));
3917       }
3918     }
3919     return result;
3920   }
3921 
3922   nsRect mBounds;
3923 };
3924 
3925 /**
3926  * A simple display item that just renders a solid color across the
3927  * specified bounds. For canvas frames (in the CSS sense) we split off the
3928  * drawing of the background color into this class (from nsDisplayBackground
3929  * via nsDisplayCanvasBackground). This is done so that we can always draw a
3930  * background color to avoid ugly flashes of white when we can't draw a full
3931  * frame tree (ie when a page is loading). The bounds can differ from the
3932  * frame's bounds -- this is needed when a frame/iframe is loading and there
3933  * is not yet a frame tree to go in the frame/iframe so we use the subdoc
3934  * frame of the parent document as a standin.
3935  */
3936 class nsDisplaySolidColorBase : public nsPaintedDisplayItem {
3937  public:
nsDisplaySolidColorBase(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,nscolor aColor)3938   nsDisplaySolidColorBase(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3939                           nscolor aColor)
3940       : nsPaintedDisplayItem(aBuilder, aFrame), mColor(aColor) {}
3941 
AllocateGeometry(nsDisplayListBuilder * aBuilder)3942   nsDisplayItemGeometry* AllocateGeometry(
3943       nsDisplayListBuilder* aBuilder) override {
3944     return new nsDisplaySolidColorGeometry(this, aBuilder, mColor);
3945   }
3946 
ComputeInvalidationRegion(nsDisplayListBuilder * aBuilder,const nsDisplayItemGeometry * aGeometry,nsRegion * aInvalidRegion)3947   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
3948                                  const nsDisplayItemGeometry* aGeometry,
3949                                  nsRegion* aInvalidRegion) const override {
3950     const nsDisplaySolidColorGeometry* geometry =
3951         static_cast<const nsDisplaySolidColorGeometry*>(aGeometry);
3952     if (mColor != geometry->mColor) {
3953       bool dummy;
3954       aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
3955       return;
3956     }
3957     ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
3958   }
3959 
GetOpaqueRegion(nsDisplayListBuilder * aBuilder,bool * aSnap)3960   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
3961                            bool* aSnap) const override {
3962     *aSnap = false;
3963     nsRegion result;
3964     if (NS_GET_A(mColor) == 255) {
3965       result = GetBounds(aBuilder, aSnap);
3966     }
3967     return result;
3968   }
3969 
IsUniform(nsDisplayListBuilder * aBuilder)3970   Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override {
3971     return Some(mColor);
3972   }
3973 
3974  protected:
3975   nscolor mColor;
3976 };
3977 
3978 class nsDisplaySolidColor : public nsDisplaySolidColorBase {
3979  public:
3980   nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
3981                       const nsRect& aBounds, nscolor aColor,
3982                       bool aCanBeReused = true)
nsDisplaySolidColorBase(aBuilder,aFrame,aColor)3983       : nsDisplaySolidColorBase(aBuilder, aFrame, aColor), mBounds(aBounds) {
3984     NS_ASSERTION(NS_GET_A(aColor) > 0,
3985                  "Don't create invisible nsDisplaySolidColors!");
3986     MOZ_COUNT_CTOR(nsDisplaySolidColor);
3987     if (!aCanBeReused) {
3988       SetCantBeReused();
3989     }
3990   }
3991 
3992   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColor)
3993 
3994   NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
3995 
3996   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
3997   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
3998   void WriteDebugInfo(std::stringstream& aStream) override;
3999   bool CreateWebRenderCommands(
4000       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4001       const StackingContextHelper& aSc,
4002       layers::RenderRootStateManager* aManager,
4003       nsDisplayListBuilder* aDisplayListBuilder) override;
4004 
ZIndex()4005   int32_t ZIndex() const override {
4006     if (mOverrideZIndex) {
4007       return mOverrideZIndex.value();
4008     }
4009     return nsDisplaySolidColorBase::ZIndex();
4010   }
4011 
SetOverrideZIndex(int32_t aZIndex)4012   void SetOverrideZIndex(int32_t aZIndex) { mOverrideZIndex = Some(aZIndex); }
4013 
4014  private:
4015   nsRect mBounds;
4016   Maybe<int32_t> mOverrideZIndex;
4017 };
4018 
4019 /**
4020  * A display item that renders a solid color over a region. This is not
4021  * exposed through CSS, its only purpose is efficient invalidation of
4022  * the find bar highlighter dimmer.
4023  */
4024 class nsDisplaySolidColorRegion : public nsPaintedDisplayItem {
4025  public:
nsDisplaySolidColorRegion(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,const nsRegion & aRegion,nscolor aColor)4026   nsDisplaySolidColorRegion(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4027                             const nsRegion& aRegion, nscolor aColor)
4028       : nsPaintedDisplayItem(aBuilder, aFrame),
4029         mRegion(aRegion),
4030         mColor(gfx::sRGBColor::FromABGR(aColor)) {
4031     NS_ASSERTION(NS_GET_A(aColor) > 0,
4032                  "Don't create invisible nsDisplaySolidColorRegions!");
4033     MOZ_COUNT_CTOR(nsDisplaySolidColorRegion);
4034   }
4035 
4036   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColorRegion)
4037 
4038   NS_DISPLAY_DECL_NAME("SolidColorRegion", TYPE_SOLID_COLOR_REGION)
4039 
AllocateGeometry(nsDisplayListBuilder * aBuilder)4040   nsDisplayItemGeometry* AllocateGeometry(
4041       nsDisplayListBuilder* aBuilder) override {
4042     return new nsDisplaySolidColorRegionGeometry(this, aBuilder, mRegion,
4043                                                  mColor);
4044   }
4045 
ComputeInvalidationRegion(nsDisplayListBuilder * aBuilder,const nsDisplayItemGeometry * aGeometry,nsRegion * aInvalidRegion)4046   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4047                                  const nsDisplayItemGeometry* aGeometry,
4048                                  nsRegion* aInvalidRegion) const override {
4049     const nsDisplaySolidColorRegionGeometry* geometry =
4050         static_cast<const nsDisplaySolidColorRegionGeometry*>(aGeometry);
4051     if (mColor == geometry->mColor) {
4052       aInvalidRegion->Xor(geometry->mRegion, mRegion);
4053     } else {
4054       aInvalidRegion->Or(geometry->mRegion.GetBounds(), mRegion.GetBounds());
4055     }
4056   }
4057 
4058   bool CreateWebRenderCommands(
4059       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4060       const StackingContextHelper& aSc,
4061       layers::RenderRootStateManager* aManager,
4062       nsDisplayListBuilder* aDisplayListBuilder) override;
4063 
4064  protected:
4065   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
4066   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4067   void WriteDebugInfo(std::stringstream& aStream) override;
4068 
4069  private:
4070   nsRegion mRegion;
4071   gfx::sRGBColor mColor;
4072 };
4073 
4074 enum class AppendedBackgroundType : uint8_t {
4075   None,
4076   Background,
4077   ThemedBackground,
4078 };
4079 
4080 /**
4081  * A display item to paint one background-image for a frame. Each background
4082  * image layer gets its own nsDisplayBackgroundImage.
4083  */
4084 class nsDisplayBackgroundImage : public nsPaintedDisplayItem {
4085  public:
4086   struct InitData {
4087     nsDisplayListBuilder* builder;
4088     ComputedStyle* backgroundStyle;
4089     nsCOMPtr<imgIContainer> image;
4090     nsRect backgroundRect;
4091     nsRect fillArea;
4092     nsRect destArea;
4093     uint32_t layer;
4094     bool isRasterImage;
4095     bool shouldFixToViewport;
4096   };
4097 
4098   /**
4099    * aLayer signifies which background layer this item represents.
4100    * aIsThemed should be the value of aFrame->IsThemed.
4101    * aBackgroundStyle should be the result of
4102    * nsCSSRendering::FindBackground, or null if FindBackground returned false.
4103    * aBackgroundRect is relative to aFrame.
4104    */
4105   static InitData GetInitData(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4106                               uint16_t aLayer, const nsRect& aBackgroundRect,
4107                               ComputedStyle* aBackgroundStyle);
4108 
4109   explicit nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder,
4110                                     nsIFrame* aFrame, const InitData& aInitData,
4111                                     nsIFrame* aFrameForBounds = nullptr);
4112   ~nsDisplayBackgroundImage() override;
4113 
4114   NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
4115 
4116   /**
4117    * This will create and append new items for all the layers of the
4118    * background. Returns the type of background that was appended.
4119    * aAllowWillPaintBorderOptimization should usually be left at true, unless
4120    * aFrame has special border drawing that causes opaque borders to not
4121    * actually be opaque.
4122    */
4123   static AppendedBackgroundType AppendBackgroundItemsToTop(
4124       nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4125       const nsRect& aBackgroundRect, nsDisplayList* aList,
4126       bool aAllowWillPaintBorderOptimization = true,
4127       ComputedStyle* aComputedStyle = nullptr,
4128       const nsRect& aBackgroundOriginRect = nsRect(),
4129       nsIFrame* aSecondaryReferenceFrame = nullptr,
4130       Maybe<nsDisplayListBuilder::AutoBuildingDisplayList>*
4131           aAutoBuildingDisplayList = nullptr);
4132 
4133   bool CreateWebRenderCommands(
4134       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4135       const StackingContextHelper& aSc,
4136       layers::RenderRootStateManager* aManager,
4137       nsDisplayListBuilder* aDisplayListBuilder) override;
4138   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4139                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
4140   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4141                            bool* aSnap) const override;
4142   Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
4143 
4144   bool CanApplyOpacity(WebRenderLayerManager* aManager,
4145                        nsDisplayListBuilder* aBuilder) const override;
4146 
4147   /**
4148    * GetBounds() returns the background painting area.
4149    */
4150   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
4151 
4152   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4153 
4154   /**
4155    * Return the background positioning area.
4156    * (GetBounds() returns the background painting area.)
4157    * Can be called only when mBackgroundStyle is non-null.
4158    */
4159   nsRect GetPositioningArea() const;
4160 
4161   /**
4162    * Returns true if existing rendered pixels of this display item may need
4163    * to be redrawn if the positioning area size changes but its position does
4164    * not.
4165    * If false, only the changed painting area needs to be redrawn when the
4166    * positioning area size changes but its position does not.
4167    */
4168   bool RenderingMightDependOnPositioningAreaSizeChange() const;
4169 
AllocateGeometry(nsDisplayListBuilder * aBuilder)4170   nsDisplayItemGeometry* AllocateGeometry(
4171       nsDisplayListBuilder* aBuilder) override {
4172     return new nsDisplayBackgroundGeometry(this, aBuilder);
4173   }
4174 
4175   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4176                                  const nsDisplayItemGeometry* aGeometry,
4177                                  nsRegion* aInvalidRegion) const override;
ShouldFixToViewport(nsDisplayListBuilder * aBuilder)4178   bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const override {
4179     return mShouldFixToViewport;
4180   }
4181 
GetDestRect()4182   nsRect GetDestRect() const { return mDestRect; }
4183 
GetDependentFrame()4184   nsIFrame* GetDependentFrame() override { return mDependentFrame; }
4185 
SetDependentFrame(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)4186   void SetDependentFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) {
4187     if (!aBuilder->IsRetainingDisplayList() || mDependentFrame == aFrame) {
4188       return;
4189     }
4190     mDependentFrame = aFrame;
4191     if (aFrame) {
4192       mDependentFrame->AddDisplayItem(this);
4193     }
4194   }
4195 
RemoveFrame(nsIFrame * aFrame)4196   void RemoveFrame(nsIFrame* aFrame) override {
4197     if (aFrame == mDependentFrame) {
4198       mDependentFrame = nullptr;
4199     }
4200     nsPaintedDisplayItem::RemoveFrame(aFrame);
4201   }
4202 
4203   // Match https://w3c.github.io/paint-timing/#contentful-image
IsContentful()4204   bool IsContentful() const override {
4205     const auto& styleImage =
4206         mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer].mImage;
4207 
4208     return styleImage.IsSizeAvailable() && styleImage.FinalImage().IsUrl();
4209   }
4210 
4211  protected:
4212   bool CanBuildWebRenderDisplayItems(layers::WebRenderLayerManager* aManager,
4213                                      nsDisplayListBuilder* aBuilder) const;
4214   nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder,
4215                            nsIFrame* aFrameForBounds = nullptr);
4216 
4217   void PaintInternal(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
4218                      const nsRect& aBounds, nsRect* aClipRect);
4219 
4220   // Cache the result of nsCSSRendering::FindBackground. Always null if
4221   // mIsThemed is true or if FindBackground returned false.
4222   RefPtr<ComputedStyle> mBackgroundStyle;
4223   nsCOMPtr<imgIContainer> mImage;
4224   nsIFrame* mDependentFrame;
4225   nsRect mBackgroundRect;  // relative to the reference frame
4226   nsRect mFillRect;
4227   nsRect mDestRect;
4228   /* Bounds of this display item */
4229   nsRect mBounds;
4230   uint16_t mLayer;
4231   bool mIsRasterImage;
4232   /* Whether the image should be treated as fixed to the viewport. */
4233   bool mShouldFixToViewport;
4234 };
4235 
4236 /**
4237  * A display item to paint background image for table. For table parts, such
4238  * as row, row group, col, col group, when drawing its background, we'll
4239  * create separate background image display item for its containning cell.
4240  * Those background image display items will reference to same DisplayItemData
4241  * if we keep the mFrame point to cell's ancestor frame. We don't want to this
4242  * happened bacause share same DisplatItemData will cause many bugs. So that
4243  * we let mFrame point to cell frame and store the table type of the ancestor
4244  * frame. And use mFrame and table type as key to generate DisplayItemData to
4245  * avoid sharing DisplayItemData.
4246  *
4247  * Also store ancestor frame as mStyleFrame for all rendering informations.
4248  */
4249 class nsDisplayTableBackgroundImage : public nsDisplayBackgroundImage {
4250  public:
4251   nsDisplayTableBackgroundImage(nsDisplayListBuilder* aBuilder,
4252                                 nsIFrame* aFrame, const InitData& aData,
4253                                 nsIFrame* aCellFrame);
4254   ~nsDisplayTableBackgroundImage() override;
4255 
4256   NS_DISPLAY_DECL_NAME("TableBackgroundImage", TYPE_TABLE_BACKGROUND_IMAGE)
4257 
4258   bool IsInvalid(nsRect& aRect) const override;
4259 
FrameForInvalidation()4260   nsIFrame* FrameForInvalidation() const override { return mStyleFrame; }
4261 
RemoveFrame(nsIFrame * aFrame)4262   void RemoveFrame(nsIFrame* aFrame) override {
4263     if (aFrame == mStyleFrame) {
4264       mStyleFrame = nullptr;
4265       SetDeletedFrame();
4266     }
4267     nsDisplayBackgroundImage::RemoveFrame(aFrame);
4268   }
4269 
4270  protected:
StyleFrame()4271   nsIFrame* StyleFrame() const override { return mStyleFrame; }
4272   nsIFrame* mStyleFrame;
4273 };
4274 
4275 /**
4276  * A display item to paint the native theme background for a frame.
4277  */
4278 class nsDisplayThemedBackground : public nsPaintedDisplayItem {
4279  public:
4280   nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4281                             const nsRect& aBackgroundRect);
4282 
4283   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayThemedBackground)
4284 
4285   NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND)
4286 
4287   void Init(nsDisplayListBuilder* aBuilder);
4288 
Destroy(nsDisplayListBuilder * aBuilder)4289   void Destroy(nsDisplayListBuilder* aBuilder) override {
4290     aBuilder->UnregisterThemeGeometry(this);
4291     nsPaintedDisplayItem::Destroy(aBuilder);
4292   }
4293 
4294   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4295                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
4296   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4297                            bool* aSnap) const override;
4298   Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
4299   bool CreateWebRenderCommands(
4300       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4301       const StackingContextHelper& aSc,
4302       layers::RenderRootStateManager* aManager,
4303       nsDisplayListBuilder* aDisplayListBuilder) override;
4304 
MustPaintOnContentSide()4305   bool MustPaintOnContentSide() const override { return true; }
4306 
4307   /**
4308    * GetBounds() returns the background painting area.
4309    */
4310   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
4311 
4312   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4313 
4314   /**
4315    * Return the background positioning area.
4316    * (GetBounds() returns the background painting area.)
4317    * Can be called only when mBackgroundStyle is non-null.
4318    */
4319   nsRect GetPositioningArea() const;
4320 
4321   /**
4322    * Return whether our frame's document does not have the state
4323    * NS_DOCUMENT_STATE_WINDOW_INACTIVE.
4324    */
4325   bool IsWindowActive() const;
4326 
AllocateGeometry(nsDisplayListBuilder * aBuilder)4327   nsDisplayItemGeometry* AllocateGeometry(
4328       nsDisplayListBuilder* aBuilder) override {
4329     return new nsDisplayThemedBackgroundGeometry(this, aBuilder);
4330   }
4331 
4332   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4333                                  const nsDisplayItemGeometry* aGeometry,
4334                                  nsRegion* aInvalidRegion) const override;
4335 
4336   void WriteDebugInfo(std::stringstream& aStream) override;
4337 
4338  protected:
4339   nsRect GetBoundsInternal();
4340 
4341   void PaintInternal(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
4342                      const nsRect& aBounds, nsRect* aClipRect);
4343 
4344   nsRect mBackgroundRect;
4345   nsRect mBounds;
4346   nsITheme::Transparency mThemeTransparency;
4347   StyleAppearance mAppearance;
4348 };
4349 
4350 class nsDisplayTableThemedBackground : public nsDisplayThemedBackground {
4351  public:
nsDisplayTableThemedBackground(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,const nsRect & aBackgroundRect,nsIFrame * aAncestorFrame)4352   nsDisplayTableThemedBackground(nsDisplayListBuilder* aBuilder,
4353                                  nsIFrame* aFrame,
4354                                  const nsRect& aBackgroundRect,
4355                                  nsIFrame* aAncestorFrame)
4356       : nsDisplayThemedBackground(aBuilder, aFrame, aBackgroundRect),
4357         mAncestorFrame(aAncestorFrame) {
4358     if (aBuilder->IsRetainingDisplayList()) {
4359       mAncestorFrame->AddDisplayItem(this);
4360     }
4361   }
4362 
~nsDisplayTableThemedBackground()4363   ~nsDisplayTableThemedBackground() override {
4364     if (mAncestorFrame) {
4365       mAncestorFrame->RemoveDisplayItem(this);
4366     }
4367   }
4368 
4369   NS_DISPLAY_DECL_NAME("TableThemedBackground",
4370                        TYPE_TABLE_THEMED_BACKGROUND_IMAGE)
4371 
FrameForInvalidation()4372   nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
4373 
RemoveFrame(nsIFrame * aFrame)4374   void RemoveFrame(nsIFrame* aFrame) override {
4375     if (aFrame == mAncestorFrame) {
4376       mAncestorFrame = nullptr;
4377       SetDeletedFrame();
4378     }
4379     nsDisplayThemedBackground::RemoveFrame(aFrame);
4380   }
4381 
4382  protected:
StyleFrame()4383   nsIFrame* StyleFrame() const override { return mAncestorFrame; }
4384   nsIFrame* mAncestorFrame;
4385 };
4386 
4387 class nsDisplayBackgroundColor : public nsPaintedDisplayItem {
4388  public:
nsDisplayBackgroundColor(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,const nsRect & aBackgroundRect,const ComputedStyle * aBackgroundStyle,const nscolor & aColor)4389   nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4390                            const nsRect& aBackgroundRect,
4391                            const ComputedStyle* aBackgroundStyle,
4392                            const nscolor& aColor)
4393       : nsPaintedDisplayItem(aBuilder, aFrame),
4394         mBackgroundRect(aBackgroundRect),
4395         mHasStyle(aBackgroundStyle),
4396         mDependentFrame(nullptr),
4397         mColor(gfx::sRGBColor::FromABGR(aColor)) {
4398     if (mHasStyle) {
4399       mBottomLayerClip =
4400           aBackgroundStyle->StyleBackground()->BottomLayer().mClip;
4401     } else {
4402       MOZ_ASSERT(aBuilder->IsForEventDelivery());
4403     }
4404   }
4405 
~nsDisplayBackgroundColor()4406   ~nsDisplayBackgroundColor() override {
4407     if (mDependentFrame) {
4408       mDependentFrame->RemoveDisplayItem(this);
4409     }
4410   }
4411 
4412   NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
4413 
HasBackgroundClipText()4414   bool HasBackgroundClipText() const {
4415     MOZ_ASSERT(mHasStyle);
4416     return mBottomLayerClip == StyleGeometryBox::Text;
4417   }
4418 
4419   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4420   void PaintWithClip(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
4421                      const DisplayItemClip& aClip) override;
4422   bool CreateWebRenderCommands(
4423       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4424       const StackingContextHelper& aSc,
4425       layers::RenderRootStateManager* aManager,
4426       nsDisplayListBuilder* aDisplayListBuilder) override;
4427   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4428                            bool* aSnap) const override;
4429   Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
4430   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4431                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
4432   bool CanApplyOpacity(WebRenderLayerManager* aManager,
4433                        nsDisplayListBuilder* aBuilder) const override;
4434 
GetOpacity()4435   float GetOpacity() const { return mColor.a; }
4436 
GetBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)4437   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override {
4438     *aSnap = true;
4439     return mBackgroundRect;
4440   }
4441 
CanPaintWithClip(const DisplayItemClip & aClip)4442   bool CanPaintWithClip(const DisplayItemClip& aClip) override {
4443     if (HasBackgroundClipText()) {
4444       return false;
4445     }
4446 
4447     if (aClip.GetRoundedRectCount() > 1) {
4448       return false;
4449     }
4450 
4451     return true;
4452   }
4453 
AllocateGeometry(nsDisplayListBuilder * aBuilder)4454   nsDisplayItemGeometry* AllocateGeometry(
4455       nsDisplayListBuilder* aBuilder) override {
4456     return new nsDisplaySolidColorGeometry(this, aBuilder, mColor.ToABGR());
4457   }
4458 
ComputeInvalidationRegion(nsDisplayListBuilder * aBuilder,const nsDisplayItemGeometry * aGeometry,nsRegion * aInvalidRegion)4459   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4460                                  const nsDisplayItemGeometry* aGeometry,
4461                                  nsRegion* aInvalidRegion) const override {
4462     const nsDisplaySolidColorGeometry* geometry =
4463         static_cast<const nsDisplaySolidColorGeometry*>(aGeometry);
4464 
4465     if (mColor.ToABGR() != geometry->mColor) {
4466       bool dummy;
4467       aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
4468       return;
4469     }
4470     ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
4471   }
4472 
GetDependentFrame()4473   nsIFrame* GetDependentFrame() override { return mDependentFrame; }
4474 
SetDependentFrame(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)4475   void SetDependentFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) {
4476     if (!aBuilder->IsRetainingDisplayList() || mDependentFrame == aFrame) {
4477       return;
4478     }
4479     mDependentFrame = aFrame;
4480     if (aFrame) {
4481       mDependentFrame->AddDisplayItem(this);
4482     }
4483   }
4484 
RemoveFrame(nsIFrame * aFrame)4485   void RemoveFrame(nsIFrame* aFrame) override {
4486     if (aFrame == mDependentFrame) {
4487       mDependentFrame = nullptr;
4488     }
4489 
4490     nsPaintedDisplayItem::RemoveFrame(aFrame);
4491   }
4492 
4493   void WriteDebugInfo(std::stringstream& aStream) override;
4494 
4495   bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
4496 
4497  protected:
4498   const nsRect mBackgroundRect;
4499   const bool mHasStyle;
4500   StyleGeometryBox mBottomLayerClip;
4501   nsIFrame* mDependentFrame;
4502   gfx::sRGBColor mColor;
4503 };
4504 
4505 class nsDisplayTableBackgroundColor : public nsDisplayBackgroundColor {
4506  public:
nsDisplayTableBackgroundColor(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,const nsRect & aBackgroundRect,const ComputedStyle * aBackgroundStyle,const nscolor & aColor,nsIFrame * aAncestorFrame)4507   nsDisplayTableBackgroundColor(nsDisplayListBuilder* aBuilder,
4508                                 nsIFrame* aFrame, const nsRect& aBackgroundRect,
4509                                 const ComputedStyle* aBackgroundStyle,
4510                                 const nscolor& aColor, nsIFrame* aAncestorFrame)
4511       : nsDisplayBackgroundColor(aBuilder, aFrame, aBackgroundRect,
4512                                  aBackgroundStyle, aColor),
4513         mAncestorFrame(aAncestorFrame) {
4514     if (aBuilder->IsRetainingDisplayList()) {
4515       mAncestorFrame->AddDisplayItem(this);
4516     }
4517   }
4518 
~nsDisplayTableBackgroundColor()4519   ~nsDisplayTableBackgroundColor() override {
4520     if (mAncestorFrame) {
4521       mAncestorFrame->RemoveDisplayItem(this);
4522     }
4523   }
4524 
4525   NS_DISPLAY_DECL_NAME("TableBackgroundColor", TYPE_TABLE_BACKGROUND_COLOR)
4526 
FrameForInvalidation()4527   nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
4528 
RemoveFrame(nsIFrame * aFrame)4529   void RemoveFrame(nsIFrame* aFrame) override {
4530     if (aFrame == mAncestorFrame) {
4531       mAncestorFrame = nullptr;
4532       SetDeletedFrame();
4533     }
4534     nsDisplayBackgroundColor::RemoveFrame(aFrame);
4535   }
4536 
CanUseAsyncAnimations(nsDisplayListBuilder * aBuilder)4537   bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override {
4538     return false;
4539   }
4540 
4541  protected:
4542   nsIFrame* mAncestorFrame;
4543 };
4544 
4545 /**
4546  * The standard display item to paint the outer CSS box-shadows of a frame.
4547  */
4548 class nsDisplayBoxShadowOuter final : public nsPaintedDisplayItem {
4549  public:
nsDisplayBoxShadowOuter(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)4550   nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4551       : nsPaintedDisplayItem(aBuilder, aFrame) {
4552     MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
4553     mBounds = GetBoundsInternal();
4554   }
4555 
4556   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowOuter)
4557 
4558   NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
4559 
4560   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4561   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
4562   bool IsInvisibleInRect(const nsRect& aRect) const override;
4563   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4564                                  const nsDisplayItemGeometry* aGeometry,
4565                                  nsRegion* aInvalidRegion) const override;
4566 
CanApplyOpacity(WebRenderLayerManager * aManager,nsDisplayListBuilder * aBuilder)4567   bool CanApplyOpacity(WebRenderLayerManager* aManager,
4568                        nsDisplayListBuilder* aBuilder) const override {
4569     return CanBuildWebRenderDisplayItems();
4570   }
4571 
4572   bool CanBuildWebRenderDisplayItems() const;
4573   bool CreateWebRenderCommands(
4574       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4575       const StackingContextHelper& aSc,
4576       layers::RenderRootStateManager* aManager,
4577       nsDisplayListBuilder* aDisplayListBuilder) override;
4578   nsRect GetBoundsInternal();
4579 
4580  private:
4581   nsRect mBounds;
4582 };
4583 
4584 /**
4585  * The standard display item to paint the inner CSS box-shadows of a frame.
4586  */
4587 class nsDisplayBoxShadowInner : public nsPaintedDisplayItem {
4588  public:
nsDisplayBoxShadowInner(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)4589   nsDisplayBoxShadowInner(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4590       : nsPaintedDisplayItem(aBuilder, aFrame) {
4591     MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);
4592   }
4593 
4594   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowInner)
4595 
4596   NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
4597 
4598   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4599 
AllocateGeometry(nsDisplayListBuilder * aBuilder)4600   nsDisplayItemGeometry* AllocateGeometry(
4601       nsDisplayListBuilder* aBuilder) override {
4602     return new nsDisplayBoxShadowInnerGeometry(this, aBuilder);
4603   }
4604 
ComputeInvalidationRegion(nsDisplayListBuilder * aBuilder,const nsDisplayItemGeometry * aGeometry,nsRegion * aInvalidRegion)4605   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
4606                                  const nsDisplayItemGeometry* aGeometry,
4607                                  nsRegion* aInvalidRegion) const override {
4608     const nsDisplayBoxShadowInnerGeometry* geometry =
4609         static_cast<const nsDisplayBoxShadowInnerGeometry*>(aGeometry);
4610     if (!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())) {
4611       // nsDisplayBoxShadowInner is based around the padding rect, but it can
4612       // touch pixels outside of this. We should invalidate the entire bounds.
4613       bool snap;
4614       aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
4615     }
4616   }
4617 
4618   static bool CanCreateWebRenderCommands(nsDisplayListBuilder* aBuilder,
4619                                          nsIFrame* aFrame,
4620                                          const nsPoint& aReferenceOffset);
4621   static void CreateInsetBoxShadowWebRenderCommands(
4622       wr::DisplayListBuilder& aBuilder, const StackingContextHelper& aSc,
4623       nsRect& aVisibleRect, nsIFrame* aFrame, const nsRect& aBorderRect);
4624   bool CreateWebRenderCommands(
4625       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4626       const StackingContextHelper& aSc,
4627       layers::RenderRootStateManager* aManager,
4628       nsDisplayListBuilder* aDisplayListBuilder) override;
4629 };
4630 
4631 /**
4632  * The standard display item to paint the CSS outline of a frame.
4633  */
4634 class nsDisplayOutline final : public nsPaintedDisplayItem {
4635  public:
nsDisplayOutline(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)4636   nsDisplayOutline(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4637       : nsPaintedDisplayItem(aBuilder, aFrame) {
4638     MOZ_COUNT_CTOR(nsDisplayOutline);
4639   }
4640 
4641   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOutline)
4642 
4643   NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
4644 
MustPaintOnContentSide()4645   bool MustPaintOnContentSide() const override {
4646     MOZ_ASSERT(IsThemedOutline(),
4647                "The only fallback path we have is for themed outlines");
4648     return true;
4649   }
4650 
4651   bool CreateWebRenderCommands(
4652       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4653       const StackingContextHelper& aSc,
4654       layers::RenderRootStateManager* aManager,
4655       nsDisplayListBuilder* aDisplayListBuilder) override;
4656   bool IsInvisibleInRect(const nsRect& aRect) const override;
4657   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
4658   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
4659 
4660  private:
4661   nsRect GetInnerRect() const;
4662   bool IsThemedOutline() const;
4663   bool HasRadius() const;
4664 };
4665 
4666 /**
4667  * A class that lets you receive events within the frame bounds but never
4668  * paints.
4669  */
4670 class nsDisplayEventReceiver final : public nsDisplayItem {
4671  public:
nsDisplayEventReceiver(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)4672   nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4673       : nsDisplayItem(aBuilder, aFrame) {
4674     MOZ_COUNT_CTOR(nsDisplayEventReceiver);
4675   }
4676 
4677   MOZ_COUNTED_DTOR_FINAL(nsDisplayEventReceiver)
4678 
4679   NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER)
4680 
4681   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4682                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) final;
4683 };
4684 
4685 /**
4686  * Similar to nsDisplayEventReceiver in that it is used for hit-testing. However
4687  * this gets built when we're doing widget painting and we need to send the
4688  * compositor some hit-test info for a frame. This is effectively a dummy item
4689  * whose sole purpose is to carry the hit-test info to the compositor.
4690  */
4691 class nsDisplayCompositorHitTestInfo final : public nsDisplayItem {
4692  public:
nsDisplayCompositorHitTestInfo(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)4693   nsDisplayCompositorHitTestInfo(nsDisplayListBuilder* aBuilder,
4694                                  nsIFrame* aFrame)
4695       : nsDisplayItem(aBuilder, aFrame) {
4696     MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);
4697     mHitTestInfo.Initialize(aBuilder, aFrame);
4698     SetHasHitTestInfo();
4699   }
4700 
nsDisplayCompositorHitTestInfo(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,const nsRect & aArea,const gfx::CompositorHitTestInfo & aHitTestFlags)4701   nsDisplayCompositorHitTestInfo(
4702       nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, const nsRect& aArea,
4703       const gfx::CompositorHitTestInfo& aHitTestFlags)
4704       : nsDisplayItem(aBuilder, aFrame) {
4705     MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);
4706     mHitTestInfo.SetAreaAndInfo(aArea, aHitTestFlags);
4707     mHitTestInfo.InitializeScrollTarget(aBuilder);
4708     SetHasHitTestInfo();
4709   }
4710 
4711   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayCompositorHitTestInfo)
4712 
4713   NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO)
4714 
4715   bool CreateWebRenderCommands(
4716       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4717       const StackingContextHelper& aSc,
4718       layers::RenderRootStateManager* aManager,
4719       nsDisplayListBuilder* aDisplayListBuilder) override;
4720 
isInvisible()4721   bool isInvisible() const { return true; }
4722 
4723   int32_t ZIndex() const override;
4724   void SetOverrideZIndex(int32_t aZIndex);
4725 
GetBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)4726   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override {
4727     *aSnap = false;
4728     return nsRect();
4729   }
4730 
GetHitTestInfo()4731   const HitTestInfo& GetHitTestInfo() final { return mHitTestInfo; }
4732 
4733  private:
4734   HitTestInfo mHitTestInfo;
4735   Maybe<int32_t> mOverrideZIndex;
4736 };
4737 
4738 class nsDisplayWrapper;
4739 
4740 /**
4741  * A class that lets you wrap a display list as a display item.
4742  *
4743  * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
4744  * list has many items, it's not clear which one has the 'underlying frame'.
4745  * Thus we force the creator to specify what the underlying frame is. The
4746  * underlying frame should be the root of a stacking context, because sorting
4747  * a list containing this item will not get at the children.
4748  *
4749  * In some cases (e.g., clipping) we want to wrap a list but we don't have a
4750  * particular underlying frame that is a stacking context root. In that case
4751  * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
4752  * detect and handle this case.
4753  */
4754 class nsDisplayWrapList : public nsPaintedDisplayItem {
4755  public:
4756   /**
4757    * Takes all the items from aList and puts them in our list.
4758    */
4759   nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4760                     nsDisplayList* aList);
4761 
4762   nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4763                     nsDisplayItem* aItem);
4764 
4765   nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4766                     nsDisplayList* aList,
4767                     const ActiveScrolledRoot* aActiveScrolledRoot,
4768                     bool aClearClipChain = false);
4769 
nsDisplayWrapList(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)4770   nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
4771       : nsPaintedDisplayItem(aBuilder, aFrame),
4772         mList(aBuilder),
4773         mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot()),
4774         mOverrideZIndex(0),
4775         mHasZIndexOverride(false) {
4776     MOZ_COUNT_CTOR(nsDisplayWrapList);
4777     mBaseBuildingRect = GetBuildingRect();
4778     mListPtr = &mList;
4779     mOriginalClipChain = mClipChain;
4780   }
4781 
4782   nsDisplayWrapList() = delete;
4783 
4784   /**
4785    * A custom copy-constructor that does not copy mList, as this would mutate
4786    * the other item.
4787    */
4788   nsDisplayWrapList(const nsDisplayWrapList& aOther) = delete;
nsDisplayWrapList(nsDisplayListBuilder * aBuilder,const nsDisplayWrapList & aOther)4789   nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
4790                     const nsDisplayWrapList& aOther)
4791       : nsPaintedDisplayItem(aBuilder, aOther),
4792         mList(aBuilder),
4793         mListPtr(&mList),
4794         mFrameActiveScrolledRoot(aOther.mFrameActiveScrolledRoot),
4795         mMergedFrames(aOther.mMergedFrames.Clone()),
4796         mBounds(aOther.mBounds),
4797         mBaseBuildingRect(aOther.mBaseBuildingRect),
4798         mOriginalClipChain(aOther.mClipChain),
4799         mOverrideZIndex(aOther.mOverrideZIndex),
4800         mHasZIndexOverride(aOther.mHasZIndexOverride),
4801         mClearingClipChain(aOther.mClearingClipChain) {
4802     MOZ_COUNT_CTOR(nsDisplayWrapList);
4803   }
4804 
4805   ~nsDisplayWrapList() override;
4806 
AsDisplayWrapList()4807   const nsDisplayWrapList* AsDisplayWrapList() const final { return this; }
AsDisplayWrapList()4808   nsDisplayWrapList* AsDisplayWrapList() final { return this; }
4809 
Destroy(nsDisplayListBuilder * aBuilder)4810   void Destroy(nsDisplayListBuilder* aBuilder) override {
4811     mList.DeleteAll(aBuilder);
4812     nsPaintedDisplayItem::Destroy(aBuilder);
4813   }
4814 
4815   /**
4816    * Creates a new nsDisplayWrapper that holds a pointer to the display list
4817    * owned by the given nsDisplayItem.
4818    */
4819   nsDisplayWrapper* CreateShallowCopy(nsDisplayListBuilder* aBuilder);
4820 
4821   /**
4822    * Call this if the wrapped list is changed.
4823    */
UpdateBounds(nsDisplayListBuilder * aBuilder)4824   void UpdateBounds(nsDisplayListBuilder* aBuilder) override {
4825     // Clear the clip chain up to the asr, but don't store it, so that we'll
4826     // recover it when we reuse the item.
4827     if (mClearingClipChain) {
4828       const DisplayItemClipChain* clip = mOriginalClipChain;
4829       while (clip && ActiveScrolledRoot::IsAncestor(GetActiveScrolledRoot(),
4830                                                     clip->mASR)) {
4831         clip = clip->mParent;
4832       }
4833       SetClipChain(clip, false);
4834     }
4835 
4836     nsRect buildingRect;
4837     mBounds = mListPtr->GetClippedBoundsWithRespectToASR(
4838         aBuilder, mActiveScrolledRoot, &buildingRect);
4839     // The display list may contain content that's visible outside the visible
4840     // rect (i.e. the current dirty rect) passed in when the item was created.
4841     // This happens when the dirty rect has been restricted to the visual
4842     // overflow rect of a frame for some reason (e.g. when setting up dirty
4843     // rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that
4844     // frame contains placeholders for out-of-flows that aren't descendants of
4845     // the frame.
4846     buildingRect.UnionRect(mBaseBuildingRect, buildingRect);
4847     SetBuildingRect(buildingRect);
4848   }
4849 
SetClipChain(const DisplayItemClipChain * aClipChain,bool aStore)4850   void SetClipChain(const DisplayItemClipChain* aClipChain,
4851                     bool aStore) override {
4852     nsDisplayItem::SetClipChain(aClipChain, aStore);
4853 
4854     if (aStore) {
4855       mOriginalClipChain = mClipChain;
4856     }
4857   }
4858 
4859   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
4860                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
4861   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
4862   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
4863                            bool* aSnap) const override;
4864   Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
4865 
4866   /**
4867    * Try to merge with the other item (which is below us in the display
4868    * list). This gets used by nsDisplayClip to coalesce clipping operations
4869    * (optimization), by nsDisplayOpacity to merge rendering for the same
4870    * content element into a single opacity group (correctness), and will be
4871    * used by nsDisplayOutline to merge multiple outlines for the same element
4872    * (also for correctness).
4873    */
Merge(const nsDisplayItem * aItem)4874   virtual void Merge(const nsDisplayItem* aItem) {
4875     MOZ_ASSERT(CanMerge(aItem));
4876     MOZ_ASSERT(Frame() != aItem->Frame());
4877     MergeFromTrackingMergedFrames(static_cast<const nsDisplayWrapList*>(aItem));
4878   }
4879 
4880   /**
4881    * Returns the underlying frames of all display items that have been
4882    * merged into this one (excluding this item's own underlying frame)
4883    * to aFrames.
4884    */
GetMergedFrames()4885   const nsTArray<nsIFrame*>& GetMergedFrames() const { return mMergedFrames; }
4886 
HasMergedFrames()4887   bool HasMergedFrames() const { return !mMergedFrames.IsEmpty(); }
4888 
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)4889   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
4890     return true;
4891   }
4892 
IsInvalid(nsRect & aRect)4893   bool IsInvalid(nsRect& aRect) const override {
4894     if (mFrame->IsInvalid(aRect) && aRect.IsEmpty()) {
4895       return true;
4896     }
4897     nsRect temp;
4898     for (uint32_t i = 0; i < mMergedFrames.Length(); i++) {
4899       if (mMergedFrames[i]->IsInvalid(temp) && temp.IsEmpty()) {
4900         aRect.SetEmpty();
4901         return true;
4902       }
4903       aRect = aRect.Union(temp);
4904     }
4905     aRect += ToReferenceFrame();
4906     return !aRect.IsEmpty();
4907   }
4908 
4909   nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override;
4910 
GetSameCoordinateSystemChildren()4911   RetainedDisplayList* GetSameCoordinateSystemChildren() const override {
4912     return mListPtr;
4913   }
4914 
GetChildren()4915   RetainedDisplayList* GetChildren() const override { return mListPtr; }
4916 
ZIndex()4917   int32_t ZIndex() const override {
4918     return (mHasZIndexOverride) ? mOverrideZIndex
4919                                 : nsPaintedDisplayItem::ZIndex();
4920   }
4921 
SetOverrideZIndex(int32_t aZIndex)4922   void SetOverrideZIndex(int32_t aZIndex) {
4923     mHasZIndexOverride = true;
4924     mOverrideZIndex = aZIndex;
4925   }
4926 
4927   /**
4928    * This creates a copy of this item, but wrapping aItem instead of
4929    * our existing list. Only gets called if this item returned nullptr
4930    * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
4931    * GetUnderlyingFrame().
4932    */
WrapWithClone(nsDisplayListBuilder * aBuilder,nsDisplayItem * aItem)4933   nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
4934                                    nsDisplayItem* aItem) {
4935     MOZ_ASSERT_UNREACHABLE("We never returned nullptr for GetUnderlyingFrame!");
4936     return nullptr;
4937   }
4938 
CreateWebRenderCommands(wr::DisplayListBuilder & aBuilder,wr::IpcResourceUpdateQueue & aResources,const StackingContextHelper & aSc,layers::RenderRootStateManager * aManager,nsDisplayListBuilder * aDisplayListBuilder)4939   bool CreateWebRenderCommands(
4940       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4941       const StackingContextHelper& aSc,
4942       layers::RenderRootStateManager* aManager,
4943       nsDisplayListBuilder* aDisplayListBuilder) override {
4944     return CreateWebRenderCommandsNewClipListOption(
4945         aBuilder, aResources, aSc, aManager, aDisplayListBuilder, true);
4946   }
4947 
4948   // Same as the above but with the option to pass the aNewClipList argument to
4949   // WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList.
4950   bool CreateWebRenderCommandsNewClipListOption(
4951       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
4952       const StackingContextHelper& aSc,
4953       layers::RenderRootStateManager* aManager,
4954       nsDisplayListBuilder* aDisplayListBuilder, bool aNewClipList);
4955 
GetFrameActiveScrolledRoot()4956   const ActiveScrolledRoot* GetFrameActiveScrolledRoot() {
4957     return mFrameActiveScrolledRoot;
4958   }
4959 
4960  protected:
MergeFromTrackingMergedFrames(const nsDisplayWrapList * aOther)4961   void MergeFromTrackingMergedFrames(const nsDisplayWrapList* aOther) {
4962     mBounds.UnionRect(mBounds, aOther->mBounds);
4963     nsRect buildingRect;
4964     buildingRect.UnionRect(GetBuildingRect(), aOther->GetBuildingRect());
4965     SetBuildingRect(buildingRect);
4966     mMergedFrames.AppendElement(aOther->mFrame);
4967     mMergedFrames.AppendElements(aOther->mMergedFrames.Clone());
4968   }
4969 
4970   RetainedDisplayList mList;
4971   RetainedDisplayList* mListPtr;
4972   // The active scrolled root for the frame that created this
4973   // wrap list.
4974   RefPtr<const ActiveScrolledRoot> mFrameActiveScrolledRoot;
4975   // The frames from items that have been merged into this item, excluding
4976   // this item's own frame.
4977   nsTArray<nsIFrame*> mMergedFrames;
4978   nsRect mBounds;
4979   // Displaylist building rect contributed by this display item itself.
4980   // Our mBuildingRect may include the visible areas of children.
4981   nsRect mBaseBuildingRect;
4982   RefPtr<const DisplayItemClipChain> mOriginalClipChain;
4983   int32_t mOverrideZIndex;
4984   bool mHasZIndexOverride;
4985   bool mClearingClipChain = false;
4986 };
4987 
4988 class nsDisplayWrapper : public nsDisplayWrapList {
4989  public:
4990   NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
4991 
4992   nsDisplayWrapper(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
4993                    nsDisplayList* aList,
4994                    const ActiveScrolledRoot* aActiveScrolledRoot,
4995                    bool aClearClipChain = false)
nsDisplayWrapList(aBuilder,aFrame,aList,aActiveScrolledRoot,aClearClipChain)4996       : nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot,
4997                           aClearClipChain) {}
4998 
4999   nsDisplayWrapper(const nsDisplayWrapper& aOther) = delete;
nsDisplayWrapper(nsDisplayListBuilder * aBuilder,const nsDisplayWrapList & aOther)5000   nsDisplayWrapper(nsDisplayListBuilder* aBuilder,
5001                    const nsDisplayWrapList& aOther)
5002       : nsDisplayWrapList(aBuilder, aOther) {}
5003 
5004   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
5005 
5006  private:
5007   NS_DISPLAY_ALLOW_CLONING()
5008   friend class nsDisplayListBuilder;
5009   friend class nsDisplayWrapList;
5010 };
5011 
5012 /**
5013  * We call WrapDisplayList on the in-flow lists: BorderBackground(),
5014  * BlockBorderBackgrounds() and Content().
5015  * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
5016  * and Floats(). This is done to support special wrapping processing for frames
5017  * that may not be in-flow descendants of the current frame.
5018  */
5019 class nsDisplayItemWrapper {
5020  public:
5021   // This is never instantiated directly (it has pure virtual methods), so no
5022   // need to count constructors and destructors.
5023 
WrapBorderBackground()5024   bool WrapBorderBackground() { return true; }
5025   virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
5026                                   nsIFrame* aFrame, nsDisplayList* aList) = 0;
5027   virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
5028                                   nsDisplayItem* aItem) = 0;
5029 
5030   nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5031                      const nsDisplayListSet& aIn, const nsDisplayListSet& aOut);
5032   nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5033                             const nsDisplayListSet& aLists);
5034 
5035  protected:
5036   nsDisplayItemWrapper() = default;
5037 };
5038 
5039 /**
5040  * The standard display item to paint a stacking context with translucency
5041  * set by the stacking context root frame's 'opacity' style.
5042  */
5043 class nsDisplayOpacity : public nsDisplayWrapList {
5044  public:
5045   nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5046                    nsDisplayList* aList,
5047                    const ActiveScrolledRoot* aActiveScrolledRoot,
5048                    bool aForEventsOnly, bool aNeedsActiveLayer);
5049 
nsDisplayOpacity(nsDisplayListBuilder * aBuilder,const nsDisplayOpacity & aOther)5050   nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
5051                    const nsDisplayOpacity& aOther)
5052       : nsDisplayWrapList(aBuilder, aOther),
5053         mOpacity(aOther.mOpacity),
5054         mForEventsOnly(aOther.mForEventsOnly),
5055         mNeedsActiveLayer(aOther.mNeedsActiveLayer),
5056         mChildOpacityState(ChildOpacityState::Unknown) {
5057     MOZ_COUNT_CTOR(nsDisplayOpacity);
5058     // We should not try to merge flattened opacities.
5059     MOZ_ASSERT(aOther.mChildOpacityState != ChildOpacityState::Applied);
5060   }
5061 
5062   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
5063                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
5064 
5065   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOpacity)
5066 
5067   NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
5068 
InvalidateCachedChildInfo(nsDisplayListBuilder * aBuilder)5069   void InvalidateCachedChildInfo(nsDisplayListBuilder* aBuilder) override {
5070     mChildOpacityState = ChildOpacityState::Unknown;
5071   }
5072 
5073   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
5074                            bool* aSnap) const override;
5075   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
5076 
CanMerge(const nsDisplayItem * aItem)5077   bool CanMerge(const nsDisplayItem* aItem) const override {
5078     // items for the same content element should be merged into a single
5079     // compositing group
5080     // aItem->GetUnderlyingFrame() returns non-null because it's
5081     // nsDisplayOpacity
5082     return HasDifferentFrame(aItem) && HasSameTypeAndClip(aItem) &&
5083            HasSameContent(aItem);
5084   }
5085 
AllocateGeometry(nsDisplayListBuilder * aBuilder)5086   nsDisplayItemGeometry* AllocateGeometry(
5087       nsDisplayListBuilder* aBuilder) override {
5088     return new nsDisplayOpacityGeometry(this, aBuilder, mOpacity);
5089   }
5090 
5091   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
5092                                  const nsDisplayItemGeometry* aGeometry,
5093                                  nsRegion* aInvalidRegion) const override;
5094 
IsInvalid(nsRect & aRect)5095   bool IsInvalid(nsRect& aRect) const override {
5096     if (mForEventsOnly) {
5097       return false;
5098     }
5099     return nsDisplayWrapList::IsInvalid(aRect);
5100   }
5101   bool CanApplyOpacity(WebRenderLayerManager* aManager,
5102                        nsDisplayListBuilder* aBuilder) const override;
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)5103   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5104     return false;
5105   }
5106 
5107   bool CanApplyOpacityToChildren(WebRenderLayerManager* aManager,
5108                                  nsDisplayListBuilder* aBuilder,
5109                                  float aInheritedOpacity);
5110 
NeedsGeometryUpdates()5111   bool NeedsGeometryUpdates() const override {
5112     // For flattened nsDisplayOpacity items, ComputeInvalidationRegion() only
5113     // handles invalidation for changed |mOpacity|. In order to keep track of
5114     // the current bounds of the item for invalidation, nsDisplayOpacityGeometry
5115     // for the corresponding DisplayItemData needs to be updated, even if the
5116     // reported invalidation region is empty.
5117     return mChildOpacityState == ChildOpacityState::Deferred;
5118   }
5119 
5120   /**
5121    * Returns true if ShouldFlattenAway() applied opacity to children.
5122    */
OpacityAppliedToChildren()5123   bool OpacityAppliedToChildren() const {
5124     return mChildOpacityState == ChildOpacityState::Applied;
5125   }
5126 
5127   static bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder,
5128                                nsIFrame* aFrame);
5129   void WriteDebugInfo(std::stringstream& aStream) override;
5130   bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
5131   bool CreateWebRenderCommands(
5132       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
5133       const StackingContextHelper& aSc,
5134       layers::RenderRootStateManager* aManager,
5135       nsDisplayListBuilder* aDisplayListBuilder) override;
5136 
GetOpacity()5137   float GetOpacity() const { return mOpacity; }
5138 
CreatesStackingContextHelper()5139   bool CreatesStackingContextHelper() override { return true; }
5140 
5141  private:
5142   NS_DISPLAY_ALLOW_CLONING()
5143 
5144   bool CanApplyToChildren(WebRenderLayerManager* aManager,
5145                           nsDisplayListBuilder* aBuilder);
5146   bool ApplyToMask();
5147 
5148   float mOpacity;
5149   bool mForEventsOnly : 1;
5150   enum class ChildOpacityState : uint8_t {
5151     // Our child list has changed since the last time ApplyToChildren was
5152     // called.
5153     Unknown,
5154     // Our children defer opacity handling to us.
5155     Deferred,
5156     // Opacity is applied to our children.
5157     Applied
5158   };
5159   bool mNeedsActiveLayer : 1;
5160 #ifndef __GNUC__
5161   ChildOpacityState mChildOpacityState : 2;
5162 #else
5163   ChildOpacityState mChildOpacityState;
5164 #endif
5165 };
5166 
5167 class nsDisplayBlendMode : public nsDisplayWrapList {
5168  public:
5169   nsDisplayBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5170                      nsDisplayList* aList, StyleBlend aBlendMode,
5171                      const ActiveScrolledRoot* aActiveScrolledRoot,
5172                      const bool aIsForBackground);
nsDisplayBlendMode(nsDisplayListBuilder * aBuilder,const nsDisplayBlendMode & aOther)5173   nsDisplayBlendMode(nsDisplayListBuilder* aBuilder,
5174                      const nsDisplayBlendMode& aOther)
5175       : nsDisplayWrapList(aBuilder, aOther),
5176         mBlendMode(aOther.mBlendMode),
5177         mIsForBackground(aOther.mIsForBackground) {
5178     MOZ_COUNT_CTOR(nsDisplayBlendMode);
5179   }
5180 
5181   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendMode)
5182 
5183   NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE)
5184 
5185   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
5186                            bool* aSnap) const override;
ComputeInvalidationRegion(nsDisplayListBuilder * aBuilder,const nsDisplayItemGeometry * aGeometry,nsRegion * aInvalidRegion)5187   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
5188                                  const nsDisplayItemGeometry* aGeometry,
5189                                  nsRegion* aInvalidRegion) const override {
5190     // We don't need to compute an invalidation region since we have
5191     // LayerTreeInvalidation
5192   }
5193 
5194   bool CreateWebRenderCommands(
5195       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
5196       const StackingContextHelper& aSc,
5197       layers::RenderRootStateManager* aManager,
5198       nsDisplayListBuilder* aDisplayListBuilder) override;
5199   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
5200 
5201   bool CanMerge(const nsDisplayItem* aItem) const override;
5202 
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)5203   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5204     return false;
5205   }
5206 
5207   gfx::CompositionOp BlendMode();
5208 
CreatesStackingContextHelper()5209   bool CreatesStackingContextHelper() override { return true; }
5210 
5211  protected:
5212   StyleBlend mBlendMode;
5213   bool mIsForBackground;
5214 
5215  private:
5216   NS_DISPLAY_ALLOW_CLONING()
5217 };
5218 
5219 class nsDisplayTableBlendMode : public nsDisplayBlendMode {
5220  public:
nsDisplayTableBlendMode(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,nsDisplayList * aList,StyleBlend aBlendMode,const ActiveScrolledRoot * aActiveScrolledRoot,nsIFrame * aAncestorFrame,const bool aIsForBackground)5221   nsDisplayTableBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5222                           nsDisplayList* aList, StyleBlend aBlendMode,
5223                           const ActiveScrolledRoot* aActiveScrolledRoot,
5224                           nsIFrame* aAncestorFrame, const bool aIsForBackground)
5225       : nsDisplayBlendMode(aBuilder, aFrame, aList, aBlendMode,
5226                            aActiveScrolledRoot, aIsForBackground),
5227         mAncestorFrame(aAncestorFrame) {
5228     if (aBuilder->IsRetainingDisplayList()) {
5229       mAncestorFrame->AddDisplayItem(this);
5230     }
5231   }
5232 
nsDisplayTableBlendMode(nsDisplayListBuilder * aBuilder,const nsDisplayTableBlendMode & aOther)5233   nsDisplayTableBlendMode(nsDisplayListBuilder* aBuilder,
5234                           const nsDisplayTableBlendMode& aOther)
5235       : nsDisplayBlendMode(aBuilder, aOther),
5236         mAncestorFrame(aOther.mAncestorFrame) {
5237     if (aBuilder->IsRetainingDisplayList()) {
5238       mAncestorFrame->AddDisplayItem(this);
5239     }
5240   }
5241 
~nsDisplayTableBlendMode()5242   ~nsDisplayTableBlendMode() override {
5243     if (mAncestorFrame) {
5244       mAncestorFrame->RemoveDisplayItem(this);
5245     }
5246   }
5247 
5248   NS_DISPLAY_DECL_NAME("TableBlendMode", TYPE_TABLE_BLEND_MODE)
5249 
FrameForInvalidation()5250   nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
5251 
RemoveFrame(nsIFrame * aFrame)5252   void RemoveFrame(nsIFrame* aFrame) override {
5253     if (aFrame == mAncestorFrame) {
5254       mAncestorFrame = nullptr;
5255       SetDeletedFrame();
5256     }
5257     nsDisplayBlendMode::RemoveFrame(aFrame);
5258   }
5259 
5260  protected:
5261   nsIFrame* mAncestorFrame;
5262 
5263  private:
5264   NS_DISPLAY_ALLOW_CLONING()
5265 };
5266 
5267 class nsDisplayBlendContainer : public nsDisplayWrapList {
5268  public:
5269   static nsDisplayBlendContainer* CreateForMixBlendMode(
5270       nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList,
5271       const ActiveScrolledRoot* aActiveScrolledRoot);
5272 
5273   static nsDisplayBlendContainer* CreateForBackgroundBlendMode(
5274       nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5275       nsIFrame* aSecondaryFrame, nsDisplayList* aList,
5276       const ActiveScrolledRoot* aActiveScrolledRoot);
5277 
5278   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendContainer)
5279 
5280   NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER)
5281 
5282   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
5283   bool CreateWebRenderCommands(
5284       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
5285       const StackingContextHelper& aSc,
5286       layers::RenderRootStateManager* aManager,
5287       nsDisplayListBuilder* aDisplayListBuilder) override;
5288 
CanMerge(const nsDisplayItem * aItem)5289   bool CanMerge(const nsDisplayItem* aItem) const override {
5290     // Items for the same content element should be merged into a single
5291     // compositing group.
5292     return HasDifferentFrame(aItem) && HasSameTypeAndClip(aItem) &&
5293            HasSameContent(aItem) &&
5294            mIsForBackground ==
5295                static_cast<const nsDisplayBlendContainer*>(aItem)
5296                    ->mIsForBackground;
5297   }
5298 
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)5299   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5300     return false;
5301   }
5302 
CreatesStackingContextHelper()5303   bool CreatesStackingContextHelper() override { return true; }
5304 
5305  protected:
5306   nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5307                           nsDisplayList* aList,
5308                           const ActiveScrolledRoot* aActiveScrolledRoot,
5309                           bool aIsForBackground);
nsDisplayBlendContainer(nsDisplayListBuilder * aBuilder,const nsDisplayBlendContainer & aOther)5310   nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder,
5311                           const nsDisplayBlendContainer& aOther)
5312       : nsDisplayWrapList(aBuilder, aOther),
5313         mIsForBackground(aOther.mIsForBackground) {
5314     MOZ_COUNT_CTOR(nsDisplayBlendContainer);
5315   }
5316 
5317   // Used to distinguish containers created at building stacking
5318   // context or appending background.
5319   bool mIsForBackground;
5320 
5321  private:
5322   NS_DISPLAY_ALLOW_CLONING()
5323 };
5324 
5325 class nsDisplayTableBlendContainer : public nsDisplayBlendContainer {
5326  public:
5327   NS_DISPLAY_DECL_NAME("TableBlendContainer", TYPE_TABLE_BLEND_CONTAINER)
5328 
FrameForInvalidation()5329   nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
5330 
RemoveFrame(nsIFrame * aFrame)5331   void RemoveFrame(nsIFrame* aFrame) override {
5332     if (aFrame == mAncestorFrame) {
5333       mAncestorFrame = nullptr;
5334       SetDeletedFrame();
5335     }
5336     nsDisplayBlendContainer::RemoveFrame(aFrame);
5337   }
5338 
5339  protected:
nsDisplayTableBlendContainer(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,nsDisplayList * aList,const ActiveScrolledRoot * aActiveScrolledRoot,bool aIsForBackground,nsIFrame * aAncestorFrame)5340   nsDisplayTableBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5341                                nsDisplayList* aList,
5342                                const ActiveScrolledRoot* aActiveScrolledRoot,
5343                                bool aIsForBackground, nsIFrame* aAncestorFrame)
5344       : nsDisplayBlendContainer(aBuilder, aFrame, aList, aActiveScrolledRoot,
5345                                 aIsForBackground),
5346         mAncestorFrame(aAncestorFrame) {
5347     if (aBuilder->IsRetainingDisplayList()) {
5348       mAncestorFrame->AddDisplayItem(this);
5349     }
5350   }
5351 
nsDisplayTableBlendContainer(nsDisplayListBuilder * aBuilder,const nsDisplayTableBlendContainer & aOther)5352   nsDisplayTableBlendContainer(nsDisplayListBuilder* aBuilder,
5353                                const nsDisplayTableBlendContainer& aOther)
5354       : nsDisplayBlendContainer(aBuilder, aOther),
5355         mAncestorFrame(aOther.mAncestorFrame) {}
5356 
~nsDisplayTableBlendContainer()5357   ~nsDisplayTableBlendContainer() override {
5358     if (mAncestorFrame) {
5359       mAncestorFrame->RemoveDisplayItem(this);
5360     }
5361   }
5362 
5363   nsIFrame* mAncestorFrame;
5364 
5365  private:
5366   NS_DISPLAY_ALLOW_CLONING()
5367 };
5368 
5369 /**
5370  * nsDisplayOwnLayer constructor flags. If we nest this class inside
5371  * nsDisplayOwnLayer then we can't forward-declare it up at the top of this
5372  * file and that makes it hard to use in all the places that we need to use it.
5373  */
5374 enum class nsDisplayOwnLayerFlags {
5375   None = 0,
5376   GenerateSubdocInvalidations = 1 << 0,
5377   GenerateScrollableLayer = 1 << 1,
5378 };
5379 
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsDisplayOwnLayerFlags)5380 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsDisplayOwnLayerFlags)
5381 
5382 /**
5383  * A display item that has no purpose but to ensure its contents get
5384  * their own layer.
5385  */
5386 class nsDisplayOwnLayer : public nsDisplayWrapList {
5387  public:
5388   enum OwnLayerType {
5389     OwnLayerForTransformWithRoundedClip,
5390     OwnLayerForStackingContext,
5391     OwnLayerForImageBoxFrame,
5392     OwnLayerForScrollbar,
5393     OwnLayerForScrollThumb,
5394     OwnLayerForSubdoc,
5395     OwnLayerForBoxFrame
5396   };
5397 
5398   /**
5399    * @param aFlags eGenerateSubdocInvalidations :
5400    * Add UserData to the created ContainerLayer, so that invalidations
5401    * for this layer are send to our nsPresContext.
5402    * eGenerateScrollableLayer : only valid on nsDisplaySubDocument (and
5403    * subclasses), indicates this layer is to be a scrollable layer, so call
5404    * ComputeFrameMetrics, etc.
5405    * @param aScrollTarget when eVerticalScrollbar or eHorizontalScrollbar
5406    * is set in the flags, this parameter should be the ViewID of the
5407    * scrollable content this scrollbar is for.
5408    */
5409   nsDisplayOwnLayer(
5410       nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList,
5411       const ActiveScrolledRoot* aActiveScrolledRoot,
5412       nsDisplayOwnLayerFlags aFlags = nsDisplayOwnLayerFlags::None,
5413       const layers::ScrollbarData& aScrollbarData = layers::ScrollbarData{},
5414       bool aForceActive = true, bool aClearClipChain = false);
5415 
5416   nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
5417                     const nsDisplayOwnLayer& aOther)
5418       : nsDisplayWrapList(aBuilder, aOther),
5419         mFlags(aOther.mFlags),
5420         mScrollbarData(aOther.mScrollbarData),
5421         mForceActive(aOther.mForceActive),
5422         mWrAnimationId(aOther.mWrAnimationId) {
5423     MOZ_COUNT_CTOR(nsDisplayOwnLayer);
5424   }
5425 
5426   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOwnLayer)
5427 
5428   NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
5429 
5430   bool CreateWebRenderCommands(
5431       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
5432       const StackingContextHelper& aSc,
5433       layers::RenderRootStateManager* aManager,
5434       nsDisplayListBuilder* aDisplayListBuilder) override;
5435   bool UpdateScrollData(layers::WebRenderScrollData* aData,
5436                         layers::WebRenderLayerScrollData* aLayerData) override;
5437   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
5438     GetChildren()->Paint(aBuilder, aCtx,
5439                          mFrame->PresContext()->AppUnitsPerDevPixel());
5440   }
5441 
5442   bool CanMerge(const nsDisplayItem* aItem) const override {
5443     // Don't allow merging, each sublist must have its own layer
5444     return false;
5445   }
5446 
5447   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5448     return false;
5449   }
5450 
5451   void WriteDebugInfo(std::stringstream& aStream) override;
5452   nsDisplayOwnLayerFlags GetFlags() { return mFlags; }
5453   bool IsScrollThumbLayer() const;
5454   bool IsScrollbarContainer() const;
5455   bool IsRootScrollbarContainer() const;
5456   bool IsZoomingLayer() const;
5457   bool IsFixedPositionLayer() const;
5458   bool IsStickyPositionLayer() const;
5459   bool HasDynamicToolbar() const;
5460 
5461   bool CreatesStackingContextHelper() override { return true; }
5462 
5463  protected:
5464   nsDisplayOwnLayerFlags mFlags;
5465 
5466   /**
5467    * If this nsDisplayOwnLayer represents a scroll thumb layer or a
5468    * scrollbar container layer, mScrollbarData stores information
5469    * about the scrollbar. Otherwise, mScrollbarData will be
5470    * default-constructed (in particular with mDirection == Nothing())
5471    * and can be ignored.
5472    */
5473   layers::ScrollbarData mScrollbarData;
5474   bool mForceActive;
5475   uint64_t mWrAnimationId;
5476 };
5477 
5478 /**
5479  * A display item for subdocuments. This is more or less the same as
5480  * nsDisplayOwnLayer, except that it always populates the FrameMetrics instance
5481  * on the ContainerLayer it builds.
5482  */
5483 class nsDisplaySubDocument : public nsDisplayOwnLayer {
5484  public:
5485   nsDisplaySubDocument(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5486                        nsSubDocumentFrame* aSubDocFrame, nsDisplayList* aList,
5487                        nsDisplayOwnLayerFlags aFlags);
5488   ~nsDisplaySubDocument() override;
5489 
5490   NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT)
5491 
5492   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
5493 
SubDocumentFrame()5494   virtual nsSubDocumentFrame* SubDocumentFrame() { return mSubDocFrame; }
5495 
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)5496   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5497     return mShouldFlatten;
5498   }
5499 
SetShouldFlattenAway(bool aShouldFlatten)5500   void SetShouldFlattenAway(bool aShouldFlatten) {
5501     mShouldFlatten = aShouldFlatten;
5502   }
5503 
5504   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
5505                            bool* aSnap) const override;
5506 
5507   nsIFrame* FrameForInvalidation() const override;
5508   void RemoveFrame(nsIFrame* aFrame) override;
5509 
5510   void Disown();
5511 
5512  protected:
5513   ViewID mScrollParentId;
5514   bool mForceDispatchToContentRegion{};
5515   bool mShouldFlatten;
5516   nsSubDocumentFrame* mSubDocFrame;
5517 };
5518 
5519 /**
5520  * A display item used to represent sticky position elements. The contents
5521  * gets its own layer and creates a stacking context, and the layer will have
5522  * position-related metadata set on it.
5523  */
5524 class nsDisplayStickyPosition : public nsDisplayOwnLayer {
5525  public:
5526   nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5527                           nsDisplayList* aList,
5528                           const ActiveScrolledRoot* aActiveScrolledRoot,
5529                           const ActiveScrolledRoot* aContainerASR,
5530                           bool aClippedToDisplayPort);
nsDisplayStickyPosition(nsDisplayListBuilder * aBuilder,const nsDisplayStickyPosition & aOther)5531   nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder,
5532                           const nsDisplayStickyPosition& aOther)
5533       : nsDisplayOwnLayer(aBuilder, aOther),
5534         mContainerASR(aOther.mContainerASR),
5535         mClippedToDisplayPort(aOther.mClippedToDisplayPort),
5536         mShouldFlatten(false) {
5537     MOZ_COUNT_CTOR(nsDisplayStickyPosition);
5538   }
5539 
MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayStickyPosition)5540   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayStickyPosition)
5541 
5542   const DisplayItemClip& GetClip() const override {
5543     return DisplayItemClip::NoClip();
5544   }
IsClippedToDisplayPort()5545   bool IsClippedToDisplayPort() const { return mClippedToDisplayPort; }
5546 
5547   NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION)
Paint(nsDisplayListBuilder * aBuilder,gfxContext * aCtx)5548   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
5549     GetChildren()->Paint(aBuilder, aCtx,
5550                          mFrame->PresContext()->AppUnitsPerDevPixel());
5551   }
5552 
5553   bool CreateWebRenderCommands(
5554       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
5555       const StackingContextHelper& aSc,
5556       layers::RenderRootStateManager* aManager,
5557       nsDisplayListBuilder* aDisplayListBuilder) override;
5558 
5559   bool UpdateScrollData(layers::WebRenderScrollData* aData,
5560                         layers::WebRenderLayerScrollData* aLayerData) override;
5561 
GetContainerASR()5562   const ActiveScrolledRoot* GetContainerASR() const { return mContainerASR; }
5563 
CreatesStackingContextHelper()5564   bool CreatesStackingContextHelper() override { return true; }
5565 
CanMoveAsync()5566   bool CanMoveAsync() override { return true; }
5567 
SetShouldFlatten(bool aShouldFlatten)5568   void SetShouldFlatten(bool aShouldFlatten) {
5569     mShouldFlatten = aShouldFlatten;
5570   }
5571 
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)5572   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) final {
5573     return mShouldFlatten;
5574   }
5575 
5576  private:
5577   NS_DISPLAY_ALLOW_CLONING()
5578 
5579   void CalculateLayerScrollRanges(StickyScrollContainer* aStickyScrollContainer,
5580                                   float aAppUnitsPerDevPixel, float aScaleX,
5581                                   float aScaleY,
5582                                   LayerRectAbsolute& aStickyOuter,
5583                                   LayerRectAbsolute& aStickyInner);
5584 
5585   StickyScrollContainer* GetStickyScrollContainer();
5586 
5587   // This stores the ASR that this sticky container item would have assuming it
5588   // has no fixed descendants. This may be the same as the ASR returned by
5589   // GetActiveScrolledRoot(), or it may be a descendant of that.
5590   RefPtr<const ActiveScrolledRoot> mContainerASR;
5591   // This flag tracks if this sticky item is just clipped to the enclosing
5592   // scrollframe's displayport, or if there are additional clips in play. In
5593   // the former case, we can skip setting the displayport clip as the scrolled-
5594   // clip of the corresponding layer. This allows sticky items to remain
5595   // unclipped when the enclosing scrollframe is scrolled past the displayport.
5596   // i.e. when the rest of the scrollframe checkerboards, the sticky item will
5597   // not. This makes sense to do because the sticky item has abnormal scrolling
5598   // behavior and may still be visible even if the rest of the scrollframe is
5599   // checkerboarded. Note that the sticky item will still be subject to the
5600   // scrollport clip.
5601   bool mClippedToDisplayPort;
5602 
5603   // True if this item should be flattened away.
5604   bool mShouldFlatten;
5605 };
5606 
5607 class nsDisplayFixedPosition : public nsDisplayOwnLayer {
5608  public:
5609   nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5610                          nsDisplayList* aList,
5611                          const ActiveScrolledRoot* aActiveScrolledRoot,
5612                          const ActiveScrolledRoot* aScrollTargetASR);
nsDisplayFixedPosition(nsDisplayListBuilder * aBuilder,const nsDisplayFixedPosition & aOther)5613   nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder,
5614                          const nsDisplayFixedPosition& aOther)
5615       : nsDisplayOwnLayer(aBuilder, aOther),
5616         mScrollTargetASR(aOther.mScrollTargetASR),
5617         mIsFixedBackground(aOther.mIsFixedBackground) {
5618     MOZ_COUNT_CTOR(nsDisplayFixedPosition);
5619   }
5620 
5621   static nsDisplayFixedPosition* CreateForFixedBackground(
5622       nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5623       nsIFrame* aSecondaryFrame, nsDisplayBackgroundImage* aImage,
5624       const uint16_t aIndex, const ActiveScrolledRoot* aScrollTargetASR);
5625 
5626   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFixedPosition)
5627 
5628   NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION)
5629 
Paint(nsDisplayListBuilder * aBuilder,gfxContext * aCtx)5630   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
5631     GetChildren()->Paint(aBuilder, aCtx,
5632                          mFrame->PresContext()->AppUnitsPerDevPixel());
5633   }
5634 
ShouldFixToViewport(nsDisplayListBuilder * aBuilder)5635   bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const override {
5636     return mIsFixedBackground;
5637   }
5638 
5639   bool CreateWebRenderCommands(
5640       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
5641       const StackingContextHelper& aSc,
5642       layers::RenderRootStateManager* aManager,
5643       nsDisplayListBuilder* aDisplayListBuilder) override;
5644   bool UpdateScrollData(layers::WebRenderScrollData* aData,
5645                         layers::WebRenderLayerScrollData* aLayerData) override;
5646   void WriteDebugInfo(std::stringstream& aStream) override;
5647 
5648  protected:
5649   // For background-attachment:fixed
5650   nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5651                          nsDisplayList* aList,
5652                          const ActiveScrolledRoot* aScrollTargetASR);
5653   ViewID GetScrollTargetId();
5654 
5655   RefPtr<const ActiveScrolledRoot> mScrollTargetASR;
5656   bool mIsFixedBackground;
5657 
5658  private:
5659   NS_DISPLAY_ALLOW_CLONING()
5660 };
5661 
5662 class nsDisplayTableFixedPosition : public nsDisplayFixedPosition {
5663  public:
5664   NS_DISPLAY_DECL_NAME("TableFixedPosition", TYPE_TABLE_FIXED_POSITION)
5665 
FrameForInvalidation()5666   nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
5667 
RemoveFrame(nsIFrame * aFrame)5668   void RemoveFrame(nsIFrame* aFrame) override {
5669     if (aFrame == mAncestorFrame) {
5670       mAncestorFrame = nullptr;
5671       SetDeletedFrame();
5672     }
5673     nsDisplayFixedPosition::RemoveFrame(aFrame);
5674   }
5675 
5676  protected:
5677   nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5678                               nsDisplayList* aList, nsIFrame* aAncestorFrame,
5679                               const ActiveScrolledRoot* aScrollTargetASR);
5680 
nsDisplayTableFixedPosition(nsDisplayListBuilder * aBuilder,const nsDisplayTableFixedPosition & aOther)5681   nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder,
5682                               const nsDisplayTableFixedPosition& aOther)
5683       : nsDisplayFixedPosition(aBuilder, aOther),
5684         mAncestorFrame(aOther.mAncestorFrame) {}
5685 
~nsDisplayTableFixedPosition()5686   ~nsDisplayTableFixedPosition() override {
5687     if (mAncestorFrame) {
5688       mAncestorFrame->RemoveDisplayItem(this);
5689     }
5690   }
5691 
5692   nsIFrame* mAncestorFrame;
5693 
5694  private:
5695   NS_DISPLAY_ALLOW_CLONING()
5696 };
5697 
5698 /**
5699  * This creates an empty scrollable layer. It has no child layers.
5700  * It is used to record the existence of a scrollable frame in the layer
5701  * tree.
5702  */
5703 class nsDisplayScrollInfoLayer : public nsDisplayWrapList {
5704  public:
5705   nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder,
5706                            nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame,
5707                            const gfx::CompositorHitTestInfo& aHitInfo,
5708                            const nsRect& aHitArea);
5709 
5710   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayScrollInfoLayer)
5711 
5712   NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER)
5713 
GetOpaqueRegion(nsDisplayListBuilder * aBuilder,bool * aSnap)5714   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
5715                            bool* aSnap) const override {
5716     *aSnap = false;
5717     return nsRegion();
5718   }
5719 
Paint(nsDisplayListBuilder * aBuilder,gfxContext * aCtx)5720   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
5721     return;
5722   }
5723 
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)5724   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5725     return false;
5726   }
5727 
5728   void WriteDebugInfo(std::stringstream& aStream) override;
5729   UniquePtr<layers::ScrollMetadata> ComputeScrollMetadata(
5730       nsDisplayListBuilder* aBuilder,
5731       layers::WebRenderLayerManager* aLayerManager);
5732   bool UpdateScrollData(layers::WebRenderScrollData* aData,
5733                         layers::WebRenderLayerScrollData* aLayerData) override;
5734   bool CreateWebRenderCommands(
5735       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
5736       const StackingContextHelper& aSc,
5737       layers::RenderRootStateManager* aManager,
5738       nsDisplayListBuilder* aDisplayListBuilder) override;
5739 
5740  protected:
5741   nsIFrame* mScrollFrame;
5742   nsIFrame* mScrolledFrame;
5743   ViewID mScrollParentId;
5744   gfx::CompositorHitTestInfo mHitInfo;
5745   nsRect mHitArea;
5746 };
5747 
5748 /**
5749  * nsDisplayZoom is used for subdocuments that have a different full zoom than
5750  * their parent documents. This item creates a container layer.
5751  */
5752 class nsDisplayZoom : public nsDisplaySubDocument {
5753  public:
5754   /**
5755    * @param aFrame is the root frame of the subdocument.
5756    * @param aList contains the display items for the subdocument.
5757    * @param aAPD is the app units per dev pixel ratio of the subdocument.
5758    * @param aParentAPD is the app units per dev pixel ratio of the parent
5759    * document.
5760    * @param aFlags eGenerateSubdocInvalidations :
5761    * Add UserData to the created ContainerLayer, so that invalidations
5762    * for this layer are send to our nsPresContext.
5763    */
5764   nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5765                 nsSubDocumentFrame* aSubDocFrame, nsDisplayList* aList,
5766                 int32_t aAPD, int32_t aParentAPD,
5767                 nsDisplayOwnLayerFlags aFlags = nsDisplayOwnLayerFlags::None);
5768 
5769   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayZoom)
5770 
5771   NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM)
5772 
5773   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
5774   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
5775                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
5776   // Get the app units per dev pixel ratio of the child document.
GetChildAppUnitsPerDevPixel()5777   int32_t GetChildAppUnitsPerDevPixel() { return mAPD; }
5778   // Get the app units per dev pixel ratio of the parent document.
GetParentAppUnitsPerDevPixel()5779   int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD; }
5780 
5781  private:
5782   int32_t mAPD, mParentAPD;
5783 };
5784 
5785 /**
5786  * nsDisplayAsyncZoom is used for APZ zooming. It wraps the contents of the
5787  * root content document's scroll frame, including fixed position content. It
5788  * does not contain the scroll frame's scrollbars. It is clipped to the scroll
5789  * frame's scroll port clip. It is not scrolled; only its non-fixed contents
5790  * are scrolled. This item creates a container layer.
5791  */
5792 class nsDisplayAsyncZoom : public nsDisplayOwnLayer {
5793  public:
5794   nsDisplayAsyncZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5795                      nsDisplayList* aList,
5796                      const ActiveScrolledRoot* aActiveScrolledRoot,
5797                      layers::FrameMetrics::ViewID aViewID);
nsDisplayAsyncZoom(nsDisplayListBuilder * aBuilder,const nsDisplayAsyncZoom & aOther)5798   nsDisplayAsyncZoom(nsDisplayListBuilder* aBuilder,
5799                      const nsDisplayAsyncZoom& aOther)
5800       : nsDisplayOwnLayer(aBuilder, aOther), mViewID(aOther.mViewID) {
5801     MOZ_COUNT_CTOR(nsDisplayAsyncZoom);
5802   }
5803 
5804 #ifdef NS_BUILD_REFCNT_LOGGING
5805   virtual ~nsDisplayAsyncZoom();
5806 #endif
5807 
5808   NS_DISPLAY_DECL_NAME("AsyncZoom", TYPE_ASYNC_ZOOM)
5809 
5810   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
5811                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
5812   bool UpdateScrollData(layers::WebRenderScrollData* aData,
5813                         layers::WebRenderLayerScrollData* aLayerData) override;
5814 
5815  protected:
5816   layers::FrameMetrics::ViewID mViewID;
5817 };
5818 
5819 /**
5820  * A base class for different effects types.
5821  */
5822 class nsDisplayEffectsBase : public nsDisplayWrapList {
5823  public:
5824   nsDisplayEffectsBase(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5825                        nsDisplayList* aList,
5826                        const ActiveScrolledRoot* aActiveScrolledRoot,
5827                        bool aClearClipChain = false);
5828   nsDisplayEffectsBase(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5829                        nsDisplayList* aList);
5830 
nsDisplayEffectsBase(nsDisplayListBuilder * aBuilder,const nsDisplayEffectsBase & aOther)5831   nsDisplayEffectsBase(nsDisplayListBuilder* aBuilder,
5832                        const nsDisplayEffectsBase& aOther)
5833       : nsDisplayWrapList(aBuilder, aOther),
5834         mEffectsBounds(aOther.mEffectsBounds) {
5835     MOZ_COUNT_CTOR(nsDisplayEffectsBase);
5836   }
5837 
5838   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayEffectsBase)
5839 
5840   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
5841                            bool* aSnap) const override;
5842   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
5843                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
5844 
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)5845   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5846     return false;
5847   }
5848 
5849   gfxRect BBoxInUserSpace() const;
5850   gfxPoint UserSpaceOffset() const;
5851 
5852   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
5853                                  const nsDisplayItemGeometry* aGeometry,
5854                                  nsRegion* aInvalidRegion) const override;
5855 
5856  protected:
5857   bool ValidateSVGFrame();
5858 
5859   // relative to mFrame
5860   nsRect mEffectsBounds;
5861 };
5862 
5863 /**
5864  * A display item to paint a stacking context with 'mask' and 'clip-path'
5865  * effects set by the stacking context root frame's style.  The 'mask' and
5866  * 'clip-path' properties may both contain multiple masks and clip paths,
5867  * respectively.
5868  *
5869  * Note that 'mask' and 'clip-path' may just contain CSS simple-images and CSS
5870  * basic shapes, respectively.  That is, they don't necessarily reference
5871  * resources such as SVG 'mask' and 'clipPath' elements.
5872  */
5873 class nsDisplayMasksAndClipPaths : public nsDisplayEffectsBase {
5874  public:
5875   nsDisplayMasksAndClipPaths(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5876                              nsDisplayList* aList,
5877                              const ActiveScrolledRoot* aActiveScrolledRoot);
nsDisplayMasksAndClipPaths(nsDisplayListBuilder * aBuilder,const nsDisplayMasksAndClipPaths & aOther)5878   nsDisplayMasksAndClipPaths(nsDisplayListBuilder* aBuilder,
5879                              const nsDisplayMasksAndClipPaths& aOther)
5880       : nsDisplayEffectsBase(aBuilder, aOther),
5881         mDestRects(aOther.mDestRects.Clone()) {
5882     MOZ_COUNT_CTOR(nsDisplayMasksAndClipPaths);
5883   }
5884 
5885   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayMasksAndClipPaths)
5886 
5887   NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK)
5888 
5889   bool CanMerge(const nsDisplayItem* aItem) const override;
5890 
Merge(const nsDisplayItem * aItem)5891   void Merge(const nsDisplayItem* aItem) override {
5892     nsDisplayWrapList::Merge(aItem);
5893 
5894     const nsDisplayMasksAndClipPaths* other =
5895         static_cast<const nsDisplayMasksAndClipPaths*>(aItem);
5896     mEffectsBounds.UnionRect(
5897         mEffectsBounds,
5898         other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
5899   }
5900 
5901   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
5902 
AllocateGeometry(nsDisplayListBuilder * aBuilder)5903   nsDisplayItemGeometry* AllocateGeometry(
5904       nsDisplayListBuilder* aBuilder) override {
5905     return new nsDisplayMasksAndClipPathsGeometry(this, aBuilder);
5906   }
5907 
5908   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
5909                                  const nsDisplayItemGeometry* aGeometry,
5910                                  nsRegion* aInvalidRegion) const override;
5911 #ifdef MOZ_DUMP_PAINTING
5912   void PrintEffects(nsACString& aTo);
5913 #endif
5914 
5915   bool IsValidMask();
5916 
5917   void PaintWithContentsPaintCallback(
5918       nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
5919       const std::function<void()>& aPaintChildren);
5920 
5921   /*
5922    * Paint mask onto aMaskContext in mFrame's coordinate space and
5923    * return whether the mask layer was painted successfully.
5924    */
5925   bool PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext,
5926                  bool aHandleOpacity, bool* aMaskPainted = nullptr);
5927 
GetDestRects()5928   const nsTArray<nsRect>& GetDestRects() { return mDestRects; }
5929 
5930   bool CreateWebRenderCommands(
5931       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
5932       const StackingContextHelper& aSc,
5933       layers::RenderRootStateManager* aManager,
5934       nsDisplayListBuilder* aDisplayListBuilder) override;
5935 
5936   Maybe<nsRect> GetClipWithRespectToASR(
5937       nsDisplayListBuilder* aBuilder,
5938       const ActiveScrolledRoot* aASR) const override;
5939 
CreatesStackingContextHelper()5940   bool CreatesStackingContextHelper() override { return true; }
5941 
5942  private:
5943   NS_DISPLAY_ALLOW_CLONING()
5944 
5945   nsTArray<nsRect> mDestRects;
5946 };
5947 
5948 class nsDisplayBackdropRootContainer : public nsDisplayWrapList {
5949  public:
nsDisplayBackdropRootContainer(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,nsDisplayList * aList,const ActiveScrolledRoot * aActiveScrolledRoot)5950   nsDisplayBackdropRootContainer(nsDisplayListBuilder* aBuilder,
5951                                  nsIFrame* aFrame, nsDisplayList* aList,
5952                                  const ActiveScrolledRoot* aActiveScrolledRoot)
5953       : nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, true) {
5954     MOZ_COUNT_CTOR(nsDisplayBackdropRootContainer);
5955   }
5956 
5957   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropRootContainer)
5958 
5959   NS_DISPLAY_DECL_NAME("BackdropRootContainer", TYPE_BACKDROP_ROOT_CONTAINER)
5960 
5961   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
5962 
5963   bool CreateWebRenderCommands(
5964       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
5965       const StackingContextHelper& aSc,
5966       layers::RenderRootStateManager* aManager,
5967       nsDisplayListBuilder* aDisplayListBuilder) override;
5968 
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)5969   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
5970     return !aBuilder->IsPaintingForWebRender();
5971   }
5972 
CreatesStackingContextHelper()5973   bool CreatesStackingContextHelper() override { return true; }
5974 };
5975 
5976 class nsDisplayBackdropFilters : public nsDisplayWrapList {
5977  public:
nsDisplayBackdropFilters(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,nsDisplayList * aList,const nsRect & aBackdropRect)5978   nsDisplayBackdropFilters(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
5979                            nsDisplayList* aList, const nsRect& aBackdropRect)
5980       : nsDisplayWrapList(aBuilder, aFrame, aList),
5981         mBackdropRect(aBackdropRect) {
5982     MOZ_COUNT_CTOR(nsDisplayBackdropFilters);
5983   }
5984 
5985   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropFilters)
5986 
5987   NS_DISPLAY_DECL_NAME("BackdropFilter", TYPE_BACKDROP_FILTER)
5988 
5989   bool CreateWebRenderCommands(
5990       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
5991       const StackingContextHelper& aSc,
5992       layers::RenderRootStateManager* aManager,
5993       nsDisplayListBuilder* aDisplayListBuilder) override;
5994   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
5995 
5996   static bool CanCreateWebRenderCommands(nsDisplayListBuilder* aBuilder,
5997                                          nsIFrame* aFrame);
5998 
ShouldFlattenAway(nsDisplayListBuilder * aBuilder)5999   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
6000     return !aBuilder->IsPaintingForWebRender();
6001   }
6002 
CreatesStackingContextHelper()6003   bool CreatesStackingContextHelper() override { return true; }
6004 
6005  private:
6006   nsRect mBackdropRect;
6007 };
6008 
6009 /**
6010  * A display item to paint a stacking context with filter effects set by the
6011  * stacking context root frame's style.
6012  *
6013  * Note that the filters may just be simple CSS filter functions.  That is,
6014  * they won't necessarily be references to SVG 'filter' elements.
6015  */
6016 class nsDisplayFilters : public nsDisplayEffectsBase {
6017  public:
6018   nsDisplayFilters(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6019                    nsDisplayList* aList);
6020 
nsDisplayFilters(nsDisplayListBuilder * aBuilder,const nsDisplayFilters & aOther)6021   nsDisplayFilters(nsDisplayListBuilder* aBuilder,
6022                    const nsDisplayFilters& aOther)
6023       : nsDisplayEffectsBase(aBuilder, aOther),
6024         mEffectsBounds(aOther.mEffectsBounds) {
6025     MOZ_COUNT_CTOR(nsDisplayFilters);
6026   }
6027 
6028   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFilters)
6029 
6030   NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER)
6031 
CanMerge(const nsDisplayItem * aItem)6032   bool CanMerge(const nsDisplayItem* aItem) const override {
6033     // Items for the same content element should be merged into a single
6034     // compositing group.
6035     return HasDifferentFrame(aItem) && HasSameTypeAndClip(aItem) &&
6036            HasSameContent(aItem);
6037   }
6038 
Merge(const nsDisplayItem * aItem)6039   void Merge(const nsDisplayItem* aItem) override {
6040     nsDisplayWrapList::Merge(aItem);
6041 
6042     const nsDisplayFilters* other = static_cast<const nsDisplayFilters*>(aItem);
6043     mEffectsBounds.UnionRect(
6044         mEffectsBounds,
6045         other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
6046   }
6047 
6048   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
6049 
GetBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)6050   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override {
6051     *aSnap = false;
6052     return mEffectsBounds + ToReferenceFrame();
6053   }
6054 
AllocateGeometry(nsDisplayListBuilder * aBuilder)6055   nsDisplayItemGeometry* AllocateGeometry(
6056       nsDisplayListBuilder* aBuilder) override {
6057     return new nsDisplayFiltersGeometry(this, aBuilder);
6058   }
6059 
6060   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
6061                                  const nsDisplayItemGeometry* aGeometry,
6062                                  nsRegion* aInvalidRegion) const override;
6063 #ifdef MOZ_DUMP_PAINTING
6064   void PrintEffects(nsACString& aTo);
6065 #endif
6066 
6067   void PaintWithContentsPaintCallback(
6068       nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
6069       const std::function<void(gfxContext* aContext)>& aPaintChildren);
6070 
6071   bool CreateWebRenderCommands(
6072       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
6073       const StackingContextHelper& aSc,
6074       layers::RenderRootStateManager* aManager,
6075       nsDisplayListBuilder* aDisplayListBuilder) override;
6076   bool CanCreateWebRenderCommands() const;
6077 
CanApplyOpacity(WebRenderLayerManager * aManager,nsDisplayListBuilder * aBuilder)6078   bool CanApplyOpacity(WebRenderLayerManager* aManager,
6079                        nsDisplayListBuilder* aBuilder) const override {
6080     return CanCreateWebRenderCommands();
6081   }
6082 
CreatesStackingContextHelper()6083   bool CreatesStackingContextHelper() override { return true; }
6084 
6085  private:
6086   NS_DISPLAY_ALLOW_CLONING()
6087 
6088   // relative to mFrame
6089   nsRect mEffectsBounds;
6090   nsRect mVisibleRect;
6091 };
6092 
6093 /* A display item that applies a transformation to all of its descendant
6094  * elements.  This wrapper should only be used if there is a transform applied
6095  * to the root element.
6096  *
6097  * The reason that a "bounds" rect is involved in transform calculations is
6098  * because CSS-transforms allow percentage values for the x and y components
6099  * of <translation-value>s, where percentages are percentages of the element's
6100  * border box.
6101  *
6102  * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
6103  * function.
6104  * INVARIANT: The wrapped frame is non-null.
6105  */
6106 class nsDisplayTransform : public nsPaintedDisplayItem {
6107   using Matrix4x4 = gfx::Matrix4x4;
6108   using Matrix4x4Flagged = gfx::Matrix4x4Flagged;
6109   using TransformReferenceBox = nsStyleTransformMatrix::TransformReferenceBox;
6110 
6111  public:
6112   enum class PrerenderDecision : uint8_t { No, Full, Partial };
6113 
6114   enum {
6115     WithTransformGetter,
6116   };
6117 
6118   /* Constructor accepts a display list, empties it, and wraps it up.  It also
6119    * ferries the underlying frame to the nsDisplayItem constructor.
6120    */
6121   nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6122                      nsDisplayList* aList, const nsRect& aChildrenBuildingRect);
6123 
6124   nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6125                      nsDisplayList* aList, const nsRect& aChildrenBuildingRect,
6126                      PrerenderDecision aPrerenderDecision);
6127 
6128   nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6129                      nsDisplayList* aList, const nsRect& aChildrenBuildingRect,
6130                      decltype(WithTransformGetter));
6131 
6132   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayTransform)
6133 
6134   NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM)
6135 
6136   void UpdateBounds(nsDisplayListBuilder* aBuilder) override;
6137 
6138   /**
6139    * This function updates bounds for items with a frame establishing
6140    * 3D rendering context.
6141    */
6142   void UpdateBoundsFor3D(nsDisplayListBuilder* aBuilder);
6143 
6144   void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override;
6145 
Destroy(nsDisplayListBuilder * aBuilder)6146   void Destroy(nsDisplayListBuilder* aBuilder) override {
6147     GetChildren()->DeleteAll(aBuilder);
6148     nsPaintedDisplayItem::Destroy(aBuilder);
6149   }
6150 
6151   nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override;
6152 
GetChildren()6153   RetainedDisplayList* GetChildren() const override { return &mChildren; }
6154 
GetUntransformedBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)6155   nsRect GetUntransformedBounds(nsDisplayListBuilder* aBuilder,
6156                                 bool* aSnap) const override {
6157     *aSnap = false;
6158     return mChildBounds;
6159   }
6160 
GetUntransformedPaintRect()6161   const nsRect& GetUntransformedPaintRect() const override {
6162     return mChildrenBuildingRect;
6163   }
6164 
6165   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
6166 
6167   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
6168                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
6169   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
6170   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
6171                            bool* aSnap) const override;
6172   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
6173   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
6174              const Maybe<gfx::Polygon>& aPolygon);
6175   bool CreateWebRenderCommands(
6176       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
6177       const StackingContextHelper& aSc,
6178       layers::RenderRootStateManager* aManager,
6179       nsDisplayListBuilder* aDisplayListBuilder) override;
6180   bool UpdateScrollData(layers::WebRenderScrollData* aData,
6181                         layers::WebRenderLayerScrollData* aLayerData) override;
6182 
AllocateGeometry(nsDisplayListBuilder * aBuilder)6183   nsDisplayItemGeometry* AllocateGeometry(
6184       nsDisplayListBuilder* aBuilder) override {
6185     return new nsDisplayTransformGeometry(
6186         this, aBuilder, GetTransformForRendering(),
6187         mFrame->PresContext()->AppUnitsPerDevPixel());
6188   }
6189 
ComputeInvalidationRegion(nsDisplayListBuilder * aBuilder,const nsDisplayItemGeometry * aGeometry,nsRegion * aInvalidRegion)6190   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
6191                                  const nsDisplayItemGeometry* aGeometry,
6192                                  nsRegion* aInvalidRegion) const override {
6193     const nsDisplayTransformGeometry* geometry =
6194         static_cast<const nsDisplayTransformGeometry*>(aGeometry);
6195 
6196     // This code is only called for flattened, inactive transform items.
6197     // Only check if the transform has changed. The bounds invalidation should
6198     // be handled by the children themselves.
6199     if (!geometry->mTransform.FuzzyEqual(GetTransformForRendering())) {
6200       bool snap;
6201       aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
6202     }
6203   }
6204 
ReferenceFrameForChildren()6205   const nsIFrame* ReferenceFrameForChildren() const override {
6206     // If we were created using a transform-getter, then we don't
6207     // belong to a transformed frame, and aren't a reference frame
6208     // for our children.
6209     if (!mHasTransformGetter) {
6210       return mFrame;
6211     }
6212     return nsPaintedDisplayItem::ReferenceFrameForChildren();
6213   }
6214 
GetBuildingRectForChildren()6215   const nsRect& GetBuildingRectForChildren() const override {
6216     return mChildrenBuildingRect;
6217   }
6218 
6219   enum { INDEX_MAX = UINT32_MAX >> TYPE_BITS };
6220 
6221   /**
6222    * We include the perspective matrix from our containing block for the
6223    * purposes of visibility calculations, but we exclude it from the transform
6224    * we set on the layer (for rendering), since there will be an
6225    * nsDisplayPerspective created for that.
6226    */
6227   const Matrix4x4Flagged& GetTransform() const;
6228   const Matrix4x4Flagged& GetInverseTransform() const;
6229 
6230   bool ShouldSkipTransform(nsDisplayListBuilder* aBuilder) const;
6231   Matrix4x4 GetTransformForRendering(
6232       LayoutDevicePoint* aOutOrigin = nullptr) const;
6233 
6234   /**
6235    * Return the transform that is aggregation of all transform on the
6236    * preserves3d chain.
6237    */
6238   const Matrix4x4& GetAccumulatedPreserved3DTransform(
6239       nsDisplayListBuilder* aBuilder);
6240 
6241   float GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder,
6242                            const nsPoint& aPoint);
6243 
6244   /**
6245    * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
6246    * space) and returns the smallest rectangle (in aFrame's coordinate space)
6247    * containing the transformed image of that rectangle.  That is, it takes
6248    * the four corners of the rectangle, transforms them according to the
6249    * matrix associated with the specified frame, then returns the smallest
6250    * rectangle containing the four transformed points.
6251    *
6252    * @param untransformedBounds The rectangle (in app units) to transform.
6253    * @param aFrame The frame whose transformation should be applied.  This
6254    *        function raises an assertion if aFrame is null or doesn't have a
6255    *        transform applied to it.
6256    * @param aRefBox the reference box to use, which would usually be just
6257    *        TransformReferemceBox(aFrame), but callers may override it if
6258    *        needed.
6259    */
6260   static nsRect TransformRect(const nsRect& aUntransformedBounds,
6261                               const nsIFrame* aFrame,
6262                               TransformReferenceBox& aRefBox);
6263 
6264   /* UntransformRect is like TransformRect, except that it inverts the
6265    * transform.
6266    */
6267   static bool UntransformRect(const nsRect& aTransformedBounds,
6268                               const nsRect& aChildBounds,
6269                               const nsIFrame* aFrame, nsRect* aOutRect);
6270 
6271   bool UntransformRect(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
6272                        nsRect* aOutRect) const;
6273 
UntransformBuildingRect(nsDisplayListBuilder * aBuilder,nsRect * aOutRect)6274   bool UntransformBuildingRect(nsDisplayListBuilder* aBuilder,
6275                                nsRect* aOutRect) const {
6276     return UntransformRect(aBuilder, GetBuildingRect(), aOutRect);
6277   }
6278 
6279   static gfx::Point3D GetDeltaToTransformOrigin(const nsIFrame* aFrame,
6280                                                 TransformReferenceBox&,
6281                                                 float aAppUnitsPerPixel);
6282 
6283   /*
6284    * Returns true if aFrame has perspective applied from its containing
6285    * block.
6286    * Returns the matrix to append to apply the persective (taking
6287    * perspective-origin into account), relative to aFrames coordinate
6288    * space).
6289    * aOutMatrix is assumed to be the identity matrix, and isn't explicitly
6290    * cleared.
6291    */
6292   static bool ComputePerspectiveMatrix(const nsIFrame* aFrame,
6293                                        float aAppUnitsPerPixel,
6294                                        Matrix4x4& aOutMatrix);
6295 
6296   struct MOZ_STACK_CLASS FrameTransformProperties {
6297     FrameTransformProperties(const nsIFrame* aFrame,
6298                              TransformReferenceBox& aRefBox,
6299                              float aAppUnitsPerPixel);
FrameTransformPropertiesFrameTransformProperties6300     FrameTransformProperties(const StyleTranslate& aTranslate,
6301                              const StyleRotate& aRotate,
6302                              const StyleScale& aScale,
6303                              const StyleTransform& aTransform,
6304                              const Maybe<ResolvedMotionPathData>& aMotion,
6305                              const gfx::Point3D& aToTransformOrigin)
6306         : mFrame(nullptr),
6307           mTranslate(aTranslate),
6308           mRotate(aRotate),
6309           mScale(aScale),
6310           mTransform(aTransform),
6311           mMotion(aMotion),
6312           mToTransformOrigin(aToTransformOrigin) {}
6313 
HasTransformFrameTransformProperties6314     bool HasTransform() const {
6315       return !mTranslate.IsNone() || !mRotate.IsNone() || !mScale.IsNone() ||
6316              !mTransform.IsNone() || mMotion.isSome();
6317     }
6318 
6319     const nsIFrame* mFrame;
6320     const StyleTranslate& mTranslate;
6321     const StyleRotate& mRotate;
6322     const StyleScale& mScale;
6323     const StyleTransform& mTransform;
6324     const Maybe<ResolvedMotionPathData> mMotion;
6325     const gfx::Point3D mToTransformOrigin;
6326   };
6327 
6328   /**
6329    * Given a frame with the transform property or an SVG transform,
6330    * returns the transformation matrix for that frame.
6331    *
6332    * @param aFrame The frame to get the matrix from.
6333    * @param aOrigin Relative to which point this transform should be applied.
6334    * @param aAppUnitsPerPixel The number of app units per graphics unit.
6335    * @param aBoundsOverride [optional] If this is nullptr (the default), the
6336    *        computation will use the value of TransformReferenceBox(aFrame).
6337    *        Otherwise, it will use the value of aBoundsOverride.  This is
6338    *        mostly for internal use and in most cases you will not need to
6339    *        specify a value.
6340    * @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated
6341    *        by aOrigin. This translation is applied *before* the CSS transform.
6342    * @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will
6343    *        include the transform of any ancestors participating in the same
6344    *        3d rendering context.
6345    * @param aFlags INCLUDE_PERSPECTIVE The resulting matrix will include the
6346    *        perspective transform from the containing block if applicable.
6347    */
6348   enum {
6349     OFFSET_BY_ORIGIN = 1 << 0,
6350     INCLUDE_PRESERVE3D_ANCESTORS = 1 << 1,
6351     INCLUDE_PERSPECTIVE = 1 << 2,
6352   };
6353   static Matrix4x4 GetResultingTransformMatrix(const nsIFrame* aFrame,
6354                                                const nsPoint& aOrigin,
6355                                                float aAppUnitsPerPixel,
6356                                                uint32_t aFlags);
6357   static Matrix4x4 GetResultingTransformMatrix(
6358       const FrameTransformProperties& aProperties, TransformReferenceBox&,
6359       float aAppUnitsPerPixel);
6360 
6361   struct PrerenderInfo {
CanUseAsyncAnimationsPrerenderInfo6362     bool CanUseAsyncAnimations() const {
6363       return mDecision != PrerenderDecision::No && mHasAnimations;
6364     }
6365     PrerenderDecision mDecision = PrerenderDecision::No;
6366     bool mHasAnimations = true;
6367   };
6368   /**
6369    * Decide whether we should prerender some or all of the contents of the
6370    * transformed frame even when it's not completely visible (yet).
6371    * Return PrerenderDecision::Full if the entire contents should be
6372    * prerendered, PrerenderDecision::Partial if some but not all of the
6373    * contents should be prerendered, or PrerenderDecision::No if only the
6374    * visible area should be rendered.
6375    * |mNoAffectDecisionInPreserve3D| is set if the prerender decision should not
6376    * affect the decision on other frames in the preserve 3d tree.
6377    * |aDirtyRect| is updated to the area that should be prerendered.
6378    */
6379   static PrerenderInfo ShouldPrerenderTransformedContent(
6380       nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsRect* aDirtyRect);
6381 
6382   bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
6383 
6384   bool MayBeAnimated(nsDisplayListBuilder* aBuilder) const;
6385 
6386   void WriteDebugInfo(std::stringstream& aStream) override;
6387 
CanMoveAsync()6388   bool CanMoveAsync() override {
6389     return EffectCompositor::HasAnimationsForCompositor(
6390         mFrame, DisplayItemType::TYPE_TRANSFORM);
6391   }
6392 
6393   /**
6394    * This item is an additional item as the boundary between parent
6395    * and child 3D rendering context.
6396    * \see nsIFrame::BuildDisplayListForStackingContext().
6397    */
IsTransformSeparator()6398   bool IsTransformSeparator() const { return mIsTransformSeparator; }
6399   /**
6400    * This item is the boundary between parent and child 3D rendering
6401    * context.
6402    */
IsLeafOf3DContext()6403   bool IsLeafOf3DContext() const {
6404     return (IsTransformSeparator() ||
6405             (!mFrame->Extend3DContext() && Combines3DTransformWithAncestors()));
6406   }
6407   /**
6408    * The backing frame of this item participates a 3D rendering
6409    * context.
6410    */
IsParticipating3DContext()6411   bool IsParticipating3DContext() const {
6412     return mFrame->Extend3DContext() || Combines3DTransformWithAncestors();
6413   }
6414 
IsPartialPrerender()6415   bool IsPartialPrerender() const {
6416     return mPrerenderDecision == PrerenderDecision::Partial;
6417   }
6418 
6419   /**
6420    * Mark this item as created together with `nsDisplayPerspective`.
6421    * \see nsIFrame::BuildDisplayListForStackingContext().
6422    */
MarkWithAssociatedPerspective()6423   void MarkWithAssociatedPerspective() { mHasAssociatedPerspective = true; }
6424 
6425   void AddSizeOfExcludingThis(nsWindowSizes&) const override;
6426 
CreatesStackingContextHelper()6427   bool CreatesStackingContextHelper() override { return true; }
6428 
6429  private:
6430   void ComputeBounds(nsDisplayListBuilder* aBuilder);
6431   nsRect TransformUntransformedBounds(nsDisplayListBuilder* aBuilder,
6432                                       const Matrix4x4Flagged& aMatrix) const;
6433   void UpdateUntransformedBounds(nsDisplayListBuilder* aBuilder);
6434 
6435   void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder);
6436   void Init(nsDisplayListBuilder* aBuilder, nsDisplayList* aChildren);
6437 
6438   static Matrix4x4 GetResultingTransformMatrixInternal(
6439       const FrameTransformProperties& aProperties,
6440       TransformReferenceBox& aRefBox, const nsPoint& aOrigin,
6441       float aAppUnitsPerPixel, uint32_t aFlags);
6442 
6443   void Collect3DTransformLeaves(nsDisplayListBuilder* aBuilder,
6444                                 nsTArray<nsDisplayTransform*>& aLeaves);
6445   using TransformPolygon = layers::BSPPolygon<nsDisplayTransform>;
6446   void CollectSorted3DTransformLeaves(nsDisplayListBuilder* aBuilder,
6447                                       nsTArray<TransformPolygon>& aLeaves);
6448 
6449   mutable RetainedDisplayList mChildren;
6450   mutable Maybe<Matrix4x4Flagged> mTransform;
6451   mutable Maybe<Matrix4x4Flagged> mInverseTransform;
6452   // Accumulated transform of ancestors on the preserves-3d chain.
6453   UniquePtr<Matrix4x4> mTransformPreserves3D;
6454   nsRect mChildrenBuildingRect;
6455 
6456   // The untransformed bounds of |mChildren|.
6457   nsRect mChildBounds;
6458   // The transformed bounds of this display item.
6459   nsRect mBounds;
6460   PrerenderDecision mPrerenderDecision : 8;
6461   // This item is a separator between 3D rendering contexts, and
6462   // mTransform have been presetted by the constructor.
6463   // This also forces us not to extend the 3D context.  Since we don't create a
6464   // transform item, a container layer, for every frame in a preserves3d
6465   // context, the transform items of a child preserves3d context may extend the
6466   // parent context unintendedly if the root of the child preserves3d context
6467   // doesn't create a transform item.
6468   bool mIsTransformSeparator : 1;
6469   // True if we have a transform getter.
6470   bool mHasTransformGetter : 1;
6471   // True if this item is created together with `nsDisplayPerspective`
6472   // from the same CSS stacking context.
6473   bool mHasAssociatedPerspective : 1;
6474 };
6475 
6476 /* A display item that applies a perspective transformation to a single
6477  * nsDisplayTransform child item. We keep this as a separate item since the
6478  * perspective-origin is relative to an ancestor of the transformed frame, and
6479  * APZ can scroll the child separately.
6480  */
6481 class nsDisplayPerspective : public nsPaintedDisplayItem {
6482  public:
6483   nsDisplayPerspective(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6484                        nsDisplayList* aList);
6485   ~nsDisplayPerspective() override = default;
6486 
6487   NS_DISPLAY_DECL_NAME("nsDisplayPerspective", TYPE_PERSPECTIVE)
6488 
Destroy(nsDisplayListBuilder * aBuilder)6489   void Destroy(nsDisplayListBuilder* aBuilder) override {
6490     mList.DeleteAll(aBuilder);
6491     nsPaintedDisplayItem::Destroy(aBuilder);
6492   }
6493 
HitTest(nsDisplayListBuilder * aBuilder,const nsRect & aRect,HitTestState * aState,nsTArray<nsIFrame * > * aOutFrames)6494   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
6495                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override {
6496     return GetChildren()->HitTest(aBuilder, aRect, aState, aOutFrames);
6497   }
6498 
GetBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)6499   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override {
6500     *aSnap = false;
6501     return GetChildren()->GetClippedBoundsWithRespectToASR(aBuilder,
6502                                                            mActiveScrolledRoot);
6503   }
6504 
ComputeInvalidationRegion(nsDisplayListBuilder * aBuilder,const nsDisplayItemGeometry * aGeometry,nsRegion * aInvalidRegion)6505   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
6506                                  const nsDisplayItemGeometry* aGeometry,
6507                                  nsRegion* aInvalidRegion) const override {}
6508 
6509   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
6510                            bool* aSnap) const override;
6511 
6512   bool CreateWebRenderCommands(
6513       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
6514       const StackingContextHelper& aSc,
6515       layers::RenderRootStateManager* aManager,
6516       nsDisplayListBuilder* aDisplayListBuilder) override;
6517 
6518   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
6519 
GetSameCoordinateSystemChildren()6520   RetainedDisplayList* GetSameCoordinateSystemChildren() const override {
6521     return &mList;
6522   }
6523 
GetChildren()6524   RetainedDisplayList* GetChildren() const override { return &mList; }
6525 
GetComponentAlphaBounds(nsDisplayListBuilder * aBuilder)6526   nsRect GetComponentAlphaBounds(
6527       nsDisplayListBuilder* aBuilder) const override {
6528     return GetChildren()->GetComponentAlphaBounds(aBuilder);
6529   }
6530 
DoUpdateBoundsPreserves3D(nsDisplayListBuilder * aBuilder)6531   void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
6532     if (GetChildren()->GetTop()) {
6533       static_cast<nsDisplayTransform*>(GetChildren()->GetTop())
6534           ->DoUpdateBoundsPreserves3D(aBuilder);
6535     }
6536   }
6537 
CreatesStackingContextHelper()6538   bool CreatesStackingContextHelper() override { return true; }
6539 
6540  private:
6541   mutable RetainedDisplayList mList;
6542 };
6543 
6544 class nsDisplayTextGeometry;
6545 
6546 /**
6547  * This class adds basic support for limiting the rendering (in the inline axis
6548  * of the writing mode) to the part inside the specified edges.
6549  * The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
6550  * of the frame's scrollable overflow rectangle and are the amount to suppress
6551  * on each side.
6552  *
6553  * Setting none, both or only one edge is allowed.
6554  * The values must be non-negative.
6555  * The default value for both edges is zero, which means everything is painted.
6556  */
6557 class nsDisplayText final : public nsPaintedDisplayItem {
6558  public:
6559   nsDisplayText(nsDisplayListBuilder* aBuilder, nsTextFrame* aFrame);
6560   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayText)
6561 
6562   NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT)
6563 
GetBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)6564   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const final {
6565     *aSnap = false;
6566     return mBounds;
6567   }
6568 
HitTest(nsDisplayListBuilder * aBuilder,const nsRect & aRect,HitTestState * aState,nsTArray<nsIFrame * > * aOutFrames)6569   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
6570                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) final {
6571     if (nsRect(ToReferenceFrame(), mFrame->GetSize()).Intersects(aRect)) {
6572       aOutFrames->AppendElement(mFrame);
6573     }
6574   }
6575 
6576   bool CreateWebRenderCommands(wr::DisplayListBuilder& aBuilder,
6577                                wr::IpcResourceUpdateQueue& aResources,
6578                                const StackingContextHelper& aSc,
6579                                layers::RenderRootStateManager* aManager,
6580                                nsDisplayListBuilder* aDisplayListBuilder) final;
6581   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) final;
6582 
GetComponentAlphaBounds(nsDisplayListBuilder * aBuilder)6583   nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const final {
6584     if (gfxPlatform::GetPlatform()->RespectsFontStyleSmoothing()) {
6585       // On OS X, web authors can turn off subpixel text rendering using the
6586       // CSS property -moz-osx-font-smoothing. If they do that, we don't need
6587       // to use component alpha layers for the affected text.
6588       if (mFrame->StyleFont()->mFont.smoothing == NS_FONT_SMOOTHING_GRAYSCALE) {
6589         return nsRect();
6590       }
6591     }
6592     bool snap;
6593     return GetBounds(aBuilder, &snap);
6594   }
6595 
6596   nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) final;
6597 
6598   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
6599                                  const nsDisplayItemGeometry* aGeometry,
6600                                  nsRegion* aInvalidRegion) const final;
6601 
6602   void RenderToContext(gfxContext* aCtx, nsDisplayListBuilder* aBuilder,
6603                        const nsRect& aVisibleRect, float aOpacity = 1.0f,
6604                        bool aIsRecording = false);
6605 
6606   bool CanApplyOpacity(WebRenderLayerManager* aManager,
6607                        nsDisplayListBuilder* aBuilder) const final;
6608 
6609   void WriteDebugInfo(std::stringstream& aStream) final;
6610 
CheckCast(nsDisplayItem * aItem)6611   static nsDisplayText* CheckCast(nsDisplayItem* aItem) {
6612     return (aItem->GetType() == DisplayItemType::TYPE_TEXT)
6613                ? static_cast<nsDisplayText*>(aItem)
6614                : nullptr;
6615   }
6616 
VisIStartEdge()6617   nscoord& VisIStartEdge() { return mVisIStartEdge; }
VisIEndEdge()6618   nscoord& VisIEndEdge() { return mVisIEndEdge; }
6619 
6620  private:
6621   nsRect mBounds;
6622   nsRect mVisibleRect;
6623 
6624   // Lengths measured from the visual inline start and end sides
6625   // (i.e. left and right respectively in horizontal writing modes,
6626   // regardless of bidi directionality; top and bottom in vertical modes).
6627   nscoord mVisIStartEdge;
6628   nscoord mVisIEndEdge;
6629 };
6630 
6631 /**
6632  * A display item that for webrender to handle SVG
6633  */
6634 class nsDisplaySVGWrapper : public nsDisplayWrapList {
6635  public:
6636   nsDisplaySVGWrapper(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6637                       nsDisplayList* aList);
6638 
6639   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySVGWrapper)
6640 
6641   NS_DISPLAY_DECL_NAME("SVGWrapper", TYPE_SVG_WRAPPER)
6642 
Paint(nsDisplayListBuilder * aBuilder,gfxContext * aCtx)6643   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
6644     GetChildren()->Paint(aBuilder, aCtx,
6645                          mFrame->PresContext()->AppUnitsPerDevPixel());
6646   }
6647   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
6648   bool CreateWebRenderCommands(
6649       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
6650       const StackingContextHelper& aSc,
6651       layers::RenderRootStateManager* aManager,
6652       nsDisplayListBuilder* aDisplayListBuilder) override;
6653 };
6654 
6655 /**
6656  * A display item for webrender to handle SVG foreign object
6657  */
6658 class nsDisplayForeignObject : public nsDisplayWrapList {
6659  public:
6660   nsDisplayForeignObject(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6661                          nsDisplayList* aList);
6662 #ifdef NS_BUILD_REFCNT_LOGGING
6663   virtual ~nsDisplayForeignObject();
6664 #endif
6665 
6666   NS_DISPLAY_DECL_NAME("ForeignObject", TYPE_FOREIGN_OBJECT)
6667 
6668   virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
Paint(nsDisplayListBuilder * aBuilder,gfxContext * aCtx)6669   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
6670     GetChildren()->Paint(aBuilder, aCtx,
6671                          mFrame->PresContext()->AppUnitsPerDevPixel());
6672   }
6673 
6674   bool CreateWebRenderCommands(
6675       wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
6676       const StackingContextHelper& aSc,
6677       layers::RenderRootStateManager* aManager,
6678       nsDisplayListBuilder* aDisplayListBuilder) override;
6679 };
6680 
6681 /**
6682  * A display item to represent a hyperlink.
6683  */
6684 class nsDisplayLink : public nsPaintedDisplayItem {
6685  public:
nsDisplayLink(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,const char * aLinkSpec,const nsRect & aRect)6686   nsDisplayLink(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6687                 const char* aLinkSpec, const nsRect& aRect)
6688       : nsPaintedDisplayItem(aBuilder, aFrame),
6689         mLinkSpec(aLinkSpec),
6690         mRect(aRect) {}
6691 
6692   NS_DISPLAY_DECL_NAME("Link", TYPE_LINK)
6693 
6694   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
6695 
6696  private:
6697   nsCString mLinkSpec;
6698   nsRect mRect;
6699 };
6700 
6701 /**
6702  * A display item to represent a destination within the document.
6703  */
6704 class nsDisplayDestination : public nsPaintedDisplayItem {
6705  public:
nsDisplayDestination(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,const char * aDestinationName,const nsPoint & aPosition)6706   nsDisplayDestination(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
6707                        const char* aDestinationName, const nsPoint& aPosition)
6708       : nsPaintedDisplayItem(aBuilder, aFrame),
6709         mDestinationName(aDestinationName),
6710         mPosition(aPosition) {}
6711 
6712   NS_DISPLAY_DECL_NAME("Destination", TYPE_DESTINATION)
6713 
6714   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
6715 
6716  private:
6717   nsCString mDestinationName;
6718   nsPoint mPosition;
6719 };
6720 
6721 class FlattenedDisplayListIterator {
6722  public:
FlattenedDisplayListIterator(nsDisplayListBuilder * aBuilder,nsDisplayList * aList)6723   FlattenedDisplayListIterator(nsDisplayListBuilder* aBuilder,
6724                                nsDisplayList* aList)
6725       : mBuilder(aBuilder), mStart(aList->begin()), mEnd(aList->end()) {
6726     ResolveFlattening();
6727   }
6728 
HasNext()6729   bool HasNext() const { return !AtEndOfCurrentList(); }
6730 
GetNextItem()6731   nsDisplayItem* GetNextItem() {
6732     MOZ_ASSERT(HasNext());
6733 
6734     nsDisplayItem* current = NextItem();
6735     Advance();
6736 
6737     if (!AtEndOfCurrentList() && current->CanMerge(NextItem())) {
6738       // Since we can merge at least two display items, create an array and
6739       // collect mergeable display items there.
6740       AutoTArray<nsDisplayItem*, 2> willMerge{current};
6741 
6742       auto it = mStart;
6743       while (it != mEnd) {
6744         nsDisplayItem* next = *it;
6745         if (current->CanMerge(next)) {
6746           willMerge.AppendElement(next);
6747           ++it;
6748         } else {
6749           break;
6750         }
6751       }
6752       mStart = it;
6753 
6754       current = mBuilder->MergeItems(willMerge);
6755     }
6756 
6757     ResolveFlattening();
6758     return current;
6759   }
6760 
6761  protected:
Advance()6762   void Advance() { ++mStart; }
6763 
AtEndOfNestedList()6764   bool AtEndOfNestedList() const {
6765     return AtEndOfCurrentList() && mStack.Length() > 0;
6766   }
6767 
AtEndOfCurrentList()6768   bool AtEndOfCurrentList() const { return mStart == mEnd; }
6769 
NextItem()6770   nsDisplayItem* NextItem() {
6771     MOZ_ASSERT(HasNext());
6772     return *mStart;
6773   }
6774 
ShouldFlattenNextItem()6775   bool ShouldFlattenNextItem() {
6776     return HasNext() && NextItem()->ShouldFlattenAway(mBuilder);
6777   }
6778 
ResolveFlattening()6779   void ResolveFlattening() {
6780     // Handle the case where we reach the end of a nested list, or the current
6781     // item should start a new nested list. Repeat this until we find an actual
6782     // item, or the very end of the outer list.
6783     while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
6784       if (AtEndOfNestedList()) {
6785         // We reached the end of the list, pop the next list from the stack.
6786         std::tie(mStart, mEnd) = mStack.PopLastElement();
6787       } else {
6788         // The next item wants to be flattened. This means that we will skip the
6789         // flattened item and directly iterate over its sublist.
6790         MOZ_ASSERT(ShouldFlattenNextItem());
6791 
6792         nsDisplayList* sublist = NextItem()->GetChildren();
6793         MOZ_ASSERT(sublist);
6794 
6795         // Skip the flattened item.
6796         Advance();
6797 
6798         // Store the current position on the stack.
6799         if (!AtEndOfCurrentList()) {
6800           mStack.AppendElement(std::make_pair(mStart, mEnd));
6801         }
6802 
6803         // Iterate over the sublist.
6804         mStart = sublist->begin();
6805         mEnd = sublist->end();
6806       }
6807     }
6808   }
6809 
6810  private:
6811   nsDisplayListBuilder* mBuilder;
6812   nsDisplayList::iterator mStart;
6813   nsDisplayList::iterator mEnd;
6814   nsTArray<std::pair<nsDisplayList::iterator, nsDisplayList::iterator>> mStack;
6815 };
6816 
6817 class PaintTelemetry {
6818  public:
6819   class AutoRecordPaint {
6820    public:
6821     AutoRecordPaint();
6822     ~AutoRecordPaint();
6823 
6824    private:
6825     TimeStamp mStart;
6826   };
6827 
6828  private:
6829   static uint32_t sPaintLevel;
6830 };
6831 
6832 }  // namespace mozilla
6833 
6834 #endif /*NSDISPLAYLIST_H_*/
6835