Bug 1574592 - Create a render target per IOSurface, laying the groundwork for multiple native layers. r=mattwoodrow
authorMarkus Stange <mstange@themasta.com>
Sun, 25 Aug 2019 17:11:25 +0000
changeset 553561 31348057830bf65dfc2286a4983562501d896864
parent 553560 2067452a1f9063e0ee7d4dc84b7a704268a99717
child 553562 717f127c6729b43ddc1f8b0ee22a3ce2abd57ae9
push id2165
push userffxbld-merge
push dateMon, 14 Oct 2019 16:30:58 +0000
treeherdermozilla-release@0eae18af659f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1574592
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1574592 - Create a render target per IOSurface, laying the groundwork for multiple native layers. r=mattwoodrow This makes CompositorOGL always render into offscreen render targets. CompositorOGL no longer expects the GLContext to have a default framebuffer. This duplicates a bunch of code from GLContextCGL, but that code can be removed from GLContextCGL once WebRender no longer needs it. This also makes it so that we don't recreate render targets on every frame; instead, we create one render target for every IOSurface in the native layer's "swap chain" and cycle through those render targets. We only throw away the render targets when the window is resized or closed. Differential Revision: https://phabricator.services.mozilla.com/D42405
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/opengl/CompositorOGL.h
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -749,56 +749,101 @@ void CompositorOGL::ClearRect(const gfx:
   ScopedGLState scopedScissorTestState(mGLContext, LOCAL_GL_SCISSOR_TEST, true);
   ScopedScissorRect autoScissorRect(mGLContext, aRect.X(), y, aRect.Width(),
                                     aRect.Height());
   mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
   mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
 }
 
 #ifdef XP_MACOSX
-class SurfaceRegistryWrapperAroundGLContextCGL
+class SurfaceRegistryWrapperAroundCompositorOGL
     : public layers::IOSurfaceRegistry {
  public:
-  explicit SurfaceRegistryWrapperAroundGLContextCGL(gl::GLContextCGL* aContext)
-      : mContext(aContext) {}
+  explicit SurfaceRegistryWrapperAroundCompositorOGL(CompositorOGL* aCompositor)
+      : mCompositor(aCompositor) {}
   void RegisterSurface(CFTypeRefPtr<IOSurfaceRef> aSurface) override {
-    mContext->RegisterIOSurface(aSurface.get());
+    mCompositor->RegisterIOSurface((IOSurfacePtr)aSurface.get());
   }
   void UnregisterSurface(CFTypeRefPtr<IOSurfaceRef> aSurface) override {
-    mContext->UnregisterIOSurface(aSurface.get());
+    mCompositor->UnregisterIOSurface((IOSurfacePtr)aSurface.get());
   }
-  RefPtr<gl::GLContextCGL> mContext;
+  RefPtr<CompositorOGL> mCompositor;
 };
