CompositorOGL.h (15874B)
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 <unordered_set> 11 12 #include "gfx2DGlue.h" 13 #include "GLContextTypes.h" // for GLContext, etc 14 #include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D, etc 15 #include "OGLShaderConfig.h" // for ShaderConfigOGL 16 #include "Units.h" // for ScreenPoint 17 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 18 #include "mozilla/RefPtr.h" // for already_AddRefed, RefPtr 19 #include "mozilla/gfx/2D.h" // for DrawTarget 20 #include "mozilla/gfx/BaseSize.h" // for BaseSize 21 #include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4 22 #include "mozilla/gfx/Point.h" // for IntSize, Point 23 #include "mozilla/gfx/Rect.h" // for Rect, IntRect 24 #include "mozilla/gfx/Triangle.h" // for Triangle 25 #include "mozilla/gfx/Types.h" // for Float, SurfaceFormat, etc 26 #include "mozilla/ipc/FileDescriptor.h" 27 #include "mozilla/layers/Compositor.h" // for SurfaceInitMode, Compositor, etc 28 #include "mozilla/layers/CompositorTypes.h" // for MaskType::MaskType::NumMaskTypes, etc 29 #include "mozilla/layers/LayersTypes.h" 30 #include "nsCOMPtr.h" // for already_AddRefed 31 #include "nsDebug.h" // for NS_ASSERTION, NS_WARNING 32 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc 33 #include "nsTArray.h" // for AutoTArray, nsTArray, etc 34 #include "nsThreadUtils.h" // for nsRunnable 35 #include "nsXULAppAPI.h" // for XRE_GetProcessType 36 #include "nscore.h" // for NS_IMETHOD 37 38 class nsIWidget; 39 40 namespace mozilla { 41 42 namespace layers { 43 44 class CompositingRenderTarget; 45 class CompositingRenderTargetOGL; 46 class DataTextureSource; 47 class ShaderProgramOGL; 48 class ShaderProgramOGLsHolder; 49 class TextureSource; 50 class TextureSourceOGL; 51 class BufferTextureHost; 52 struct Effect; 53 struct EffectChain; 54 55 /** 56 * Interface for pools of temporary gl textures for the compositor. 57 * The textures are fully owned by the pool, so the latter is responsible 58 * calling fDeleteTextures accordingly. 59 * Users of GetTexture receive a texture that is only valid for the duration 60 * of the current frame. 61 * This is primarily intended for direct texturing APIs that need to attach 62 * shared objects (such as an EGLImage) to a gl texture. 63 */ 64 class CompositorTexturePoolOGL { 65 protected: 66 virtual ~CompositorTexturePoolOGL() = default; 67 68 public: 69 NS_INLINE_DECL_REFCOUNTING(CompositorTexturePoolOGL) 70 71 virtual void Clear() = 0; 72 73 virtual GLuint GetTexture(GLenum aTarget, GLenum aEnum) = 0; 74 75 virtual void EndFrame() = 0; 76 }; 77 78 /** 79 * Agressively reuses textures. One gl texture per texture unit in total. 80 * So far this hasn't shown the best results on b2g. 81 */ 82 class PerUnitTexturePoolOGL : public CompositorTexturePoolOGL { 83 public: 84 explicit PerUnitTexturePoolOGL(gl::GLContext* aGL); 85 virtual ~PerUnitTexturePoolOGL(); 86 87 void Clear() override { DestroyTextures(); } 88 89 GLuint GetTexture(GLenum aTarget, GLenum aUnit) override; 90 91 void EndFrame() override {} 92 93 protected: 94 void DestroyTextures(); 95 96 GLenum mTextureTarget; 97 nsTArray<GLuint> mTextures; 98 RefPtr<gl::GLContext> mGL; 99 }; 100 101 // If you want to make this class not final, first remove calls to virtual 102 // methods (Destroy) that are made in the destructor. 103 class CompositorOGL final : public Compositor { 104 typedef mozilla::gl::GLContext GLContext; 105 106 friend class CompositingRenderTargetOGL; 107 108 RefPtr<ShaderProgramOGLsHolder> mProgramsHolder; 109 110 public: 111 explicit CompositorOGL(widget::CompositorWidget* aWidget, 112 int aSurfaceWidth = -1, int aSurfaceHeight = -1, 113 bool aUseExternalSurfaceSize = false); 114 115 protected: 116 virtual ~CompositorOGL(); 117 118 public: 119 CompositorOGL* AsCompositorOGL() override { return this; } 120 121 already_AddRefed<DataTextureSource> CreateDataTextureSource( 122 TextureFlags aFlags = TextureFlags::NO_FLAGS) override; 123 124 bool Initialize(GLContext* aGLContext, 125 RefPtr<ShaderProgramOGLsHolder> aProgramsHolder, 126 nsCString* const out_failureReason); 127 128 bool Initialize(nsCString* const out_failureReason) override; 129 130 void Destroy() override; 131 132 // Returns a render target for the native layer. 133 // aInvalidRegion is in window coordinates, i.e. in the same space as 134 // aNativeLayer->GetPosition(). 135 already_AddRefed<CompositingRenderTargetOGL> RenderTargetForNativeLayer( 136 NativeLayer* aNativeLayer, const gfx::IntRegion& aInvalidRegion); 137 138 already_AddRefed<CompositingRenderTarget> CreateRenderTarget( 139 const gfx::IntRect& aRect, SurfaceInitMode aInit) override; 140 141 void SetRenderTarget(CompositingRenderTarget* aSurface) override; 142 already_AddRefed<CompositingRenderTarget> GetCurrentRenderTarget() 143 const override; 144 already_AddRefed<CompositingRenderTarget> GetWindowRenderTarget() 145 const override; 146 147 bool ReadbackRenderTarget(CompositingRenderTarget* aSource, 148 AsyncReadbackBuffer* aDest) override; 149 150 already_AddRefed<AsyncReadbackBuffer> CreateAsyncReadbackBuffer( 151 const gfx::IntSize& aSize) override; 152 153 bool BlitRenderTarget(CompositingRenderTarget* aSource, 154 const gfx::IntSize& aSourceSize, 155 const gfx::IntSize& aDestSize) override; 156 157 void DrawQuad(const gfx::Rect& aRect, const gfx::IntRect& aClipRect, 158 const EffectChain& aEffectChain, gfx::Float aOpacity, 159 const gfx::Matrix4x4& aTransform, 160 const gfx::Rect& aVisibleRect) override; 161 162 void EndFrame() override; 163 164 int32_t GetMaxTextureSize() const override; 165 166 /** 167 * Set the size of the EGL surface we're rendering to, if we're rendering to 168 * an EGL surface. 169 */ 170 void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override; 171 172 typedef uint32_t MakeCurrentFlags; 173 static const MakeCurrentFlags ForceMakeCurrent = 0x1; 174 void MakeCurrent(MakeCurrentFlags aFlags = 0); 175 176 #ifdef MOZ_DUMP_PAINTING 177 const char* Name() const override { return "OGL"; } 178 #endif // MOZ_DUMP_PAINTING 179 180 void Pause() override; 181 bool Resume() override; 182 183 GLContext* gl() const { return mGLContext; } 184 GLContext* GetGLContext() const override { return mGLContext; } 185 186 /** 187 * Clear the program state. This must be called 188 * before operating on the GLContext directly. */ 189 void ResetProgram(); 190 191 gfx::SurfaceFormat GetFBOFormat() const { 192 return gfx::SurfaceFormat::R8G8B8A8; 193 } 194 195 /** 196 * The compositor provides with temporary textures for use with direct 197 * textruing. 198 */ 199 GLuint GetTemporaryTexture(GLenum aTarget, GLenum aUnit); 200 201 const gfx::IntSize GetDestinationSurfaceSize() const { 202 return gfx::IntSize(mSurfaceSize.width, mSurfaceSize.height); 203 } 204 205 /** 206 * Allow the origin of the surface to be offset so that content does not 207 * start at (0, 0) on the surface. 208 */ 209 void SetSurfaceOrigin(const ScreenIntPoint& aOrigin) { 210 mSurfaceOrigin = aOrigin; 211 } 212 213 // Register TextureSource which own device data that have to be deleted before 214 // destroying this CompositorOGL. 215 void RegisterTextureSource(TextureSource* aTextureSource); 216 void UnregisterTextureSource(TextureSource* aTextureSource); 217 218 ipc::FileDescriptor GetReleaseFence(); 219 220 private: 221 template <typename Geometry> 222 void DrawGeometry(const Geometry& aGeometry, const gfx::Rect& aRect, 223 const gfx::IntRect& aClipRect, 224 const EffectChain& aEffectChain, gfx::Float aOpacity, 225 const gfx::Matrix4x4& aTransform, 226 const gfx::Rect& aVisibleRect); 227 228 void PrepareViewport(CompositingRenderTargetOGL* aRenderTarget); 229 230 void InsertFrameDoneSync(); 231 232 bool NeedToRecreateFullWindowRenderTarget() const; 233 234 /** Widget associated with this compositor */ 235 LayoutDeviceIntSize mWidgetSize; 236 RefPtr<GLContext> mGLContext; 237 bool mOwnsGLContext = true; 238 RefPtr<SurfacePoolHandle> mSurfacePoolHandle; 239 gfx::Matrix4x4 mProjMatrix; 240 bool mCanRenderToDefaultFramebuffer = true; 241 242 /** The size of the surface we are rendering to */ 243 gfx::IntSize mSurfaceSize; 244 245 /** The origin of the content on the surface */ 246 ScreenIntPoint mSurfaceOrigin; 247 248 already_AddRefed<mozilla::gl::GLContext> CreateContext(); 249 250 /** Texture target to use for FBOs */ 251 GLenum mFBOTextureTarget; 252 253 /** Currently bound render target */ 254 RefPtr<CompositingRenderTargetOGL> mCurrentRenderTarget; 255 256 // The 1x1 dummy render target that's the "current" render target between 257 // BeginFrameForNativeLayers and EndFrame but outside pairs of 258 // Begin/EndRenderingToNativeLayer. Created on demand. 259 RefPtr<CompositingRenderTarget> mNativeLayersReferenceRT; 260 261 // The render target that profiler screenshots / frame recording read from. 262 // This will be the actual window framebuffer when rendering to a window, and 263 // it will be mFullWindowRenderTarget when rendering to native layers. 264 RefPtr<CompositingRenderTargetOGL> mWindowRenderTarget; 265 266 // Non-null when using native layers and frame recording is requested. 267 // EndNormalDrawing() maintains a copy of the entire window contents in this 268 // render target, by copying from the native layer render targets. 269 RefPtr<CompositingRenderTargetOGL> mFullWindowRenderTarget; 270 271 /** 272 * VBO that has some basics in it for a textured quad, including vertex 273 * coords and texcoords. 274 */ 275 GLuint mQuadVBO; 276 277 /** 278 * VBO that stores dynamic triangle geometry. 279 */ 280 GLuint mTriangleVBO; 281 282 // Used to apply back-pressure in WaitForPreviousFrameDoneSync(). 283 GLsync mPreviousFrameDoneSync; 284 GLsync mThisFrameDoneSync; 285 286 bool mHasBGRA; 287 288 /** 289 * When rendering to some EGL surfaces (e.g. on Android), we rely on being 290 * told about size changes (via SetSurfaceSize) rather than pulling this 291 * information from the widget. 292 */ 293 bool mUseExternalSurfaceSize; 294 295 /** 296 * Have we had DrawQuad calls since the last frame was rendered? 297 */ 298 bool mFrameInProgress; 299 300 // Only true between BeginFromeForNativeLayers and EndFrame, and only if the 301 // full window render target needed to be recreated in the current frame. 302 bool mShouldInvalidateWindow = false; 303 304 /* Start a new frame. 305 */ 306 Maybe<gfx::IntRect> BeginFrameForWindow( 307 const nsIntRegion& aInvalidRegion, const Maybe<gfx::IntRect>& aClipRect, 308 const gfx::IntRect& aRenderBounds, 309 const nsIntRegion& aOpaqueRegion) override; 310 311 Maybe<gfx::IntRect> BeginFrame(const nsIntRegion& aInvalidRegion, 312 const Maybe<gfx::IntRect>& aClipRect, 313 const gfx::IntRect& aRenderBounds, 314 const nsIntRegion& aOpaqueRegion); 315 316 ShaderConfigOGL GetShaderConfigFor(Effect* aEffect, bool aDEAAEnabled = false, 317 bool aRoundedClip = false) const; 318 319 ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL& aConfig); 320 321 void ApplyPrimitiveConfig(ShaderConfigOGL& aConfig, const gfx::Rect&) { 322 aConfig.SetDynamicGeometry(false); 323 } 324 325 void ApplyPrimitiveConfig(ShaderConfigOGL& aConfig, 326 const nsTArray<gfx::TexturedTriangle>&) { 327 aConfig.SetDynamicGeometry(true); 328 } 329 330 /** 331 * Create a FBO backed by a texture. 332 * Note that the texture target type will be 333 * of the type returned by FBOTextureTarget; different 334 * shaders are required to sample from the different 335 * texture types. 336 */ 337 void CreateFBOWithTexture(const gfx::IntRect& aRect, bool aCopyFromSource, 338 GLuint aSourceFrameBuffer, GLuint* aFBO, 339 GLuint* aTexture, 340 gfx::IntSize* aAllocSize = nullptr); 341 342 GLuint CreateTexture(const gfx::IntRect& aRect, bool aCopyFromSource, 343 GLuint aSourceFrameBuffer, 344 gfx::IntSize* aAllocSize = nullptr); 345 346 gfx::Point3D GetLineCoefficients(const gfx::Point& aPoint1, 347 const gfx::Point& aPoint2); 348 349 void CleanupResources(); 350 351 void BindAndDrawQuads(ShaderProgramOGL* aProg, int aQuads, 352 const gfx::Rect* aLayerRect, 353 const gfx::Rect* aTextureRect); 354 355 void BindAndDrawQuad(ShaderProgramOGL* aProg, const gfx::Rect& aLayerRect, 356 const gfx::Rect& aTextureRect = gfx::Rect(0.0f, 0.0f, 357 1.0f, 1.0f)) { 358 gfx::Rect layerRects[4]; 359 gfx::Rect textureRects[4]; 360 layerRects[0] = aLayerRect; 361 textureRects[0] = aTextureRect; 362 BindAndDrawQuads(aProg, 1, layerRects, textureRects); 363 } 364 365 void BindAndDrawGeometry(ShaderProgramOGL* aProgram, const gfx::Rect& aRect); 366 367 void BindAndDrawGeometry(ShaderProgramOGL* aProgram, 368 const nsTArray<gfx::TexturedTriangle>& aTriangles); 369 370 void BindAndDrawGeometryWithTextureRect(ShaderProgramOGL* aProg, 371 const gfx::Rect& aRect, 372 const gfx::Rect& aTexCoordRect, 373 TextureSource* aTexture); 374 375 void BindAndDrawGeometryWithTextureRect( 376 ShaderProgramOGL* aProg, 377 const nsTArray<gfx::TexturedTriangle>& aTriangles, 378 const gfx::Rect& aTexCoordRect, TextureSource* aTexture); 379 380 void InitializeVAO(const GLuint aAttribIndex, const GLint aComponents, 381 const GLsizei aStride, const size_t aOffset); 382 383 gfx::Rect GetTextureCoordinates(gfx::Rect textureRect, 384 TextureSource* aTexture); 385 386 /** 387 * Copies the content of the current render target to the set transaction 388 * target. 389 */ 390 void CopyToTarget(gfx::DrawTarget* aTarget, const nsIntPoint& aTopLeft, 391 const gfx::Matrix& aWorldMatrix); 392 393 /** 394 * Implements the flipping of the y-axis to convert from layers/compositor 395 * coordinates to OpenGL coordinates. 396 * 397 * Indeed, the only coordinate system that OpenGL knows has the y-axis 398 * pointing upwards, but the layers/compositor coordinate system has the 399 * y-axis pointing downwards, for good reason as Web pages are typically 400 * scrolled downwards. So, some flipping has to take place; FlippedY does it. 401 */ 402 GLint FlipY(GLint y) const { return mViewportSize.height - y; } 403 404 // The DrawTarget from BeginFrameForTarget, which EndFrame needs to copy the 405 // window contents into. 406 // Only non-null between BeginFrameForTarget and EndFrame. 407 RefPtr<gfx::DrawTarget> mTarget; 408 gfx::IntRect mTargetBounds; 409 410 RefPtr<CompositorTexturePoolOGL> mTexturePool; 411 412 // The native layer that we're currently rendering to, if any. 413 // Non-null only between BeginFrame and EndFrame if BeginFrame has been called 414 // with a non-null aNativeLayer. 415 RefPtr<NativeLayer> mCurrentNativeLayer; 416 417 #ifdef MOZ_WIDGET_GTK 418 // Hold TextureSources which own device data that have to be deleted before 419 // destroying this CompositorOGL. 420 std::unordered_set<TextureSource*> mRegisteredTextureSources; 421 #endif 422 423 // FileDescriptor of release fence. 424 // Release fence is a fence that is used for waiting until usage/composite of 425 // AHardwareBuffer is ended. The fence is delivered to client side via 426 // ImageBridge. It is used only on android. 427 ipc::FileDescriptor mReleaseFenceFd; 428 429 bool mDestroyed; 430 431 /** 432 * Size of the OpenGL context's primary framebuffer in pixels. Used by 433 * FlipY for the y-flipping calculation and by the DEAA shader. 434 */ 435 gfx::IntSize mViewportSize; 436 437 gfx::IntRegion mCurrentFrameInvalidRegion; 438 }; 439 440 } // namespace layers 441 } // namespace mozilla 442 443 #endif /* MOZILLA_GFX_COMPOSITOROGL_H */