Line data Source code
1 : /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
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 : /* SharedSurface abstracts an actual surface (can be a GL texture, but
7 : * not necessarily) that handles sharing.
8 : * Its specializations are:
9 : * SharedSurface_Basic (client-side bitmap, does readback)
10 : * SharedSurface_GLTexture
11 : * SharedSurface_EGLImage
12 : * SharedSurface_ANGLEShareHandle
13 : */
14 :
15 : #ifndef SHARED_SURFACE_H_
16 : #define SHARED_SURFACE_H_
17 :
18 : #include <queue>
19 : #include <set>
20 : #include <stdint.h>
21 :
22 : #include "GLContextTypes.h"
23 : #include "GLDefs.h"
24 : #include "mozilla/Attributes.h"
25 : #include "mozilla/DebugOnly.h"
26 : #include "mozilla/gfx/Point.h"
27 : #include "mozilla/Mutex.h"
28 : #include "mozilla/UniquePtr.h"
29 : #include "mozilla/WeakPtr.h"
30 : #include "ScopedGLHelpers.h"
31 : #include "SurfaceTypes.h"
32 :
33 : class nsIThread;
34 :
35 : namespace mozilla {
36 : namespace gfx {
37 : class DataSourceSurface;
38 : class DrawTarget;
39 : } // namespace gfx
40 :
41 : namespace layers {
42 : class LayersIPCChannel;
43 : class SharedSurfaceTextureClient;
44 : enum class TextureFlags : uint32_t;
45 : class SurfaceDescriptor;
46 : class TextureClient;
47 : } // namespace layers
48 :
49 : namespace gl {
50 :
51 : class GLContext;
52 : class SurfaceFactory;
53 : class ShSurfHandle;
54 :
55 : class SharedSurface
56 : {
57 : public:
58 : static void ProdCopy(SharedSurface* src, SharedSurface* dest,
59 : SurfaceFactory* factory);
60 :
61 : const SharedSurfaceType mType;
62 : const AttachmentType mAttachType;
63 : const WeakPtr<GLContext> mGL;
64 : const gfx::IntSize mSize;
65 : const bool mHasAlpha;
66 : const bool mCanRecycle;
67 : protected:
68 : bool mIsLocked;
69 : bool mIsProducerAcquired;
70 :
71 : SharedSurface(SharedSurfaceType type,
72 : AttachmentType attachType,
73 : GLContext* gl,
74 : const gfx::IntSize& size,
75 : bool hasAlpha,
76 : bool canRecycle);
77 :
78 : public:
79 0 : virtual ~SharedSurface() {
80 0 : }
81 :
82 : // Specifies to the TextureClient any flags which
83 : // are required by the SharedSurface backend.
84 : virtual layers::TextureFlags GetTextureFlags() const;
85 :
86 0 : bool IsLocked() const { return mIsLocked; }
87 0 : bool IsProducerAcquired() const { return mIsProducerAcquired; }
88 :
89 : // This locks the SharedSurface as the production buffer for the context.
90 : // This is needed by backends which use PBuffers and/or EGLSurfaces.
91 : void LockProd();
92 :
93 : // Unlocking is harmless if we're already unlocked.
94 : void UnlockProd();
95 :
96 : // This surface has been moved to the front buffer and will not be locked again
97 : // until it is recycled. Do any finalization steps here.
98 0 : virtual void Commit(){}
99 :
100 : protected:
101 : virtual void LockProdImpl() = 0;
102 : virtual void UnlockProdImpl() = 0;
103 :
104 : virtual void ProducerAcquireImpl() = 0;
105 : virtual void ProducerReleaseImpl() = 0;
106 0 : virtual void ProducerReadAcquireImpl() { ProducerAcquireImpl(); }
107 0 : virtual void ProducerReadReleaseImpl() { ProducerReleaseImpl(); }
108 :
109 : public:
110 0 : void ProducerAcquire() {
111 0 : MOZ_ASSERT(!mIsProducerAcquired);
112 0 : ProducerAcquireImpl();
113 0 : mIsProducerAcquired = true;
114 0 : }
115 0 : void ProducerRelease() {
116 0 : MOZ_ASSERT(mIsProducerAcquired);
117 0 : ProducerReleaseImpl();
118 0 : mIsProducerAcquired = false;
119 0 : }
120 0 : void ProducerReadAcquire() {
121 0 : MOZ_ASSERT(!mIsProducerAcquired);
122 0 : ProducerReadAcquireImpl();
123 0 : mIsProducerAcquired = true;
124 0 : }
125 0 : void ProducerReadRelease() {
126 0 : MOZ_ASSERT(mIsProducerAcquired);
127 0 : ProducerReadReleaseImpl();
128 0 : mIsProducerAcquired = false;
129 0 : }
130 :
131 : // This function waits until the buffer is no longer being used.
132 : // To optimize the performance, some implementaions recycle SharedSurfaces
133 : // even when its buffer is still being used.
134 0 : virtual void WaitForBufferOwnership() {}
135 :
136 : // For use when AttachType is correct.
137 0 : virtual GLenum ProdTextureTarget() const {
138 0 : MOZ_ASSERT(mAttachType == AttachmentType::GLTexture);
139 0 : return LOCAL_GL_TEXTURE_2D;
140 : }
141 :
142 0 : virtual GLuint ProdTexture() {
143 0 : MOZ_ASSERT(mAttachType == AttachmentType::GLTexture);
144 0 : MOZ_CRASH("GFX: Did you forget to override this function?");
145 : }
146 :
147 0 : virtual GLuint ProdRenderbuffer() {
148 0 : MOZ_ASSERT(mAttachType == AttachmentType::GLRenderbuffer);
149 0 : MOZ_CRASH("GFX: Did you forget to override this function?");
150 : }
151 :
152 0 : virtual bool CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x,
153 : GLint y, GLsizei width, GLsizei height, GLint border)
154 : {
155 0 : return false;
156 : }
157 :
158 0 : virtual bool ReadPixels(GLint x, GLint y,
159 : GLsizei width, GLsizei height,
160 : GLenum format, GLenum type,
161 : GLvoid* pixels)
162 : {
163 0 : return false;
164 : }
165 :
166 0 : virtual bool NeedsIndirectReads() const {
167 0 : return false;
168 : }
169 :
170 : virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) = 0;
171 :
172 0 : virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) {
173 0 : return false;
174 : }
175 : };
176 :
177 : template<typename T>
178 0 : class RefSet
179 : {
180 : std::set<T*> mSet;
181 :
182 : public:
183 0 : ~RefSet() {
184 0 : clear();
185 0 : }
186 :
187 0 : auto begin() -> decltype(mSet.begin()) {
188 0 : return mSet.begin();
189 : }
190 :
191 0 : void clear() {
192 0 : for (auto itr = mSet.begin(); itr != mSet.end(); ++itr) {
193 0 : (*itr)->Release();
194 : }
195 0 : mSet.clear();
196 0 : }
197 :
198 0 : bool empty() const {
199 0 : return mSet.empty();
200 : }
201 :
202 0 : bool insert(T* x) {
203 0 : if (mSet.insert(x).second) {
204 0 : x->AddRef();
205 0 : return true;
206 : }
207 :
208 0 : return false;
209 : }
210 :
211 0 : bool erase(T* x) {
212 0 : if (mSet.erase(x)) {
213 0 : x->Release();
214 0 : return true;
215 : }
216 :
217 0 : return false;
218 : }
219 : };
220 :
221 : template<typename T>
222 0 : class RefQueue
223 : {
224 : std::queue<T*> mQueue;
225 :
226 : public:
227 0 : ~RefQueue() {
228 0 : clear();
229 0 : }
230 :
231 0 : void clear() {
232 0 : while (!empty()) {
233 0 : pop();
234 : }
235 0 : }
236 :
237 0 : bool empty() const {
238 0 : return mQueue.empty();
239 : }
240 :
241 0 : size_t size() const {
242 0 : return mQueue.size();
243 : }
244 :
245 0 : void push(T* x) {
246 0 : mQueue.push(x);
247 0 : x->AddRef();
248 0 : }
249 :
250 0 : T* front() const {
251 0 : return mQueue.front();
252 : }
253 :
254 0 : void pop() {
255 0 : T* x = mQueue.front();
256 0 : x->Release();
257 0 : mQueue.pop();
258 0 : }
259 : };
260 :
261 : class SurfaceFactory : public SupportsWeakPtr<SurfaceFactory>
262 : {
263 : public:
264 : // Should use the VIRTUAL version, but it's currently incompatible
265 : // with SupportsWeakPtr. (bug 1049278)
266 0 : MOZ_DECLARE_WEAKREFERENCE_TYPENAME(SurfaceFactory)
267 :
268 : const SharedSurfaceType mType;
269 : GLContext* const mGL;
270 : const SurfaceCaps mCaps;
271 : const RefPtr<layers::LayersIPCChannel> mAllocator;
272 : const layers::TextureFlags mFlags;
273 : const GLFormats mFormats;
274 : Mutex mMutex;
275 : protected:
276 : SurfaceCaps mDrawCaps;
277 : SurfaceCaps mReadCaps;
278 : RefQueue<layers::SharedSurfaceTextureClient> mRecycleFreePool;
279 : RefSet<layers::SharedSurfaceTextureClient> mRecycleTotalPool;
280 :
281 : SurfaceFactory(SharedSurfaceType type, GLContext* gl, const SurfaceCaps& caps,
282 : const RefPtr<layers::LayersIPCChannel>& allocator,
283 : const layers::TextureFlags& flags);
284 :
285 : public:
286 : virtual ~SurfaceFactory();
287 :
288 0 : const SurfaceCaps& DrawCaps() const {
289 0 : return mDrawCaps;
290 : }
291 :
292 0 : const SurfaceCaps& ReadCaps() const {
293 0 : return mReadCaps;
294 : }
295 :
296 : protected:
297 : virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) = 0;
298 :
299 : void StartRecycling(layers::SharedSurfaceTextureClient* tc);
300 : void SetRecycleCallback(layers::SharedSurfaceTextureClient* tc);
301 : void StopRecycling(layers::SharedSurfaceTextureClient* tc);
302 :
303 : public:
304 : UniquePtr<SharedSurface> NewSharedSurface(const gfx::IntSize& size);
305 : //already_AddRefed<ShSurfHandle> NewShSurfHandle(const gfx::IntSize& size);
306 : already_AddRefed<layers::SharedSurfaceTextureClient> NewTexClient(const gfx::IntSize& size,
307 : const layers::LayersIPCChannel* aLayersChannel = nullptr);
308 :
309 : static void RecycleCallback(layers::TextureClient* tc, void* /*closure*/);
310 :
311 : // Auto-deletes surfs of the wrong type.
312 : bool Recycle(layers::SharedSurfaceTextureClient* texClient);
313 : };
314 :
315 : class ScopedReadbackFB
316 : {
317 : GLContext* const mGL;
318 : ScopedBindFramebuffer mAutoFB;
319 : GLuint mTempFB;
320 : GLuint mTempTex;
321 : SharedSurface* mSurfToUnlock;
322 : SharedSurface* mSurfToLock;
323 :
324 : public:
325 : explicit ScopedReadbackFB(SharedSurface* src);
326 : ~ScopedReadbackFB();
327 : };
328 :
329 : bool ReadbackSharedSurface(SharedSurface* src, gfx::DrawTarget* dst);
330 : uint32_t ReadPixel(SharedSurface* src);
331 :
332 : } // namespace gl
333 : } // namespace mozilla
334 :
335 : #endif // SHARED_SURFACE_H_
|