+
+void CompositorOGL::RegisterIOSurface(IOSurfacePtr aSurface) {
+  MOZ_RELEASE_ASSERT(mRegisteredIOSurfaceRenderTargets.find(aSurface) ==
+                         mRegisteredIOSurfaceRenderTargets.end(),
+                     "double-registering IOSurface");
+
+  IOSurfaceRef surface = (IOSurfaceRef)aSurface;
+  auto glContextCGL = GLContextCGL::Cast(mGLContext);
+  MOZ_RELEASE_ASSERT(glContextCGL, "Unexpected GLContext type");
+
+  IntSize size(IOSurfaceGetWidth(surface), IOSurfaceGetHeight(surface));
+
+  mGLContext->MakeCurrent();
+  GLuint tex = mGLContext->CreateTexture();
+  {
+    const ScopedBindTexture bindTex(mGLContext, tex,
+                                    LOCAL_GL_TEXTURE_RECTANGLE_ARB);
+    CGLTexImageIOSurface2D(glContextCGL->GetCGLContext(),
+                           LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_RGBA,
+                           size.width, size.height, LOCAL_GL_BGRA,
+                           LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0);
+  }
+
+  GLuint fbo = mGLContext->CreateFramebuffer();
+  {
+    const ScopedBindFramebuffer bindFB(mGLContext, fbo);
+    mGLContext->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
+                                      LOCAL_GL_COLOR_ATTACHMENT0,
+                                      LOCAL_GL_TEXTURE_RECTANGLE_ARB, tex, 0);
+  }
+
+  RefPtr<CompositingRenderTargetOGL> rt =
+      new CompositingRenderTargetOGL(this, gfx::IntPoint(), tex, fbo);
+  rt->Initialize(size, size, LOCAL_GL_TEXTURE_RECTANGLE_ARB, INIT_MODE_NONE);
+
+  mRegisteredIOSurfaceRenderTargets.insert({aSurface, rt});
+}
+
+void CompositorOGL::UnregisterIOSurface(IOSurfacePtr aSurface) {
+  size_t removeCount = mRegisteredIOSurfaceRenderTargets.erase(aSurface);
+  MOZ_RELEASE_ASSERT(removeCount == 1,
+                     "Unregistering IOSurface that's not registered");
+}
 #endif
 
 already_AddRefed<CompositingRenderTargetOGL>
 CompositorOGL::RenderTargetForNativeLayer(NativeLayer* aNativeLayer) {
 #ifdef XP_MACOSX
   NativeLayerCA* nativeLayer = aNativeLayer->AsNativeLayerCA();
   MOZ_RELEASE_ASSERT(nativeLayer, "Unexpected native layer type");
   nativeLayer->SetSurfaceIsFlipped(true);
   auto glContextCGL = GLContextCGL::Cast(mGLContext);
   MOZ_RELEASE_ASSERT(glContextCGL, "Unexpected GLContext type");
   RefPtr<layers::IOSurfaceRegistry> currentRegistry =
       nativeLayer->GetSurfaceRegistry();
   if (!currentRegistry) {
     nativeLayer->SetSurfaceRegistry(
-        MakeAndAddRef<SurfaceRegistryWrapperAroundGLContextCGL>(glContextCGL));
+        MakeAndAddRef<SurfaceRegistryWrapperAroundCompositorOGL>(this));
   } else {
-    MOZ_RELEASE_ASSERT(static_cast<SurfaceRegistryWrapperAroundGLContextCGL*>(
+    MOZ_RELEASE_ASSERT(static_cast<SurfaceRegistryWrapperAroundCompositorOGL*>(
                            currentRegistry.get())
-                           ->mContext == glContextCGL);
+                           ->mCompositor == this);
   }
   CFTypeRefPtr<IOSurfaceRef> surf = nativeLayer->NextSurface();
   if (!surf) {
     return nullptr;
   }
-  glContextCGL->UseRegisteredIOSurfaceForDefaultFramebuffer(surf.get());
-  return CompositingRenderTargetOGL::RenderTargetForWindow(
-      this, nativeLayer->GetRect().Size());
+
+  auto match = mRegisteredIOSurfaceRenderTargets.find((IOSurfacePtr)surf.get());
+  MOZ_RELEASE_ASSERT(match != mRegisteredIOSurfaceRenderTargets.end(),
+                     "IOSurface has not been registered with this Compositor");
+  return do_AddRef(match->second);
 #else
   MOZ_CRASH("Unexpected native layer on this platform");
 #endif
 }
 
 void CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
                                const IntRect* aClipRectIn,
                                const IntRect& aRenderBounds,
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -3,16 +3,17 @@
 /* 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
@@ -31,16 +32,24 @@
 #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
 
+#ifdef XP_MACOSX
+// This file uses IOSurfacePtr instead of IOSurfaceRef because IOSurfaceRef is
+// hard to forward declare, and including <IOSurface/IOSurface.h> brings in
+// MacTypes.h which defines Point and Rect which cause name lookup trouble.
+struct DummyIOSurface;
+typedef DummyIOSurface* IOSurfacePtr;
+#endif
+
 class nsIWidget;
 
 namespace mozilla {
 
 namespace layers {
 
 class CompositingRenderTarget;
 class CompositingRenderTargetOGL;
@@ -264,16 +273,21 @@ class CompositorOGL final : public Compo
     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);
 
+#ifdef XP_MACOSX
+  void RegisterIOSurface(IOSurfacePtr aSurface);
+  void UnregisterIOSurface(IOSurfacePtr aSurface);
+#endif
+
  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);
 
@@ -471,14 +485,26 @@ class CompositorOGL final : public Compo
 
   /**
    * 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;
 
   ShaderProgramOGL* mCurrentProgram;
+
+#ifdef XP_MACOSX
+  struct IOSurfaceRefHasher {
+    std::size_t operator()(const IOSurfacePtr& aSurface) const {
+      return HashGeneric(reinterpret_cast<uintptr_t>(aSurface));
+    }
+  };
+
+  std::unordered_map<IOSurfacePtr, RefPtr<CompositingRenderTargetOGL>,
+                     IOSurfaceRefHasher>
+      mRegisteredIOSurfaceRenderTargets;
+#endif
 };
 
 }  // namespace layers
 }  // namespace mozilla
 
 #endif /* MOZILLA_GFX_COMPOSITOROGL_H */