/src/mozilla-central/gfx/layers/opengl/CompositorOGL.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef MOZILLA_GFX_COMPOSITOROGL_H |
8 | | #define MOZILLA_GFX_COMPOSITOROGL_H |
9 | | |
10 | | #include "gfx2DGlue.h" |
11 | | #include "GLContextTypes.h" // for GLContext, etc |
12 | | #include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D, etc |
13 | | #include "OGLShaderProgram.h" // for ShaderProgramOGL, etc |
14 | | #include "Units.h" // for ScreenPoint |
15 | | #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc |
16 | | #include "mozilla/Attributes.h" // for override, final |
17 | | #include "mozilla/RefPtr.h" // for already_AddRefed, RefPtr |
18 | | #include "mozilla/gfx/2D.h" // for DrawTarget |
19 | | #include "mozilla/gfx/BaseSize.h" // for BaseSize |
20 | | #include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4 |
21 | | #include "mozilla/gfx/Point.h" // for IntSize, Point |
22 | | #include "mozilla/gfx/Rect.h" // for Rect, IntRect |
23 | | #include "mozilla/gfx/Triangle.h" // for Triangle |
24 | | #include "mozilla/gfx/Types.h" // for Float, SurfaceFormat, etc |
25 | | #include "mozilla/layers/Compositor.h" // for SurfaceInitMode, Compositor, etc |
26 | | #include "mozilla/layers/CompositorTypes.h" // for MaskType::MaskType::NumMaskTypes, etc |
27 | | #include "mozilla/layers/LayersTypes.h" |
28 | | #include "nsCOMPtr.h" // for already_AddRefed |
29 | | #include "nsDebug.h" // for NS_ASSERTION, NS_WARNING |
30 | | #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc |
31 | | #include "nsTArray.h" // for AutoTArray, nsTArray, etc |
32 | | #include "nsThreadUtils.h" // for nsRunnable |
33 | | #include "nsXULAppAPI.h" // for XRE_GetProcessType |
34 | | #include "nscore.h" // for NS_IMETHOD |
35 | | |
36 | | class nsIWidget; |
37 | | |
38 | | namespace mozilla { |
39 | | |
40 | | namespace layers { |
41 | | |
42 | | class CompositingRenderTarget; |
43 | | class CompositingRenderTargetOGL; |
44 | | class DataTextureSource; |
45 | | class GLManagerCompositor; |
46 | | class TextureSource; |
47 | | class TextureSourceOGL; |
48 | | class BufferTextureHost; |
49 | | struct Effect; |
50 | | struct EffectChain; |
51 | | class GLBlitTextureImageHelper; |
52 | | |
53 | | /** |
54 | | * Interface for pools of temporary gl textures for the compositor. |
55 | | * The textures are fully owned by the pool, so the latter is responsible |
56 | | * calling fDeleteTextures accordingly. |
57 | | * Users of GetTexture receive a texture that is only valid for the duration |
58 | | * of the current frame. |
59 | | * This is primarily intended for direct texturing APIs that need to attach |
60 | | * shared objects (such as an EGLImage) to a gl texture. |
61 | | */ |
62 | | class CompositorTexturePoolOGL |
63 | | { |
64 | | protected: |
65 | 0 | virtual ~CompositorTexturePoolOGL() {} |
66 | | |
67 | | public: |
68 | | NS_INLINE_DECL_REFCOUNTING(CompositorTexturePoolOGL) |
69 | | |
70 | | virtual void Clear() = 0; |
71 | | |
72 | | virtual GLuint GetTexture(GLenum aTarget, GLenum aEnum) = 0; |
73 | | |
74 | | virtual void EndFrame() = 0; |
75 | | }; |
76 | | |
77 | | /** |
78 | | * Agressively reuses textures. One gl texture per texture unit in total. |
79 | | * So far this hasn't shown the best results on b2g. |
80 | | */ |
81 | | class PerUnitTexturePoolOGL : public CompositorTexturePoolOGL |
82 | | { |
83 | | public: |
84 | | explicit PerUnitTexturePoolOGL(gl::GLContext* aGL) |
85 | | : mTextureTarget(0) // zero is never a valid texture target |
86 | | , mGL(aGL) |
87 | 0 | {} |
88 | | |
89 | | virtual ~PerUnitTexturePoolOGL() |
90 | 0 | { |
91 | 0 | DestroyTextures(); |
92 | 0 | } |
93 | | |
94 | | virtual void Clear() override |
95 | 0 | { |
96 | 0 | DestroyTextures(); |
97 | 0 | } |
98 | | |
99 | | virtual GLuint GetTexture(GLenum aTarget, GLenum aUnit) override; |
100 | | |
101 | 0 | virtual void EndFrame() override {} |
102 | | |
103 | | protected: |
104 | | void DestroyTextures(); |
105 | | |
106 | | GLenum mTextureTarget; |
107 | | nsTArray<GLuint> mTextures; |
108 | | RefPtr<gl::GLContext> mGL; |
109 | | }; |
110 | | |
111 | | // If you want to make this class not final, first remove calls to virtual |
112 | | // methods (Destroy) that are made in the destructor. |
113 | | class CompositorOGL final : public Compositor |
114 | | { |
115 | | typedef mozilla::gl::GLContext GLContext; |
116 | | |
117 | | friend class GLManagerCompositor; |
118 | | friend class CompositingRenderTargetOGL; |
119 | | |
120 | | std::map<ShaderConfigOGL, ShaderProgramOGL*> mPrograms; |
121 | | public: |
122 | | explicit CompositorOGL(CompositorBridgeParent* aParent, |
123 | | widget::CompositorWidget* aWidget, |
124 | | int aSurfaceWidth = -1, int aSurfaceHeight = -1, |
125 | | bool aUseExternalSurfaceSize = false); |
126 | | |
127 | | protected: |
128 | | virtual ~CompositorOGL(); |
129 | | |
130 | | public: |
131 | 0 | virtual CompositorOGL* AsCompositorOGL() override { return this; } |
132 | | |
133 | | virtual already_AddRefed<DataTextureSource> |
134 | | CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override; |
135 | | |
136 | | virtual already_AddRefed<DataTextureSource> |
137 | | CreateDataTextureSourceAroundYCbCr(TextureHost* aTexture) override; |
138 | | |
139 | | virtual already_AddRefed<DataTextureSource> |
140 | | CreateDataTextureSourceAround(gfx::DataSourceSurface* aSurface) override; |
141 | | |
142 | | virtual bool Initialize(nsCString* const out_failureReason) override; |
143 | | |
144 | | virtual void Destroy() override; |
145 | | |
146 | | virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override |
147 | 0 | { |
148 | 0 | TextureFactoryIdentifier result = |
149 | 0 | TextureFactoryIdentifier(LayersBackend::LAYERS_OPENGL, |
150 | 0 | XRE_GetProcessType(), |
151 | 0 | GetMaxTextureSize(), |
152 | 0 | SupportsTextureDirectMapping(), |
153 | 0 | false, |
154 | 0 | mFBOTextureTarget == LOCAL_GL_TEXTURE_2D, |
155 | 0 | SupportsPartialTextureUpdate()); |
156 | 0 | return result; |
157 | 0 | } |
158 | | |
159 | | virtual already_AddRefed<CompositingRenderTarget> |
160 | | CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) override; |
161 | | |
162 | | virtual already_AddRefed<CompositingRenderTarget> |
163 | | CreateRenderTargetFromSource(const gfx::IntRect &aRect, |
164 | | const CompositingRenderTarget *aSource, |
165 | | const gfx::IntPoint &aSourcePoint) override; |
166 | | |
167 | | virtual void SetRenderTarget(CompositingRenderTarget *aSurface) override; |
168 | | virtual CompositingRenderTarget* GetCurrentRenderTarget() const override; |
169 | | virtual CompositingRenderTarget* GetWindowRenderTarget() const override; |
170 | | |
171 | | virtual bool |
172 | | ReadbackRenderTarget(CompositingRenderTarget* aSource, |
173 | | AsyncReadbackBuffer* aDest) override; |
174 | | |
175 | | virtual already_AddRefed<AsyncReadbackBuffer> |
176 | | CreateAsyncReadbackBuffer(const gfx::IntSize& aSize) override; |
177 | | |
178 | | virtual bool |
179 | | BlitRenderTarget(CompositingRenderTarget* aSource, |
180 | | const gfx::IntSize& aSourceSize, |
181 | | const gfx::IntSize& aDestSize) override; |
182 | | |
183 | | virtual void DrawQuad(const gfx::Rect& aRect, |
184 | | const gfx::IntRect& aClipRect, |
185 | | const EffectChain &aEffectChain, |
186 | | gfx::Float aOpacity, |
187 | | const gfx::Matrix4x4& aTransform, |
188 | | const gfx::Rect& aVisibleRect) override; |
189 | | |
190 | | virtual void DrawTriangles(const nsTArray<gfx::TexturedTriangle>& aTriangles, |
191 | | const gfx::Rect& aRect, |
192 | | const gfx::IntRect& aClipRect, |
193 | | const EffectChain& aEffectChain, |
194 | | gfx::Float aOpacity, |
195 | | const gfx::Matrix4x4& aTransform, |
196 | | const gfx::Rect& aVisibleRect) override; |
197 | | |
198 | | virtual bool SupportsLayerGeometry() const override; |
199 | | |
200 | | virtual void EndFrame() override; |
201 | | |
202 | | virtual bool SupportsPartialTextureUpdate() override; |
203 | | |
204 | | virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) override |
205 | 0 | { |
206 | 0 | if (!mGLContext) |
207 | 0 | return false; |
208 | 0 | int32_t maxSize = GetMaxTextureSize(); |
209 | 0 | return aSize <= gfx::IntSize(maxSize, maxSize); |
210 | 0 | } |
211 | | |
212 | | virtual int32_t GetMaxTextureSize() const override; |
213 | | |
214 | | /** |
215 | | * Set the size of the EGL surface we're rendering to, if we're rendering to |
216 | | * an EGL surface. |
217 | | */ |
218 | | virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override; |
219 | | |
220 | 0 | virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) override { |
221 | 0 | mRenderOffset = aOffset; |
222 | 0 | } |
223 | | |
224 | | virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) override; |
225 | | |
226 | | #ifdef MOZ_DUMP_PAINTING |
227 | | virtual const char* Name() const override { return "OGL"; } |
228 | | #endif // MOZ_DUMP_PAINTING |
229 | | |
230 | 0 | virtual LayersBackend GetBackendType() const override { |
231 | 0 | return LayersBackend::LAYERS_OPENGL; |
232 | 0 | } |
233 | | |
234 | | virtual void Pause() override; |
235 | | virtual bool Resume() override; |
236 | | |
237 | | GLContext* gl() const { return mGLContext; } |
238 | 0 | GLContext* GetGLContext() const override { return mGLContext; } |
239 | | |
240 | | #ifdef XP_DARWIN |
241 | | virtual void MaybeUnlockBeforeNextComposition(TextureHost* aTextureHost) override; |
242 | | virtual void TryUnlockTextures() override; |
243 | | #endif |
244 | | |
245 | | /** |
246 | | * Clear the program state. This must be called |
247 | | * before operating on the GLContext directly. */ |
248 | | void ResetProgram(); |
249 | | |
250 | | gfx::SurfaceFormat GetFBOFormat() const { |
251 | | return gfx::SurfaceFormat::R8G8B8A8; |
252 | | } |
253 | | |
254 | | GLBlitTextureImageHelper* BlitTextureImageHelper(); |
255 | | |
256 | | /** |
257 | | * The compositor provides with temporary textures for use with direct |
258 | | * textruing. |
259 | | */ |
260 | | GLuint GetTemporaryTexture(GLenum aTarget, GLenum aUnit); |
261 | | |
262 | | const gfx::Matrix4x4& GetProjMatrix() const { |
263 | | return mProjMatrix; |
264 | | } |
265 | | |
266 | | void SetProjMatrix(const gfx::Matrix4x4& aProjMatrix) { |
267 | | mProjMatrix = aProjMatrix; |
268 | | } |
269 | | |
270 | | const gfx::IntSize GetDestinationSurfaceSize() const { |
271 | | return gfx::IntSize (mSurfaceSize.width, mSurfaceSize.height); |
272 | | } |
273 | | |
274 | | const ScreenPoint& GetScreenRenderOffset() const { |
275 | | return mRenderOffset; |
276 | | } |
277 | | |
278 | | private: |
279 | | template<typename Geometry> |
280 | | void DrawGeometry(const Geometry& aGeometry, |
281 | | const gfx::Rect& aRect, |
282 | | const gfx::IntRect& aClipRect, |
283 | | const EffectChain& aEffectChain, |
284 | | gfx::Float aOpacity, |
285 | | const gfx::Matrix4x4& aTransform, |
286 | | const gfx::Rect& aVisibleRect); |
287 | | |
288 | | void PrepareViewport(CompositingRenderTargetOGL *aRenderTarget); |
289 | | |
290 | | bool SupportsTextureDirectMapping(); |
291 | | |
292 | | /** Widget associated with this compositor */ |
293 | | LayoutDeviceIntSize mWidgetSize; |
294 | | RefPtr<GLContext> mGLContext; |
295 | | UniquePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper; |
296 | | gfx::Matrix4x4 mProjMatrix; |
297 | | |
298 | | #ifdef XP_DARWIN |
299 | | nsTArray<RefPtr<BufferTextureHost>> mMaybeUnlockBeforeNextComposition; |
300 | | #endif |
301 | | |
302 | | /** The size of the surface we are rendering to */ |
303 | | gfx::IntSize mSurfaceSize; |
304 | | |
305 | | ScreenPoint mRenderOffset; |
306 | | |
307 | | already_AddRefed<mozilla::gl::GLContext> CreateContext(); |
308 | | |
309 | | /** Texture target to use for FBOs */ |
310 | | GLenum mFBOTextureTarget; |
311 | | |
312 | | /** Currently bound render target */ |
313 | | RefPtr<CompositingRenderTargetOGL> mCurrentRenderTarget; |
314 | | |
315 | | CompositingRenderTargetOGL* mWindowRenderTarget; |
316 | | |
317 | | /** |
318 | | * VBO that has some basics in it for a textured quad, including vertex |
319 | | * coords and texcoords. |
320 | | */ |
321 | | GLuint mQuadVBO; |
322 | | |
323 | | |
324 | | /** |
325 | | * VBO that stores dynamic triangle geometry. |
326 | | */ |
327 | | GLuint mTriangleVBO; |
328 | | |
329 | | bool mHasBGRA; |
330 | | |
331 | | /** |
332 | | * When rendering to some EGL surfaces (e.g. on Android), we rely on being told |
333 | | * about size changes (via SetSurfaceSize) rather than pulling this information |
334 | | * from the widget. |
335 | | */ |
336 | | bool mUseExternalSurfaceSize; |
337 | | |
338 | | /** |
339 | | * Have we had DrawQuad calls since the last frame was rendered? |
340 | | */ |
341 | | bool mFrameInProgress; |
342 | | |
343 | | /* |
344 | | * Clear aRect on current render target. |
345 | | */ |
346 | | virtual void ClearRect(const gfx::Rect& aRect) override; |
347 | | |
348 | | /* Start a new frame. If aClipRectIn is null and aClipRectOut is non-null, |
349 | | * sets *aClipRectOut to the screen dimensions. |
350 | | */ |
351 | | virtual void BeginFrame(const nsIntRegion& aInvalidRegion, |
352 | | const gfx::IntRect *aClipRectIn, |
353 | | const gfx::IntRect& aRenderBounds, |
354 | | const nsIntRegion& aOpaqueRegion, |
355 | | gfx::IntRect *aClipRectOut = nullptr, |
356 | | gfx::IntRect *aRenderBoundsOut = nullptr) override; |
357 | | |
358 | | ShaderConfigOGL GetShaderConfigFor(Effect *aEffect, |
359 | | TextureSourceOGL *aSourceMask = nullptr, |
360 | | gfx::CompositionOp aOp = gfx::CompositionOp::OP_OVER, |
361 | | bool aColorMatrix = false, |
362 | | bool aDEAAEnabled = false) const; |
363 | | |
364 | | ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL &aConfig); |
365 | | |
366 | | void ApplyPrimitiveConfig(ShaderConfigOGL& aConfig, |
367 | | const gfx::Rect&) |
368 | 0 | { |
369 | 0 | aConfig.SetDynamicGeometry(false); |
370 | 0 | } |
371 | | |
372 | | void ApplyPrimitiveConfig(ShaderConfigOGL& aConfig, |
373 | | const nsTArray<gfx::TexturedTriangle>&) |
374 | 0 | { |
375 | 0 | aConfig.SetDynamicGeometry(true); |
376 | 0 | } |
377 | | |
378 | | /** |
379 | | * Create a FBO backed by a texture. |
380 | | * Note that the texture target type will be |
381 | | * of the type returned by FBOTextureTarget; different |
382 | | * shaders are required to sample from the different |
383 | | * texture types. |
384 | | */ |
385 | | void CreateFBOWithTexture(const gfx::IntRect& aRect, bool aCopyFromSource, |
386 | | GLuint aSourceFrameBuffer, |
387 | | GLuint *aFBO, GLuint *aTexture, |
388 | | gfx::IntSize* aAllocSize = nullptr); |
389 | | |
390 | | GLuint CreateTexture(const gfx::IntRect& aRect, bool aCopyFromSource, |
391 | | GLuint aSourceFrameBuffer, |
392 | | gfx::IntSize* aAllocSize = nullptr); |
393 | | |
394 | | gfx::Point3D GetLineCoefficients(const gfx::Point& aPoint1, |
395 | | const gfx::Point& aPoint2); |
396 | | |
397 | | void ActivateProgram(ShaderProgramOGL *aProg); |
398 | | |
399 | | void CleanupResources(); |
400 | | |
401 | | void BindAndDrawQuads(ShaderProgramOGL *aProg, |
402 | | int aQuads, |
403 | | const gfx::Rect* aLayerRect, |
404 | | const gfx::Rect* aTextureRect); |
405 | | |
406 | | void BindAndDrawQuad(ShaderProgramOGL *aProg, |
407 | | const gfx::Rect& aLayerRect, |
408 | | const gfx::Rect& aTextureRect = |
409 | | gfx::Rect(0.0f, 0.0f, 1.0f, 1.0f)) |
410 | 0 | { |
411 | 0 | gfx::Rect layerRects[4]; |
412 | 0 | gfx::Rect textureRects[4]; |
413 | 0 | layerRects[0] = aLayerRect; |
414 | 0 | textureRects[0] = aTextureRect; |
415 | 0 | BindAndDrawQuads(aProg, 1, layerRects, textureRects); |
416 | 0 | } |
417 | | |
418 | | void BindAndDrawGeometry(ShaderProgramOGL* aProgram, |
419 | | const gfx::Rect& aRect); |
420 | | |
421 | | void BindAndDrawGeometry(ShaderProgramOGL* aProgram, |
422 | | const nsTArray<gfx::TexturedTriangle>& aTriangles); |
423 | | |
424 | | void BindAndDrawGeometryWithTextureRect(ShaderProgramOGL *aProg, |
425 | | const gfx::Rect& aRect, |
426 | | const gfx::Rect& aTexCoordRect, |
427 | | TextureSource *aTexture); |
428 | | |
429 | | void BindAndDrawGeometryWithTextureRect(ShaderProgramOGL *aProg, |
430 | | const nsTArray<gfx::TexturedTriangle>& aTriangles, |
431 | | const gfx::Rect& aTexCoordRect, |
432 | | TextureSource *aTexture); |
433 | | |
434 | | void InitializeVAO(const GLuint aAttribIndex, const GLint aComponents, |
435 | | const GLsizei aStride, const size_t aOffset); |
436 | | |
437 | | gfx::Rect GetTextureCoordinates(gfx::Rect textureRect, |
438 | | TextureSource* aTexture); |
439 | | |
440 | | /** |
441 | | * Bind the texture behind the current render target as the backdrop for a |
442 | | * mix-blend shader. |
443 | | */ |
444 | | void BindBackdrop(ShaderProgramOGL* aProgram, GLuint aBackdrop, GLenum aTexUnit); |
445 | | |
446 | | /** |
447 | | * Copies the content of our backbuffer to the set transaction target. |
448 | | * Does not restore the target FBO, so only call from EndFrame. |
449 | | */ |
450 | | void CopyToTarget(gfx::DrawTarget* aTarget, const nsIntPoint& aTopLeft, const gfx::Matrix& aWorldMatrix); |
451 | | |
452 | | /** |
453 | | * Implements the flipping of the y-axis to convert from layers/compositor |
454 | | * coordinates to OpenGL coordinates. |
455 | | * |
456 | | * Indeed, the only coordinate system that OpenGL knows has the y-axis |
457 | | * pointing upwards, but the layers/compositor coordinate system has the |
458 | | * y-axis pointing downwards, for good reason as Web pages are typically |
459 | | * scrolled downwards. So, some flipping has to take place; FlippedY does it. |
460 | | */ |
461 | 0 | GLint FlipY(GLint y) const { return mViewportSize.height - y; } |
462 | | |
463 | | RefPtr<CompositorTexturePoolOGL> mTexturePool; |
464 | | |
465 | | bool mDestroyed; |
466 | | |
467 | | /** |
468 | | * Size of the OpenGL context's primary framebuffer in pixels. Used by |
469 | | * FlipY for the y-flipping calculation and by the DEAA shader. |
470 | | */ |
471 | | gfx::IntSize mViewportSize; |
472 | | |
473 | | ShaderProgramOGL *mCurrentProgram; |
474 | | }; |
475 | | |
476 | | } // namespace layers |
477 | | } // namespace mozilla |
478 | | |
479 | | #endif /* MOZILLA_GFX_COMPOSITOROGL_H */ |