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 : /* GLScreenBuffer is the abstraction for the "default framebuffer" used
7 : * by an offscreen GLContext. Since it's only for offscreen GLContext's,
8 : * it's only useful for things like WebGL, and is NOT used by the
9 : * compositor's GLContext. Remember that GLContext provides an abstraction
10 : * so that even if you want to draw to the 'screen', even if that's not
11 : * actually the screen, just draw to 0. This GLScreenBuffer class takes the
12 : * logic handling out of GLContext.
13 : */
14 :
15 : #ifndef SCREEN_BUFFER_H_
16 : #define SCREEN_BUFFER_H_
17 :
18 : #include "GLContextTypes.h"
19 : #include "GLDefs.h"
20 : #include "mozilla/gfx/2D.h"
21 : #include "mozilla/gfx/Point.h"
22 : #include "mozilla/UniquePtr.h"
23 : #include "SharedSurface.h"
24 : #include "SurfaceTypes.h"
25 :
26 : namespace mozilla {
27 : namespace layers {
28 : class KnowsCompositor;
29 : class LayersIPCChannel;
30 : class SharedSurfaceTextureClient;
31 : } // namespace layers
32 :
33 : namespace gl {
34 :
35 : class GLContext;
36 : class SharedSurface;
37 : class ShSurfHandle;
38 : class SurfaceFactory;
39 :
40 : class DrawBuffer
41 : {
42 : public:
43 : // Fallible!
44 : // But it may return true with *out_buffer==nullptr if unneeded.
45 : static bool Create(GLContext* const gl,
46 : const SurfaceCaps& caps,
47 : const GLFormats& formats,
48 : const gfx::IntSize& size,
49 : UniquePtr<DrawBuffer>* out_buffer);
50 :
51 : protected:
52 : GLContext* const mGL;
53 : public:
54 : const gfx::IntSize mSize;
55 : const GLsizei mSamples;
56 : const GLuint mFB;
57 : protected:
58 : const GLuint mColorMSRB;
59 : const GLuint mDepthRB;
60 : const GLuint mStencilRB;
61 :
62 0 : DrawBuffer(GLContext* gl,
63 : const gfx::IntSize& size,
64 : GLsizei samples,
65 : GLuint fb,
66 : GLuint colorMSRB,
67 : GLuint depthRB,
68 : GLuint stencilRB)
69 0 : : mGL(gl)
70 : , mSize(size)
71 : , mSamples(samples)
72 : , mFB(fb)
73 : , mColorMSRB(colorMSRB)
74 : , mDepthRB(depthRB)
75 0 : , mStencilRB(stencilRB)
76 0 : {}
77 :
78 : public:
79 : virtual ~DrawBuffer();
80 : };
81 :
82 : class ReadBuffer
83 : {
84 : public:
85 : // Infallible, always non-null.
86 : static UniquePtr<ReadBuffer> Create(GLContext* gl,
87 : const SurfaceCaps& caps,
88 : const GLFormats& formats,
89 : SharedSurface* surf);
90 :
91 : protected:
92 : GLContext* const mGL;
93 : public:
94 : const GLuint mFB;
95 : protected:
96 : // mFB has the following attachments:
97 : const GLuint mDepthRB;
98 : const GLuint mStencilRB;
99 : // note no mColorRB here: this is provided by mSurf.
100 : SharedSurface* mSurf;
101 :
102 0 : ReadBuffer(GLContext* gl,
103 : GLuint fb,
104 : GLuint depthRB,
105 : GLuint stencilRB,
106 : SharedSurface* surf)
107 0 : : mGL(gl)
108 : , mFB(fb)
109 : , mDepthRB(depthRB)
110 : , mStencilRB(stencilRB)
111 0 : , mSurf(surf)
112 0 : {}
113 :
114 : public:
115 : virtual ~ReadBuffer();
116 :
117 : // Cannot attach a surf of a different AttachType or Size than before.
118 : void Attach(SharedSurface* surf);
119 :
120 : const gfx::IntSize& Size() const;
121 :
122 0 : SharedSurface* SharedSurf() const {
123 0 : return mSurf;
124 : }
125 :
126 : void SetReadBuffer(GLenum mode) const;
127 : };
128 :
129 :
130 : class GLScreenBuffer
131 : {
132 : public:
133 : // Infallible.
134 : static UniquePtr<GLScreenBuffer> Create(GLContext* gl,
135 : const gfx::IntSize& size,
136 : const SurfaceCaps& caps);
137 :
138 : static UniquePtr<SurfaceFactory>
139 : CreateFactory(GLContext* gl,
140 : const SurfaceCaps& caps,
141 : layers::KnowsCompositor* compositorConnection,
142 : const layers::TextureFlags& flags);
143 : static UniquePtr<SurfaceFactory>
144 : CreateFactory(GLContext* gl,
145 : const SurfaceCaps& caps,
146 : layers::LayersIPCChannel* ipcChannel,
147 : const mozilla::layers::LayersBackend backend,
148 : const layers::TextureFlags& flags);
149 :
150 : protected:
151 : GLContext* const mGL; // Owns us.
152 : public:
153 : const SurfaceCaps mCaps;
154 : protected:
155 : UniquePtr<SurfaceFactory> mFactory;
156 :
157 : RefPtr<layers::SharedSurfaceTextureClient> mBack;
158 : RefPtr<layers::SharedSurfaceTextureClient> mFront;
159 :
160 : UniquePtr<DrawBuffer> mDraw;
161 : UniquePtr<ReadBuffer> mRead;
162 :
163 : bool mNeedsBlit;
164 :
165 : GLenum mUserReadBufferMode;
166 : GLenum mUserDrawBufferMode;
167 :
168 : // Below are the parts that help us pretend to be framebuffer 0:
169 : GLuint mUserDrawFB;
170 : GLuint mUserReadFB;
171 : GLuint mInternalDrawFB;
172 : GLuint mInternalReadFB;
173 :
174 : #ifdef DEBUG
175 : bool mInInternalMode_DrawFB;
176 : bool mInInternalMode_ReadFB;
177 : #endif
178 :
179 : GLScreenBuffer(GLContext* gl,
180 : const SurfaceCaps& caps,
181 : UniquePtr<SurfaceFactory> factory);
182 :
183 : public:
184 : virtual ~GLScreenBuffer();
185 :
186 0 : SurfaceFactory* Factory() const {
187 0 : return mFactory.get();
188 : }
189 :
190 0 : const RefPtr<layers::SharedSurfaceTextureClient>& Front() const {
191 0 : return mFront;
192 : }
193 :
194 0 : SharedSurface* SharedSurf() const {
195 0 : MOZ_ASSERT(mRead);
196 0 : return mRead->SharedSurf();
197 : }
198 :
199 0 : bool ShouldPreserveBuffer() const {
200 0 : return mCaps.preserve;
201 : }
202 :
203 0 : GLuint DrawFB() const {
204 0 : if (!mDraw)
205 0 : return ReadFB();
206 :
207 0 : return mDraw->mFB;
208 : }
209 :
210 0 : GLuint ReadFB() const {
211 0 : return mRead->mFB;
212 : }
213 :
214 0 : GLsizei Samples() const {
215 0 : if (!mDraw)
216 0 : return 0;
217 :
218 0 : return mDraw->mSamples;
219 : }
220 :
221 : uint32_t DepthBits() const;
222 :
223 : void DeletingFB(GLuint fb);
224 :
225 0 : const gfx::IntSize& Size() const {
226 0 : MOZ_ASSERT(mRead);
227 0 : MOZ_ASSERT(!mDraw || mDraw->mSize == mRead->Size());
228 0 : return mRead->Size();
229 : }
230 :
231 : void BindAsFramebuffer(GLContext* const gl, GLenum target) const;
232 :
233 : void RequireBlit();
234 : void AssureBlitted();
235 : void AfterDrawCall();
236 : void BeforeReadCall();
237 :
238 : bool CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x,
239 : GLint y, GLsizei width, GLsizei height, GLint border);
240 :
241 : void SetReadBuffer(GLenum userMode);
242 : void SetDrawBuffer(GLenum userMode);
243 :
244 0 : GLenum GetReadBufferMode() const { return mUserReadBufferMode; }
245 0 : GLenum GetDrawBufferMode() const { return mUserDrawBufferMode; }
246 :
247 : /**
248 : * Attempts to read pixels from the current bound framebuffer, if
249 : * it is backed by a SharedSurface.
250 : *
251 : * Returns true if the pixel data has been read back, false
252 : * otherwise.
253 : */
254 : bool ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
255 : GLenum format, GLenum type, GLvoid* pixels);
256 :
257 : // Morph changes the factory used to create surfaces.
258 : void Morph(UniquePtr<SurfaceFactory> newFactory);
259 :
260 : protected:
261 : // Returns false on error or inability to resize.
262 : bool Swap(const gfx::IntSize& size);
263 :
264 : public:
265 : bool PublishFrame(const gfx::IntSize& size);
266 :
267 : bool Resize(const gfx::IntSize& size);
268 :
269 : protected:
270 : bool Attach(SharedSurface* surf, const gfx::IntSize& size);
271 :
272 : bool CreateDraw(const gfx::IntSize& size, UniquePtr<DrawBuffer>* out_buffer);
273 : UniquePtr<ReadBuffer> CreateRead(SharedSurface* surf);
274 :
275 : public:
276 : /* `fb` in these functions is the framebuffer the GLContext is hoping to
277 : * bind. When this is 0, we intercept the call and bind our own
278 : * framebuffers. As a client of these functions, just bind 0 when you want
279 : * to draw to the default framebuffer/'screen'.
280 : */
281 : void BindFB(GLuint fb);
282 : void BindDrawFB(GLuint fb);
283 : void BindReadFB(GLuint fb);
284 : GLuint GetFB() const;
285 : GLuint GetDrawFB() const;
286 : GLuint GetReadFB() const;
287 :
288 : // Here `fb` is the actual framebuffer you want bound. Binding 0 will
289 : // bind the (generally useless) default framebuffer.
290 : void BindFB_Internal(GLuint fb);
291 : void BindDrawFB_Internal(GLuint fb);
292 : void BindReadFB_Internal(GLuint fb);
293 :
294 : bool IsDrawFramebufferDefault() const;
295 : bool IsReadFramebufferDefault() const;
296 : };
297 :
298 : } // namespace gl
299 : } // namespace mozilla
300 :
301 : #endif // SCREEN_BUFFER_H_
|