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_CANVASCLIENT_H
7 #define MOZILLA_GFX_CANVASCLIENT_H
8 
9 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
10 #include "mozilla/Attributes.h"         // for override
11 #include "mozilla/RefPtr.h"             // for RefPtr, already_AddRefed
12 #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
13 #include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
14 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
15 #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
16 #include "mozilla/layers/PersistentBufferProvider.h"
17 
18 // Fix X11 header brain damage that conflicts with MaybeOneOf::None
19 #undef None
20 #include "mozilla/MaybeOneOf.h"
21 
22 #include "mozilla/mozalloc.h"           // for operator delete
23 
24 #include "mozilla/gfx/Point.h"          // for IntSize
25 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
26 
27 namespace mozilla {
28 namespace layers {
29 
30 class AsyncCanvasRenderer;
31 class ClientCanvasLayer;
32 class CompositableForwarder;
33 class ShadowableLayer;
34 class SharedSurfaceTextureClient;
35 
36 /**
37  * Compositable client for 2d and webgl canvas.
38  */
39 class CanvasClient : public CompositableClient
40 {
41 public:
42   typedef MaybeOneOf<ClientCanvasLayer*, AsyncCanvasRenderer*> Renderer;
43 
44   /**
45    * Creates, configures, and returns a new canvas client. If necessary, a
46    * message will be sent to the compositor to create a corresponding image
47    * host.
48    */
49   enum CanvasClientType {
50     CanvasClientSurface,
51     CanvasClientGLContext,
52     CanvasClientTypeShSurf,
53     CanvasClientAsync, // webgl on workers
54   };
55   static already_AddRefed<CanvasClient> CreateCanvasClient(CanvasClientType aType,
56                                                        CompositableForwarder* aFwd,
57                                                        TextureFlags aFlags);
58 
CanvasClient(CompositableForwarder * aFwd,TextureFlags aFlags)59   CanvasClient(CompositableForwarder* aFwd, TextureFlags aFlags)
60     : CompositableClient(aFwd, aFlags)
61     , mFrameID(0)
62   {
63     mTextureFlags = aFlags;
64   }
65 
~CanvasClient()66   virtual ~CanvasClient() {}
67 
Clear()68   virtual void Clear() {};
69 
70   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) = 0;
71 
AddTextureClient(TextureClient * aTexture)72   virtual bool AddTextureClient(TextureClient* aTexture) override
73   {
74     ++mFrameID;
75     return CompositableClient::AddTextureClient(aTexture);
76   }
77 
UpdateAsync(AsyncCanvasRenderer * aRenderer)78   virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) {}
79 
UpdateFromTexture(TextureClient * aTexture)80   virtual void UpdateFromTexture(TextureClient* aTexture) {}
81 
Updated()82   virtual void Updated() { }
83 
84 protected:
85   int32_t mFrameID;
86 };
87 
88 // Used for 2D canvases and WebGL canvas on non-GL systems where readback is requried.
89 class CanvasClient2D : public CanvasClient
90 {
91 public:
CanvasClient2D(CompositableForwarder * aLayerForwarder,TextureFlags aFlags)92   CanvasClient2D(CompositableForwarder* aLayerForwarder,
93                  TextureFlags aFlags)
94     : CanvasClient(aLayerForwarder, aFlags)
95   {
96   }
97 
GetTextureInfo()98   TextureInfo GetTextureInfo() const override
99   {
100     return TextureInfo(CompositableType::IMAGE, mTextureFlags);
101   }
102 
Clear()103   virtual void Clear() override
104   {
105     mBackBuffer = mFrontBuffer = nullptr;
106   }
107 
108   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) override;
109 
110   virtual void UpdateFromTexture(TextureClient* aBuffer) override;
111 
AddTextureClient(TextureClient * aTexture)112   virtual bool AddTextureClient(TextureClient* aTexture) override
113   {
114     return CanvasClient::AddTextureClient(aTexture);
115   }
116 
OnDetach()117   virtual void OnDetach() override
118   {
119     mBackBuffer = mFrontBuffer = nullptr;
120   }
121 
122 private:
123   already_AddRefed<TextureClient>
124     CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
125                                  gfx::IntSize aSize,
126                                  TextureFlags aFlags,
127                                  ClientCanvasLayer* aLayer);
128 
129   RefPtr<TextureClient> mBackBuffer;
130   RefPtr<TextureClient> mFrontBuffer;
131   // We store this texture separately to make sure it is not written into
132   // in Update() if for some silly reason we end up alternating between
133   // UpdateFromTexture and Update.
134   // This code is begging for a cleanup. The situation described above should
135   // not be made possible.
136   RefPtr<TextureClient> mBufferProviderTexture;
137 };
138 
139 // Used for GL canvases where we don't need to do any readback, i.e., with a
140 // GL backend.
141 class CanvasClientSharedSurface : public CanvasClient
142 {
143 private:
144   RefPtr<SharedSurfaceTextureClient> mShSurfClient;
145   RefPtr<TextureClient> mReadbackClient;
146   RefPtr<TextureClient> mFront;
147   RefPtr<TextureClient> mNewFront;
148 
149   void ClearSurfaces();
150 
151 public:
152   CanvasClientSharedSurface(CompositableForwarder* aLayerForwarder,
153                             TextureFlags aFlags);
154 
155   ~CanvasClientSharedSurface();
156 
GetTextureInfo()157   virtual TextureInfo GetTextureInfo() const override {
158     return TextureInfo(CompositableType::IMAGE);
159   }
160 
Clear()161   virtual void Clear() override {
162     ClearSurfaces();
163   }
164 
165   virtual void Update(gfx::IntSize aSize,
166                       ClientCanvasLayer* aLayer) override;
167   void UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer);
168 
169   virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
170 
171   virtual void Updated() override;
172 
173   virtual void OnDetach() override;
174 };
175 
176 /**
177  * Used for OMT<canvas> uploads using the image bridge protocol.
178  * Actual CanvasClient is on the ImageBridgeChild thread, so we
179  * only forward its AsyncID here
180  */
181 class CanvasClientBridge final : public CanvasClient
182 {
183 public:
CanvasClientBridge(CompositableForwarder * aLayerForwarder,TextureFlags aFlags)184   CanvasClientBridge(CompositableForwarder* aLayerForwarder,
185                      TextureFlags aFlags)
186     : CanvasClient(aLayerForwarder, aFlags)
187     , mAsyncID(0)
188     , mLayer(nullptr)
189   {
190   }
191 
GetTextureInfo()192   TextureInfo GetTextureInfo() const override
193   {
194     return TextureInfo(CompositableType::IMAGE);
195   }
196 
Update(gfx::IntSize aSize,ClientCanvasLayer * aLayer)197   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) override
198   {
199   }
200 
201   virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
202 
SetLayer(ShadowableLayer * aLayer)203   void SetLayer(ShadowableLayer* aLayer)
204   {
205     mLayer = aLayer;
206   }
207 
208 protected:
209   uint64_t mAsyncID;
210   ShadowableLayer* mLayer;
211 };
212 
213 } // namespace layers
214 } // namespace mozilla
215 
216 #endif
217