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/. */
7 #ifndef MOZILLA_GFX_PersistentBUFFERPROVIDER_H
8 #define MOZILLA_GFX_PersistentBUFFERPROVIDER_H
10 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
11 #include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed, etc
12 #include "mozilla/layers/KnowsCompositor.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"
22 class ClientWebGLContext
;
27 class DrawTargetWebgl
;
35 * A PersistentBufferProvider is for users which require the temporary use of
36 * a DrawTarget to draw into. When they're done drawing they return the
37 * DrawTarget, when they later need to continue drawing they get a DrawTarget
38 * from the provider again, the provider will guarantee the contents of the
39 * previously returned DrawTarget is persisted into the one newly returned.
41 class PersistentBufferProvider
: public RefCounted
<PersistentBufferProvider
>,
42 public SupportsWeakPtr
{
44 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProvider
)
46 virtual ~PersistentBufferProvider() = default;
48 virtual bool IsShared() const { return false; }
49 virtual bool IsAccelerated() const { return false; }
52 * Get a DrawTarget from the PersistentBufferProvider.
54 * \param aPersistedRect This indicates the area of the DrawTarget that needs
55 * to have remained the same since the call to
58 virtual already_AddRefed
<gfx::DrawTarget
> BorrowDrawTarget(
59 const gfx::IntRect
& aPersistedRect
) = 0;
62 * Return a DrawTarget to the PersistentBufferProvider and indicate the
63 * contents of this DrawTarget is to be considered current by the
64 * BufferProvider. The caller should forget any references to the DrawTarget.
66 virtual bool ReturnDrawTarget(already_AddRefed
<gfx::DrawTarget
> aDT
) = 0;
69 * Temporarily borrow a snapshot of the provider. If a target is supplied,
70 * the snapshot will be optimized for it, if applicable.
72 virtual already_AddRefed
<gfx::SourceSurface
> BorrowSnapshot(
73 gfx::DrawTarget
* aTarget
= nullptr) = 0;
75 virtual void ReturnSnapshot(
76 already_AddRefed
<gfx::SourceSurface
> aSnapshot
) = 0;
78 virtual TextureClient
* GetTextureClient() { return nullptr; }
80 virtual void OnMemoryPressure() {}
82 virtual void OnShutdown() {}
84 virtual bool SetKnowsCompositor(KnowsCompositor
* aKnowsCompositor
,
85 bool& aOutLostFrontTexture
) {
89 virtual void ClearCachedResources() {}
92 * Return true if this provider preserves the drawing state (clips,
93 * transforms, etc.) across frames. In practice this means users of the
94 * provider can skip popping all of the clips at the end of the frames and
95 * pushing them back at the beginning of the following frames, which can be
96 * costly (cf. bug 1294351).
98 virtual bool PreservesDrawingState() const = 0;
101 * Whether or not the provider should be recreated, such as when profiling
102 * heuristics determine this type of provider is no longer advantageous to
105 virtual bool RequiresRefresh() const { return false; }
108 * Provide a WebGL front buffer for compositing, if available.
110 virtual Maybe
<layers::SurfaceDescriptor
> GetFrontBuffer() {
115 class PersistentBufferProviderBasic
: public PersistentBufferProvider
{
117 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderBasic
,
120 static already_AddRefed
<PersistentBufferProviderBasic
> Create(
121 gfx::IntSize aSize
, gfx::SurfaceFormat aFormat
,
122 gfx::BackendType aBackend
);
124 explicit PersistentBufferProviderBasic(gfx::DrawTarget
* aTarget
);
126 already_AddRefed
<gfx::DrawTarget
> BorrowDrawTarget(
127 const gfx::IntRect
& aPersistedRect
) override
;
129 bool ReturnDrawTarget(already_AddRefed
<gfx::DrawTarget
> aDT
) override
;
131 already_AddRefed
<gfx::SourceSurface
> BorrowSnapshot(
132 gfx::DrawTarget
* aTarget
) override
;
134 void ReturnSnapshot(already_AddRefed
<gfx::SourceSurface
> aSnapshot
) override
;
136 bool PreservesDrawingState() const override
{ return true; }
138 void OnShutdown() override
{ Destroy(); }
143 ~PersistentBufferProviderBasic() override
;
145 RefPtr
<gfx::DrawTarget
> mDrawTarget
;
146 RefPtr
<gfx::SourceSurface
> mSnapshot
;
149 class PersistentBufferProviderAccelerated
150 : public PersistentBufferProviderBasic
{
152 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderAccelerated
,
155 explicit PersistentBufferProviderAccelerated(gfx::DrawTarget
* aTarget
);
157 bool IsAccelerated() const override
{ return true; }
159 Maybe
<layers::SurfaceDescriptor
> GetFrontBuffer() override
;
161 already_AddRefed
<gfx::DrawTarget
> BorrowDrawTarget(
162 const gfx::IntRect
& aPersistedRect
) override
;
164 bool ReturnDrawTarget(already_AddRefed
<gfx::DrawTarget
> aDT
) override
;
166 already_AddRefed
<gfx::SourceSurface
> BorrowSnapshot(
167 gfx::DrawTarget
* aTarget
) override
;
169 bool RequiresRefresh() const override
;
171 void OnMemoryPressure() override
;
174 ~PersistentBufferProviderAccelerated() override
;
176 gfx::DrawTargetWebgl
* GetDrawTargetWebgl() const;
180 * Provides access to a buffer which can be sent to the compositor without
183 class PersistentBufferProviderShared
: public PersistentBufferProvider
,
184 public ActiveResource
{
186 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderShared
,
189 static already_AddRefed
<PersistentBufferProviderShared
> Create(
190 gfx::IntSize aSize
, gfx::SurfaceFormat aFormat
,
191 KnowsCompositor
* aKnowsCompositor
, bool aWillReadFrequently
= false);
193 bool IsShared() const override
{ return true; }
195 already_AddRefed
<gfx::DrawTarget
> BorrowDrawTarget(
196 const gfx::IntRect
& aPersistedRect
) override
;
198 bool ReturnDrawTarget(already_AddRefed
<gfx::DrawTarget
> aDT
) override
;
200 already_AddRefed
<gfx::SourceSurface
> BorrowSnapshot(
201 gfx::DrawTarget
* aTarget
) override
;
203 void ReturnSnapshot(already_AddRefed
<gfx::SourceSurface
> aSnapshot
) override
;
205 TextureClient
* GetTextureClient() override
;
207 void NotifyInactive() override
;
209 void OnShutdown() override
{ Destroy(); }
211 bool SetKnowsCompositor(KnowsCompositor
* aKnowsCompositor
,
212 bool& aOutLostFrontTexture
) override
;
214 void ClearCachedResources() override
;
216 bool PreservesDrawingState() const override
{ return false; }
218 bool IsAccelerated() const override
;
221 PersistentBufferProviderShared(gfx::IntSize aSize
, gfx::SurfaceFormat aFormat
,
222 KnowsCompositor
* aKnowsCompositor
,
223 RefPtr
<TextureClient
>& aTexture
,
224 bool aWillReadFrequently
);
226 ~PersistentBufferProviderShared();
228 TextureClient
* GetTexture(const Maybe
<uint32_t>& aIndex
);
229 bool CheckIndex(uint32_t aIndex
) { return aIndex
< mTextures
.length(); }
234 gfx::SurfaceFormat mFormat
;
235 RefPtr
<KnowsCompositor
> mKnowsCompositor
;
236 // If the texture has its own synchronization then copying back from the
237 // previous texture can cause contention issues and even deadlocks. So we use
238 // a separate permanent back buffer and copy into the shared back buffer when
239 // the DrawTarget is returned, before making it the new front buffer.
240 RefPtr
<TextureClient
> mPermanentBackBuffer
;
241 static const size_t kMaxTexturesAllowed
= 5;
242 Vector
<RefPtr
<TextureClient
>, kMaxTexturesAllowed
+ 2> mTextures
;
243 // Offset of the texture in mTextures that the canvas uses.
244 Maybe
<uint32_t> mBack
;
245 // Offset of the texture in mTextures that is presented to the compositor.
246 Maybe
<uint32_t> mFront
;
247 // Whether to avoid acceleration.
248 bool mWillReadFrequently
= false;
250 RefPtr
<gfx::DrawTarget
> mDrawTarget
;
251 RefPtr
<gfx::SourceSurface
> mSnapshot
;
252 size_t mMaxAllowedTextures
= kMaxTexturesAllowed
;
255 struct AutoReturnSnapshot final
{
256 PersistentBufferProvider
* mBufferProvider
;
257 RefPtr
<gfx::SourceSurface
>* mSnapshot
;
259 explicit AutoReturnSnapshot(PersistentBufferProvider
* aProvider
= nullptr)
260 : mBufferProvider(aProvider
), mSnapshot(nullptr) {}
262 ~AutoReturnSnapshot() {
263 if (mBufferProvider
) {
264 mBufferProvider
->ReturnSnapshot(mSnapshot
? mSnapshot
->forget()
270 } // namespace layers
271 } // namespace mozilla