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/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"
22 class ClientWebGLContext
;
31 class CompositableForwarder
;
32 class FwdTransactionTracker
;
33 class KnowsCompositor
;
34 struct RemoteTextureOwnerId
;
38 * A PersistentBufferProvider is for users which require the temporary use of
39 * a DrawTarget to draw into. When they're done drawing they return the
40 * DrawTarget, when they later need to continue drawing they get a DrawTarget
41 * from the provider again, the provider will guarantee the contents of the
42 * previously returned DrawTarget is persisted into the one newly returned.
44 class PersistentBufferProvider
: public RefCounted
<PersistentBufferProvider
>,
45 public SupportsWeakPtr
{
47 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProvider
)
49 virtual ~PersistentBufferProvider() = default;
51 virtual bool IsShared() const { return false; }
52 virtual bool IsAccelerated() const { return false; }
55 * Get a DrawTarget from the PersistentBufferProvider.
57 * \param aPersistedRect This indicates the area of the DrawTarget that needs
58 * to have remained the same since the call to
61 virtual already_AddRefed
<gfx::DrawTarget
> BorrowDrawTarget(
62 const gfx::IntRect
& aPersistedRect
) = 0;
65 * Return a DrawTarget to the PersistentBufferProvider and indicate the
66 * contents of this DrawTarget is to be considered current by the
67 * BufferProvider. The caller should forget any references to the DrawTarget.
69 virtual bool ReturnDrawTarget(already_AddRefed
<gfx::DrawTarget
> aDT
) = 0;
72 * Temporarily borrow a snapshot of the provider. If a target is supplied,
73 * the snapshot will be optimized for it, if applicable.
75 virtual already_AddRefed
<gfx::SourceSurface
> BorrowSnapshot(
76 gfx::DrawTarget
* aTarget
= nullptr) = 0;
78 virtual void ReturnSnapshot(
79 already_AddRefed
<gfx::SourceSurface
> aSnapshot
) = 0;
81 virtual TextureClient
* GetTextureClient() { return nullptr; }
83 virtual void OnMemoryPressure() {}
85 virtual void OnShutdown() {}
87 virtual bool SetKnowsCompositor(KnowsCompositor
* aKnowsCompositor
,
88 bool& aOutLostFrontTexture
) {
92 virtual void ClearCachedResources() {}
95 * Return true if this provider preserves the drawing state (clips,
96 * transforms, etc.) across frames. In practice this means users of the
97 * provider can skip popping all of the clips at the end of the frames and
98 * pushing them back at the beginning of the following frames, which can be
99 * costly (cf. bug 1294351).
101 virtual bool PreservesDrawingState() const = 0;
104 * Whether or not the provider should be recreated, such as when profiling
105 * heuristics determine this type of provider is no longer advantageous to
108 virtual bool RequiresRefresh() const { return false; }
110 virtual Maybe
<SurfaceDescriptor
> GetFrontBuffer() { return Nothing(); }
112 virtual already_AddRefed
<FwdTransactionTracker
> UseCompositableForwarder(
113 CompositableForwarder
* aForwarder
) {
118 class PersistentBufferProviderBasic
: public PersistentBufferProvider
{
120 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderBasic
,
123 static already_AddRefed
<PersistentBufferProviderBasic
> Create(
124 gfx::IntSize aSize
, gfx::SurfaceFormat aFormat
,
125 gfx::BackendType aBackend
);
127 explicit PersistentBufferProviderBasic(gfx::DrawTarget
* aTarget
);
129 already_AddRefed
<gfx::DrawTarget
> BorrowDrawTarget(
130 const gfx::IntRect
& aPersistedRect
) override
;
132 bool ReturnDrawTarget(already_AddRefed
<gfx::DrawTarget
> aDT
) override
;
134 already_AddRefed
<gfx::SourceSurface
> BorrowSnapshot(
135 gfx::DrawTarget
* aTarget
) override
;
137 void ReturnSnapshot(already_AddRefed
<gfx::SourceSurface
> aSnapshot
) override
;
139 bool PreservesDrawingState() const override
{ return true; }
141 void OnShutdown() override
{ Destroy(); }
146 ~PersistentBufferProviderBasic() override
;
148 RefPtr
<gfx::DrawTarget
> mDrawTarget
;
149 RefPtr
<gfx::SourceSurface
> mSnapshot
;
152 class PersistentBufferProviderAccelerated
: public PersistentBufferProvider
{
154 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderAccelerated
,
157 static already_AddRefed
<PersistentBufferProviderAccelerated
> Create(
158 gfx::IntSize aSize
, gfx::SurfaceFormat aFormat
,
159 KnowsCompositor
* aKnowsCompositor
);
161 bool IsAccelerated() const override
{ return true; }
163 already_AddRefed
<gfx::DrawTarget
> BorrowDrawTarget(
164 const gfx::IntRect
& aPersistedRect
) override
;
166 bool ReturnDrawTarget(already_AddRefed
<gfx::DrawTarget
> aDT
) override
;
168 already_AddRefed
<gfx::SourceSurface
> BorrowSnapshot(
169 gfx::DrawTarget
* aTarget
) override
;
171 void ReturnSnapshot(already_AddRefed
<gfx::SourceSurface
> aSnapshot
) override
;
173 bool PreservesDrawingState() const override
{ return true; }
175 void OnShutdown() override
{ Destroy(); }
177 Maybe
<SurfaceDescriptor
> GetFrontBuffer() override
;
179 bool RequiresRefresh() const override
;
181 already_AddRefed
<FwdTransactionTracker
> UseCompositableForwarder(
182 CompositableForwarder
* aForwarder
) override
;
185 explicit PersistentBufferProviderAccelerated(
186 const RefPtr
<TextureClient
>& aTexture
);
187 ~PersistentBufferProviderAccelerated() override
;
191 RefPtr
<TextureClient
> mTexture
;
193 RefPtr
<gfx::DrawTarget
> mDrawTarget
;
194 RefPtr
<gfx::SourceSurface
> mSnapshot
;
198 * Provides access to a buffer which can be sent to the compositor without
201 class PersistentBufferProviderShared
: public PersistentBufferProvider
,
202 public ActiveResource
{
204 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderShared
,
207 static already_AddRefed
<PersistentBufferProviderShared
> Create(
208 gfx::IntSize aSize
, gfx::SurfaceFormat aFormat
,
209 KnowsCompositor
* aKnowsCompositor
, bool aWillReadFrequently
= false,
210 const Maybe
<uint64_t>& aWindowID
= Nothing());
212 bool IsShared() const override
{ return true; }
214 already_AddRefed
<gfx::DrawTarget
> BorrowDrawTarget(
215 const gfx::IntRect
& aPersistedRect
) override
;
217 bool ReturnDrawTarget(already_AddRefed
<gfx::DrawTarget
> aDT
) override
;
219 already_AddRefed
<gfx::SourceSurface
> BorrowSnapshot(
220 gfx::DrawTarget
* aTarget
) override
;
222 void ReturnSnapshot(already_AddRefed
<gfx::SourceSurface
> aSnapshot
) override
;
224 TextureClient
* GetTextureClient() override
;
226 void NotifyInactive() override
;
228 void OnShutdown() override
{ Destroy(); }
230 bool SetKnowsCompositor(KnowsCompositor
* aKnowsCompositor
,
231 bool& aOutLostFrontTexture
) override
;
233 void ClearCachedResources() override
;
235 bool PreservesDrawingState() const override
{ return false; }
238 PersistentBufferProviderShared(gfx::IntSize aSize
, gfx::SurfaceFormat aFormat
,
239 KnowsCompositor
* aKnowsCompositor
,
240 RefPtr
<TextureClient
>& aTexture
,
241 bool aWillReadFrequently
,
242 const Maybe
<uint64_t>& aWindowID
);
244 ~PersistentBufferProviderShared();
246 TextureClient
* GetTexture(const Maybe
<uint32_t>& aIndex
);
247 bool CheckIndex(uint32_t aIndex
) { return aIndex
< mTextures
.length(); }
252 gfx::SurfaceFormat mFormat
;
253 RefPtr
<KnowsCompositor
> mKnowsCompositor
;
254 // If the texture has its own synchronization then copying back from the
255 // previous texture can cause contention issues and even deadlocks. So we use
256 // a separate permanent back buffer and copy into the shared back buffer when
257 // the DrawTarget is returned, before making it the new front buffer.
258 RefPtr
<TextureClient
> mPermanentBackBuffer
;
259 static const size_t kMaxTexturesAllowed
= 5;
260 Vector
<RefPtr
<TextureClient
>, kMaxTexturesAllowed
+ 2> mTextures
;
261 // Offset of the texture in mTextures that the canvas uses.
262 Maybe
<uint32_t> mBack
;
263 // Offset of the texture in mTextures that is presented to the compositor.
264 Maybe
<uint32_t> mFront
;
265 // Whether to avoid acceleration.
266 bool mWillReadFrequently
= false;
267 // Owning window ID of the buffer provider.
268 Maybe
<uint64_t> mWindowID
;
270 RefPtr
<gfx::DrawTarget
> mDrawTarget
;
271 RefPtr
<gfx::SourceSurface
> mSnapshot
;
272 size_t mMaxAllowedTextures
= kMaxTexturesAllowed
;
275 struct AutoReturnSnapshot final
{
276 PersistentBufferProvider
* mBufferProvider
;
277 RefPtr
<gfx::SourceSurface
>* mSnapshot
;
279 explicit AutoReturnSnapshot(PersistentBufferProvider
* aProvider
= nullptr)
280 : mBufferProvider(aProvider
), mSnapshot(nullptr) {}
282 ~AutoReturnSnapshot() {
283 if (mBufferProvider
) {
284 mBufferProvider
->ReturnSnapshot(mSnapshot
? mSnapshot
->forget()
290 } // namespace layers
291 } // namespace mozilla