PersistentBufferProvider.h (10306B)
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_GFX_PersistentBUFFERPROVIDER_H 8 #define MOZILLA_GFX_PersistentBUFFERPROVIDER_H 9 10 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 11 #include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed, etc 12 #include "mozilla/layers/ActiveResource.h" 13 #include "mozilla/layers/LayersSurfaces.h" 14 #include "mozilla/layers/LayersTypes.h" 15 #include "mozilla/RefCounted.h" 16 #include "mozilla/gfx/Types.h" 17 #include "mozilla/Vector.h" 18 #include "mozilla/WeakPtr.h" 19 20 namespace mozilla { 21 22 class ClientWebGLContext; 23 24 namespace gfx { 25 class SourceSurface; 26 class DrawTarget; 27 } // namespace gfx 28 29 namespace layers { 30 31 class CompositableForwarder; 32 class FwdTransactionTracker; 33 class KnowsCompositor; 34 class TextureClient; 35 36 /** 37 * A PersistentBufferProvider is for users which require the temporary use of 38 * a DrawTarget to draw into. When they're done drawing they return the 39 * DrawTarget, when they later need to continue drawing they get a DrawTarget 40 * from the provider again, the provider will guarantee the contents of the 41 * previously returned DrawTarget is persisted into the one newly returned. 42 */ 43 class PersistentBufferProvider : public RefCounted<PersistentBufferProvider>, 44 public SupportsWeakPtr { 45 public: 46 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProvider) 47 48 virtual ~PersistentBufferProvider() = default; 49 50 virtual bool IsShared() const { return false; } 51 virtual bool IsAccelerated() const { return false; } 52 53 /** 54 * Get a DrawTarget from the PersistentBufferProvider. 55 * 56 * \param aPersistedRect This indicates the area of the DrawTarget that needs 57 * to have remained the same since the call to 58 * ReturnDrawTarget. 59 */ 60 virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget( 61 const gfx::IntRect& aPersistedRect) = 0; 62 63 /** 64 * Return a DrawTarget to the PersistentBufferProvider and indicate the 65 * contents of this DrawTarget is to be considered current by the 66 * BufferProvider. The caller should forget any references to the DrawTarget. 67 */ 68 virtual bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) = 0; 69 70 /** 71 * Temporarily borrow a snapshot of the provider. If a target is supplied, 72 * the snapshot will be optimized for it, if applicable. 73 */ 74 virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot( 75 gfx::DrawTarget* aTarget = nullptr) = 0; 76 77 virtual void ReturnSnapshot( 78 already_AddRefed<gfx::SourceSurface> aSnapshot) = 0; 79 80 virtual TextureClient* GetTextureClient() { return nullptr; } 81 82 virtual Maybe<RemoteTextureOwnerId> GetRemoteTextureOwnerId() const { 83 return Nothing(); 84 } 85 86 virtual void OnMemoryPressure() {} 87 88 virtual void OnShutdown() {} 89 90 virtual bool SetKnowsCompositor(KnowsCompositor* aKnowsCompositor, 91 bool& aOutLostFrontTexture) { 92 return true; 93 } 94 95 virtual void ClearCachedResources() {} 96 97 /** 98 * Return true if this provider preserves the drawing state (clips, 99 * transforms, etc.) across frames. In practice this means users of the 100 * provider can skip popping all of the clips at the end of the frames and 101 * pushing them back at the beginning of the following frames, which can be 102 * costly (cf. bug 1294351). 103 */ 104 virtual bool PreservesDrawingState() const = 0; 105 106 /** 107 * Whether or not the provider should be recreated, such as when profiling 108 * heuristics determine this type of provider is no longer advantageous to 109 * use. 110 */ 111 virtual bool RequiresRefresh() const { return false; } 112 113 virtual Maybe<SurfaceDescriptor> GetFrontBuffer() { return Nothing(); } 114 115 virtual already_AddRefed<FwdTransactionTracker> UseCompositableForwarder( 116 CompositableForwarder* aForwarder) { 117 return nullptr; 118 } 119 }; 120 121 class PersistentBufferProviderBasic : public PersistentBufferProvider { 122 public: 123 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderBasic, 124 override) 125 126 static already_AddRefed<PersistentBufferProviderBasic> Create( 127 gfx::IntSize aSize, gfx::SurfaceFormat aFormat, 128 gfx::BackendType aBackend); 129 130 explicit PersistentBufferProviderBasic(gfx::DrawTarget* aTarget); 131 132 already_AddRefed<gfx::DrawTarget> BorrowDrawTarget( 133 const gfx::IntRect& aPersistedRect) override; 134 135 bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) override; 136 137 already_AddRefed<gfx::SourceSurface> BorrowSnapshot( 138 gfx::DrawTarget* aTarget) override; 139 140 void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override; 141 142 bool PreservesDrawingState() const override { return true; } 143 144 void OnShutdown() override { Destroy(); } 145 146 protected: 147 void Destroy(); 148 149 ~PersistentBufferProviderBasic() override; 150 151 RefPtr<gfx::DrawTarget> mDrawTarget; 152 RefPtr<gfx::SourceSurface> mSnapshot; 153 }; 154 155 class PersistentBufferProviderAccelerated : public PersistentBufferProvider { 156 public: 157 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderAccelerated, 158 override) 159 160 static already_AddRefed<PersistentBufferProviderAccelerated> Create( 161 gfx::IntSize aSize, gfx::SurfaceFormat aFormat, 162 KnowsCompositor* aKnowsCompositor); 163 164 bool IsAccelerated() const override { return true; } 165 166 already_AddRefed<gfx::DrawTarget> BorrowDrawTarget( 167 const gfx::IntRect& aPersistedRect) override; 168 169 bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) override; 170 171 already_AddRefed<gfx::SourceSurface> BorrowSnapshot( 172 gfx::DrawTarget* aTarget) override; 173 174 void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override; 175 176 Maybe<RemoteTextureOwnerId> GetRemoteTextureOwnerId() const override { 177 return Some(mRemoteTextureOwnerId); 178 } 179 180 bool PreservesDrawingState() const override { return true; } 181 182 void OnShutdown() override { Destroy(); } 183 184 Maybe<SurfaceDescriptor> GetFrontBuffer() override; 185 186 bool RequiresRefresh() const override; 187 188 already_AddRefed<FwdTransactionTracker> UseCompositableForwarder( 189 CompositableForwarder* aForwarder) override; 190 191 protected: 192 explicit PersistentBufferProviderAccelerated( 193 RemoteTextureOwnerId aRemoteTextureOwnerId, 194 const RefPtr<TextureClient>& aTexture); 195 ~PersistentBufferProviderAccelerated() override; 196 197 void Destroy(); 198 199 RemoteTextureOwnerId mRemoteTextureOwnerId; 200 RefPtr<TextureClient> mTexture; 201 202 RefPtr<gfx::DrawTarget> mDrawTarget; 203 RefPtr<gfx::SourceSurface> mSnapshot; 204 }; 205 206 /** 207 * Provides access to a buffer which can be sent to the compositor without 208 * requiring a copy. 209 */ 210 class PersistentBufferProviderShared : public PersistentBufferProvider, 211 public ActiveResource { 212 public: 213 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderShared, 214 override) 215 216 static already_AddRefed<PersistentBufferProviderShared> Create( 217 gfx::IntSize aSize, gfx::SurfaceFormat aFormat, 218 KnowsCompositor* aKnowsCompositor, bool aWillReadFrequently = false, 219 const Maybe<uint64_t>& aWindowID = Nothing()); 220 221 bool IsShared() const override { return true; } 222 223 already_AddRefed<gfx::DrawTarget> BorrowDrawTarget( 224 const gfx::IntRect& aPersistedRect) override; 225 226 bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) override; 227 228 already_AddRefed<gfx::SourceSurface> BorrowSnapshot( 229 gfx::DrawTarget* aTarget) override; 230 231 void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override; 232 233 TextureClient* GetTextureClient() override; 234 235 void NotifyInactive() override; 236 237 void OnShutdown() override { Destroy(); } 238 239 bool SetKnowsCompositor(KnowsCompositor* aKnowsCompositor, 240 bool& aOutLostFrontTexture) override; 241 242 void ClearCachedResources() override; 243 244 bool PreservesDrawingState() const override { return false; } 245 246 protected: 247 PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, 248 KnowsCompositor* aKnowsCompositor, 249 RefPtr<TextureClient>& aTexture, 250 bool aWillReadFrequently, 251 const Maybe<uint64_t>& aWindowID); 252 253 ~PersistentBufferProviderShared(); 254 255 TextureClient* GetTexture(const Maybe<uint32_t>& aIndex); 256 bool CheckIndex(uint32_t aIndex) { return aIndex < mTextures.length(); } 257 258 void Destroy(); 259 260 gfx::IntSize mSize; 261 gfx::SurfaceFormat mFormat; 262 RefPtr<KnowsCompositor> mKnowsCompositor; 263 // If the texture has its own synchronization then copying back from the 264 // previous texture can cause contention issues and even deadlocks. So we use 265 // a separate permanent back buffer and copy into the shared back buffer when 266 // the DrawTarget is returned, before making it the new front buffer. 267 RefPtr<TextureClient> mPermanentBackBuffer; 268 static const size_t kMaxTexturesAllowed = 5; 269 Vector<RefPtr<TextureClient>, kMaxTexturesAllowed + 2> mTextures; 270 // Offset of the texture in mTextures that the canvas uses. 271 Maybe<uint32_t> mBack; 272 // Offset of the texture in mTextures that is presented to the compositor. 273 Maybe<uint32_t> mFront; 274 // Whether to avoid acceleration. 275 bool mWillReadFrequently = false; 276 // Owning window ID of the buffer provider. 277 Maybe<uint64_t> mWindowID; 278 279 RefPtr<gfx::DrawTarget> mDrawTarget; 280 RefPtr<gfx::SourceSurface> mSnapshot; 281 size_t mMaxAllowedTextures = kMaxTexturesAllowed; 282 }; 283 284 struct AutoReturnSnapshot final { 285 PersistentBufferProvider* mBufferProvider; 286 RefPtr<gfx::SourceSurface>* mSnapshot; 287 288 explicit AutoReturnSnapshot(PersistentBufferProvider* aProvider = nullptr) 289 : mBufferProvider(aProvider), mSnapshot(nullptr) {} 290 291 ~AutoReturnSnapshot() { 292 if (mBufferProvider) { 293 mBufferProvider->ReturnSnapshot(mSnapshot ? mSnapshot->forget() 294 : nullptr); 295 } 296 } 297 }; 298 299 } // namespace layers 300 } // namespace mozilla 301 302 #endif