Source code

Revision control

Other Tools

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