WindowRenderer.h (10645B)
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 MOZILLA_PAINTING_WINDOWRENDERER_H 8 #define MOZILLA_PAINTING_WINDOWRENDERER_H 9 10 #include "gfxContext.h" 11 #include "mozilla/ScrollPositionUpdate.h" // for ScrollPositionUpdate 12 #include "mozilla/dom/Animation.h" // for Animation 13 #include "mozilla/gfx/GPUProcessListener.h" 14 #include "mozilla/layers/LayersTypes.h" 15 #include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid, ScrollableLayerGuid::ViewID 16 #include "mozilla/webrender/webrender_ffi.h" 17 #include "nsRefPtrHashtable.h" // for nsRefPtrHashtable 18 19 namespace mozilla { 20 namespace layers { 21 class LayerManager; 22 class WebRenderLayerManager; 23 class KnowsCompositor; 24 class CompositorBridgeChild; 25 class FrameUniformityData; 26 class PersistentBufferProvider; 27 } // namespace layers 28 class FallbackRenderer; 29 class nsDisplayListBuilder; 30 class nsDisplayList; 31 32 class FrameRecorder { 33 public: 34 /** 35 * Record (and return) frame-intervals and paint-times for frames which were 36 * presented between calling StartFrameTimeRecording and 37 * StopFrameTimeRecording. 38 * 39 * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is 40 * called too late 41 * (elements were overwritten since Start), result is considered invalid 42 * and hence empty.) 43 * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were 44 * less frequent). 45 * Can be changed (up to 1 hour) via pref: 46 * toolkit.framesRecording.bufferSize. 47 * - Note: the first frame-interval may be longer than expected because last 48 * frame 49 * might have been presented some time before calling 50 * StartFrameTimeRecording. 51 */ 52 53 /** 54 * Returns a handle which represents current recording start position. 55 */ 56 virtual uint32_t StartFrameTimeRecording(int32_t aBufferSize); 57 58 /** 59 * Clears, then populates aFrameIntervals with the recorded frame timing 60 * data. The array will be empty if data was overwritten since 61 * aStartIndex was obtained. 62 */ 63 virtual void StopFrameTimeRecording(uint32_t aStartIndex, 64 nsTArray<float>& aFrameIntervals); 65 66 void RecordFrame(); 67 68 private: 69 struct FramesTimingRecording { 70 // Stores state and data for frame intervals and paint times recording. 71 // see LayerManager::StartFrameTimeRecording() at Layers.cpp for more 72 // details. 73 FramesTimingRecording() 74 : mNextIndex(0), 75 mLatestStartIndex(0), 76 mCurrentRunStartIndex(0), 77 mIsPaused(true) {} 78 nsTArray<float> mIntervals; 79 TimeStamp mLastFrameTime; 80 uint32_t mNextIndex; 81 uint32_t mLatestStartIndex; 82 uint32_t mCurrentRunStartIndex; 83 bool mIsPaused; 84 }; 85 FramesTimingRecording mRecording; 86 }; 87 88 /** 89 * WindowRenderer is the retained rendering object owned by an nsIWidget for 90 * drawing the contents of that window, the role previously handled by 91 * LayerManager. 92 * 93 * It can be WebRender, (deprecated) Layers, or an immediate-mode 94 * FallbackRenderer. 95 * 96 * The intention is for LayerManager to be removed entirely in the near future, 97 * with WebRender inheriting directly from this class. It is likely that more 98 * cleanup can be done once that happens. 99 */ 100 class WindowRenderer : public FrameRecorder { 101 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 102 103 public: 104 // Cast to implementation types. 105 virtual layers::WebRenderLayerManager* AsWebRender() { return nullptr; } 106 virtual FallbackRenderer* AsFallback() { return nullptr; } 107 108 // Required functionality 109 110 /** 111 * Start a new transaction. Nested transactions are not allowed so 112 * there must be no transaction currently in progress. 113 * This transaction will update the state of the window from which 114 * this LayerManager was obtained. 115 */ 116 virtual bool BeginTransaction(const nsCString& aURL = nsCString()) = 0; 117 118 enum EndTransactionFlags { 119 END_DEFAULT = 0, 120 END_NO_IMMEDIATE_REDRAW = 1 << 0, // Do not perform the drawing phase 121 END_NO_COMPOSITE = 122 1 << 1, // Do not composite after drawing painted layer contents. 123 END_NO_REMOTE_COMPOSITE = 1 << 2 // Do not schedule a composition with a 124 // remote Compositor, if one exists. 125 }; 126 127 /** 128 * Attempts to end an "empty transaction". There must have been no 129 * changes to the layer tree since the BeginTransaction(). 130 * It's possible for this to fail; PaintedLayers may need to be updated 131 * due to VRAM data being lost, for example. In such cases this method 132 * returns false, and the caller must proceed with a normal layer tree 133 * update and EndTransaction. 134 */ 135 virtual bool EndEmptyTransaction( 136 EndTransactionFlags aFlags = END_DEFAULT) = 0; 137 138 virtual void Destroy() {} 139 140 /** 141 * Type of layer manager this is. This is to be used sparsely in order to 142 * avoid a lot of Layers backend specific code. It should be used only when 143 * Layers backend specific functionality is necessary. 144 */ 145 virtual layers::LayersBackend GetBackendType() = 0; 146 147 /** 148 * Type of layers backend that will be used to composite this layer tree. 149 * When compositing is done remotely, then this returns the layers type 150 * of the compositor. 151 */ 152 virtual layers::LayersBackend GetCompositorBackendType() { 153 return GetBackendType(); 154 } 155 156 /** 157 * Checks if we need to invalidate the OS widget to trigger 158 * painting when updating this renderer. 159 */ 160 virtual bool NeedsWidgetInvalidation() { return true; } 161 162 /** 163 * Make sure that the previous transaction has been entirely 164 * completed. 165 * 166 * Note: This may sychronously wait on a remote compositor 167 * to complete rendering. 168 */ 169 virtual void FlushRendering(wr::RenderReasons aReasons) {} 170 171 /** 172 * Make sure that the previous transaction has been 173 * received. This will synchronsly wait on a remote compositor. 174 */ 175 virtual void WaitOnTransactionProcessed() {} 176 177 /** 178 * returns the maximum texture size on this layer backend, or INT32_MAX 179 * if there is no maximum 180 */ 181 virtual int32_t GetMaxTextureSize() const { return INT32_MAX; } 182 183 /** 184 * Return the name of the layer manager's backend. 185 */ 186 virtual void GetBackendName(nsAString& aName) = 0; 187 188 virtual void GetFrameUniformity(layers::FrameUniformityData* aOutData) {} 189 190 virtual bool AddPendingScrollUpdateForNextTransaction( 191 layers::ScrollableLayerGuid::ViewID aScrollId, 192 const ScrollPositionUpdate& aUpdateInfo) { 193 return false; 194 } 195 196 /** 197 * Creates a PersistentBufferProvider for use with canvas which is optimized 198 * for inter-operating with this layermanager. 199 */ 200 virtual already_AddRefed<layers::PersistentBufferProvider> 201 CreatePersistentBufferProvider(const mozilla::gfx::IntSize& aSize, 202 mozilla::gfx::SurfaceFormat aFormat, 203 bool aWillReadFrequently = false); 204 205 // Helper wrappers around cast to impl and then cast again. 206 207 virtual layers::KnowsCompositor* AsKnowsCompositor() { return nullptr; } 208 209 virtual layers::CompositorBridgeChild* GetCompositorBridgeChild() { 210 return nullptr; 211 } 212 213 // Provided functionality 214 215 void AddPartialPrerenderedAnimation(uint64_t aCompositorAnimationId, 216 dom::Animation* aAnimation); 217 void RemovePartialPrerenderedAnimation(uint64_t aCompositorAnimationId, 218 dom::Animation* aAnimation); 219 void UpdatePartialPrerenderedAnimations( 220 const nsTArray<uint64_t>& aJankedAnimations); 221 222 protected: 223 virtual ~WindowRenderer() = default; 224 225 // Transform animations which are not fully pre-rendered because it's on a 226 // large frame. We need to update the pre-rendered area once after we tried 227 // to composite area which is outside of the pre-rendered area on the 228 // compositor. 229 nsRefPtrHashtable<nsUint64HashKey, dom::Animation> 230 mPartialPrerenderedAnimations; 231 }; 232 233 /** 234 * FallbackRenderer is non-retained renderer that acts as a direct wrapper 235 * around calling Paint on the provided DisplayList. This is used for cases 236 * where initializing WebRender is too costly, and we don't need 237 * retaining/invalidation (like small popup windows). 238 * 239 * It doesn't support any sort of EmptyTransaction, and only draws during 240 * EndTransaction if a composite is requested (no END_NO_COMPOSITE flag 241 * provided) 242 */ 243 class FallbackRenderer : public WindowRenderer { 244 public: 245 FallbackRenderer* AsFallback() final { return this; } 246 247 void SetTarget(gfxContext* aContext); 248 249 bool BeginTransaction(const nsCString& aURL = nsCString()) final; 250 251 bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) final { 252 return false; 253 } 254 255 layers::LayersBackend GetBackendType() final { 256 return layers::LayersBackend::LAYERS_NONE; 257 } 258 259 void GetBackendName(nsAString& name) final { name.AssignLiteral("Fallback"); } 260 261 void EndTransactionWithColor(const nsIntRect& aRect, 262 const gfx::DeviceColor& aColor); 263 void EndTransactionWithList(nsDisplayListBuilder* aBuilder, 264 nsDisplayList* aList, 265 int32_t aAppUnitsPerDevPixel, 266 EndTransactionFlags aFlags); 267 268 gfxContext* mTarget = nullptr; 269 270 protected: 271 FallbackRenderer() = default; 272 }; 273 274 /** 275 * DefaultFallbackRenderer is intended to be used when the caller does not want 276 * it to be destroyed/recreated based on the compositing state. 277 */ 278 class DefaultFallbackRenderer final : public FallbackRenderer { 279 NS_INLINE_DECL_REFCOUNTING(DefaultFallbackRenderer, final) 280 281 public: 282 DefaultFallbackRenderer() = default; 283 284 private: 285 ~DefaultFallbackRenderer() final = default; 286 }; 287 288 /** 289 * BackgroundedFallbackRenderer is intended to be used as a placeholder while we 290 * wait for compositing to be reinstantiated. 291 */ 292 class BackgroundedFallbackRenderer final : public FallbackRenderer, 293 public gfx::GPUProcessListener { 294 NS_INLINE_DECL_REFCOUNTING(BackgroundedFallbackRenderer, final) 295 296 public: 297 explicit BackgroundedFallbackRenderer(nsIWidget* aWidget); 298 299 void Destroy() final; 300 301 void OnCompositorDestroyBackgrounded() final; 302 303 private: 304 ~BackgroundedFallbackRenderer() final; 305 306 // The widget to notify when compositing is reinstantiated. 307 nsIWidget* mWidget; 308 }; 309 310 } // namespace mozilla 311 312 #endif /* MOZILLA_PAINTING_WINDOWRENDERER_H */