Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; 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_ASYNCCOMPOSITIONMANAGER_H
7 : #define GFX_ASYNCCOMPOSITIONMANAGER_H
8 :
9 : #include "Units.h" // for ScreenPoint, etc
10 : #include "mozilla/layers/LayerManagerComposite.h" // for LayerManagerComposite
11 : #include "mozilla/Attributes.h" // for final, etc
12 : #include "mozilla/RefPtr.h" // for RefCounted
13 : #include "mozilla/TimeStamp.h" // for TimeStamp
14 : #include "mozilla/dom/ScreenOrientation.h" // for ScreenOrientation
15 : #include "mozilla/gfx/BasePoint.h" // for BasePoint
16 : #include "mozilla/gfx/Matrix.h" // for Matrix4x4
17 : #include "mozilla/layers/AnimationMetricsTracker.h" // for AnimationMetricsTracker
18 : #include "mozilla/layers/FrameUniformityData.h" // For FrameUniformityData
19 : #include "mozilla/layers/LayersMessages.h" // for TargetConfig
20 : #include "mozilla/RefPtr.h" // for nsRefPtr
21 : #include "nsISupportsImpl.h" // for LayerManager::AddRef, etc
22 :
23 : namespace mozilla {
24 : namespace layers {
25 :
26 : class AsyncPanZoomController;
27 : class Layer;
28 : class LayerManagerComposite;
29 : class AutoResolveRefLayers;
30 : class CompositorBridgeParent;
31 :
32 : // Represents async transforms consisting of a scale and a translation.
33 : struct AsyncTransform {
34 56 : explicit AsyncTransform(LayerToParentLayerScale aScale = LayerToParentLayerScale(),
35 : ParentLayerPoint aTranslation = ParentLayerPoint())
36 56 : : mScale(aScale)
37 56 : , mTranslation(aTranslation)
38 56 : {}
39 :
40 96 : operator AsyncTransformComponentMatrix() const
41 : {
42 192 : return AsyncTransformComponentMatrix::Scaling(mScale.scale, mScale.scale, 1)
43 288 : .PostTranslate(mTranslation.x, mTranslation.y, 0);
44 : }
45 :
46 : bool operator==(const AsyncTransform& rhs) const {
47 : return mTranslation == rhs.mTranslation && mScale == rhs.mScale;
48 : }
49 :
50 : bool operator!=(const AsyncTransform& rhs) const {
51 : return !(*this == rhs);
52 : }
53 :
54 : LayerToParentLayerScale mScale;
55 : ParentLayerPoint mTranslation;
56 : };
57 :
58 : /**
59 : * Manage async composition effects. This class is only used with OMTC and only
60 : * lives on the compositor thread. It is a layer on top of the layer manager
61 : * (LayerManagerComposite) which deals with elements of composition which are
62 : * usually dealt with by dom or layout when main thread rendering, but which can
63 : * short circuit that stuff to directly affect layers as they are composited,
64 : * for example, off-main thread animation, async video, async pan/zoom.
65 : */
66 : class AsyncCompositionManager final
67 : {
68 : friend class AutoResolveRefLayers;
69 : ~AsyncCompositionManager();
70 :
71 : public:
72 1 : NS_INLINE_DECL_REFCOUNTING(AsyncCompositionManager)
73 :
74 : explicit AsyncCompositionManager(CompositorBridgeParent* aParent, HostLayerManager* aManager);
75 :
76 : /**
77 : * This forces the is-first-paint flag to true. This is intended to
78 : * be called by the widget code when it loses its viewport information
79 : * (or for whatever reason wants to refresh the viewport information).
80 : * The information refresh happens because the compositor will call
81 : * AndroidDynamicToolbarAnimator::FirstPaint() on the next frame of composition.
82 : */
83 0 : void ForceIsFirstPaint() { mIsFirstPaint = true; }
84 :
85 : // Sample transforms for layer trees. Return true to request
86 : // another animation frame.
87 : enum class TransformsToSkip : uint8_t { NoneOfThem = 0, APZ = 1 };
88 : bool TransformShadowTree(TimeStamp aCurrentFrame,
89 : TimeDuration aVsyncRate,
90 : TransformsToSkip aSkip = TransformsToSkip::NoneOfThem);
91 :
92 : // Calculates the correct rotation and applies the transform to
93 : // our layer manager
94 : void ComputeRotation();
95 :
96 : // Call after updating our layer tree.
97 24 : void Updated(bool isFirstPaint, const TargetConfig& aTargetConfig)
98 : {
99 24 : mIsFirstPaint |= isFirstPaint;
100 24 : mLayersUpdated = true;
101 24 : mTargetConfig = aTargetConfig;
102 24 : }
103 :
104 25 : bool RequiresReorientation(mozilla::dom::ScreenOrientationInternal aOrientation) const
105 : {
106 25 : return mTargetConfig.orientation() != aOrientation;
107 : }
108 :
109 : // True if the underlying layer tree is ready to be composited.
110 0 : bool ReadyForCompose() { return mReadyForCompose; }
111 :
112 : // Returns true if the next composition will be the first for a
113 : // particular document.
114 25 : bool IsFirstPaint() { return mIsFirstPaint; }
115 :
116 : // GetFrameUniformity will return the frame uniformity for each layer attached to an APZ
117 : // from the recorded data in RecordShadowTransform
118 : void GetFrameUniformity(FrameUniformityData* aFrameUniformityData);
119 :
120 : // Stores the clip rect of a layer in two parts: a fixed part and a scrolled
121 : // part. When a layer is fixed, the clip needs to be adjusted to account for
122 : // async transforms. Only the fixed part needs to be adjusted, so we need
123 : // to store the two parts separately.
124 430 : struct ClipParts {
125 : Maybe<ParentLayerIntRect> mFixedClip;
126 : Maybe<ParentLayerIntRect> mScrolledClip;
127 :
128 40 : Maybe<ParentLayerIntRect> Intersect() const {
129 40 : return IntersectMaybeRects(mFixedClip, mScrolledClip);
130 : }
131 : };
132 :
133 : typedef std::map<Layer*, ClipParts> ClipPartsCache;
134 :
135 : /**
136 : * Compute the updated shadow transform for a scroll thumb layer that
137 : * reflects async scrolling of the associated scroll frame.
138 : *
139 : * @param aCurrentTransform The current shadow transform on the scroll thumb
140 : * layer, as returned by Layer::GetLocalTransform() or similar.
141 : * @param aScrollableContentTransform The current content transform on the
142 : * scrollable content, as returned by Layer::GetTransform().
143 : * @param aApzc The APZC that scrolls the scroll frame.
144 : * @param aMetrics The metrics associated with the scroll frame, reflecting
145 : * the last paint of the associated content. Note: this metrics should
146 : * NOT reflect async scrolling, i.e. they should be the layer tree's
147 : * copy of the metrics, or APZC's last-content-paint metrics.
148 : * @param aThumbData The scroll thumb data for the the scroll thumb layer.
149 : * @param aScrollbarIsDescendant True iff. the scroll thumb layer is a
150 : * descendant of the layer bearing the scroll frame's metrics.
151 : * @param aOutClipTransform If not null, and |aScrollbarIsDescendant| is true,
152 : * this will be populated with a transform that should be applied to the
153 : * clip rects of all layers between the scroll thumb layer and the ancestor
154 : * layer for the scrollable content.
155 : * @return The new shadow transform for the scroll thumb layer, including
156 : * any pre- or post-scales.
157 : */
158 : static LayerToParentLayerMatrix4x4 ComputeTransformForScrollThumb(
159 : const LayerToParentLayerMatrix4x4& aCurrentTransform,
160 : const gfx::Matrix4x4& aScrollableContentTransform,
161 : AsyncPanZoomController* aApzc,
162 : const FrameMetrics& aMetrics,
163 : const ScrollThumbData& aThumbData,
164 : bool aScrollbarIsDescendant,
165 : AsyncTransformComponentMatrix* aOutClipTransform);
166 : private:
167 : // Return true if an AsyncPanZoomController content transform was
168 : // applied for |aLayer|. |*aOutFoundRoot| is set to true on Android only, if
169 : // one of the metrics on one of the layers was determined to be the "root"
170 : // and its state was synced to the Java front-end. |aOutFoundRoot| must be
171 : // non-null.
172 : bool ApplyAsyncContentTransformToTree(Layer* aLayer,
173 : bool* aOutFoundRoot);
174 : /**
175 : * Update the shadow transform for aLayer assuming that is a scrollbar,
176 : * so that it stays in sync with the content that is being scrolled by APZ.
177 : */
178 : void ApplyAsyncTransformToScrollbar(Layer* aLayer);
179 :
180 : /**
181 : * Adds a translation to the transform of any fixed position (whose parent
182 : * layer is not fixed) or sticky position layer descendant of
183 : * |aTransformedSubtreeRoot|. The translation is chosen so that the layer's
184 : * anchor point relative to |aTransformedSubtreeRoot|'s parent layer is the same
185 : * as it was when |aTransformedSubtreeRoot|'s GetLocalTransform() was
186 : * |aPreviousTransformForRoot|. |aCurrentTransformForRoot| is
187 : * |aTransformedSubtreeRoot|'s current GetLocalTransform() modulo any
188 : * overscroll-related transform, which we don't want to adjust for.
189 : * For sticky position layers, the translation is further intersected with
190 : * the layer's sticky scroll ranges.
191 : * This function will also adjust layers so that the given content document
192 : * fixed position margins will be respected during asynchronous panning and
193 : * zooming.
194 : * |aTransformScrollId| is the scroll id of the scroll frame that scrolls
195 : * |aTransformedSubtreeRoot|.
196 : * |aClipPartsCache| optionally maps layers to separate fixed and scrolled
197 : * clips, so we can only adjust the fixed portion.
198 : * This function has a recursive implementation; aStartTraversalAt specifies
199 : * where to start the current recursion of the traversal. For the initial
200 : * call, it should be the same as aTrasnformedSubtreeRoot.
201 : */
202 : void AlignFixedAndStickyLayers(Layer* aTransformedSubtreeRoot,
203 : Layer* aStartTraversalAt,
204 : FrameMetrics::ViewID aTransformScrollId,
205 : const LayerToParentLayerMatrix4x4& aPreviousTransformForRoot,
206 : const LayerToParentLayerMatrix4x4& aCurrentTransformForRoot,
207 : const ScreenMargin& aFixedLayerMargins,
208 : ClipPartsCache* aClipPartsCache);
209 :
210 : /**
211 : * DRAWING PHASE ONLY
212 : *
213 : * For reach RefLayer in our layer tree, look up its referent and connect it
214 : * to the layer tree, if found.
215 : * aHasRemoteContent - indicates if the layer tree contains a remote reflayer.
216 : * May be null.
217 : * aResolvePlugins - incoming value indicates if plugin windows should be
218 : * updated through a call on aCompositor's UpdatePluginWindowState. Applies
219 : * to linux and windows only, may be null. On return value indicates
220 : * if any updates occured.
221 : */
222 : void ResolveRefLayers(CompositorBridgeParent* aCompositor, bool* aHasRemoteContent,
223 : bool* aResolvePlugins);
224 :
225 : /**
226 : * Detaches all referents resolved by ResolveRefLayers.
227 : * Assumes that mLayerManager->GetRoot() and mTargetConfig have not changed
228 : * since ResolveRefLayers was called.
229 : */
230 : void DetachRefLayers();
231 :
232 : // Records the shadow transforms for the tree of layers rooted at the given layer
233 : void RecordShadowTransforms(Layer* aLayer);
234 :
235 : TargetConfig mTargetConfig;
236 : CSSRect mContentRect;
237 :
238 : RefPtr<HostLayerManager> mLayerManager;
239 : // When this flag is set, the next composition will be the first for a
240 : // particular document (i.e. the document displayed on the screen will change).
241 : // This happens when loading a new page or switching tabs. We notify the
242 : // front-end (e.g. Java on Android) about this so that it take the new page
243 : // size and zoom into account when providing us with the next view transform.
244 : bool mIsFirstPaint;
245 :
246 : // This flag is set during a layers update, so that the first composition
247 : // after a layers update has it set. It is cleared after that first composition.
248 : bool mLayersUpdated;
249 :
250 : bool mReadyForCompose;
251 :
252 : gfx::Matrix mWorldTransform;
253 : LayerTransformRecorder mLayerTransformRecorder;
254 :
255 : TimeStamp mPreviousFrameTimeStamp;
256 : AnimationMetricsTracker mAnimationMetricsTracker;
257 :
258 : CompositorBridgeParent* mCompositorBridge;
259 :
260 : #ifdef MOZ_WIDGET_ANDROID
261 : public:
262 : void SetFixedLayerMargins(ScreenIntCoord aTop, ScreenIntCoord aBottom);
263 : private:
264 : // The following two fields are only needed on Fennec with C++ APZ, because
265 : // then we need to reposition the gecko scrollbar to deal with the
266 : // dynamic toolbar shifting content around.
267 : FrameMetrics::ViewID mRootScrollableId;
268 : ScreenMargin mFixedLayerMargins;
269 : #endif
270 : };
271 :
272 29 : MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(AsyncCompositionManager::TransformsToSkip)
273 :
274 : class MOZ_STACK_CLASS AutoResolveRefLayers {
275 : public:
276 113 : explicit AutoResolveRefLayers(AsyncCompositionManager* aManager,
277 : CompositorBridgeParent* aCompositor = nullptr,
278 : bool* aHasRemoteContent = nullptr,
279 113 : bool* aResolvePlugins = nullptr) :
280 113 : mManager(aManager)
281 : {
282 113 : if (mManager) {
283 113 : mManager->ResolveRefLayers(aCompositor, aHasRemoteContent, aResolvePlugins);
284 : }
285 113 : }
286 :
287 113 : ~AutoResolveRefLayers()
288 113 : {
289 113 : if (mManager) {
290 113 : mManager->DetachRefLayers();
291 : }
292 113 : }
293 :
294 : private:
295 : AsyncCompositionManager* mManager;
296 :
297 : AutoResolveRefLayers(const AutoResolveRefLayers&) = delete;
298 : AutoResolveRefLayers& operator=(const AutoResolveRefLayers&) = delete;
299 : };
300 :
301 : } // namespace layers
302 : } // namespace mozilla
303 :
304 : #endif
|