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 "FrameMetrics.h" // for FrameMetrics 12 #include "mozilla/layers/APZUtils.h" // for GeckoViewMetrics 13 #include "mozilla/layers/CompositorBridgeParent.h" // for TransformsToSkip 14 #include "mozilla/layers/LayerManagerComposite.h" // for LayerManagerComposite 15 #include "mozilla/Attributes.h" // for final, etc 16 #include "mozilla/RefPtr.h" // for RefCounted 17 #include "mozilla/TimeStamp.h" // for TimeStamp 18 #include "mozilla/gfx/BasePoint.h" // for BasePoint 19 #include "mozilla/gfx/Matrix.h" // for Matrix4x4 20 #include "mozilla/HalScreenConfiguration.h" // For ScreenOrientation 21 #include "mozilla/layers/FrameUniformityData.h" // For FrameUniformityData 22 #include "mozilla/layers/LayersMessages.h" // for TargetConfig 23 #include "mozilla/RefPtr.h" // for nsRefPtr 24 #include "nsISupportsImpl.h" // for LayerManager::AddRef, etc 25 26 namespace mozilla { 27 namespace layers { 28 29 class Layer; 30 class LayerManagerComposite; 31 class AutoResolveRefLayers; 32 class CompositorBridgeParent; 33 class SampleTime; 34 35 /** 36 * Manage async composition effects. This class is only used with OMTC and only 37 * lives on the compositor thread. It is a layer on top of the layer manager 38 * (LayerManagerComposite) which deals with elements of composition which are 39 * usually dealt with by dom or layout when main thread rendering, but which can 40 * short circuit that stuff to directly affect layers as they are composited, 41 * for example, off-main thread animation, async video, async pan/zoom. 42 */ 43 class AsyncCompositionManager final { 44 friend class AutoResolveRefLayers; 45 ~AsyncCompositionManager(); 46 47 public: 48 NS_INLINE_DECL_REFCOUNTING(AsyncCompositionManager) 49 50 AsyncCompositionManager(CompositorBridgeParent* aParent, 51 HostLayerManager* aManager); 52 53 /** 54 * This forces the is-first-paint flag to true. This is intended to 55 * be called by the widget code when it loses its viewport information 56 * (or for whatever reason wants to refresh the viewport information). 57 * The information refresh happens because the compositor will call 58 * AndroidDynamicToolbarAnimator::FirstPaint() on the next frame of 59 * composition. 60 */ ForceIsFirstPaint()61 void ForceIsFirstPaint() { mIsFirstPaint = true; } 62 63 // Sample transforms for layer trees. Return true to request 64 // another animation frame. 65 bool TransformShadowTree( 66 const SampleTime& aCurrentFrame, TimeDuration aVsyncRate, 67 CompositorBridgeParentBase::TransformsToSkip aSkip = 68 CompositorBridgeParentBase::TransformsToSkip::NoneOfThem); 69 70 // Calculates the correct rotation and applies the transform to 71 // our layer manager 72 void ComputeRotation(); 73 74 // Call after updating our layer tree. Updated(bool isFirstPaint,const TargetConfig & aTargetConfig)75 void Updated(bool isFirstPaint, const TargetConfig& aTargetConfig) { 76 mIsFirstPaint |= isFirstPaint; 77 mLayersUpdated = true; 78 mTargetConfig = aTargetConfig; 79 } 80 RequiresReorientation(hal::ScreenOrientation aOrientation)81 bool RequiresReorientation(hal::ScreenOrientation aOrientation) const { 82 return mTargetConfig.orientation() != aOrientation; 83 } 84 85 // True if the underlying layer tree is ready to be composited. ReadyForCompose()86 bool ReadyForCompose() { return mReadyForCompose; } 87 88 // Returns true if the next composition will be the first for a 89 // particular document. IsFirstPaint()90 bool IsFirstPaint() { return mIsFirstPaint; } 91 92 // GetFrameUniformity will return the frame uniformity for each layer attached 93 // to an APZ from the recorded data in RecordShadowTransform 94 void GetFrameUniformity(FrameUniformityData* aFrameUniformityData); 95 96 // Stores the clip rect of a layer in two parts: a fixed part and a scrolled 97 // part. When a layer is fixed, the clip needs to be adjusted to account for 98 // async transforms. Only the fixed part needs to be adjusted, so we need 99 // to store the two parts separately. 100 struct ClipParts { 101 Maybe<ParentLayerIntRect> mFixedClip; 102 Maybe<ParentLayerIntRect> mScrolledClip; 103 IntersectClipParts104 Maybe<ParentLayerIntRect> Intersect() const { 105 return IntersectMaybeRects(mFixedClip, mScrolledClip); 106 } 107 }; 108 109 typedef std::map<Layer*, ClipParts> ClipPartsCache; 110 111 private: 112 // Return true if an AsyncPanZoomController content transform was 113 // applied for |aLayer|. |*aOutFoundRoot| is set to true on Android only, if 114 // one of the metrics on one of the layers was determined to be the "root" 115 // and its state was synced to the Java front-end. |aOutFoundRoot| must be 116 // non-null. 117 bool ApplyAsyncContentTransformToTree(Layer* aLayer, bool* aOutFoundRoot); 118 /** 119 * Update the shadow transform for aLayer assuming that is a scrollbar, 120 * so that it stays in sync with the content that is being scrolled by APZ. 121 */ 122 void ApplyAsyncTransformToScrollbar(Layer* aLayer); 123 124 /** 125 * Adds a translation to the transform of any fixed position (whose parent 126 * layer is not fixed) or sticky position layer descendant of 127 * |aTransformedSubtreeRoot|. The translation is chosen so that the layer's 128 * anchor point relative to |aTransformedSubtreeRoot|'s parent layer is the 129 * same as it was when |aTransformedSubtreeRoot|'s GetLocalTransform() was 130 * |aPreviousTransformForRoot|. |aCurrentTransformForRoot| is 131 * |aTransformedSubtreeRoot|'s current GetLocalTransform() modulo any 132 * overscroll-related transform, which we don't want to adjust for. 133 * For sticky position layers, the translation is further intersected with 134 * the layer's sticky scroll ranges. 135 * This function will also adjust layers so that the given content document 136 * fixed position margins will be respected during asynchronous panning and 137 * zooming. 138 * |aTransformScrollId| is the scroll id of the scroll frame that scrolls 139 * |aTransformedSubtreeRoot|. 140 * |aClipPartsCache| maps layers to separate fixed and scrolled 141 * clips, so we can only adjust the fixed portion. 142 * This function has a recursive implementation; aStartTraversalAt specifies 143 * where to start the current recursion of the traversal. For the initial 144 * call, it should be the same as aTrasnformedSubtreeRoot. 145 */ 146 void AlignFixedAndStickyLayers( 147 Layer* aTransformedSubtreeRoot, Layer* aStartTraversalAt, 148 SideBits aStuckSides, ScrollableLayerGuid::ViewID aTransformScrollId, 149 const LayerToParentLayerMatrix4x4& aPreviousTransformForRoot, 150 const LayerToParentLayerMatrix4x4& aCurrentTransformForRoot, 151 const ScreenMargin& aCompositorFixedLayerMargins, 152 ClipPartsCache& aClipPartsCache, 153 const ScreenMargin& aGeckoFixedLayerMargins); 154 155 /** 156 * Helper function for AlignFixedAndStickyLayers() to perform a transform 157 * adjustment for a single fixed or sticky layer, rather than all such 158 * layers rooted at a subtree. May also be called directly. 159 */ 160 void AdjustFixedOrStickyLayer( 161 Layer* aTransformedSubtreeRoot, Layer* aFixedOrSticky, 162 SideBits aStuckSides, ScrollableLayerGuid::ViewID aTransformScrollId, 163 const LayerToParentLayerMatrix4x4& aPreviousTransformForRoot, 164 const LayerToParentLayerMatrix4x4& aCurrentTransformForRoot, 165 const ScreenMargin& aCompositorFixedLayerMargins, 166 ClipPartsCache& aClipPartsCache, 167 const ScreenMargin& aGeckoFixedLayerMargins); 168 169 /** 170 * DRAWING PHASE ONLY 171 * 172 * For reach RefLayer in our layer tree, look up its referent and connect it 173 * to the layer tree, if found. 174 * aHasRemoteContent - indicates if the layer tree contains a remote reflayer. 175 * May be null. 176 */ 177 void ResolveRefLayers(CompositorBridgeParent* aCompositor, 178 bool* aHasRemoteContent); 179 180 /** 181 * Detaches all referents resolved by ResolveRefLayers. 182 * Assumes that mLayerManager->GetRoot() and mTargetConfig have not changed 183 * since ResolveRefLayers was called. 184 */ 185 void DetachRefLayers(); 186 187 // Records the shadow transforms for the tree of layers rooted at the given 188 // layer 189 void RecordShadowTransforms(Layer* aLayer); 190 191 bool SampleAnimations(Layer* aLayer, TimeStamp aCurrentFrameTime); 192 193 TargetConfig mTargetConfig; 194 CSSRect mContentRect; 195 196 RefPtr<HostLayerManager> mLayerManager; 197 // When this flag is set, the next composition will be the first for a 198 // particular document (i.e. the document displayed on the screen will 199 // change). This happens when loading a new page or switching tabs. We notify 200 // the front-end (e.g. Java on Android) about this so that it take the new 201 // page size and zoom into account when providing us with the next view 202 // transform. 203 bool mIsFirstPaint; 204 205 // This flag is set during a layers update, so that the first composition 206 // after a layers update has it set. It is cleared after that first 207 // composition. 208 bool mLayersUpdated; 209 210 bool mReadyForCompose; 211 212 gfx::Matrix mWorldTransform; 213 LayerTransformRecorder mLayerTransformRecorder; 214 215 TimeStamp mPreviousFrameTimeStamp; 216 217 MOZ_NON_OWNING_REF CompositorBridgeParent* mCompositorBridge; 218 219 public: 220 void SetFixedLayerMargins(ScreenIntCoord aTop, ScreenIntCoord aBottom); 221 ScreenMargin GetFixedLayerMargins() const; 222 223 private: 224 ScreenMargin mFixedLayerMargins; 225 226 #ifdef MOZ_WIDGET_ANDROID 227 private: 228 // This calculates whether GeckoView metrics should be sent to Java. 229 bool GeckoViewMetricsHaveUpdated(const GeckoViewMetrics& aMetrics); 230 // This holds the most recent GeckoView metrics sent to Java, and is used 231 // to send new updates when it changes. 232 GeckoViewMetrics mLastMetrics; 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 ScrollableLayerGuid::ViewID mRootScrollableId; 237 #endif 238 }; 239 240 class MOZ_STACK_CLASS AutoResolveRefLayers { 241 public: 242 explicit AutoResolveRefLayers(AsyncCompositionManager* aManager, 243 CompositorBridgeParent* aCompositor = nullptr, 244 bool* aHasRemoteContent = nullptr) mManager(aManager)245 : mManager(aManager) { 246 if (mManager) { 247 mManager->ResolveRefLayers(aCompositor, aHasRemoteContent); 248 } 249 } 250 ~AutoResolveRefLayers()251 ~AutoResolveRefLayers() { 252 if (mManager) { 253 mManager->DetachRefLayers(); 254 } 255 } 256 257 private: 258 AsyncCompositionManager* mManager; 259 260 AutoResolveRefLayers(const AutoResolveRefLayers&) = delete; 261 AutoResolveRefLayers& operator=(const AutoResolveRefLayers&) = delete; 262 }; 263 264 } // namespace layers 265 } // namespace mozilla 266 267 #endif 268