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