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