tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsDisplayList.h (254233B)


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