summaryrefslogtreecommitdiffstats
path: root/gfx/layers/opengl/CompositorOGL.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/opengl/CompositorOGL.h')
-rw-r--r--gfx/layers/opengl/CompositorOGL.h446
1 files changed, 446 insertions, 0 deletions
diff --git a/gfx/layers/opengl/CompositorOGL.h b/gfx/layers/opengl/CompositorOGL.h
new file mode 100644
index 0000000000..878372aa64
--- /dev/null
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -0,0 +1,446 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_GFX_COMPOSITOROGL_H
+#define MOZILLA_GFX_COMPOSITOROGL_H
+
+#include <map>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "gfx2DGlue.h"
+#include "GLContextTypes.h" // for GLContext, etc
+#include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D, etc
+#include "OGLShaderConfig.h" // for ShaderConfigOGL
+#include "Units.h" // for ScreenPoint
+#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
+#include "mozilla/Attributes.h" // for override, final
+#include "mozilla/RefPtr.h" // for already_AddRefed, RefPtr
+#include "mozilla/gfx/2D.h" // for DrawTarget
+#include "mozilla/gfx/BaseSize.h" // for BaseSize
+#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
+#include "mozilla/gfx/Point.h" // for IntSize, Point
+#include "mozilla/gfx/Rect.h" // for Rect, IntRect
+#include "mozilla/gfx/Triangle.h" // for Triangle
+#include "mozilla/gfx/Types.h" // for Float, SurfaceFormat, etc
+#include "mozilla/ipc/FileDescriptor.h"
+#include "mozilla/layers/Compositor.h" // for SurfaceInitMode, Compositor, etc
+#include "mozilla/layers/CompositorTypes.h" // for MaskType::MaskType::NumMaskTypes, etc
+#include "mozilla/layers/LayersTypes.h"
+#include "nsCOMPtr.h" // for already_AddRefed
+#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING
+#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
+#include "nsTArray.h" // for AutoTArray, nsTArray, etc
+#include "nsThreadUtils.h" // for nsRunnable
+#include "nsXULAppAPI.h" // for XRE_GetProcessType
+#include "nscore.h" // for NS_IMETHOD
+
+class nsIWidget;
+
+namespace mozilla {
+
+namespace layers {
+
+class CompositingRenderTarget;
+class CompositingRenderTargetOGL;
+class DataTextureSource;
+class ShaderProgramOGL;
+class ShaderProgramOGLsHolder;
+class TextureSource;
+class TextureSourceOGL;
+class BufferTextureHost;
+struct Effect;
+struct EffectChain;
+
+/**
+ * Interface for pools of temporary gl textures for the compositor.
+ * The textures are fully owned by the pool, so the latter is responsible
+ * calling fDeleteTextures accordingly.
+ * Users of GetTexture receive a texture that is only valid for the duration
+ * of the current frame.
+ * This is primarily intended for direct texturing APIs that need to attach
+ * shared objects (such as an EGLImage) to a gl texture.
+ */
+class CompositorTexturePoolOGL {
+ protected:
+ virtual ~CompositorTexturePoolOGL() = default;
+
+ public:
+ NS_INLINE_DECL_REFCOUNTING(CompositorTexturePoolOGL)
+
+ virtual void Clear() = 0;
+
+ virtual GLuint GetTexture(GLenum aTarget, GLenum aEnum) = 0;
+
+ virtual void EndFrame() = 0;
+};
+
+/**
+ * Agressively reuses textures. One gl texture per texture unit in total.
+ * So far this hasn't shown the best results on b2g.
+ */
+class PerUnitTexturePoolOGL : public CompositorTexturePoolOGL {
+ public:
+ explicit PerUnitTexturePoolOGL(gl::GLContext* aGL);
+ virtual ~PerUnitTexturePoolOGL();
+
+ void Clear() override { DestroyTextures(); }
+
+ GLuint GetTexture(GLenum aTarget, GLenum aUnit) override;
+
+ void EndFrame() override {}
+
+ protected:
+ void DestroyTextures();
+
+ GLenum mTextureTarget;
+ nsTArray<GLuint> mTextures;
+ RefPtr<gl::GLContext> mGL;
+};
+
+// If you want to make this class not final, first remove calls to virtual
+// methods (Destroy) that are made in the destructor.
+class CompositorOGL final : public Compositor {
+ typedef mozilla::gl::GLContext GLContext;
+
+ friend class CompositingRenderTargetOGL;
+
+ RefPtr<ShaderProgramOGLsHolder> mProgramsHolder;
+
+ public:
+ explicit CompositorOGL(widget::CompositorWidget* aWidget,
+ int aSurfaceWidth = -1, int aSurfaceHeight = -1,
+ bool aUseExternalSurfaceSize = false);
+
+ protected:
+ virtual ~CompositorOGL();
+
+ public:
+ CompositorOGL* AsCompositorOGL() override { return this; }
+
+ already_AddRefed<DataTextureSource> CreateDataTextureSource(
+ TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
+
+ bool Initialize(GLContext* aGLContext,
+ RefPtr<ShaderProgramOGLsHolder> aProgramsHolder,
+ nsCString* const out_failureReason);
+
+ bool Initialize(nsCString* const out_failureReason) override;
+
+ void Destroy() override;
+
+ // Returns a render target for the native layer.
+ // aInvalidRegion is in window coordinates, i.e. in the same space as
+ // aNativeLayer->GetPosition().
+ already_AddRefed<CompositingRenderTargetOGL> RenderTargetForNativeLayer(
+ NativeLayer* aNativeLayer, const gfx::IntRegion& aInvalidRegion);
+
+ already_AddRefed<CompositingRenderTarget> CreateRenderTarget(
+ const gfx::IntRect& aRect, SurfaceInitMode aInit) override;
+
+ void SetRenderTarget(CompositingRenderTarget* aSurface) override;
+ already_AddRefed<CompositingRenderTarget> GetCurrentRenderTarget()
+ const override;
+ already_AddRefed<CompositingRenderTarget> GetWindowRenderTarget()
+ const override;
+
+ bool ReadbackRenderTarget(CompositingRenderTarget* aSource,
+ AsyncReadbackBuffer* aDest) override;
+
+ already_AddRefed<AsyncReadbackBuffer> CreateAsyncReadbackBuffer(
+ const gfx::IntSize& aSize) override;
+
+ bool BlitRenderTarget(CompositingRenderTarget* aSource,
+ const gfx::IntSize& aSourceSize,
+ const gfx::IntSize& aDestSize) override;
+
+ void DrawQuad(const gfx::Rect& aRect, const gfx::IntRect& aClipRect,
+ const EffectChain& aEffectChain, gfx::Float aOpacity,
+ const gfx::Matrix4x4& aTransform,
+ const gfx::Rect& aVisibleRect) override;
+
+ void EndFrame() override;
+
+ int32_t GetMaxTextureSize() const override;
+
+ /**
+ * Set the size of the EGL surface we're rendering to, if we're rendering to
+ * an EGL surface.
+ */
+ void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override;
+
+ typedef uint32_t MakeCurrentFlags;
+ static const MakeCurrentFlags ForceMakeCurrent = 0x1;
+ void MakeCurrent(MakeCurrentFlags aFlags = 0);
+
+#ifdef MOZ_DUMP_PAINTING
+ const char* Name() const override { return "OGL"; }
+#endif // MOZ_DUMP_PAINTING
+
+ void Pause() override;
+ bool Resume() override;
+
+ GLContext* gl() const { return mGLContext; }
+ GLContext* GetGLContext() const override { return mGLContext; }
+
+ /**
+ * Clear the program state. This must be called
+ * before operating on the GLContext directly. */
+ void ResetProgram();
+
+ gfx::SurfaceFormat GetFBOFormat() const {
+ return gfx::SurfaceFormat::R8G8B8A8;
+ }
+
+ /**
+ * The compositor provides with temporary textures for use with direct
+ * textruing.
+ */
+ GLuint GetTemporaryTexture(GLenum aTarget, GLenum aUnit);
+
+ const gfx::IntSize GetDestinationSurfaceSize() const {
+ return gfx::IntSize(mSurfaceSize.width, mSurfaceSize.height);
+ }
+
+ /**
+ * Allow the origin of the surface to be offset so that content does not
+ * start at (0, 0) on the surface.
+ */
+ void SetSurfaceOrigin(const ScreenIntPoint& aOrigin) {
+ mSurfaceOrigin = aOrigin;
+ }
+
+ // Register TextureSource which own device data that have to be deleted before
+ // destroying this CompositorOGL.
+ void RegisterTextureSource(TextureSource* aTextureSource);
+ void UnregisterTextureSource(TextureSource* aTextureSource);
+
+ ipc::FileDescriptor GetReleaseFence();
+
+ private:
+ template <typename Geometry>
+ void DrawGeometry(const Geometry& aGeometry, const gfx::Rect& aRect,
+ const gfx::IntRect& aClipRect,
+ const EffectChain& aEffectChain, gfx::Float aOpacity,
+ const gfx::Matrix4x4& aTransform,
+ const gfx::Rect& aVisibleRect);
+
+ void PrepareViewport(CompositingRenderTargetOGL* aRenderTarget);
+
+ void InsertFrameDoneSync();
+
+ bool NeedToRecreateFullWindowRenderTarget() const;
+
+ /** Widget associated with this compositor */
+ LayoutDeviceIntSize mWidgetSize;
+ RefPtr<GLContext> mGLContext;
+ bool mOwnsGLContext = true;
+ RefPtr<SurfacePoolHandle> mSurfacePoolHandle;
+ gfx::Matrix4x4 mProjMatrix;
+ bool mCanRenderToDefaultFramebuffer = true;
+
+ /** The size of the surface we are rendering to */
+ gfx::IntSize mSurfaceSize;
+
+ /** The origin of the content on the surface */
+ ScreenIntPoint mSurfaceOrigin;
+
+ already_AddRefed<mozilla::gl::GLContext> CreateContext();
+
+ /** Texture target to use for FBOs */
+ GLenum mFBOTextureTarget;
+
+ /** Currently bound render target */
+ RefPtr<CompositingRenderTargetOGL> mCurrentRenderTarget;
+
+ // The 1x1 dummy render target that's the "current" render target between
+ // BeginFrameForNativeLayers and EndFrame but outside pairs of
+ // Begin/EndRenderingToNativeLayer. Created on demand.
+ RefPtr<CompositingRenderTarget> mNativeLayersReferenceRT;
+
+ // The render target that profiler screenshots / frame recording read from.
+ // This will be the actual window framebuffer when rendering to a window, and
+ // it will be mFullWindowRenderTarget when rendering to native layers.
+ RefPtr<CompositingRenderTargetOGL> mWindowRenderTarget;
+
+ // Non-null when using native layers and frame recording is requested.
+ // EndNormalDrawing() maintains a copy of the entire window contents in this
+ // render target, by copying from the native layer render targets.
+ RefPtr<CompositingRenderTargetOGL> mFullWindowRenderTarget;
+
+ /**
+ * VBO that has some basics in it for a textured quad, including vertex
+ * coords and texcoords.
+ */
+ GLuint mQuadVBO;
+
+ /**
+ * VBO that stores dynamic triangle geometry.
+ */
+ GLuint mTriangleVBO;
+
+ // Used to apply back-pressure in WaitForPreviousFrameDoneSync().
+ GLsync mPreviousFrameDoneSync;
+ GLsync mThisFrameDoneSync;
+
+ bool mHasBGRA;
+
+ /**
+ * When rendering to some EGL surfaces (e.g. on Android), we rely on being
+ * told about size changes (via SetSurfaceSize) rather than pulling this
+ * information from the widget.
+ */
+ bool mUseExternalSurfaceSize;
+
+ /**
+ * Have we had DrawQuad calls since the last frame was rendered?
+ */
+ bool mFrameInProgress;
+
+ // Only true between BeginFromeForNativeLayers and EndFrame, and only if the
+ // full window render target needed to be recreated in the current frame.
+ bool mShouldInvalidateWindow = false;
+
+ /* Start a new frame.
+ */
+ Maybe<gfx::IntRect> BeginFrameForWindow(
+ const nsIntRegion& aInvalidRegion, const Maybe<gfx::IntRect>& aClipRect,
+ const gfx::IntRect& aRenderBounds,
+ const nsIntRegion& aOpaqueRegion) override;
+
+ Maybe<gfx::IntRect> BeginFrame(const nsIntRegion& aInvalidRegion,
+ const Maybe<gfx::IntRect>& aClipRect,
+ const gfx::IntRect& aRenderBounds,
+ const nsIntRegion& aOpaqueRegion);
+
+ ShaderConfigOGL GetShaderConfigFor(Effect* aEffect,
+ bool aDEAAEnabled = false) const;
+
+ ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL& aConfig);
+
+ void ApplyPrimitiveConfig(ShaderConfigOGL& aConfig, const gfx::Rect&) {
+ aConfig.SetDynamicGeometry(false);
+ }
+
+ void ApplyPrimitiveConfig(ShaderConfigOGL& aConfig,
+ const nsTArray<gfx::TexturedTriangle>&) {
+ aConfig.SetDynamicGeometry(true);
+ }
+
+ /**
+ * Create a FBO backed by a texture.
+ * Note that the texture target type will be
+ * of the type returned by FBOTextureTarget; different
+ * shaders are required to sample from the different
+ * texture types.
+ */
+ void CreateFBOWithTexture(const gfx::IntRect& aRect, bool aCopyFromSource,
+ GLuint aSourceFrameBuffer, GLuint* aFBO,
+ GLuint* aTexture,
+ gfx::IntSize* aAllocSize = nullptr);
+
+ GLuint CreateTexture(const gfx::IntRect& aRect, bool aCopyFromSource,
+ GLuint aSourceFrameBuffer,
+ gfx::IntSize* aAllocSize = nullptr);
+
+ gfx::Point3D GetLineCoefficients(const gfx::Point& aPoint1,
+ const gfx::Point& aPoint2);
+
+ void CleanupResources();
+
+ void BindAndDrawQuads(ShaderProgramOGL* aProg, int aQuads,
+ const gfx::Rect* aLayerRect,
+ const gfx::Rect* aTextureRect);
+
+ void BindAndDrawQuad(ShaderProgramOGL* aProg, const gfx::Rect& aLayerRect,
+ const gfx::Rect& aTextureRect = gfx::Rect(0.0f, 0.0f,
+ 1.0f, 1.0f)) {
+ gfx::Rect layerRects[4];
+ gfx::Rect textureRects[4];
+ layerRects[0] = aLayerRect;
+ textureRects[0] = aTextureRect;
+ BindAndDrawQuads(aProg, 1, layerRects, textureRects);
+ }
+
+ void BindAndDrawGeometry(ShaderProgramOGL* aProgram, const gfx::Rect& aRect);
+
+ void BindAndDrawGeometry(ShaderProgramOGL* aProgram,
+ const nsTArray<gfx::TexturedTriangle>& aTriangles);
+
+ void BindAndDrawGeometryWithTextureRect(ShaderProgramOGL* aProg,
+ const gfx::Rect& aRect,
+ const gfx::Rect& aTexCoordRect,
+ TextureSource* aTexture);
+
+ void BindAndDrawGeometryWithTextureRect(
+ ShaderProgramOGL* aProg,
+ const nsTArray<gfx::TexturedTriangle>& aTriangles,
+ const gfx::Rect& aTexCoordRect, TextureSource* aTexture);
+
+ void InitializeVAO(const GLuint aAttribIndex, const GLint aComponents,
+ const GLsizei aStride, const size_t aOffset);
+
+ gfx::Rect GetTextureCoordinates(gfx::Rect textureRect,
+ TextureSource* aTexture);
+
+ /**
+ * Copies the content of the current render target to the set transaction
+ * target.
+ */
+ void CopyToTarget(gfx::DrawTarget* aTarget, const nsIntPoint& aTopLeft,
+ const gfx::Matrix& aWorldMatrix);
+
+ /**
+ * Implements the flipping of the y-axis to convert from layers/compositor
+ * coordinates to OpenGL coordinates.
+ *
+ * Indeed, the only coordinate system that OpenGL knows has the y-axis
+ * pointing upwards, but the layers/compositor coordinate system has the
+ * y-axis pointing downwards, for good reason as Web pages are typically
+ * scrolled downwards. So, some flipping has to take place; FlippedY does it.
+ */
+ GLint FlipY(GLint y) const { return mViewportSize.height - y; }
+
+ // The DrawTarget from BeginFrameForTarget, which EndFrame needs to copy the
+ // window contents into.
+ // Only non-null between BeginFrameForTarget and EndFrame.
+ RefPtr<gfx::DrawTarget> mTarget;
+ gfx::IntRect mTargetBounds;
+
+ RefPtr<CompositorTexturePoolOGL> mTexturePool;
+
+ // The native layer that we're currently rendering to, if any.
+ // Non-null only between BeginFrame and EndFrame if BeginFrame has been called
+ // with a non-null aNativeLayer.
+ RefPtr<NativeLayer> mCurrentNativeLayer;
+
+#ifdef MOZ_WIDGET_GTK
+ // Hold TextureSources which own device data that have to be deleted before
+ // destroying this CompositorOGL.
+ std::unordered_set<TextureSource*> mRegisteredTextureSources;
+#endif
+
+ // FileDescriptor of release fence.
+ // Release fence is a fence that is used for waiting until usage/composite of
+ // AHardwareBuffer is ended. The fence is delivered to client side via
+ // ImageBridge. It is used only on android.
+ ipc::FileDescriptor mReleaseFenceFd;
+
+ bool mDestroyed;
+
+ /**
+ * Size of the OpenGL context's primary framebuffer in pixels. Used by
+ * FlipY for the y-flipping calculation and by the DEAA shader.
+ */
+ gfx::IntSize mViewportSize;
+
+ gfx::IntRegion mCurrentFrameInvalidRegion;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif /* MOZILLA_GFX_COMPOSITOROGL_H */