Bug 1532201 - Enable SurfaceFactory_EGLImage usage with WebRender r=nical
☠☠ backed out by 0b5ac3196257 ☠ ☠
authorsotaro <sotaro.ikeda.g@gmail.com>
Mon, 01 Apr 2019 22:07:47 +0000
changeset 467477 48d248c9f5fdddf38e15a155b6101a0319db592a
parent 467476 95b5f7a786ab5f33e5b535f3a87da5891f9d5908
child 467478 9567622873d62601425b04227642048475fa6137
push id35799
push usercbrindusan@mozilla.com
push dateTue, 02 Apr 2019 08:35:12 +0000
treeherdermozilla-central@ea0977445697 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1532201
milestone68.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 1532201 - Enable SurfaceFactory_EGLImage usage with WebRender r=nical Differential Revision: https://phabricator.services.mozilla.com/D24668
gfx/gl/GLScreenBuffer.cpp
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
gfx/webrender_bindings/RenderEGLImageTextureHost.cpp
gfx/webrender_bindings/RenderEGLImageTextureHost.h
gfx/webrender_bindings/moz.build
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -83,19 +83,17 @@ UniquePtr<SurfaceFactory> GLScreenBuffer
     factory = SurfaceFactory_IOSurface::Create(gl, caps, ipcChannel, flags);
 #elif defined(MOZ_X11)
     if (sGLXLibrary.UseTextureFromPixmap())
       factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
 #elif defined(MOZ_WIDGET_UIKIT)
     factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel,
                                                    mFlags);
 #elif defined(MOZ_WIDGET_ANDROID)
-    // XXX WebRender does not support SurfaceFactory_EGLImage usage.
-    if (XRE_IsParentProcess() && !gfxPrefs::WebGLSurfaceTextureEnabled() &&
-        backend != layers::LayersBackend::LAYERS_WR) {
+    if (XRE_IsParentProcess() && !gfxPrefs::WebGLSurfaceTextureEnabled()) {
       factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
     } else {
       factory =
           SurfaceFactory_SurfaceTexture::Create(gl, caps, ipcChannel, flags);
     }
 #else
     if (gl->GetContextType() == GLContextType::EGL) {
       if (XRE_IsParentProcess()) {
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -11,16 +11,17 @@
 #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/RenderEGLImageTextureHost.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
@@ -812,16 +813,70 @@ void EGLImageTextureHost::SetTextureSour
 }
 
 gfx::SurfaceFormat EGLImageTextureHost::GetFormat() const {
   MOZ_ASSERT(mTextureSource);
   return mTextureSource ? mTextureSource->GetFormat()
                         : gfx::SurfaceFormat::UNKNOWN;
 }
 
+void EGLImageTextureHost::CreateRenderTexture(
+    const wr::ExternalImageId& aExternalImageId) {
+  RefPtr<wr::RenderTextureHost> texture =
+      new wr::RenderEGLImageTextureHost(mImage, mSync, mSize);
+  wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId),
+                                                 texture.forget());
+}
+
+void EGLImageTextureHost::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::TextureExternalHandle;
+
+  gfx::SurfaceFormat format =
+      mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8;
+
+  switch (format) {
+    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 formatTmp = format == gfx::SurfaceFormat::R8G8B8A8
+                           ? gfx::SurfaceFormat::B8G8R8A8
+                           : gfx::SurfaceFormat::B8G8R8X8;
+      wr::ImageDescriptor descriptor(GetSize(), formatTmp);
+      (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
+      break;
+    }
+  }
+}
+
+void EGLImageTextureHost::PushDisplayItems(
+    wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds,
+    const wr::LayoutRect& aClip, wr::ImageRendering aFilter,
+    const Range<wr::ImageKey>& aImageKeys) {
+  gfx::SurfaceFormat format =
+      mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8;
+
+  switch (format) {
+    case gfx::SurfaceFormat::R8G8B8X8:
+    case gfx::SurfaceFormat::R8G8B8A8: {
+      MOZ_ASSERT(aImageKeys.length() == 1);
+      aBuilder.PushImage(aBounds, aClip, true, aFilter, aImageKeys[0],
+                         !(mFlags & TextureFlags::NON_PREMULTIPLIED));
+      break;
+    }
+  }
+}
+
 //
 
 GLTextureHost::GLTextureHost(TextureFlags aFlags, GLuint aTextureHandle,
                              GLenum aTarget, GLsync aSync, gfx::IntSize aSize,
                              bool aHasAlpha)
     : TextureHost(aFlags),
       mTexture(aTextureHandle),
       mTarget(aTarget),
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -540,16 +540,30 @@ class EGLImageTextureHost final : public
   }
 
   gl::GLContext* gl() const;
 
   virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual const char* Name() override { return "EGLImageTextureHost"; }
 
