tor-browser

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

ClipManager.h (7036B)


      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 #ifndef GFX_CLIPMANAGER_H
      8 #define GFX_CLIPMANAGER_H
      9 
     10 #include <stack>
     11 #include <unordered_map>
     12 
     13 #include "mozilla/Attributes.h"
     14 #include "mozilla/webrender/WebRenderAPI.h"
     15 #include "mozilla/layout/StickyScrollContainer.h"
     16 
     17 namespace mozilla {
     18 
     19 class nsDisplayItem;
     20 class nsDisplayStickyPosition;
     21 struct ActiveScrolledRoot;
     22 struct DisplayItemClipChain;
     23 
     24 namespace wr {
     25 class DisplayListBuilder;
     26 }
     27 
     28 namespace layers {
     29 
     30 class StackingContextHelper;
     31 class WebRenderLayerManager;
     32 
     33 /**
     34 * This class manages creating and assigning scroll layers and clips in
     35 * WebRender based on the gecko display list. It has a few public functions that
     36 * are intended to be invoked while traversing the Gecko display list, and it
     37 * uses the ASR and clip information from the display list to create the
     38 * necessary clip state in WebRender.
     39 *
     40 * The structure of the clip state in WebRender ends up quite similar to how
     41 * it is in Gecko. For each ASR in Gecko, we create a scroll layer (i.e. a
     42 * scrolling clip) in WebRender; these form a tree structure similar to the
     43 * ASR tree structure. Ancestors of scroll layers are always other scroll
     44 * layers, or the root scroll node.
     45 * The DisplayItemClipChain list of clips from the gecko display list is
     46 * converted to a WR clip chain and pushed on the stack prior to creating
     47 * any WR commands for that item, and is popped afterwards. In addition,
     48 * the WR clip chain has a parent pointer, which points to the clip chain for
     49 * any enclosing stacking context. This again results in a strucuture very
     50 * similar to that in Gecko, where the clips from container display items get
     51 * applied to the contained display items.
     52 */
     53 class ClipManager {
     54 public:
     55  ClipManager();
     56 
     57  void BeginBuild(WebRenderLayerManager* aManager,
     58                  wr::DisplayListBuilder& aBuilder);
     59  void EndBuild();
     60 
     61  void BeginList(const StackingContextHelper& aStackingContext);
     62  void EndList(const StackingContextHelper& aStackingContext);
     63 
     64  wr::WrSpaceAndClipChain SwitchItem(nsDisplayListBuilder* aBuilder,
     65                                     nsDisplayItem* aItem);
     66  ~ClipManager();
     67 
     68  void PushOverrideForASR(const ActiveScrolledRoot* aASR,
     69                          const wr::WrSpatialId& aSpatialId);
     70  void PopOverrideForASR(const ActiveScrolledRoot* aASR);
     71 
     72 private:
     73  wr::WrSpatialId SpatialIdAfterOverride(const wr::WrSpatialId& aSpatialId);
     74  wr::WrSpatialId GetSpatialId(const ActiveScrolledRoot* aASR);
     75 
     76  static StickyScrollContainer* GetStickyScrollContainer(
     77      const ActiveScrolledRoot* aASR);
     78  Maybe<wr::WrSpatialId> DefineSpatialNodes(nsDisplayListBuilder* aBuilder,
     79                                            const ActiveScrolledRoot* aASR,
     80                                            nsDisplayItem* aItem);
     81  Maybe<wr::WrSpatialId> DefineStickyNode(
     82      nsDisplayListBuilder* aBuilder, Maybe<wr::WrSpatialId> aParentSpatialId,
     83      const ActiveScrolledRoot* aASR, nsDisplayItem* aItem);
     84 
     85  Maybe<wr::WrClipChainId> DefineClipChain(const DisplayItemClipChain* aChain,
     86                                           int32_t aAppUnitsPerDevPixel);
     87 
     88  WebRenderLayerManager* MOZ_NON_OWNING_REF mManager;
     89  wr::DisplayListBuilder* mBuilder;
     90 
     91  // Stack of clip caches. Each cache contains a map from gecko
     92  // DisplayItemClipChain objects to webrender WrClipIds, which allows us to
     93  // avoid redefining identical clips in WR. However, the gecko
     94  // DisplayItemClipChain items get deduplicated quite aggressively, without
     95  // regard to things like the enclosing reference frame or mask. On the WR
     96  // side, we cannot deduplicate clips that aggressively. So what we do is
     97  // any time we enter a new reference frame (for example) we create a new clip
     98  // cache on mCacheStack. This ensures we continue caching stuff within a given
     99  // reference frame, but disallow caching stuff across reference frames. In
    100  // general we need to do this anytime PushOverrideForASR is called, as that is
    101  // called for the same set of conditions for which we cannot deduplicate
    102  // clips.
    103  struct ClipChainCacheEntry {
    104    Maybe<wr::WrClipChainId> mWrChainID;
    105  };
    106  using ClipIdMap =
    107      std::unordered_map<const DisplayItemClipChain*, ClipChainCacheEntry>;
    108  std::stack<ClipIdMap> mCacheStack;
    109 
    110  // A map that holds the cache overrides created by (a) "out of band" clips,
    111  // i.e. clips that are generated by display items but that ClipManager
    112  // doesn't know about and (b) stacking contexts that affect clip positioning.
    113  // These are called "cache overrides" because while we're inside these things,
    114  // we cannot use the ASR from the gecko display list as-is. Fundamentally this
    115  // results from a mismatch between the ASR+clip items on the gecko side and
    116  // the ClipScrollTree on the WR side; the WR side incorporates things like
    117  // transforms and stacking context origins while the gecko side manages those
    118  // differently.
    119  // Any time ClipManager wants to define a new clip as a child of ASR X, it
    120  // should first check the cache overrides to see if there is a cache override
    121  // item ((a) or (b) above) that is already a child of X, and then define that
    122  // clip as a child of Y instead. This map stores X -> Y, which allows
    123  // ClipManager to do the necessary lookup. Note that there theoretically might
    124  // be multiple different "Y" clips (in case of nested cache overrides), which
    125  // is why we need a stack.
    126  std::unordered_map<wr::WrSpatialId, std::stack<wr::WrSpatialId>> mASROverride;
    127 
    128  // This holds some clip state for a single nsDisplayItem
    129  struct ItemClips {
    130    ItemClips(const ActiveScrolledRoot* aASR,
    131              const DisplayItemClipChain* aChain, int32_t aAppUnitsPerDevPixel,
    132              bool aSeparateLeaf);
    133 
    134    // These are the "inputs" - they come from the nsDisplayItem
    135    const ActiveScrolledRoot* mASR;
    136    const DisplayItemClipChain* mChain;
    137    int32_t mAppUnitsPerDevPixel;
    138    bool mSeparateLeaf;
    139 
    140    // These are the "outputs" - they are pushed to WR as needed
    141    wr::WrSpatialId mScrollId;
    142    Maybe<wr::WrClipChainId> mClipChainId;
    143 
    144    void UpdateSeparateLeaf(wr::DisplayListBuilder& aBuilder,
    145                            int32_t aAppUnitsPerDevPixel);
    146    bool HasSameInputs(const ItemClips& aOther);
    147    wr::WrSpaceAndClipChain GetSpaceAndClipChain() const;
    148  };
    149 
    150  // A stack of ItemClips corresponding to the nsDisplayItem ancestry. Each
    151  // time we recurse into a nsDisplayItem's child list, this stack size
    152  // increases by one. The topmost item on the stack is for the display item
    153  // we are currently processing and items deeper on the stack are for that
    154  // display item's ancestors.
    155  std::stack<ItemClips> mItemClipStack;
    156 };
    157 
    158 }  // namespace layers
    159 }  // namespace mozilla
    160 
    161 #endif