Bug 1499255 - Make SurfaceTextureHost to support WebRender r=nical
authorsotaro <sotaro.ikeda.g@gmail.com>
Fri, 16 Nov 2018 11:22:15 +0900
changeset 446618 b5ebe325c20d5e747953a9cec13e00d1e81fa79c
parent 446617 4977113b1fa2e3f78c6005aed694d64e7b6bf7d0
child 446619 bc6ffce8b9b68f5a114dd1f11d4fe9a8efff15d1
push id109906
push usersikeda@mozilla.com
push dateFri, 16 Nov 2018 02:22:34 +0000
treeherdermozilla-inbound@b5ebe325c20d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1499255
milestone65.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 1499255 - Make SurfaceTextureHost to support WebRender r=nical
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
gfx/webrender_bindings/RenderAndroidSurfaceTextureHostOGL.cpp
gfx/webrender_bindings/RenderAndroidSurfaceTextureHostOGL.h
gfx/webrender_bindings/moz.build
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -11,26 +11,31 @@
 #include "GLLibraryEGL.h"               // for GLLibraryEGL
 #include "GLUploadHelpers.h"
 #include "GLReadTexImageHelper.h"
 #include "gfx2DGlue.h"                  // for ContentForFormat, etc
 #include "mozilla/gfx/2D.h"             // for DataSourceSurface
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/gfx/Logging.h"        // for gfxCriticalError
 #include "mozilla/layers/ISurfaceAllocator.h"
+#include "mozilla/webrender/WebRenderAPI.h"
 #include "nsRegion.h"                   // for nsIntRegion
 #include "AndroidSurfaceTexture.h"
 #include "GfxTexturesReporter.h"        // for GfxTexturesReporter
 #include "GLBlitTextureImageHelper.h"
 #include "GeckoProfiler.h"
 
 #ifdef XP_MACOSX
 #include "mozilla/layers/MacIOSurfaceTextureHostOGL.h"
 #endif
 
+#ifdef MOZ_WIDGET_ANDROID
+#include "mozilla/webrender/RenderAndroidSurfaceTextureHostOGL.h"
+#endif
+
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 class Compositor;
 
@@ -673,16 +678,76 @@ SurfaceTextureHost::DeallocateDeviceData
   }
 
   if (mSurfTex) {
     mSurfTex->DecrementUse();
     mSurfTex = nullptr;
   }
 }
 
+void
+SurfaceTextureHost::CreateRenderTexture(const wr::ExternalImageId& aExternalImageId)
+{
+  RefPtr<wr::RenderTextureHost> texture =
+      new wr::RenderAndroidSurfaceTextureHostOGL(mSurfTex, mSize, mFormat, mContinuousUpdate);
+  wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget());
+}
+
+void
+SurfaceTextureHost::PushResourceUpdates(wr::TransactionBuilder& aResources,
+                                        ResourceUpdateOp aOp,
+                                        const Range<wr::ImageKey>& aImageKeys,
+                                        const wr::ExternalImageId& aExtID)
+{
+  auto method = aOp == TextureHost::ADD_IMAGE ? &wr::TransactionBuilder::AddExternalImage
+                                              : &wr::TransactionBuilder::UpdateExternalImage;
+  auto bufferType = wr::WrExternalImageBufferType::TextureRectHandle;
+
+  switch (GetFormat()) {
+    case gfx::SurfaceFormat::R8G8B8X8:
+    case gfx::SurfaceFormat::R8G8B8A8: {
+      MOZ_ASSERT(aImageKeys.length() == 1);
+
+      // XXX Add RGBA handling. Temporary hack to avoid crash
+      // With BGRA format setting, rendering works without problem.
+      auto format = GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ? gfx::SurfaceFormat::B8G8R8A8
+                                                                : gfx::SurfaceFormat::B8G8R8X8;
+      wr::ImageDescriptor descriptor(GetSize(), format);
+      (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
+      break;
+    }
+    default: {
+      MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+    }
+  }
+}
+
+void
+SurfaceTextureHost::PushDisplayItems(wr::DisplayListBuilder& aBuilder,
+                                     const wr::LayoutRect& aBounds,
+                                     const wr::LayoutRect& aClip,
+                                     wr::ImageRendering aFilter,
+                                     const Range<wr::ImageKey>& aImageKeys)
+{
+  switch (GetFormat()) {
+    case gfx::SurfaceFormat::R8G8B8X8:
+    case gfx::SurfaceFormat::R8G8B8A8:
+    case gfx::SurfaceFormat::B8G8R8A8:
+    case gfx::SurfaceFormat::B8G8R8X8: {
+
+      MOZ_ASSERT(aImageKeys.length() == 1);
+      aBuilder.PushImage(aBounds, aClip, true, aFilter, aImageKeys[0], !(mFlags & TextureFlags::NON_PREMULTIPLIED));
+      break;
+    }
+    default: {
+      MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+    }
+  }
+}
+
 #endif // MOZ_WIDGET_ANDROID
 
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
 // EGLImage
 
 EGLImageTextureSource::EGLImageTextureSource(TextureSourceProvider* aProvider,
                                              EGLImage aImage,
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -21,16 +21,17 @@
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for IntSize, IntPoint
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat, etc
 #include "mozilla/layers/CompositorOGL.h"  // for CompositorOGL
 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureHost.h"  // for TextureHost, etc
 #include "mozilla/mozalloc.h"           // for operator delete, etc
+#include "mozilla/webrender/RenderThread.h"
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_WARNING
 #include "nsISupportsImpl.h"            // for TextureImage::Release, etc
 #include "nsRegionFwd.h"                // for nsIntRegion
 #include "OGLShaderProgram.h"           // for ShaderProgramType, etc
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "GeneratedJNIWrappers.h"
@@ -469,16 +470,29 @@ public:
   }
 
   gl::GLContext* gl() const;
 
   virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual const char* Name() override { return "SurfaceTextureHost"; }
 
+  virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
+
+  virtual void PushResourceUpdates(wr::TransactionBuilder& aResources,
+                                   ResourceUpdateOp aOp,
+                                   const Range<wr::ImageKey>& aImageKeys,
+                                   const wr::ExternalImageId& aExtID) override;
+
+  virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
+                                const wr::LayoutRect& aBounds,
+                                const wr::LayoutRect& aClip,
+                                wr::ImageRendering aFilter,
+                                const Range<wr::ImageKey>& aImageKeys) override;
+
 protected:
   bool EnsureAttached();
 
   mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
   const gfx::IntSize mSize;
   const gfx::SurfaceFormat mFormat;
   bool mContinuousUpdate;
   const bool mIgnoreTransform;
