Line data Source code
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_ASYNCCOMPOSITIONMANAGER_H
8 : #define GFX_ASYNCCOMPOSITIONMANAGER_H
9 :
10 : #include "Units.h" // for ScreenPoint, etc
11 : #include "mozilla/layers/LayerManagerComposite.h" // for LayerManagerComposite
12 : #include "mozilla/Attributes.h" // for final, etc
13 : #include "mozilla/RefPtr.h" // for RefCounted
14 : #include "mozilla/TimeStamp.h" // for TimeStamp
15 : #include "mozilla/dom/ScreenOrientation.h" // for ScreenOrientation
16 : #include "mozilla/gfx/BasePoint.h" // for BasePoint
17 : #include "mozilla/gfx/Matrix.h" // for Matrix4x4
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 : #include "CompositorBridgeParent.h" // for TransformsToSkip
23 :
24 : namespace mozilla {
25 : namespace layers {
26 :
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 : explicit AsyncTransform(LayerToParentLayerScale aScale = LayerToParentLayerScale(),
35 : ParentLayerPoint aTranslation = ParentLayerPoint())
36 0 : : mScale(aScale)
37 16 : , mTranslation(aTranslation)
38 : {}
39 :
40 16 : operator AsyncTransformComponentMatrix() const
41 : {
42 0 : return AsyncTransformComponentMatrix::Scaling(mScale.scale, mScale.scale, 1)
43 48 : .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 5 : 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 : bool TransformShadowTree(
88 : TimeStamp aCurrentFrame,
89 : TimeDuration aVsyncRate,
90 : CompositorBridgeParentBase::TransformsToSkip aSkip =
91 : CompositorBridgeParentBase::TransformsToSkip::NoneOfThem);
92 :
93 : // Calculates the correct rotation and applies the transform to
94 : // our layer manager
95 : void ComputeRotation();
96 :
97 : // Call after updating our layer tree.
98 0 : void Updated(bool isFirstPaint, const TargetConfig& aTargetConfig)
99 : {
100 0 : mIsFirstPaint |= isFirstPaint;
101 0 : mLayersUpdated = true;
102 7 : mTargetConfig = aTargetConfig;
103 7 : }
104 :
105 : bool RequiresReorientation(mozilla::dom::ScreenOrientationInternal aOrientation) const
106 : {
107 7 : return mTargetConfig.orientation() != aOrientation;
108 : }
109 :
110 : // True if the underlying layer tree is ready to be composited.
111 : bool ReadyForCompose() { return mReadyForCompose; }
112 :
113 : // Returns true if the next composition will be the first for a
114 : // particular document.
115 : bool IsFirstPaint() { return mIsFirstPaint; }
116 :
117 : // GetFrameUniformity will return the frame uniformity for each layer attached to an APZ
118 : // from the recorded data in RecordShadowTransform
119 : void GetFrameUniformity(FrameUniformityData* aFrameUniformityData);
120 :
121 : // Stores the clip rect of a layer in two parts: a fixed part and a scrolled
122 : // part. When a layer is fixed, the clip needs to be adjusted to account for
123 : // async transforms. Only the fixed part needs to be adjusted, so we need
124 : // to store the two parts separately.
125 96 : struct ClipParts {
126 : Maybe<ParentLayerIntRect> mFixedClip;
127 : Maybe<ParentLayerIntRect> mScrolledClip;
128 :
129 8 : Maybe<ParentLayerIntRect> Intersect() const {
130 8 : return IntersectMaybeRects(mFixedClip, mScrolledClip);
131 : }
132 : };
133 :
134 : typedef std::map<Layer*, ClipParts> ClipPartsCache;
135 :
136 : private:
137 : // Return true if an AsyncPanZoomController content transform was
138 : // applied for |aLayer|. |*aOutFoundRoot| is set to true on Android only, if
139 : // one of the metrics on one of the layers was determined to be the "root"
140 : // and its state was synced to the Java front-end. |aOutFoundRoot| must be
141 : // non-null.
142 : bool ApplyAsyncContentTransformToTree(Layer* aLayer,
143 : bool* aOutFoundRoot);
144 : /**
145 : * Update the shadow transform for aLayer assuming that is a scrollbar,
146 : * so that it stays in sync with the content that is being scrolled by APZ.
147 : */
148 : void ApplyAsyncTransformToScrollbar(Layer* aLayer);
149 :
150 : /**
151 : * Adds a translation to the transform of any fixed position (whose parent
152 : * layer is not fixed) or sticky position layer descendant of
153 : * |aTransformedSubtreeRoot|. The translation is chosen so that the layer's
154 : * anchor point relative to |aTransformedSubtreeRoot|'s parent layer is the same
155 : * as it was when |aTransformedSubtreeRoot|'s GetLocalTransform() was
156 : * |aPreviousTransformForRoot|. |aCurrentTransformForRoot| is
157 : * |aTransformedSubtreeRoot|'s current GetLocalTransform() modulo any
158 : * overscroll-related transform, which we don't want to adjust for.
159 : * For sticky position layers, the translation is further intersected with
160 : * the layer's sticky scroll ranges.
161 : * This function will also adjust layers so that the given content document
162 : * fixed position margins will be respected during asynchronous panning and
163 : * zooming.
164 : * |aTransformScrollId| is the scroll id of the scroll frame that scrolls
165 : * |aTransformedSubtreeRoot|.
166 : * |aClipPartsCache| optionally maps layers to separate fixed and scrolled
167 : * clips, so we can only adjust the fixed portion.
168 : * This function has a recursive implementation; aStartTraversalAt specifies
169 : * where to start the current recursion of the traversal. For the initial
170 : * call, it should be the same as aTrasnformedSubtreeRoot.
171 : */
172 : void AlignFixedAndStickyLayers(Layer* aTransformedSubtreeRoot,
173 : Layer* aStartTraversalAt,
174 : FrameMetrics::ViewID aTransformScrollId,
175 : const LayerToParentLayerMatrix4x4& aPreviousTransformForRoot,
176 : const LayerToParentLayerMatrix4x4& aCurrentTransformForRoot,
177 : const ScreenMargin& aFixedLayerMargins,
178 : ClipPartsCache* aClipPartsCache);
179 :
180 : /**
181 : * DRAWING PHASE ONLY
182 : *
183 : * For reach RefLayer in our layer tree, look up its referent and connect it
184 : * to the layer tree, if found.
185 : * aHasRemoteContent - indicates if the layer tree contains a remote reflayer.
186 : * May be null.
187 : * aResolvePlugins - incoming value indicates if plugin windows should be
188 : * updated through a call on aCompositor's UpdatePluginWindowState. Applies
189 : * to linux and windows only, may be null. On return value indicates
190 : * if any updates occured.
191 : */
192 : void ResolveRefLayers(CompositorBridgeParent* aCompositor, bool* aHasRemoteContent,
193 : bool* aResolvePlugins);
194 :
195 : /**
196 : * Detaches all referents resolved by ResolveRefLayers.
197 : * Assumes that mLayerManager->GetRoot() and mTargetConfig have not changed
198 : * since ResolveRefLayers was called.
199 : */
200 : void DetachRefLayers();
201 :
202 : // Records the shadow transforms for the tree of layers rooted at the given layer
203 : void RecordShadowTransforms(Layer* aLayer);
204 :
205 : TargetConfig mTargetConfig;
206 : CSSRect mContentRect;
207 :
208 : RefPtr<HostLayerManager> mLayerManager;
209 : // When this flag is set, the next composition will be the first for a
210 : // particular document (i.e. the document displayed on the screen will change).
211 : // This happens when loading a new page or switching tabs. We notify the
212 : // front-end (e.g. Java on Android) about this so that it take the new page
213 : // size and zoom into account when providing us with the next view transform.
214 : bool mIsFirstPaint;
215 :
216 : // This flag is set during a layers update, so that the first composition
217 : // after a layers update has it set. It is cleared after that first composition.
218 : bool mLayersUpdated;
219 :
220 : bool mReadyForCompose;
221 :
222 : gfx::Matrix mWorldTransform;
223 : LayerTransformRecorder mLayerTransformRecorder;
224 :
225 : TimeStamp mPreviousFrameTimeStamp;
226 :
227 : MOZ_NON_OWNING_REF CompositorBridgeParent* mCompositorBridge;
228 :
229 : #ifdef MOZ_WIDGET_ANDROID
230 : public:
231 : void SetFixedLayerMargins(ScreenIntCoord aTop, ScreenIntCoord aBottom);
232 : private:
233 : // The following two fields are only needed on Fennec with C++ APZ, because
234 : // then we need to reposition the gecko scrollbar to deal with the
235 : // dynamic toolbar shifting content around.
236 : FrameMetrics::ViewID mRootScrollableId;
237 : ScreenMargin mFixedLayerMargins;
238 : #endif
239 : };
240 :
241 : class MOZ_STACK_CLASS AutoResolveRefLayers {
242 : public:
243 0 : explicit AutoResolveRefLayers(AsyncCompositionManager* aManager,
244 : CompositorBridgeParent* aCompositor = nullptr,
245 : bool* aHasRemoteContent = nullptr,
246 0 : bool* aResolvePlugins = nullptr) :
247 0 : mManager(aManager)
248 : {
249 0 : if (mManager) {
250 0 : mManager->ResolveRefLayers(aCompositor, aHasRemoteContent, aResolvePlugins);
251 : }
252 0 : }
253 :
254 0 : ~AutoResolveRefLayers()
255 0 : {
256 0 : if (mManager) {
257 0 : mManager->DetachRefLayers();
258 : }
259 0 : }
260 :
261 : private:
262 : AsyncCompositionManager* mManager;
263 :
264 : AutoResolveRefLayers(const AutoResolveRefLayers&) = delete;
265 : AutoResolveRefLayers& operator=(const AutoResolveRefLayers&) = delete;
266 : };
267 :
268 : } // namespace layers
269 : } // namespace mozilla
270 :
271 : #endif
|