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_LAYERMETRICSWRAPPER_H
8 #define GFX_LAYERMETRICSWRAPPER_H
11 #include "UnitTransforms.h"
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
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:
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.
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.
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.
99 * Implementation notes:
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.
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).
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.
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.
123 class MOZ_STACK_CLASS LayerMetricsWrapper final
{
130 LayerMetricsWrapper() : mLayer(nullptr), mIndex(0) {}
132 explicit LayerMetricsWrapper(Layer
* aRoot
, StartAt aStart
= StartAt::TOP
)
133 : mLayer(aRoot
), mIndex(0) {
140 mIndex
= mLayer
->GetScrollMetadataCount();
145 case StartAt::BOTTOM
:
149 MOZ_ASSERT_UNREACHABLE("Unknown startAt value");
154 explicit LayerMetricsWrapper(Layer
* aLayer
, uint32_t aMetricsIndex
)
155 : mLayer(aLayer
), mIndex(aMetricsIndex
) {
157 MOZ_ASSERT(mIndex
== 0 || mIndex
< mLayer
->GetScrollMetadataCount());
160 bool IsValid() const { return mLayer
!= nullptr; }
162 explicit operator bool() const { return IsValid(); }
164 LayerMetricsWrapper
GetParent() const {
165 MOZ_ASSERT(IsValid());
168 return LayerMetricsWrapper(mLayer
, mIndex
+ 1);
170 if (mLayer
->GetParent()) {
171 return LayerMetricsWrapper(mLayer
->GetParent(), StartAt::BOTTOM
);
173 return LayerMetricsWrapper(nullptr);
176 LayerMetricsWrapper
GetFirstChild() const {
177 MOZ_ASSERT(IsValid());
179 if (!AtBottomLayer()) {
180 return LayerMetricsWrapper(mLayer
, mIndex
- 1);
182 return LayerMetricsWrapper(mLayer
->GetFirstChild());
185 LayerMetricsWrapper
GetLastChild() const {
186 MOZ_ASSERT(IsValid());
188 if (!AtBottomLayer()) {
189 return LayerMetricsWrapper(mLayer
, mIndex
- 1);
191 return LayerMetricsWrapper(mLayer
->GetLastChild());
194 LayerMetricsWrapper
GetPrevSibling() const {
195 MOZ_ASSERT(IsValid());
198 return LayerMetricsWrapper(mLayer
->GetPrevSibling());
200 return LayerMetricsWrapper(nullptr);
203 LayerMetricsWrapper
GetNextSibling() const {
204 MOZ_ASSERT(IsValid());
207 return LayerMetricsWrapper(mLayer
->GetNextSibling());
209 return LayerMetricsWrapper(nullptr);
212 const ScrollMetadata
& Metadata() const {
213 MOZ_ASSERT(IsValid());
215 if (mIndex
>= mLayer
->GetScrollMetadataCount()) {
216 return *ScrollMetadata::sNullMetadata
;
218 return mLayer
->GetScrollMetadata(mIndex
);
221 const FrameMetrics
& Metrics() const { return Metadata().GetMetrics(); }
223 AsyncPanZoomController
* GetApzc() const {
224 MOZ_ASSERT(IsValid());
226 if (mIndex
>= mLayer
->GetScrollMetadataCount()) {
229 return mLayer
->GetAsyncPanZoomController(mIndex
);
232 void SetApzc(AsyncPanZoomController
* aApzc
) const {
233 MOZ_ASSERT(IsValid());
235 if (mLayer
->GetScrollMetadataCount() == 0) {
236 MOZ_ASSERT(mIndex
== 0);
237 MOZ_ASSERT(aApzc
== nullptr);
240 MOZ_ASSERT(mIndex
< mLayer
->GetScrollMetadataCount());
241 mLayer
->SetAsyncPanZoomController(mIndex
, aApzc
);
244 const char* Name() const {
245 MOZ_ASSERT(IsValid());
247 if (AtBottomLayer()) {
248 return mLayer
->Name();
250 return "DummyContainerLayer";
253 LayerManager
* Manager() const {
254 MOZ_ASSERT(IsValid());
256 return mLayer
->Manager();
259 gfx::Matrix4x4
GetTransform() const {
260 MOZ_ASSERT(IsValid());
262 if (AtBottomLayer()) {
263 return mLayer
->GetTransform();
265 return gfx::Matrix4x4();
268 CSSTransformMatrix
GetTransformTyped() const {
269 return ViewAs
<CSSTransformMatrix
>(GetTransform());
272 bool TransformIsPerspective() const {
273 MOZ_ASSERT(IsValid());
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();
285 bool Combines3DTransformWithAncestors() const {
286 MOZ_ASSERT(IsValid());
288 return mLayer
->Combines3DTransformWithAncestors();
291 EventRegions
GetEventRegions() const {
292 MOZ_ASSERT(IsValid());
294 if (AtBottomLayer()) {
295 return mLayer
->GetEventRegions();
297 return EventRegions();
300 LayerIntRegion
GetVisibleRegion() const {
301 MOZ_ASSERT(IsValid());
303 if (AtBottomLayer()) {
304 return mLayer
->GetVisibleRegion();
307 return ViewAs
<LayerPixel
>(
308 TransformBy(mLayer
->GetTransformTyped(), mLayer
->GetVisibleRegion()),
309 PixelCastJustification::MovingDownToChildren
);
312 LayerIntSize
GetRemoteDocumentSize() const {
313 MOZ_ASSERT(IsValid());
315 return AsRefLayer() ? AsRefLayer()->GetRemoteDocumentSize()
319 bool HasTransformAnimation() const {
320 MOZ_ASSERT(IsValid());
322 if (AtBottomLayer()) {
323 return mLayer
->HasTransformAnimation();
328 RefLayer
* AsRefLayer() const {
329 MOZ_ASSERT(IsValid());
331 if (AtBottomLayer()) {
332 return mLayer
->AsRefLayer();
337 Maybe
<LayersId
> GetReferentId() const {
338 MOZ_ASSERT(IsValid());
340 if (AtBottomLayer()) {
341 return mLayer
->AsRefLayer() ? Some(mLayer
->AsRefLayer()->GetReferentId())
347 Maybe
<ParentLayerIntRect
> GetClipRect() const {
348 MOZ_ASSERT(IsValid());
350 Maybe
<ParentLayerIntRect
> result
;
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());
362 // The scroll metadata can have a clip rect as well.
363 result
= IntersectMaybeRects(result
, Metadata().GetClipRect());
368 float GetPresShellResolution() const {
369 MOZ_ASSERT(IsValid());
371 if (AtTopLayer() && mLayer
->AsContainerLayer()) {
372 return mLayer
->AsContainerLayer()->GetPresShellResolution();
378 EventRegionsOverride
GetEventRegionsOverride() const {
379 MOZ_ASSERT(IsValid());
382 return AsRefLayer()->GetEventRegionsOverride();
384 return EventRegionsOverride::NoOverride
;
387 const ScrollbarData
& GetScrollbarData() const {
388 MOZ_ASSERT(IsValid());
390 return mLayer
->GetScrollbarData();
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.
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.
409 ScrollableLayerGuid::ViewID
GetFixedPositionScrollContainerId() const {
410 MOZ_ASSERT(IsValid());
412 if (AtBottomLayer()) {
413 return mLayer
->GetFixedPositionScrollContainerId();
415 return ScrollableLayerGuid::NULL_SCROLL_ID
;
418 SideBits
GetFixedPositionSides() const {
419 MOZ_ASSERT(IsValid());
421 if (AtBottomLayer()) {
422 return mLayer
->GetFixedPositionSides();
424 return SideBits::eNone
;
427 ScrollableLayerGuid::ViewID
GetStickyScrollContainerId() const {
428 MOZ_ASSERT(IsValid());
430 if (AtBottomLayer() && mLayer
->GetIsStickyPosition()) {
431 return mLayer
->GetStickyScrollContainerId();
433 return ScrollableLayerGuid::NULL_SCROLL_ID
;
436 const LayerRectAbsolute
& GetStickyScrollRangeOuter() const {
437 MOZ_ASSERT(IsValid());
439 if (AtBottomLayer() && mLayer
->GetIsStickyPosition()) {
440 return mLayer
->GetStickyScrollRangeOuter();
443 static const LayerRectAbsolute empty
;
447 const LayerRectAbsolute
& GetStickyScrollRangeInner() const {
448 MOZ_ASSERT(IsValid());
450 if (AtBottomLayer() && mLayer
->GetIsStickyPosition()) {
451 return mLayer
->GetStickyScrollRangeInner();
454 static const LayerRectAbsolute empty
;
458 Maybe
<uint64_t> GetStickyPositionAnimationId() const {
459 MOZ_ASSERT(IsValid());
460 // This function is only really needed for template-compatibility with
461 // WebRenderScrollDataWrapper. Although it will be called, the return
462 // value is not used.
466 Maybe
<uint64_t> GetZoomAnimationId() const {
467 MOZ_ASSERT(IsValid());
468 // This function is only really needed for template-compatibility with
469 // WebRenderScrollDataWrapper. Although it will be called, the return
470 // value is not used.
474 bool IsBackfaceHidden() const {
475 MOZ_ASSERT(IsValid());
477 return mLayer
->IsBackfaceHidden();
480 Maybe
<ScrollableLayerGuid::ViewID
> IsAsyncZoomContainer() const {
481 MOZ_ASSERT(IsValid());
483 return mLayer
->IsAsyncZoomContainer();
486 // Expose an opaque pointer to the layer. Mostly used for printf
487 // purposes. This is not intended to be a general-purpose accessor
488 // for the underlying layer.
489 const void* GetLayer() const {
490 MOZ_ASSERT(IsValid());
492 return (void*)mLayer
;
495 bool operator==(const LayerMetricsWrapper
& aOther
) const {
496 return mLayer
== aOther
.mLayer
&& mIndex
== aOther
.mIndex
;
499 bool operator!=(const LayerMetricsWrapper
& aOther
) const {
500 return !(*this == aOther
);
504 bool AtBottomLayer() const { return mIndex
== 0; }
506 bool AtTopLayer() const {
507 return mLayer
->GetScrollMetadataCount() == 0 ||
508 mIndex
== mLayer
->GetScrollMetadataCount() - 1;
516 } // namespace layers
517 } // namespace mozilla
519 #endif /* GFX_LAYERMETRICSWRAPPER_H */