new file mode 100644
--- /dev/null
+++ b/gfx/webrender_bindings/RenderAndroidSurfaceTextureHostOGL.cpp
@@ -0,0 +1,120 @@
+/* -*- 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/. */
+
+#include "RenderAndroidSurfaceTextureHostOGL.h"
+
+#include "mozilla/gfx/Logging.h"
+
+namespace mozilla {
+namespace wr {
+
+RenderAndroidSurfaceTextureHostOGL::RenderAndroidSurfaceTextureHostOGL(
+  const java::GeckoSurfaceTexture::GlobalRef& aSurfTex,
+  gfx::IntSize aSize,
+  gfx::SurfaceFormat aFormat,
+  bool aContinuousUpdate)
+  : mSurfTex(aSurfTex)
+  , mSize(aSize)
+{
+  MOZ_COUNT_CTOR_INHERITED(RenderAndroidSurfaceTextureHostOGL, RenderTextureHostOGL);
+
+  if (mSurfTex) {
+    mSurfTex->IncrementUse();
+  }
+}
+
+RenderAndroidSurfaceTextureHostOGL::~RenderAndroidSurfaceTextureHostOGL()
+{
+  MOZ_COUNT_DTOR_INHERITED(RenderAndroidSurfaceTextureHostOGL, RenderTextureHostOGL);
+  DeleteTextureHandle();
+  if (mSurfTex) {
+    mSurfTex->DecrementUse();
+  }
+}
+
+GLuint
+RenderAndroidSurfaceTextureHostOGL::GetGLHandle(uint8_t aChannelIndex) const
+{
+  if (!mSurfTex) {
+    return 0;
+  }
+  return mSurfTex->GetTexName();
+}
+
+gfx::IntSize
+RenderAndroidSurfaceTextureHostOGL::GetSize(uint8_t aChannelIndex) const
+{
+  return mSize;
+}
+
+wr::WrExternalImage
+RenderAndroidSurfaceTextureHostOGL::Lock(uint8_t aChannelIndex,
+                                       gl::GLContext* aGL,
+                                       wr::ImageRendering aRendering)
+{
+  MOZ_ASSERT(aChannelIndex == 0);
+
+  if (mGL.get() != aGL) {
+    // release the texture handle in the previous gl context
+    DeleteTextureHandle();
+    mGL = aGL;
+    mGL->MakeCurrent();
+  }
+
+  if (!mSurfTex || !mGL || !mGL->MakeCurrent()) {
+    return InvalidToWrExternalImage();
+  }
+
+  if (!mSurfTex->IsAttachedToGLContext((int64_t)mGL.get())) {
+    GLuint texName;
+    mGL->fGenTextures(1, &texName);
+    // Cache rendering filter.
+    mCachedRendering = aRendering;
+    ActivateBindAndTexParameteri(mGL,
+                                 LOCAL_GL_TEXTURE0,
+                                 LOCAL_GL_TEXTURE_EXTERNAL_OES,
+                                 texName,
+                                 aRendering);
+
+    if (NS_FAILED(mSurfTex->AttachToGLContext((int64_t)mGL.get(), texName))) {
+      MOZ_ASSERT(0);
+      mGL->fDeleteTextures(1, &texName);
+      return InvalidToWrExternalImage();;
+    }
+  } else if(IsFilterUpdateNecessary(aRendering)) {
+    // Cache new rendering filter.
+    mCachedRendering = aRendering;
+    ActivateBindAndTexParameteri(mGL,
+                                 LOCAL_GL_TEXTURE0,
+                                 LOCAL_GL_TEXTURE_EXTERNAL_OES,
+                                 mSurfTex->GetTexName(),
+                                 aRendering);
+  }
+
+  // XXX Call UpdateTexImage() only when it is necessary.
+  // For now, alyways call UpdateTexImage().
+  //if (mContinuousUpdate) {
+    mSurfTex->UpdateTexImage();
+  //}
+
+  return NativeTextureToWrExternalImage(mSurfTex->GetTexName(), 0, 0,
+                                        mSize.width, mSize.height);
+}
+
+void
+RenderAndroidSurfaceTextureHostOGL::Unlock()
+{
+}
+
+void
+RenderAndroidSurfaceTextureHostOGL::DeleteTextureHandle()
+{
+  // XXX Do we need to call mSurfTex->DetachFromGLContext() here?
+  // But Surface texture is shared among many SurfaceTextureHosts.
+}
+
+} // namespace wr
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/webrender_bindings/RenderAndroidSurfaceTextureHostOGL.h
@@ -0,0 +1,49 @@
+/* -*- 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_RENDERANDROIDSURFACETEXTUREHOSTOGL_H
+#define MOZILLA_GFX_RENDERANDROIDSURFACETEXTUREHOSTOGL_H
+
+#include "GeneratedJNIWrappers.h"
+#include "mozilla/layers/TextureHostOGL.h"
+#include "RenderTextureHostOGL.h"
+
+namespace mozilla {
+
+namespace wr {
+
+class RenderAndroidSurfaceTextureHostOGL final : public RenderTextureHostOGL
+{
+public:
+  explicit RenderAndroidSurfaceTextureHostOGL(const java::GeckoSurfaceTexture::GlobalRef& aSurfTex,
+                                              gfx::IntSize aSize,
+                                              gfx::SurfaceFormat aFormat,
+                                              bool aContinuousUpdate);
+
+  wr::WrExternalImage Lock(uint8_t aChannelIndex,
+                           gl::GLContext* aGL,
+                           wr::ImageRendering aRendering) override;
+  void Unlock() override;
+
+  virtual gfx::IntSize GetSize(uint8_t aChannelIndex) const override;
+  virtual GLuint GetGLHandle(uint8_t aChannelIndex) const override;
+
+private:
+  virtual ~RenderAndroidSurfaceTextureHostOGL();
+  void DeleteTextureHandle();
+
+  const mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
+  const gfx::IntSize mSize;
+  // XXX const bool mContinuousUpdate;
+  // XXX const bool mIgnoreTransform;
+
+  RefPtr<gl::GLContext> mGL;
+};
+
+} // namespace wr
+} // namespace mozilla
+
+#endif // MOZILLA_GFX_RENDERANDROIDSURFACETEXTUREHOSTOGL_H
--- a/gfx/webrender_bindings/moz.build
+++ b/gfx/webrender_bindings/moz.build
@@ -41,16 +41,24 @@ UNIFIED_SOURCES += [
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     EXPORTS.mozilla.webrender += [
         'RenderMacIOSurfaceTextureHostOGL.h',
     ]
     UNIFIED_SOURCES += [
         'RenderMacIOSurfaceTextureHostOGL.cpp',
     ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
+    EXPORTS.mozilla.webrender += [
+        'RenderAndroidSurfaceTextureHostOGL.h',
+    ]
+    UNIFIED_SOURCES += [
+        'RenderAndroidSurfaceTextureHostOGL.cpp',
+    ]
+
 if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
     DEFINES['MOZ_ENABLE_D3D10_LAYER'] = True
     EXPORTS.mozilla.webrender += [
         'RenderCompositorANGLE.h',
         'RenderD3D11TextureHostOGL.h',
     ]
     UNIFIED_SOURCES += [
         'RenderD3D11TextureHostOGL.cpp',