1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/opengl/CompositorOGL.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,424 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef MOZILLA_GFX_COMPOSITOROGL_H 1.10 +#define MOZILLA_GFX_COMPOSITOROGL_H 1.11 + 1.12 +#include "gfx2DGlue.h" 1.13 +#include "GLContextTypes.h" // for GLContext, etc 1.14 +#include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D, etc 1.15 +#include "OGLShaderProgram.h" // for ShaderProgramOGL, etc 1.16 +#include "Units.h" // for ScreenPoint 1.17 +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 1.18 +#include "mozilla/Attributes.h" // for MOZ_OVERRIDE, MOZ_FINAL 1.19 +#include "mozilla/RefPtr.h" // for TemporaryRef, RefPtr 1.20 +#include "mozilla/gfx/2D.h" // for DrawTarget 1.21 +#include "mozilla/gfx/BaseSize.h" // for BaseSize 1.22 +#include "mozilla/gfx/Point.h" // for IntSize, Point 1.23 +#include "mozilla/gfx/Rect.h" // for Rect, IntRect 1.24 +#include "mozilla/gfx/Types.h" // for Float, SurfaceFormat, etc 1.25 +#include "mozilla/layers/Compositor.h" // for SurfaceInitMode, Compositor, etc 1.26 +#include "mozilla/layers/CompositorTypes.h" // for MaskType::NumMaskTypes, etc 1.27 +#include "mozilla/layers/LayersTypes.h" 1.28 +#include "nsAutoPtr.h" // for nsRefPtr, nsAutoPtr 1.29 +#include "nsCOMPtr.h" // for already_AddRefed 1.30 +#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING 1.31 +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc 1.32 +#include "nsSize.h" // for nsIntSize 1.33 +#include "nsTArray.h" // for nsAutoTArray, nsTArray, etc 1.34 +#include "nsThreadUtils.h" // for nsRunnable 1.35 +#include "nsXULAppAPI.h" // for XRE_GetProcessType 1.36 +#include "nscore.h" // for NS_IMETHOD 1.37 +#include "VBOArena.h" // for gl::VBOArena 1.38 +#ifdef MOZ_WIDGET_GONK 1.39 +#include <ui/GraphicBuffer.h> 1.40 +#endif 1.41 + 1.42 +class gfx3DMatrix; 1.43 +class nsIWidget; 1.44 + 1.45 +namespace mozilla { 1.46 +class TimeStamp; 1.47 + 1.48 +namespace gfx { 1.49 +class Matrix4x4; 1.50 +} 1.51 + 1.52 +namespace layers { 1.53 + 1.54 +class CompositingRenderTarget; 1.55 +class CompositingRenderTargetOGL; 1.56 +class DataTextureSource; 1.57 +class GLManagerCompositor; 1.58 +class TextureSource; 1.59 +struct Effect; 1.60 +struct EffectChain; 1.61 + 1.62 +/** 1.63 + * Interface for pools of temporary gl textures for the compositor. 1.64 + * The textures are fully owned by the pool, so the latter is responsible 1.65 + * calling fDeleteTextures accordingly. 1.66 + * Users of GetTexture receive a texture that is only valid for the duration 1.67 + * of the current frame. 1.68 + * This is primarily intended for direct texturing APIs that need to attach 1.69 + * shared objects (such as an EGLImage) to a gl texture. 1.70 + */ 1.71 +class CompositorTexturePoolOGL 1.72 +{ 1.73 +protected: 1.74 + virtual ~CompositorTexturePoolOGL() {} 1.75 + 1.76 +public: 1.77 + NS_INLINE_DECL_REFCOUNTING(CompositorTexturePoolOGL) 1.78 + 1.79 + virtual void Clear() = 0; 1.80 + 1.81 + virtual GLuint GetTexture(GLenum aTarget, GLenum aEnum) = 0; 1.82 + 1.83 + virtual void EndFrame() = 0; 1.84 +}; 1.85 + 1.86 +/** 1.87 + * Agressively reuses textures. One gl texture per texture unit in total. 1.88 + * So far this hasn't shown the best results on b2g. 1.89 + */ 1.90 +class PerUnitTexturePoolOGL : public CompositorTexturePoolOGL 1.91 +{ 1.92 +public: 1.93 + PerUnitTexturePoolOGL(gl::GLContext* aGL) 1.94 + : mTextureTarget(0) // zero is never a valid texture target 1.95 + , mGL(aGL) 1.96 + {} 1.97 + 1.98 + virtual ~PerUnitTexturePoolOGL() 1.99 + { 1.100 + DestroyTextures(); 1.101 + } 1.102 + 1.103 + virtual void Clear() MOZ_OVERRIDE 1.104 + { 1.105 + DestroyTextures(); 1.106 + } 1.107 + 1.108 + virtual GLuint GetTexture(GLenum aTarget, GLenum aUnit) MOZ_OVERRIDE; 1.109 + 1.110 + virtual void EndFrame() MOZ_OVERRIDE {} 1.111 + 1.112 +protected: 1.113 + void DestroyTextures(); 1.114 + 1.115 + GLenum mTextureTarget; 1.116 + nsTArray<GLuint> mTextures; 1.117 + RefPtr<gl::GLContext> mGL; 1.118 +}; 1.119 + 1.120 +/** 1.121 + * Reuse gl textures from a pool of textures that haven't yet been 1.122 + * used during the current frame. 1.123 + * All the textures that are not used at the end of a frame are 1.124 + * deleted. 1.125 + * This strategy seems to work well with gralloc textures because destroying 1.126 + * unused textures which are bound to gralloc buffers let drivers know that it 1.127 + * can unlock the gralloc buffers. 1.128 + */ 1.129 +class PerFrameTexturePoolOGL : public CompositorTexturePoolOGL 1.130 +{ 1.131 +public: 1.132 + PerFrameTexturePoolOGL(gl::GLContext* aGL) 1.133 + : mTextureTarget(0) // zero is never a valid texture target 1.134 + , mGL(aGL) 1.135 + {} 1.136 + 1.137 + virtual ~PerFrameTexturePoolOGL() 1.138 + { 1.139 + DestroyTextures(); 1.140 + } 1.141 + 1.142 + virtual void Clear() MOZ_OVERRIDE 1.143 + { 1.144 + DestroyTextures(); 1.145 + } 1.146 + 1.147 + virtual GLuint GetTexture(GLenum aTarget, GLenum aUnit) MOZ_OVERRIDE; 1.148 + 1.149 + virtual void EndFrame() MOZ_OVERRIDE; 1.150 + 1.151 +protected: 1.152 + void DestroyTextures(); 1.153 + 1.154 + GLenum mTextureTarget; 1.155 + RefPtr<gl::GLContext> mGL; 1.156 + nsTArray<GLuint> mCreatedTextures; 1.157 + nsTArray<GLuint> mUnusedTextures; 1.158 +}; 1.159 + 1.160 +class CompositorOGL : public Compositor 1.161 +{ 1.162 + typedef mozilla::gl::GLContext GLContext; 1.163 + 1.164 + friend class GLManagerCompositor; 1.165 + 1.166 + std::map<ShaderConfigOGL, ShaderProgramOGL*> mPrograms; 1.167 +public: 1.168 + CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth = -1, int aSurfaceHeight = -1, 1.169 + bool aUseExternalSurfaceSize = false); 1.170 + 1.171 + virtual ~CompositorOGL(); 1.172 + 1.173 + virtual TemporaryRef<DataTextureSource> 1.174 + CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE; 1.175 + 1.176 + virtual bool Initialize() MOZ_OVERRIDE; 1.177 + 1.178 + virtual void Destroy() MOZ_OVERRIDE; 1.179 + 1.180 + virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() MOZ_OVERRIDE 1.181 + { 1.182 + return TextureFactoryIdentifier(LayersBackend::LAYERS_OPENGL, 1.183 + XRE_GetProcessType(), 1.184 + GetMaxTextureSize(), 1.185 + mFBOTextureTarget == LOCAL_GL_TEXTURE_2D, 1.186 + SupportsPartialTextureUpdate()); 1.187 + } 1.188 + 1.189 + virtual TemporaryRef<CompositingRenderTarget> 1.190 + CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) MOZ_OVERRIDE; 1.191 + 1.192 + virtual TemporaryRef<CompositingRenderTarget> 1.193 + CreateRenderTargetFromSource(const gfx::IntRect &aRect, 1.194 + const CompositingRenderTarget *aSource, 1.195 + const gfx::IntPoint &aSourcePoint) MOZ_OVERRIDE; 1.196 + 1.197 + virtual void SetRenderTarget(CompositingRenderTarget *aSurface) MOZ_OVERRIDE; 1.198 + virtual CompositingRenderTarget* GetCurrentRenderTarget() const MOZ_OVERRIDE; 1.199 + 1.200 + virtual void DrawQuad(const gfx::Rect& aRect, 1.201 + const gfx::Rect& aClipRect, 1.202 + const EffectChain &aEffectChain, 1.203 + gfx::Float aOpacity, 1.204 + const gfx::Matrix4x4 &aTransform) MOZ_OVERRIDE 1.205 + { 1.206 + DrawQuadInternal(aRect, aClipRect, aEffectChain, 1.207 + aOpacity, aTransform, LOCAL_GL_TRIANGLE_STRIP); 1.208 + } 1.209 + 1.210 + virtual void DrawLines(const std::vector<gfx::Point>& aLines, 1.211 + const gfx::Rect& aClipRect, 1.212 + const gfx::Color& aColor, 1.213 + gfx::Float aOpacity, 1.214 + const gfx::Matrix4x4 &aTransform) MOZ_OVERRIDE; 1.215 + 1.216 + 1.217 + virtual void EndFrame() MOZ_OVERRIDE; 1.218 + virtual void SetFBAcquireFence(Layer* aLayer) MOZ_OVERRIDE; 1.219 + virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) MOZ_OVERRIDE; 1.220 + virtual void AbortFrame() MOZ_OVERRIDE; 1.221 + 1.222 + virtual bool SupportsPartialTextureUpdate() MOZ_OVERRIDE; 1.223 + 1.224 + virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) MOZ_OVERRIDE 1.225 + { 1.226 + if (!mGLContext) 1.227 + return false; 1.228 + int32_t maxSize = GetMaxTextureSize(); 1.229 + return aSize <= gfx::IntSize(maxSize, maxSize); 1.230 + } 1.231 + 1.232 + virtual int32_t GetMaxTextureSize() const MOZ_OVERRIDE; 1.233 + 1.234 + /** 1.235 + * Set the size of the EGL surface we're rendering to, if we're rendering to 1.236 + * an EGL surface. 1.237 + */ 1.238 + virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) MOZ_OVERRIDE; 1.239 + 1.240 + virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) MOZ_OVERRIDE { 1.241 + mRenderOffset = aOffset; 1.242 + } 1.243 + 1.244 + virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) MOZ_OVERRIDE; 1.245 + 1.246 + virtual void SetTargetContext(gfx::DrawTarget* aTarget) MOZ_OVERRIDE 1.247 + { 1.248 + mTarget = aTarget; 1.249 + } 1.250 + 1.251 + virtual void PrepareViewport(const gfx::IntSize& aSize, 1.252 + const gfx::Matrix& aWorldTransform) MOZ_OVERRIDE; 1.253 + 1.254 + 1.255 +#ifdef MOZ_DUMP_PAINTING 1.256 + virtual const char* Name() const MOZ_OVERRIDE { return "OGL"; } 1.257 +#endif // MOZ_DUMP_PAINTING 1.258 + 1.259 + virtual LayersBackend GetBackendType() const MOZ_OVERRIDE { 1.260 + return LayersBackend::LAYERS_OPENGL; 1.261 + } 1.262 + 1.263 + virtual void Pause() MOZ_OVERRIDE; 1.264 + virtual bool Resume() MOZ_OVERRIDE; 1.265 + 1.266 + virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; } 1.267 + 1.268 + GLContext* gl() const { return mGLContext; } 1.269 + gfx::SurfaceFormat GetFBOFormat() const { 1.270 + return gfx::SurfaceFormat::R8G8B8A8; 1.271 + } 1.272 + 1.273 + /** 1.274 + * The compositor provides with temporary textures for use with direct 1.275 + * textruing like gralloc texture. 1.276 + * Doing so lets us use gralloc the way it has been designed to be used 1.277 + * (see https://wiki.mozilla.org/Platform/GFX/Gralloc) 1.278 + */ 1.279 + GLuint GetTemporaryTexture(GLenum aTarget, GLenum aUnit); 1.280 + 1.281 + const gfx::Matrix4x4& GetProjMatrix() const { 1.282 + return mProjMatrix; 1.283 + } 1.284 +private: 1.285 + virtual void DrawQuadInternal(const gfx::Rect& aRect, 1.286 + const gfx::Rect& aClipRect, 1.287 + const EffectChain &aEffectChain, 1.288 + gfx::Float aOpacity, 1.289 + const gfx::Matrix4x4 &aTransformi, 1.290 + GLuint aDrawMode); 1.291 + 1.292 + virtual gfx::IntSize GetWidgetSize() const MOZ_OVERRIDE 1.293 + { 1.294 + return gfx::ToIntSize(mWidgetSize); 1.295 + } 1.296 + 1.297 + /** 1.298 + * Context target, nullptr when drawing directly to our swap chain. 1.299 + */ 1.300 + RefPtr<gfx::DrawTarget> mTarget; 1.301 + 1.302 + /** Widget associated with this compositor */ 1.303 + nsIWidget *mWidget; 1.304 + nsIntSize mWidgetSize; 1.305 + nsRefPtr<GLContext> mGLContext; 1.306 + gfx::Matrix4x4 mProjMatrix; 1.307 + 1.308 + /** The size of the surface we are rendering to */ 1.309 + nsIntSize mSurfaceSize; 1.310 + 1.311 + ScreenPoint mRenderOffset; 1.312 + 1.313 + already_AddRefed<mozilla::gl::GLContext> CreateContext(); 1.314 + 1.315 + /** Texture target to use for FBOs */ 1.316 + GLenum mFBOTextureTarget; 1.317 + 1.318 + /** Currently bound render target */ 1.319 + RefPtr<CompositingRenderTargetOGL> mCurrentRenderTarget; 1.320 +#ifdef DEBUG 1.321 + CompositingRenderTargetOGL* mWindowRenderTarget; 1.322 +#endif 1.323 + 1.324 + /** 1.325 + * VBO that has some basics in it for a textured quad, including vertex 1.326 + * coords and texcoords. 1.327 + */ 1.328 + GLuint mQuadVBO; 1.329 + 1.330 + /** 1.331 + * When we can't use mQuadVBO, we allocate VBOs from this arena instead. 1.332 + */ 1.333 + gl::VBOArena mVBOs; 1.334 + 1.335 + bool mHasBGRA; 1.336 + 1.337 + /** 1.338 + * When rendering to some EGL surfaces (e.g. on Android), we rely on being told 1.339 + * about size changes (via SetSurfaceSize) rather than pulling this information 1.340 + * from the widget. 1.341 + */ 1.342 + bool mUseExternalSurfaceSize; 1.343 + 1.344 + /** 1.345 + * Have we had DrawQuad calls since the last frame was rendered? 1.346 + */ 1.347 + bool mFrameInProgress; 1.348 + 1.349 + /* 1.350 + * Clear aRect on current render target. 1.351 + */ 1.352 + virtual void ClearRect(const gfx::Rect& aRect) MOZ_OVERRIDE; 1.353 + 1.354 + /* Start a new frame. If aClipRectIn is null and aClipRectOut is non-null, 1.355 + * sets *aClipRectOut to the screen dimensions. 1.356 + */ 1.357 + virtual void BeginFrame(const nsIntRegion& aInvalidRegion, 1.358 + const gfx::Rect *aClipRectIn, 1.359 + const gfx::Matrix& aTransform, 1.360 + const gfx::Rect& aRenderBounds, 1.361 + gfx::Rect *aClipRectOut = nullptr, 1.362 + gfx::Rect *aRenderBoundsOut = nullptr) MOZ_OVERRIDE; 1.363 + 1.364 + ShaderConfigOGL GetShaderConfigFor(Effect *aEffect, MaskType aMask = MaskNone) const; 1.365 + ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL &aConfig); 1.366 + 1.367 + /** 1.368 + * Create a FBO backed by a texture. 1.369 + * Note that the texture target type will be 1.370 + * of the type returned by FBOTextureTarget; different 1.371 + * shaders are required to sample from the different 1.372 + * texture types. 1.373 + */ 1.374 + void CreateFBOWithTexture(const gfx::IntRect& aRect, bool aCopyFromSource, 1.375 + GLuint aSourceFrameBuffer, 1.376 + GLuint *aFBO, GLuint *aTexture); 1.377 + 1.378 + GLintptr QuadVBOVertexOffset() { return 0; } 1.379 + GLintptr QuadVBOTexCoordOffset() { return sizeof(float)*4*2; } 1.380 + 1.381 + void BindQuadVBO(); 1.382 + void QuadVBOVerticesAttrib(GLuint aAttribIndex); 1.383 + void QuadVBOTexCoordsAttrib(GLuint aAttribIndex); 1.384 + void BindAndDrawQuad(GLuint aVertAttribIndex, 1.385 + GLuint aTexCoordAttribIndex, 1.386 + GLuint aDrawMode = LOCAL_GL_TRIANGLE_STRIP); 1.387 + void BindAndDrawQuad(ShaderProgramOGL *aProg, 1.388 + GLuint aDrawMode = LOCAL_GL_TRIANGLE_STRIP); 1.389 + void BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg, 1.390 + const gfx3DMatrix& aTextureTransform, 1.391 + const gfx::Rect& aTexCoordRect, 1.392 + TextureSource *aTexture); 1.393 + 1.394 + void CleanupResources(); 1.395 + 1.396 + /** 1.397 + * Copies the content of our backbuffer to the set transaction target. 1.398 + * Does not restore the target FBO, so only call from EndFrame. 1.399 + */ 1.400 + void CopyToTarget(gfx::DrawTarget* aTarget, const gfx::Matrix& aWorldMatrix); 1.401 + 1.402 + /** 1.403 + * Implements the flipping of the y-axis to convert from layers/compositor 1.404 + * coordinates to OpenGL coordinates. 1.405 + * 1.406 + * Indeed, the only coordinate system that OpenGL knows has the y-axis 1.407 + * pointing upwards, but the layers/compositor coordinate system has the 1.408 + * y-axis pointing downwards, for good reason as Web pages are typically 1.409 + * scrolled downwards. So, some flipping has to take place; FlippedY does it. 1.410 + */ 1.411 + GLint FlipY(GLint y) const { return mHeight - y; } 1.412 + 1.413 + RefPtr<CompositorTexturePoolOGL> mTexturePool; 1.414 + 1.415 + bool mDestroyed; 1.416 + 1.417 + /** 1.418 + * Height of the OpenGL context's primary framebuffer in pixels. Used by 1.419 + * FlipY for the y-flipping calculation. 1.420 + */ 1.421 + GLint mHeight; 1.422 +}; 1.423 + 1.424 +} 1.425 +} 1.426 + 1.427 +#endif /* MOZILLA_GFX_COMPOSITOROGL_H */