+  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:
   const EGLImage mImage;
   const EGLSync mSync;
   const gfx::IntSize mSize;
   const bool mHasAlpha;
   RefPtr<EGLImageTextureSource> mTextureSource;
 };
 
new file mode 100644
--- /dev/null
+++ b/gfx/webrender_bindings/RenderEGLImageTextureHost.cpp
@@ -0,0 +1,109 @@
+/* -*- 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 "RenderEGLImageTextureHost.h"
+
+#include "mozilla/gfx/Logging.h"
+#include "GLContext.h"
+#include "GLLibraryEGL.h"
+
+namespace mozilla {
+namespace wr {
+
+RenderEGLImageTextureHost::RenderEGLImageTextureHost(EGLImage aImage,
+                                                     EGLSync aSync,
+                                                     gfx::IntSize aSize)
+    : mImage(aImage),
+      mSync(aSync),
+      mSize(aSize),
+      mTextureTarget(LOCAL_GL_TEXTURE_2D),
+      mTextureHandle(0) {
+  MOZ_COUNT_CTOR_INHERITED(RenderEGLImageTextureHost, RenderTextureHostOGL);
+}
+
+RenderEGLImageTextureHost::~RenderEGLImageTextureHost() {
+  MOZ_COUNT_DTOR_INHERITED(RenderEGLImageTextureHost, RenderTextureHostOGL);
+  DeleteTextureHandle();
+}
+
+GLuint RenderEGLImageTextureHost::GetGLHandle(uint8_t aChannelIndex) const {
+  return mTextureHandle;
+}
+
+gfx::IntSize RenderEGLImageTextureHost::GetSize(uint8_t aChannelIndex) const {
+  return mSize;
+}
+
+wr::WrExternalImage RenderEGLImageTextureHost::Lock(
+    uint8_t aChannelIndex, gl::GLContext* aGL, wr::ImageRendering aRendering) {
+  MOZ_ASSERT(aChannelIndex == 0);
+
+  if (mGL.get() != aGL) {
+    if (mGL) {
+      // This should not happen. SharedSurface_EGLImage is created only in
+      // parent process.
+      MOZ_ASSERT_UNREACHABLE("Unexpected GL context");
+      return InvalidToWrExternalImage();
+    }
+    mGL = aGL;
+  }
+
+  if (!mImage || !mGL || !mGL->MakeCurrent()) {
+    return InvalidToWrExternalImage();
+  }
+
+  EGLint status = LOCAL_EGL_CONDITION_SATISFIED;
+  if (mSync) {
+    auto* egl = gl::GLLibraryEGL::Get();
+    MOZ_ASSERT(egl->IsExtensionSupported(gl::GLLibraryEGL::KHR_fence_sync));
+    status = egl->fClientWaitSync(egl->Display(), mSync, 0, LOCAL_EGL_FOREVER);
+    // We do not need to delete sync here. It is deleted by
+    // SharedSurface_EGLImage.
+    mSync = 0;
+  }
+
+  if (status != LOCAL_EGL_CONDITION_SATISFIED) {
+    MOZ_ASSERT(
+        status != 0,
+        "ClientWaitSync generated an error. Has mSync already been destroyed?");
+    return InvalidToWrExternalImage();
+  }
+
+  if (!mTextureHandle) {
+    mTextureTarget = mGL->GetPreferredEGLImageTextureTarget();
+    MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D ||
+               mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL);
+
+    mGL->fGenTextures(1, &mTextureHandle);
+    // Cache rendering filter.
+    mCachedRendering = aRendering;
+    ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0, mTextureTarget,
+                                 mTextureHandle, aRendering);
+    mGL->fEGLImageTargetTexture2D(mTextureTarget, mImage);
+  } else if (IsFilterUpdateNecessary(aRendering)) {
+    // Cache new rendering filter.
+    mCachedRendering = aRendering;
+    ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0, mTextureTarget,
+                                 mTextureHandle, aRendering);
+  }
+
+  return NativeTextureToWrExternalImage(mTextureHandle, 0, 0, mSize.width,
+                                        mSize.height);
+}
+
+void RenderEGLImageTextureHost::Unlock() {}
+
+void RenderEGLImageTextureHost::DeleteTextureHandle() {
+  if (mTextureHandle) {
+    // XXX recycle gl texture, since SharedSurface_EGLImage and
+    // RenderEGLImageTextureHost is not recycled.
+    mGL->fDeleteTextures(1, &mTextureHandle);
+    mTextureHandle = 0;
+  }
+}
+
+}  // namespace wr
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/webrender_bindings/RenderEGLImageTextureHost.h
@@ -0,0 +1,46 @@
+/* -*- 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_RENDEREGLIMAGETEXTUREHOSTOGL_H
+#define MOZILLA_GFX_RENDEREGLIMAGETEXTUREHOSTOGL_H
+
+#include "mozilla/layers/TextureHostOGL.h"
+#include "RenderTextureHostOGL.h"
+
+namespace mozilla {
+
+namespace wr {
+
+// RenderEGLImageTextureHost is created only for SharedSurface_EGLImage that is
+// created in parent process.
+class RenderEGLImageTextureHost final : public RenderTextureHostOGL {
+ public:
+  RenderEGLImageTextureHost(EGLImage aImage, EGLSync aSync, gfx::IntSize aSize);
+
+  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 ~RenderEGLImageTextureHost();
+  void DeleteTextureHandle();
+
+  const EGLImage mImage;
+  EGLSync mSync;
+  const gfx::IntSize mSize;
+
+  RefPtr<gl::GLContext> mGL;
+  GLenum mTextureTarget;
+  GLuint mTextureHandle;
+};
+
+}  // namespace wr
+}  // namespace mozilla
+
+#endif  // MOZILLA_GFX_RENDEREGLIMAGETEXTUREHOSTOGL_H
--- a/gfx/webrender_bindings/moz.build
+++ b/gfx/webrender_bindings/moz.build
@@ -6,16 +6,17 @@
 
 with Files('**'):
     BUG_COMPONENT = ('Core', 'Graphics: WebRender')
 
 EXPORTS.mozilla.webrender += [
     'RenderBufferTextureHost.h',
     'RenderCompositor.h',
     'RenderCompositorOGL.h',
+    'RenderEGLImageTextureHost.h',
     'RendererOGL.h',
     'RendererScreenshotGrabber.h',
     'RenderSharedSurfaceTextureHost.h',
     'RenderTextureHost.h',
     'RenderTextureHostOGL.h',
     'RenderTextureHostWrapper.h',
     'RenderThread.h',
     'webrender_ffi.h',
@@ -23,16 +24,17 @@ EXPORTS.mozilla.webrender += [
     'WebRenderTypes.h',
 ]
 
 UNIFIED_SOURCES += [
     'Moz2DImageRenderer.cpp',
     'RenderBufferTextureHost.cpp',
     'RenderCompositor.cpp',
     'RenderCompositorOGL.cpp',
+    'RenderEGLImageTextureHost.cpp',
     'RendererOGL.cpp',
     'RendererScreenshotGrabber.cpp',
     'RenderSharedSurfaceTextureHost.cpp',
     'RenderTextureHost.cpp',
     'RenderTextureHostOGL.cpp',
     'RenderTextureHostWrapper.cpp',
     'RenderThread.cpp',
     'WebRenderAPI.cpp',