1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef MOZILLA_GFX_PersistentBUFFERPROVIDER_H
7 #define MOZILLA_GFX_PersistentBUFFERPROVIDER_H
8 
9 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
10 #include "mozilla/RefPtr.h"             // for RefPtr, already_AddRefed, etc
11 #include "mozilla/layers/LayersTypes.h"
12 #include "mozilla/layers/ShadowLayers.h"
13 #include "mozilla/gfx/Types.h"
14 #include "mozilla/Vector.h"
15 
16 namespace mozilla {
17 
18 namespace gfx {
19   class SourceSurface;
20   class DrawTarget;
21 }
22 
23 namespace layers {
24 
25 class CopyableCanvasLayer;
26 
27 /**
28  * A PersistentBufferProvider is for users which require the temporary use of
29  * a DrawTarget to draw into. When they're done drawing they return the
30  * DrawTarget, when they later need to continue drawing they get a DrawTarget
31  * from the provider again, the provider will guarantee the contents of the
32  * previously returned DrawTarget is persisted into the one newly returned.
33  */
34 class PersistentBufferProvider : public RefCounted<PersistentBufferProvider>
35 {
36 public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProvider)37   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProvider)
38 
39   virtual ~PersistentBufferProvider() { }
40 
GetType()41   virtual LayersBackend GetType() { return LayersBackend::LAYERS_NONE; }
42 
43   /**
44    * Get a DrawTarget from the PersistentBufferProvider.
45    *
46    * \param aPersistedRect This indicates the area of the DrawTarget that needs
47    *                       to have remained the same since the call to
48    *                       ReturnDrawTarget.
49    */
50   virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget(const gfx::IntRect& aPersistedRect) = 0;
51 
52   /**
53    * Return a DrawTarget to the PersistentBufferProvider and indicate the
54    * contents of this DrawTarget is to be considered current by the
55    * BufferProvider. The caller should forget any references to the DrawTarget.
56    */
57   virtual bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) = 0;
58 
59   virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() = 0;
60 
61   virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) = 0;
62 
GetTextureClient()63   virtual TextureClient* GetTextureClient() { return nullptr; }
64 
OnShutdown()65   virtual void OnShutdown() {}
66 
SetForwarder(ShadowLayerForwarder * aFwd)67   virtual bool SetForwarder(ShadowLayerForwarder* aFwd) { return true; }
68 
69   /**
70    * Return true if this provider preserves the drawing state (clips, transforms,
71    * etc.) across frames. In practice this means users of the provider can skip
72    * popping all of the clips at the end of the frames and pushing them back at
73    * the beginning of the following frames, which can be costly (cf. bug 1294351).
74    */
75   virtual bool PreservesDrawingState() const = 0;
76 };
77 
78 
79 class PersistentBufferProviderBasic : public PersistentBufferProvider
80 {
81 public:
82   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderBasic, override)
83 
84   static already_AddRefed<PersistentBufferProviderBasic>
85   Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aBackend);
86 
87   explicit PersistentBufferProviderBasic(gfx::DrawTarget* aTarget);
88 
GetType()89   virtual LayersBackend GetType() override { return LayersBackend::LAYERS_BASIC; }
90 
91   virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget(const gfx::IntRect& aPersistedRect) override;
92 
93   virtual bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) override;
94 
95   virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() override;
96 
97   virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override;
98 
PreservesDrawingState()99   virtual bool PreservesDrawingState() const override { return true; }
100 private:
101   ~PersistentBufferProviderBasic();
102 
103   RefPtr<gfx::DrawTarget> mDrawTarget;
104   RefPtr<gfx::SourceSurface> mSnapshot;
105 };
106 
107 
108 /**
109  * Provides access to a buffer which can be sent to the compositor without
110  * requiring a copy.
111  */
112 class PersistentBufferProviderShared : public PersistentBufferProvider
113                                      , public ActiveResource
114 {
115 public:
116   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderShared, override)
117 
118   static already_AddRefed<PersistentBufferProviderShared>
119   Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
120          ShadowLayerForwarder* aFwd);
121 
GetType()122   virtual LayersBackend GetType() override { return LayersBackend::LAYERS_CLIENT; }
123 
124   virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget(const gfx::IntRect& aPersistedRect) override;
125 
126   virtual bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) override;
127 
128   virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() override;
129 
130   virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override;
131 
132   virtual TextureClient* GetTextureClient() override;
133 
134   virtual void NotifyInactive() override;
135 
OnShutdown()136   virtual void OnShutdown() override { Destroy(); }
137 
138   virtual bool SetForwarder(ShadowLayerForwarder* aFwd) override;
139 
PreservesDrawingState()140   virtual bool PreservesDrawingState() const override { return false; }
141 protected:
142   PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
143                                  ShadowLayerForwarder* aFwd,
144                                  RefPtr<TextureClient>& aTexture);
145 
146   ~PersistentBufferProviderShared();
147 
148   TextureClient* GetTexture(Maybe<uint32_t> aIndex);
CheckIndex(uint32_t aIndex)149   bool CheckIndex(uint32_t aIndex) { return aIndex < mTextures.length(); }
150 
151   void Destroy();
152 
153   gfx::IntSize mSize;
154   gfx::SurfaceFormat mFormat;
155   RefPtr<ShadowLayerForwarder> mFwd;
156   Vector<RefPtr<TextureClient>, 4> mTextures;
157   // Offset of the texture in mTextures that the canvas uses.
158   Maybe<uint32_t> mBack;
159   // Offset of the texture in mTextures that is presented to the compositor.
160   Maybe<uint32_t> mFront;
161 
162   RefPtr<gfx::DrawTarget> mDrawTarget;
163   RefPtr<gfx::SourceSurface > mSnapshot;
164 };
165 
166 struct AutoReturnSnapshot
167 {
168   PersistentBufferProvider* mBufferProvider;
169   RefPtr<gfx::SourceSurface>* mSnapshot;
170 
171   explicit AutoReturnSnapshot(PersistentBufferProvider* aProvider = nullptr)
mBufferProviderAutoReturnSnapshot172   : mBufferProvider(aProvider)
173   , mSnapshot(nullptr)
174   {}
175 
~AutoReturnSnapshotAutoReturnSnapshot176   ~AutoReturnSnapshot()
177   {
178     if (mBufferProvider) {
179       mBufferProvider->ReturnSnapshot(mSnapshot ? mSnapshot->forget() : nullptr);
180     }
181   }
182 };
183 
184 } // namespace layers
185 } // namespace mozilla
186 
187 #endif
188