|
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_COMPOSITOROGL_H |
|
7 #define MOZILLA_GFX_COMPOSITOROGL_H |
|
8 |
|
9 #include "gfx2DGlue.h" |
|
10 #include "GLContextTypes.h" // for GLContext, etc |
|
11 #include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D, etc |
|
12 #include "OGLShaderProgram.h" // for ShaderProgramOGL, etc |
|
13 #include "Units.h" // for ScreenPoint |
|
14 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc |
|
15 #include "mozilla/Attributes.h" // for MOZ_OVERRIDE, MOZ_FINAL |
|
16 #include "mozilla/RefPtr.h" // for TemporaryRef, RefPtr |
|
17 #include "mozilla/gfx/2D.h" // for DrawTarget |
|
18 #include "mozilla/gfx/BaseSize.h" // for BaseSize |
|
19 #include "mozilla/gfx/Point.h" // for IntSize, Point |
|
20 #include "mozilla/gfx/Rect.h" // for Rect, IntRect |
|
21 #include "mozilla/gfx/Types.h" // for Float, SurfaceFormat, etc |
|
22 #include "mozilla/layers/Compositor.h" // for SurfaceInitMode, Compositor, etc |
|
23 #include "mozilla/layers/CompositorTypes.h" // for MaskType::NumMaskTypes, etc |
|
24 #include "mozilla/layers/LayersTypes.h" |
|
25 #include "nsAutoPtr.h" // for nsRefPtr, nsAutoPtr |
|
26 #include "nsCOMPtr.h" // for already_AddRefed |
|
27 #include "nsDebug.h" // for NS_ASSERTION, NS_WARNING |
|
28 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc |
|
29 #include "nsSize.h" // for nsIntSize |
|
30 #include "nsTArray.h" // for nsAutoTArray, nsTArray, etc |
|
31 #include "nsThreadUtils.h" // for nsRunnable |
|
32 #include "nsXULAppAPI.h" // for XRE_GetProcessType |
|
33 #include "nscore.h" // for NS_IMETHOD |
|
34 #include "VBOArena.h" // for gl::VBOArena |
|
35 #ifdef MOZ_WIDGET_GONK |
|
36 #include <ui/GraphicBuffer.h> |
|
37 #endif |
|
38 |
|
39 class gfx3DMatrix; |
|
40 class nsIWidget; |
|
41 |
|
42 namespace mozilla { |
|
43 class TimeStamp; |
|
44 |
|
45 namespace gfx { |
|
46 class Matrix4x4; |
|
47 } |
|
48 |
|
49 namespace layers { |
|
50 |
|
51 class CompositingRenderTarget; |
|
52 class CompositingRenderTargetOGL; |
|
53 class DataTextureSource; |
|
54 class GLManagerCompositor; |
|
55 class TextureSource; |
|
56 struct Effect; |
|
57 struct EffectChain; |
|
58 |
|
59 /** |
|
60 * Interface for pools of temporary gl textures for the compositor. |
|
61 * The textures are fully owned by the pool, so the latter is responsible |
|
62 * calling fDeleteTextures accordingly. |
|
63 * Users of GetTexture receive a texture that is only valid for the duration |
|
64 * of the current frame. |
|
65 * This is primarily intended for direct texturing APIs that need to attach |
|
66 * shared objects (such as an EGLImage) to a gl texture. |
|
67 */ |
|
68 class CompositorTexturePoolOGL |
|
69 { |
|
70 protected: |
|
71 virtual ~CompositorTexturePoolOGL() {} |
|
72 |
|
73 public: |
|
74 NS_INLINE_DECL_REFCOUNTING(CompositorTexturePoolOGL) |
|
75 |
|
76 virtual void Clear() = 0; |
|
77 |
|
78 virtual GLuint GetTexture(GLenum aTarget, GLenum aEnum) = 0; |
|
79 |
|
80 virtual void EndFrame() = 0; |
|
81 }; |
|
82 |
|
83 /** |
|
84 * Agressively reuses textures. One gl texture per texture unit in total. |
|
85 * So far this hasn't shown the best results on b2g. |
|
86 */ |
|
87 class PerUnitTexturePoolOGL : public CompositorTexturePoolOGL |
|
88 { |
|
89 public: |
|
90 PerUnitTexturePoolOGL(gl::GLContext* aGL) |
|
91 : mTextureTarget(0) // zero is never a valid texture target |
|
92 , mGL(aGL) |
|
93 {} |
|
94 |
|
95 virtual ~PerUnitTexturePoolOGL() |
|
96 { |
|
97 DestroyTextures(); |
|
98 } |
|
99 |
|
100 virtual void Clear() MOZ_OVERRIDE |
|
101 { |
|
102 DestroyTextures(); |
|
103 } |
|
104 |
|
105 virtual GLuint GetTexture(GLenum aTarget, GLenum aUnit) MOZ_OVERRIDE; |
|
106 |
|
107 virtual void EndFrame() MOZ_OVERRIDE {} |
|
108 |
|
109 protected: |
|
110 void DestroyTextures(); |
|
111 |
|
112 GLenum mTextureTarget; |
|
113 nsTArray<GLuint> mTextures; |
|
114 RefPtr<gl::GLContext> mGL; |
|
115 }; |
|
116 |
|
117 /** |
|
118 * Reuse gl textures from a pool of textures that haven't yet been |
|
119 * used during the current frame. |
|
120 * All the textures that are not used at the end of a frame are |
|
121 * deleted. |
|
122 * This strategy seems to work well with gralloc textures because destroying |
|
123 * unused textures which are bound to gralloc buffers let drivers know that it |
|
124 * can unlock the gralloc buffers. |
|
125 */ |
|
126 class PerFrameTexturePoolOGL : public CompositorTexturePoolOGL |
|
127 { |
|
128 public: |
|
129 PerFrameTexturePoolOGL(gl::GLContext* aGL) |
|
130 : mTextureTarget(0) // zero is never a valid texture target |
|
131 , mGL(aGL) |
|
132 {} |
|
133 |
|
134 virtual ~PerFrameTexturePoolOGL() |
|
135 { |
|
136 DestroyTextures(); |
|
137 } |
|
138 |
|
139 virtual void Clear() MOZ_OVERRIDE |
|
140 { |
|
141 DestroyTextures(); |
|
142 } |
|
143 |
|
144 virtual GLuint GetTexture(GLenum aTarget, GLenum aUnit) MOZ_OVERRIDE; |
|
145 |
|
146 virtual void EndFrame() MOZ_OVERRIDE; |
|
147 |
|
148 protected: |
|
149 void DestroyTextures(); |
|
150 |
|
151 GLenum mTextureTarget; |
|
152 RefPtr<gl::GLContext> mGL; |
|
153 nsTArray<GLuint> mCreatedTextures; |
|
154 nsTArray<GLuint> mUnusedTextures; |
|
155 }; |
|
156 |
|
157 class CompositorOGL : public Compositor |
|
158 { |
|
159 typedef mozilla::gl::GLContext GLContext; |
|
160 |
|
161 friend class GLManagerCompositor; |
|
162 |
|
163 std::map<ShaderConfigOGL, ShaderProgramOGL*> mPrograms; |
|
164 public: |
|
165 CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth = -1, int aSurfaceHeight = -1, |
|
166 bool aUseExternalSurfaceSize = false); |
|
167 |
|
168 virtual ~CompositorOGL(); |
|
169 |
|
170 virtual TemporaryRef<DataTextureSource> |
|
171 CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE; |
|
172 |
|
173 virtual bool Initialize() MOZ_OVERRIDE; |
|
174 |
|
175 virtual void Destroy() MOZ_OVERRIDE; |
|
176 |
|
177 virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() MOZ_OVERRIDE |
|
178 { |
|
179 return TextureFactoryIdentifier(LayersBackend::LAYERS_OPENGL, |
|
180 XRE_GetProcessType(), |
|
181 GetMaxTextureSize(), |
|
182 mFBOTextureTarget == LOCAL_GL_TEXTURE_2D, |
|
183 SupportsPartialTextureUpdate()); |
|
184 } |
|
185 |
|
186 virtual TemporaryRef<CompositingRenderTarget> |
|
187 CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) MOZ_OVERRIDE; |
|
188 |
|
189 virtual TemporaryRef<CompositingRenderTarget> |
|
190 CreateRenderTargetFromSource(const gfx::IntRect &aRect, |
|
191 const CompositingRenderTarget *aSource, |
|
192 const gfx::IntPoint &aSourcePoint) MOZ_OVERRIDE; |
|
193 |
|
194 virtual void SetRenderTarget(CompositingRenderTarget *aSurface) MOZ_OVERRIDE; |
|
195 virtual CompositingRenderTarget* GetCurrentRenderTarget() const MOZ_OVERRIDE; |
|
196 |
|
197 virtual void DrawQuad(const gfx::Rect& aRect, |
|
198 const gfx::Rect& aClipRect, |
|
199 const EffectChain &aEffectChain, |
|
200 gfx::Float aOpacity, |
|
201 const gfx::Matrix4x4 &aTransform) MOZ_OVERRIDE |
|
202 { |
|
203 DrawQuadInternal(aRect, aClipRect, aEffectChain, |
|
204 aOpacity, aTransform, LOCAL_GL_TRIANGLE_STRIP); |
|
205 } |
|
206 |
|
207 virtual void DrawLines(const std::vector<gfx::Point>& aLines, |
|
208 const gfx::Rect& aClipRect, |
|
209 const gfx::Color& aColor, |
|
210 gfx::Float aOpacity, |
|
211 const gfx::Matrix4x4 &aTransform) MOZ_OVERRIDE; |
|
212 |
|
213 |
|
214 virtual void EndFrame() MOZ_OVERRIDE; |
|
215 virtual void SetFBAcquireFence(Layer* aLayer) MOZ_OVERRIDE; |
|
216 virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) MOZ_OVERRIDE; |
|
217 virtual void AbortFrame() MOZ_OVERRIDE; |
|
218 |
|
219 virtual bool SupportsPartialTextureUpdate() MOZ_OVERRIDE; |
|
220 |
|
221 virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) MOZ_OVERRIDE |
|
222 { |
|
223 if (!mGLContext) |
|
224 return false; |
|
225 int32_t maxSize = GetMaxTextureSize(); |
|
226 return aSize <= gfx::IntSize(maxSize, maxSize); |
|
227 } |
|
228 |
|
229 virtual int32_t GetMaxTextureSize() const MOZ_OVERRIDE; |
|
230 |
|
231 /** |
|
232 * Set the size of the EGL surface we're rendering to, if we're rendering to |
|
233 * an EGL surface. |
|
234 */ |
|
235 virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) MOZ_OVERRIDE; |
|
236 |
|
237 virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) MOZ_OVERRIDE { |
|
238 mRenderOffset = aOffset; |
|
239 } |
|
240 |
|
241 virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) MOZ_OVERRIDE; |
|
242 |
|
243 virtual void SetTargetContext(gfx::DrawTarget* aTarget) MOZ_OVERRIDE |
|
244 { |
|
245 mTarget = aTarget; |
|
246 } |
|
247 |
|
248 virtual void PrepareViewport(const gfx::IntSize& aSize, |
|
249 const gfx::Matrix& aWorldTransform) MOZ_OVERRIDE; |
|
250 |
|
251 |
|
252 #ifdef MOZ_DUMP_PAINTING |
|
253 virtual const char* Name() const MOZ_OVERRIDE { return "OGL"; } |
|
254 #endif // MOZ_DUMP_PAINTING |
|
255 |
|
256 virtual LayersBackend GetBackendType() const MOZ_OVERRIDE { |
|
257 return LayersBackend::LAYERS_OPENGL; |
|
258 } |
|
259 |
|
260 virtual void Pause() MOZ_OVERRIDE; |
|
261 virtual bool Resume() MOZ_OVERRIDE; |
|
262 |
|
263 virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; } |
|
264 |
|
265 GLContext* gl() const { return mGLContext; } |
|
266 gfx::SurfaceFormat GetFBOFormat() const { |
|
267 return gfx::SurfaceFormat::R8G8B8A8; |
|
268 } |
|
269 |
|
270 /** |
|
271 * The compositor provides with temporary textures for use with direct |
|
272 * textruing like gralloc texture. |
|
273 * Doing so lets us use gralloc the way it has been designed to be used |
|
274 * (see https://wiki.mozilla.org/Platform/GFX/Gralloc) |
|
275 */ |
|
276 GLuint GetTemporaryTexture(GLenum aTarget, GLenum aUnit); |
|
277 |
|
278 const gfx::Matrix4x4& GetProjMatrix() const { |
|
279 return mProjMatrix; |
|
280 } |
|
281 private: |
|
282 virtual void DrawQuadInternal(const gfx::Rect& aRect, |
|
283 const gfx::Rect& aClipRect, |
|
284 const EffectChain &aEffectChain, |
|
285 gfx::Float aOpacity, |
|
286 const gfx::Matrix4x4 &aTransformi, |
|
287 GLuint aDrawMode); |
|
288 |
|
289 virtual gfx::IntSize GetWidgetSize() const MOZ_OVERRIDE |
|
290 { |
|
291 return gfx::ToIntSize(mWidgetSize); |
|
292 } |
|
293 |
|
294 /** |
|
295 * Context target, nullptr when drawing directly to our swap chain. |
|
296 */ |
|
297 RefPtr<gfx::DrawTarget> mTarget; |
|
298 |
|
299 /** Widget associated with this compositor */ |
|
300 nsIWidget *mWidget; |
|
301 nsIntSize mWidgetSize; |
|
302 nsRefPtr<GLContext> mGLContext; |
|
303 gfx::Matrix4x4 mProjMatrix; |
|
304 |
|
305 /** The size of the surface we are rendering to */ |
|
306 nsIntSize mSurfaceSize; |
|
307 |
|
308 ScreenPoint mRenderOffset; |
|
309 |
|
310 already_AddRefed<mozilla::gl::GLContext> CreateContext(); |
|
311 |
|
312 /** Texture target to use for FBOs */ |
|
313 GLenum mFBOTextureTarget; |
|
314 |
|
315 /** Currently bound render target */ |
|
316 RefPtr<CompositingRenderTargetOGL> mCurrentRenderTarget; |
|
317 #ifdef DEBUG |
|
318 CompositingRenderTargetOGL* mWindowRenderTarget; |
|
319 #endif |
|
320 |
|
321 /** |
|
322 * VBO that has some basics in it for a textured quad, including vertex |
|
323 * coords and texcoords. |
|
324 */ |
|
325 GLuint mQuadVBO; |
|
326 |
|
327 /** |
|
328 * When we can't use mQuadVBO, we allocate VBOs from this arena instead. |
|
329 */ |
|
330 gl::VBOArena mVBOs; |
|
331 |
|
332 bool mHasBGRA; |
|
333 |
|
334 /** |
|
335 * When rendering to some EGL surfaces (e.g. on Android), we rely on being told |
|
336 * about size changes (via SetSurfaceSize) rather than pulling this information |
|
337 * from the widget. |
|
338 */ |
|
339 bool mUseExternalSurfaceSize; |
|
340 |
|
341 /** |
|
342 * Have we had DrawQuad calls since the last frame was rendered? |
|
343 */ |
|
344 bool mFrameInProgress; |
|
345 |
|
346 /* |
|
347 * Clear aRect on current render target. |
|
348 */ |
|
349 virtual void ClearRect(const gfx::Rect& aRect) MOZ_OVERRIDE; |
|
350 |
|
351 /* Start a new frame. If aClipRectIn is null and aClipRectOut is non-null, |
|
352 * sets *aClipRectOut to the screen dimensions. |
|
353 */ |
|
354 virtual void BeginFrame(const nsIntRegion& aInvalidRegion, |
|
355 const gfx::Rect *aClipRectIn, |
|
356 const gfx::Matrix& aTransform, |
|
357 const gfx::Rect& aRenderBounds, |
|
358 gfx::Rect *aClipRectOut = nullptr, |
|
359 gfx::Rect *aRenderBoundsOut = nullptr) MOZ_OVERRIDE; |
|
360 |
|
361 ShaderConfigOGL GetShaderConfigFor(Effect *aEffect, MaskType aMask = MaskNone) const; |
|
362 ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL &aConfig); |
|
363 |
|
364 /** |
|
365 * Create a FBO backed by a texture. |
|
366 * Note that the texture target type will be |
|
367 * of the type returned by FBOTextureTarget; different |
|
368 * shaders are required to sample from the different |
|
369 * texture types. |
|
370 */ |
|
371 void CreateFBOWithTexture(const gfx::IntRect& aRect, bool aCopyFromSource, |
|
372 GLuint aSourceFrameBuffer, |
|
373 GLuint *aFBO, GLuint *aTexture); |
|
374 |
|
375 GLintptr QuadVBOVertexOffset() { return 0; } |
|
376 GLintptr QuadVBOTexCoordOffset() { return sizeof(float)*4*2; } |
|
377 |
|
378 void BindQuadVBO(); |
|
379 void QuadVBOVerticesAttrib(GLuint aAttribIndex); |
|
380 void QuadVBOTexCoordsAttrib(GLuint aAttribIndex); |
|
381 void BindAndDrawQuad(GLuint aVertAttribIndex, |
|
382 GLuint aTexCoordAttribIndex, |
|
383 GLuint aDrawMode = LOCAL_GL_TRIANGLE_STRIP); |
|
384 void BindAndDrawQuad(ShaderProgramOGL *aProg, |
|
385 GLuint aDrawMode = LOCAL_GL_TRIANGLE_STRIP); |
|
386 void BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg, |
|
387 const gfx3DMatrix& aTextureTransform, |
|
388 const gfx::Rect& aTexCoordRect, |
|
389 TextureSource *aTexture); |
|
390 |
|
391 void CleanupResources(); |
|
392 |
|
393 /** |
|
394 * Copies the content of our backbuffer to the set transaction target. |
|
395 * Does not restore the target FBO, so only call from EndFrame. |
|
396 */ |
|
397 void CopyToTarget(gfx::DrawTarget* aTarget, const gfx::Matrix& aWorldMatrix); |
|
398 |
|
399 /** |
|
400 * Implements the flipping of the y-axis to convert from layers/compositor |
|
401 * coordinates to OpenGL coordinates. |
|
402 * |
|
403 * Indeed, the only coordinate system that OpenGL knows has the y-axis |
|
404 * pointing upwards, but the layers/compositor coordinate system has the |
|
405 * y-axis pointing downwards, for good reason as Web pages are typically |
|
406 * scrolled downwards. So, some flipping has to take place; FlippedY does it. |
|
407 */ |
|
408 GLint FlipY(GLint y) const { return mHeight - y; } |
|
409 |
|
410 RefPtr<CompositorTexturePoolOGL> mTexturePool; |
|
411 |
|
412 bool mDestroyed; |
|
413 |
|
414 /** |
|
415 * Height of the OpenGL context's primary framebuffer in pixels. Used by |
|
416 * FlipY for the y-flipping calculation. |
|
417 */ |
|
418 GLint mHeight; |
|
419 }; |
|
420 |
|
421 } |
|
422 } |
|
423 |
|
424 #endif /* MOZILLA_GFX_COMPOSITOROGL_H */ |