Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef GFX_WEBRENDERSCROLLDATAWRAPPER_H
7 : #define GFX_WEBRENDERSCROLLDATAWRAPPER_H
8 :
9 : #include "FrameMetrics.h"
10 : #include "mozilla/layers/CompositorBridgeParent.h"
11 : #include "mozilla/layers/WebRenderBridgeParent.h"
12 : #include "mozilla/layers/WebRenderScrollData.h"
13 :
14 : namespace mozilla {
15 : namespace layers {
16 :
17 : /*
18 : * This class is a wrapper to walk through a WebRenderScrollData object, with
19 : * an exposed API that is template-compatible to LayerMetricsWrapper. This allows
20 : * APZ to walk through both layer trees and WebRender scroll metadata structures
21 : * without a lot of code duplication.
22 : * (Note that not all functions from LayerMetricsWrapper are implemented here,
23 : * only the ones we've needed in APZ code so far.)
24 : *
25 : * A WebRenderScrollData object is basically a flattened layer tree, with a
26 : * number of WebRenderLayerScrollData objects that have a 1:1 correspondence
27 : * to layers in a layer tree. Therefore the mLayer pointer in this class can
28 : * be considered equivalent to the mLayer pointer in the LayerMetricsWrapper.
29 : * There are some extra fields (mData, mLayerIndex, mContainingSubtreeLastIndex)
30 : * to move around between these "layers" given the flattened representation.
31 : * The mMetadataIndex field in this class corresponds to the mIndex field in
32 : * LayerMetricsWrapper, as both classes also need to manage walking through
33 : * "virtual" container layers implied by the list of ScrollMetadata objects.
34 : *
35 : * One important note here is that this class holds a pointer to the "owning"
36 : * WebRenderScrollData. The caller must ensure that this class does not outlive
37 : * the owning WebRenderScrollData, or this may result in use-after-free errors.
38 : * This class being declared a MOZ_STACK_CLASS should help with that.
39 : *
40 : * Refer to LayerMetricsWrapper.h for actual documentation on the exposed API.
41 : */
42 : class MOZ_STACK_CLASS WebRenderScrollDataWrapper {
43 : public:
44 : // Basic constructor for external callers. Starts the walker at the root of
45 : // the tree.
46 0 : explicit WebRenderScrollDataWrapper(const WebRenderScrollData* aData = nullptr)
47 0 : : mData(aData)
48 : , mLayerIndex(0)
49 : , mContainingSubtreeLastIndex(0)
50 : , mLayer(nullptr)
51 0 : , mMetadataIndex(0)
52 : {
53 0 : if (!mData) {
54 0 : return;
55 : }
56 0 : mLayer = mData->GetLayerData(mLayerIndex);
57 0 : if (!mLayer) {
58 0 : return;
59 : }
60 :
61 : // sanity check on the data
62 0 : MOZ_ASSERT(mData->GetLayerCount() == (size_t)(1 + mLayer->GetDescendantCount()));
63 0 : mContainingSubtreeLastIndex = mData->GetLayerCount();
64 :
65 : // See documentation in LayerMetricsWrapper.h about this. mMetadataIndex
66 : // in this class is equivalent to mIndex in that class.
67 0 : mMetadataIndex = mLayer->GetScrollMetadataCount();
68 0 : if (mMetadataIndex > 0) {
69 0 : mMetadataIndex--;
70 : }
71 : }
72 :
73 : private:
74 : // Internal constructor for walking from one WebRenderLayerScrollData to
75 : // another. In this case we need to recompute the mMetadataIndex to be the
76 : // "topmost" scroll metadata on the new layer.
77 0 : WebRenderScrollDataWrapper(const WebRenderScrollData* aData,
78 : size_t aLayerIndex,
79 : size_t aContainingSubtreeLastIndex)
80 0 : : mData(aData)
81 : , mLayerIndex(aLayerIndex)
82 : , mContainingSubtreeLastIndex(aContainingSubtreeLastIndex)
83 : , mLayer(nullptr)
84 0 : , mMetadataIndex(0)
85 : {
86 0 : MOZ_ASSERT(mData);
87 0 : mLayer = mData->GetLayerData(mLayerIndex);
88 0 : MOZ_ASSERT(mLayer);
89 :
90 : // See documentation in LayerMetricsWrapper.h about this. mMetadataIndex
91 : // in this class is equivalent to mIndex in that class.
92 0 : mMetadataIndex = mLayer->GetScrollMetadataCount();
93 0 : if (mMetadataIndex > 0) {
94 0 : mMetadataIndex--;
95 : }
96 0 : }
97 :
98 : // Internal constructor for walking from one metadata to another metadata on
99 : // the same WebRenderLayerScrollData.
100 0 : WebRenderScrollDataWrapper(const WebRenderScrollData* aData,
101 : size_t aLayerIndex,
102 : size_t aContainingSubtreeLastIndex,
103 : const WebRenderLayerScrollData* aLayer,
104 : uint32_t aMetadataIndex)
105 0 : : mData(aData)
106 : , mLayerIndex(aLayerIndex)
107 : , mContainingSubtreeLastIndex(aContainingSubtreeLastIndex)
108 : , mLayer(aLayer)
109 0 : , mMetadataIndex(aMetadataIndex)
110 : {
111 0 : MOZ_ASSERT(mData);
112 0 : MOZ_ASSERT(mLayer);
113 0 : MOZ_ASSERT(mLayer == mData->GetLayerData(mLayerIndex));
114 0 : MOZ_ASSERT(mMetadataIndex == 0 || mMetadataIndex < mLayer->GetScrollMetadataCount());
115 0 : }
116 :
117 : public:
118 0 : bool IsValid() const
119 : {
120 0 : return mLayer != nullptr;
121 : }
122 :
123 0 : explicit operator bool() const
124 : {
125 0 : return IsValid();
126 : }
127 :
128 0 : bool IsScrollInfoLayer() const
129 : {
130 0 : MOZ_ASSERT(IsValid());
131 :
132 0 : return Metrics().IsScrollable()
133 0 : && mLayer->IsScrollInfoLayer();
134 : }
135 :
136 0 : WebRenderScrollDataWrapper GetLastChild() const
137 : {
138 0 : MOZ_ASSERT(IsValid());
139 :
140 0 : if (!AtBottomLayer()) {
141 : // If we're still walking around in the virtual container layers created
142 : // by the ScrollMetadata array, we just need to update the metadata index
143 : // and that's it.
144 0 : return WebRenderScrollDataWrapper(mData, mLayerIndex,
145 0 : mContainingSubtreeLastIndex, mLayer, mMetadataIndex - 1);
146 : }
147 :
148 : // Otherwise, we need to walk to a different WebRenderLayerScrollData in
149 : // mData.
150 :
151 : // Since mData contains the layer in depth-first, last-to-first order,
152 : // the index after mLayerIndex must be mLayerIndex's last child, if it
153 : // has any children (indicated by GetDescendantCount() > 0). Furthermore
154 : // we compute the first index outside the subtree rooted at this node
155 : // (in |subtreeLastIndex|) and pass that in to the child wrapper to use as
156 : // its mContainingSubtreeLastIndex.
157 0 : if (mLayer->GetDescendantCount() > 0) {
158 0 : size_t prevSiblingIndex = mLayerIndex + 1 + mLayer->GetDescendantCount();
159 0 : size_t subtreeLastIndex = std::min(mContainingSubtreeLastIndex, prevSiblingIndex);
160 0 : return WebRenderScrollDataWrapper(mData, mLayerIndex + 1, subtreeLastIndex);
161 : }
162 :
163 : // We've run out of descendants. But! If the original layer was a RefLayer,
164 : // then it connects to another layer tree and we need to traverse that too.
165 : // So return a WebRenderScrollDataWrapper for the root of the child layer
166 : // tree.
167 0 : if (mLayer->GetReferentId()) {
168 : CompositorBridgeParent::LayerTreeState* lts =
169 0 : CompositorBridgeParent::GetIndirectShadowTree(mLayer->GetReferentId().value());
170 0 : if (lts && lts->mWrBridge) {
171 0 : return WebRenderScrollDataWrapper(&(lts->mWrBridge->GetScrollData()));
172 : }
173 : }
174 :
175 0 : return WebRenderScrollDataWrapper();
176 : }
177 :
178 0 : WebRenderScrollDataWrapper GetPrevSibling() const
179 : {
180 0 : MOZ_ASSERT(IsValid());
181 :
182 0 : if (!AtTopLayer()) {
183 : // The virtual container layers don't have siblings
184 0 : return WebRenderScrollDataWrapper();
185 : }
186 :
187 : // Skip past the descendants to get to the previous sibling. However, we
188 : // might be at the last sibling already.
189 0 : size_t prevSiblingIndex = mLayerIndex + 1 + mLayer->GetDescendantCount();
190 0 : if (prevSiblingIndex < mContainingSubtreeLastIndex) {
191 0 : return WebRenderScrollDataWrapper(mData, prevSiblingIndex, mContainingSubtreeLastIndex);
192 : }
193 0 : return WebRenderScrollDataWrapper();
194 : }
195 :
196 0 : const ScrollMetadata& Metadata() const
197 : {
198 0 : MOZ_ASSERT(IsValid());
199 :
200 0 : if (mMetadataIndex >= mLayer->GetScrollMetadataCount()) {
201 0 : return *ScrollMetadata::sNullMetadata;
202 : }
203 0 : return mLayer->GetScrollMetadata(*mData, mMetadataIndex);
204 : }
205 :
206 0 : const FrameMetrics& Metrics() const
207 : {
208 0 : return Metadata().GetMetrics();
209 : }
210 :
211 0 : AsyncPanZoomController* GetApzc() const
212 : {
213 0 : return nullptr;
214 : }
215 :
216 0 : void SetApzc(AsyncPanZoomController* aApzc) const
217 : {
218 0 : }
219 :
220 0 : const char* Name() const
221 : {
222 0 : return "WebRenderScrollDataWrapper";
223 : }
224 :
225 0 : gfx::Matrix4x4 GetTransform() const
226 : {
227 0 : MOZ_ASSERT(IsValid());
228 :
229 0 : if (AtBottomLayer()) {
230 0 : return mLayer->GetTransform();
231 : }
232 0 : return gfx::Matrix4x4();
233 : }
234 :
235 0 : CSSTransformMatrix GetTransformTyped() const
236 : {
237 0 : return ViewAs<CSSTransformMatrix>(GetTransform());
238 : }
239 :
240 0 : bool TransformIsPerspective() const
241 : {
242 0 : MOZ_ASSERT(IsValid());
243 :
244 0 : if (AtBottomLayer()) {
245 0 : return mLayer->GetTransformIsPerspective();
246 : }
247 0 : return false;
248 : }
249 :
250 0 : EventRegions GetEventRegions() const
251 : {
252 0 : MOZ_ASSERT(IsValid());
253 :
254 0 : if (AtBottomLayer()) {
255 0 : return mLayer->GetEventRegions();
256 : }
257 0 : return EventRegions();
258 : }
259 :
260 0 : LayerIntRegion GetVisibleRegion() const
261 : {
262 0 : MOZ_ASSERT(IsValid());
263 :
264 0 : if (AtBottomLayer()) {
265 0 : return mLayer->GetVisibleRegion();
266 : }
267 :
268 : return ViewAs<LayerPixel>(
269 0 : TransformBy(mLayer->GetTransformTyped(), mLayer->GetVisibleRegion()),
270 0 : PixelCastJustification::MovingDownToChildren);
271 : }
272 :
273 0 : Maybe<uint64_t> GetReferentId() const
274 : {
275 0 : MOZ_ASSERT(IsValid());
276 :
277 0 : if (AtBottomLayer()) {
278 0 : return mLayer->GetReferentId();
279 : }
280 0 : return Nothing();
281 : }
282 :
283 0 : Maybe<ParentLayerIntRect> GetClipRect() const
284 : {
285 : // TODO
286 0 : return Nothing();
287 : }
288 :
289 0 : EventRegionsOverride GetEventRegionsOverride() const
290 : {
291 0 : MOZ_ASSERT(IsValid());
292 0 : return mLayer->GetEventRegionsOverride();
293 : }
294 :
295 0 : const ScrollThumbData& GetScrollThumbData() const
296 : {
297 0 : MOZ_ASSERT(IsValid());
298 0 : return mLayer->GetScrollThumbData();
299 : }
300 :
301 0 : uint64_t GetScrollbarAnimationId() const
302 : {
303 0 : MOZ_ASSERT(IsValid());
304 0 : return mLayer->GetScrollbarAnimationId();
305 : }
306 :
307 0 : FrameMetrics::ViewID GetScrollbarTargetContainerId() const
308 : {
309 0 : MOZ_ASSERT(IsValid());
310 0 : return mLayer->GetScrollbarTargetContainerId();
311 : }
312 :
313 0 : bool IsScrollbarContainer() const
314 : {
315 0 : MOZ_ASSERT(IsValid());
316 0 : return mLayer->IsScrollbarContainer();
317 : }
318 :
319 0 : FrameMetrics::ViewID GetFixedPositionScrollContainerId() const
320 : {
321 0 : MOZ_ASSERT(IsValid());
322 0 : return mLayer->GetFixedPositionScrollContainerId();
323 : }
324 :
325 : const void* GetLayer() const
326 : {
327 : MOZ_ASSERT(IsValid());
328 : return mLayer;
329 : }
330 :
331 : private:
332 0 : bool AtBottomLayer() const
333 : {
334 0 : return mMetadataIndex == 0;
335 : }
336 :
337 0 : bool AtTopLayer() const
338 : {
339 0 : return mLayer->GetScrollMetadataCount() == 0 || mMetadataIndex == mLayer->GetScrollMetadataCount() - 1;
340 : }
341 :
342 : private:
343 : const WebRenderScrollData* mData;
344 : // The index (in mData->mLayerScrollData) of the WebRenderLayerScrollData this
345 : // wrapper is pointing to.
346 : size_t mLayerIndex;
347 : // The upper bound on the set of valid indices inside the subtree rooted at
348 : // the parent of this "layer". That is, any layer index |i| in the range
349 : // mLayerIndex <= i < mContainingSubtreeLastIndex is guaranteed to point to
350 : // a layer that is a descendant of "parent", where "parent" is the parent
351 : // layer of the layer at mLayerIndex. This is needed in order to implement
352 : // GetPrevSibling() correctly.
353 : size_t mContainingSubtreeLastIndex;
354 : // The WebRenderLayerScrollData this wrapper is pointing to.
355 : const WebRenderLayerScrollData* mLayer;
356 : // The index of the scroll metadata within mLayer that this wrapper is
357 : // pointing to.
358 : uint32_t mMetadataIndex;
359 : };
360 :
361 : } // namespace layers
362 : } // namespace mozilla
363 :
364 : #endif /* GFX_WEBRENDERSCROLLDATAWRAPPER_H */
|