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_LAYERMETRICSWRAPPER_H
7 : #define GFX_LAYERMETRICSWRAPPER_H
8 :
9 : #include "Layers.h"
10 : #include "UnitTransforms.h"
11 :
12 : namespace mozilla {
13 : namespace layers {
14 :
15 : /**
16 : * A wrapper class around a target Layer with that allows user code to
17 : * walk through the FrameMetrics objects on the layer the same way it
18 : * would walk through a ContainerLayer hierarchy. Consider the following
19 : * layer tree:
20 : *
21 : * +---+
22 : * | A |
23 : * +---+
24 : * / | \
25 : * / | \
26 : * / | \
27 : * +---+ +-----+ +---+
28 : * | B | | C | | D |
29 : * +---+ +-----+ +---+
30 : * | FMn |
31 : * | . |
32 : * | . |
33 : * | . |
34 : * | FM1 |
35 : * | FM0 |
36 : * +-----+
37 : * / \
38 : * / \
39 : * +---+ +---+
40 : * | E | | F |
41 : * +---+ +---+
42 : *
43 : * In this layer tree, there are six layers with A being the root and B,D,E,F
44 : * being leaf nodes. Layer C is in the middle and has n+1 FrameMetrics, labelled
45 : * FM0...FMn. FM0 is the FrameMetrics you get by calling c->GetFrameMetrics(0)
46 : * and FMn is the FrameMetrics you can obtain by calling
47 : * c->GetFrameMetrics(c->GetScrollMetadataCount() - 1). This layer tree is
48 : * conceptually equivalent to this one below:
49 : *
50 : * +---+
51 : * | A |
52 : * +---+
53 : * / | \
54 : * / | \
55 : * / | \
56 : * +---+ +-----+ +---+
57 : * | B | | Cn | | D |
58 : * +---+ +-----+ +---+
59 : * |
60 : * .
61 : * .
62 : * .
63 : * |
64 : * +-----+
65 : * | C1 |
66 : * +-----+
67 : * |
68 : * +-----+
69 : * | C0 |
70 : * +-----+
71 : * / \
72 : * / \
73 : * +---+ +---+
74 : * | E | | F |
75 : * +---+ +---+
76 : *
77 : * In this layer tree, the layer C has been expanded into a stack of container
78 : * layers C1...Cn, where C1 has FrameMetrics FM1 and Cn has FrameMetrics Fn.
79 : * Although in this example C (in the first layer tree) and C0 (in the second
80 : * layer tree) are both ContainerLayers (because they have children), they
81 : * do not have to be. They may just be PaintedLayers or ColorLayers, for example,
82 : * which do not have any children. However, the type of C will always be the
83 : * same as the type of C0.
84 : *
85 : * The LayerMetricsWrapper class allows client code to treat the first layer
86 : * tree as though it were the second. That is, instead of client code having
87 : * to iterate through the FrameMetrics objects directly, it can use a
88 : * LayerMetricsWrapper to encapsulate that aspect of the layer tree and just
89 : * walk the tree as if it were a stack of ContainerLayers.
90 : *
91 : * The functions on this class do different things depending on which
92 : * simulated ContainerLayer is being wrapped. For example, if the
93 : * LayerMetricsWrapper is pretending to be C0, the GetNextSibling() function
94 : * will return null even though the underlying layer C does actually have
95 : * a next sibling. The LayerMetricsWrapper pretending to be Cn will return
96 : * D as the next sibling.
97 : *
98 : * Implementation notes:
99 : *
100 : * The AtTopLayer() and AtBottomLayer() functions in this class refer to
101 : * Cn and C0 in the second layer tree above; that is, they are predicates
102 : * to test if the LayerMetricsWrapper is simulating the topmost or bottommost
103 : * layer, as those will have special behaviour.
104 : *
105 : * It is possible to wrap a nullptr in a LayerMetricsWrapper, in which case
106 : * the IsValid() function will return false. This is required to allow
107 : * LayerMetricsWrapper to be a MOZ_STACK_CLASS (desirable because it is used
108 : * in loops and recursion).
109 : *
110 : * This class purposely does not expose the wrapped layer directly to avoid
111 : * user code from accidentally calling functions directly on it. Instead
112 : * any necessary functions should be wrapped in this class. It does expose
113 : * the wrapped layer as a void* for printf purposes.
114 : *
115 : * The implementation may look like it special-cases mIndex == 0 and/or
116 : * GetScrollMetadataCount() == 0. This is an artifact of the fact that both
117 : * mIndex and GetScrollMetadataCount() are uint32_t and GetScrollMetadataCount()
118 : * can return 0 but mIndex cannot store -1. This seems better than the
119 : * alternative of making mIndex a int32_t that can store -1, but then having
120 : * to cast to uint32_t all over the place.
121 : */
122 : class MOZ_STACK_CLASS LayerMetricsWrapper {
123 : public:
124 : enum StartAt {
125 : TOP,
126 : BOTTOM,
127 : };
128 :
129 0 : LayerMetricsWrapper()
130 0 : : mLayer(nullptr)
131 0 : , mIndex(0)
132 : {
133 0 : }
134 :
135 852 : explicit LayerMetricsWrapper(Layer* aRoot, StartAt aStart = StartAt::TOP)
136 852 : : mLayer(aRoot)
137 852 : , mIndex(0)
138 : {
139 852 : if (!mLayer) {
140 426 : return;
141 : }
142 :
143 426 : switch (aStart) {
144 : case StartAt::TOP:
145 426 : mIndex = mLayer->GetScrollMetadataCount();
146 426 : if (mIndex > 0) {
147 79 : mIndex--;
148 : }
149 426 : break;
150 : case StartAt::BOTTOM:
151 0 : mIndex = 0;
152 0 : break;
153 : default:
154 0 : MOZ_ASSERT_UNREACHABLE("Unknown startAt value");
155 : break;
156 : }
157 : }
158 :
159 0 : explicit LayerMetricsWrapper(Layer* aLayer, uint32_t aMetricsIndex)
160 0 : : mLayer(aLayer)
161 0 : , mIndex(aMetricsIndex)
162 : {
163 0 : MOZ_ASSERT(mLayer);
164 0 : MOZ_ASSERT(mIndex == 0 || mIndex < mLayer->GetScrollMetadataCount());
165 0 : }
166 :
167 6646 : bool IsValid() const
168 : {
169 6646 : return mLayer != nullptr;
170 : }
171 :
172 1249 : explicit operator bool() const
173 : {
174 1249 : return IsValid();
175 : }
176 :
177 250 : bool IsScrollInfoLayer() const
178 : {
179 250 : MOZ_ASSERT(IsValid());
180 :
181 : // If we are not at the bottommost layer then it's
182 : // a stack of container layers all the way down to
183 : // mLayer, which we can ignore. We only care about
184 : // non-container descendants.
185 250 : return Metrics().IsScrollable()
186 78 : && mLayer->AsContainerLayer()
187 306 : && !mLayer->GetFirstChild();
188 : }
189 :
190 0 : LayerMetricsWrapper GetParent() const
191 : {
192 0 : MOZ_ASSERT(IsValid());
193 :
194 0 : if (!AtTopLayer()) {
195 0 : return LayerMetricsWrapper(mLayer, mIndex + 1);
196 : }
197 0 : if (mLayer->GetParent()) {
198 0 : return LayerMetricsWrapper(mLayer->GetParent(), StartAt::BOTTOM);
199 : }
200 0 : return LayerMetricsWrapper(nullptr);
201 : }
202 :
203 215 : LayerMetricsWrapper GetFirstChild() const
204 : {
205 215 : MOZ_ASSERT(IsValid());
206 :
207 215 : if (!AtBottomLayer()) {
208 0 : return LayerMetricsWrapper(mLayer, mIndex - 1);
209 : }
210 215 : return LayerMetricsWrapper(mLayer->GetFirstChild());
211 : }
212 :
213 211 : LayerMetricsWrapper GetLastChild() const
214 : {
215 211 : MOZ_ASSERT(IsValid());
216 :
217 211 : if (!AtBottomLayer()) {
218 0 : return LayerMetricsWrapper(mLayer, mIndex - 1);
219 : }
220 211 : return LayerMetricsWrapper(mLayer->GetLastChild());
221 : }
222 :
223 183 : LayerMetricsWrapper GetPrevSibling() const
224 : {
225 183 : MOZ_ASSERT(IsValid());
226 :
227 183 : if (AtTopLayer()) {
228 183 : return LayerMetricsWrapper(mLayer->GetPrevSibling());
229 : }
230 0 : return LayerMetricsWrapper(nullptr);
231 : }
232 :
233 186 : LayerMetricsWrapper GetNextSibling() const
234 : {
235 186 : MOZ_ASSERT(IsValid());
236 :
237 186 : if (AtTopLayer()) {
238 186 : return LayerMetricsWrapper(mLayer->GetNextSibling());
239 : }
240 0 : return LayerMetricsWrapper(nullptr);
241 : }
242 :
243 875 : const ScrollMetadata& Metadata() const
244 : {
245 875 : MOZ_ASSERT(IsValid());
246 :
247 875 : if (mIndex >= mLayer->GetScrollMetadataCount()) {
248 568 : return *ScrollMetadata::sNullMetadata;
249 : }
250 307 : return mLayer->GetScrollMetadata(mIndex);
251 : }
252 :
253 528 : const FrameMetrics& Metrics() const
254 : {
255 528 : return Metadata().GetMetrics();
256 : }
257 :
258 249 : AsyncPanZoomController* GetApzc() const
259 : {
260 249 : MOZ_ASSERT(IsValid());
261 :
262 249 : if (mIndex >= mLayer->GetScrollMetadataCount()) {
263 175 : return nullptr;
264 : }
265 74 : return mLayer->GetAsyncPanZoomController(mIndex);
266 : }
267 :
268 211 : void SetApzc(AsyncPanZoomController* aApzc) const
269 : {
270 211 : MOZ_ASSERT(IsValid());
271 :
272 211 : if (mLayer->GetScrollMetadataCount() == 0) {
273 172 : MOZ_ASSERT(mIndex == 0);
274 172 : MOZ_ASSERT(aApzc == nullptr);
275 172 : return;
276 : }
277 39 : MOZ_ASSERT(mIndex < mLayer->GetScrollMetadataCount());
278 39 : mLayer->SetAsyncPanZoomController(mIndex, aApzc);
279 : }
280 :
281 211 : const char* Name() const
282 : {
283 211 : MOZ_ASSERT(IsValid());
284 :
285 211 : if (AtBottomLayer()) {
286 211 : return mLayer->Name();
287 : }
288 0 : return "DummyContainerLayer";
289 : }
290 :
291 0 : LayerManager* Manager() const
292 : {
293 0 : MOZ_ASSERT(IsValid());
294 :
295 0 : return mLayer->Manager();
296 : }
297 :
298 422 : gfx::Matrix4x4 GetTransform() const
299 : {
300 422 : MOZ_ASSERT(IsValid());
301 :
302 422 : if (AtBottomLayer()) {
303 422 : return mLayer->GetTransform();
304 : }
305 0 : return gfx::Matrix4x4();
306 : }
307 :
308 211 : CSSTransformMatrix GetTransformTyped() const
309 : {
310 211 : return ViewAs<CSSTransformMatrix>(GetTransform());
311 : }
312 :
313 211 : bool TransformIsPerspective() const
314 : {
315 211 : MOZ_ASSERT(IsValid());
316 :
317 : // mLayer->GetTransformIsPerspective() tells us whether
318 : // mLayer->GetTransform() is a perspective transform. Since
319 : // mLayer->GetTransform() is only used at the bottom layer, we only
320 : // need to check GetTransformIsPerspective() at the bottom layer too.
321 211 : if (AtBottomLayer()) {
322 211 : return mLayer->GetTransformIsPerspective();
323 : }
324 0 : return false;
325 : }
326 :
327 211 : EventRegions GetEventRegions() const
328 : {
329 211 : MOZ_ASSERT(IsValid());
330 :
331 211 : if (AtBottomLayer()) {
332 211 : return mLayer->GetEventRegions();
333 : }
334 0 : return EventRegions();
335 : }
336 :
337 211 : LayerIntRegion GetVisibleRegion() const
338 : {
339 211 : MOZ_ASSERT(IsValid());
340 :
341 211 : if (AtBottomLayer()) {
342 211 : return mLayer->GetVisibleRegion();
343 : }
344 :
345 : return ViewAs<LayerPixel>(
346 0 : TransformBy(mLayer->GetTransformTyped(), mLayer->GetVisibleRegion()),
347 0 : PixelCastJustification::MovingDownToChildren);
348 : }
349 :
350 0 : bool HasTransformAnimation() const
351 : {
352 0 : MOZ_ASSERT(IsValid());
353 :
354 0 : if (AtBottomLayer()) {
355 0 : return mLayer->HasTransformAnimation();
356 : }
357 0 : return false;
358 : }
359 :
360 0 : RefLayer* AsRefLayer() const
361 : {
362 0 : MOZ_ASSERT(IsValid());
363 :
364 0 : if (AtBottomLayer()) {
365 0 : return mLayer->AsRefLayer();
366 : }
367 0 : return nullptr;
368 : }
369 :
370 211 : Maybe<uint64_t> GetReferentId() const
371 : {
372 211 : MOZ_ASSERT(IsValid());
373 :
374 211 : if (AtBottomLayer()) {
375 211 : return mLayer->AsRefLayer()
376 267 : ? Some(mLayer->AsRefLayer()->GetReferentId())
377 422 : : Nothing();
378 : }
379 0 : return Nothing();
380 : }
381 :
382 274 : Maybe<ParentLayerIntRect> GetClipRect() const
383 : {
384 274 : MOZ_ASSERT(IsValid());
385 :
386 274 : Maybe<ParentLayerIntRect> result;
387 :
388 : // The layer can have a clip rect and a scrolled clip, which are considered
389 : // to apply only to the bottommost LayerMetricsWrapper.
390 : // TODO: These actually apply in a different coordinate space than the
391 : // scroll clip of the bottommost metrics, so we shouldn't be intersecting
392 : // them with the scroll clip; bug 1269537 tracks fixing this.
393 274 : if (AtBottomLayer()) {
394 274 : result = mLayer->GetClipRect();
395 274 : result = IntersectMaybeRects(result, mLayer->GetScrolledClipRect());
396 : }
397 :
398 : // The scroll metadata can have a clip rect as well.
399 274 : result = IntersectMaybeRects(result, Metadata().GetClipRect());
400 :
401 274 : return result;
402 : }
403 :
404 0 : float GetPresShellResolution() const
405 : {
406 0 : MOZ_ASSERT(IsValid());
407 :
408 0 : if (AtTopLayer() && mLayer->AsContainerLayer()) {
409 0 : return mLayer->AsContainerLayer()->GetPresShellResolution();
410 : }
411 :
412 0 : return 1.0f;
413 : }
414 :
415 211 : EventRegionsOverride GetEventRegionsOverride() const
416 : {
417 211 : MOZ_ASSERT(IsValid());
418 :
419 211 : if (mLayer->AsContainerLayer()) {
420 92 : return mLayer->AsContainerLayer()->GetEventRegionsOverride();
421 : }
422 119 : return EventRegionsOverride::NoOverride;
423 : }
424 :
425 211 : const ScrollThumbData& GetScrollThumbData() const
426 : {
427 211 : MOZ_ASSERT(IsValid());
428 :
429 211 : return mLayer->GetScrollThumbData();
430 : }
431 :
432 211 : uint64_t GetScrollbarAnimationId() const
433 : {
434 211 : MOZ_ASSERT(IsValid());
435 : // This function is only really needed for template-compatibility with
436 : // WebRenderScrollDataWrapper. Although it will be called, the return
437 : // value is not used.
438 211 : return 0;
439 : }
440 :
441 211 : FrameMetrics::ViewID GetScrollbarTargetContainerId() const
442 : {
443 211 : MOZ_ASSERT(IsValid());
444 :
445 211 : return mLayer->GetScrollbarTargetContainerId();
446 : }
447 :
448 211 : bool IsScrollbarContainer() const
449 : {
450 211 : MOZ_ASSERT(IsValid());
451 211 : return mLayer->IsScrollbarContainer();
452 : }
453 :
454 211 : FrameMetrics::ViewID GetFixedPositionScrollContainerId() const
455 : {
456 211 : MOZ_ASSERT(IsValid());
457 :
458 211 : return mLayer->GetFixedPositionScrollContainerId();
459 : }
460 :
461 : // Expose an opaque pointer to the layer. Mostly used for printf
462 : // purposes. This is not intended to be a general-purpose accessor
463 : // for the underlying layer.
464 0 : const void* GetLayer() const
465 : {
466 0 : MOZ_ASSERT(IsValid());
467 :
468 0 : return (void*)mLayer;
469 : }
470 :
471 0 : bool operator==(const LayerMetricsWrapper& aOther) const
472 : {
473 0 : return mLayer == aOther.mLayer
474 0 : && mIndex == aOther.mIndex;
475 : }
476 :
477 0 : bool operator!=(const LayerMetricsWrapper& aOther) const
478 : {
479 0 : return !(*this == aOther);
480 : }
481 :
482 : private:
483 2177 : bool AtBottomLayer() const
484 : {
485 2177 : return mIndex == 0;
486 : }
487 :
488 369 : bool AtTopLayer() const
489 : {
490 369 : return mLayer->GetScrollMetadataCount() == 0 || mIndex == mLayer->GetScrollMetadataCount() - 1;
491 : }
492 :
493 : private:
494 : Layer* mLayer;
495 : uint32_t mIndex;
496 : };
497 :
498 : } // namespace layers
499 : } // namespace mozilla
500 :
501 : #endif /* GFX_LAYERMETRICSWRAPPER_H */
|