From 572a63549aea81f76ea968966a31fdaaa8a2650c Mon Sep 17 00:00:00 2001 From: sotaro Date: Mon, 1 Apr 2019 22:07:47 +0000 Subject: [PATCH] Bug 1532201 - Enable SurfaceFactory_EGLImage usage with WebRender r=nical Differential Revision: https://phabricator.services.mozilla.com/D24668 --HG-- extra : moz-landing-system : lando --- gfx/gl/GLScreenBuffer.cpp | 4 +- gfx/layers/opengl/TextureHostOGL.cpp | 55 +++++++++ gfx/layers/opengl/TextureHostOGL.h | 14 +++ .../RenderEGLImageTextureHost.cpp | 109 ++++++++++++++++++ .../RenderEGLImageTextureHost.h | 46 ++++++++ gfx/webrender_bindings/moz.build | 2 + 6 files changed, 227 insertions(+), 3 deletions(-) create mode 100644 gfx/webrender_bindings/RenderEGLImageTextureHost.cpp create mode 100644 gfx/webrender_bindings/RenderEGLImageTextureHost.h diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp index 3137fb562d0e..d4acdf99ee4d 100644 --- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -88,9 +88,7 @@ UniquePtr GLScreenBuffer::CreateFactory( factory = MakeUnique(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 = diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index a88d6dd92cc1..bd80ce686e12 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -16,6 +16,7 @@ #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" @@ -817,6 +818,60 @@ gfx::SurfaceFormat EGLImageTextureHost::GetFormat() const { : gfx::SurfaceFormat::UNKNOWN; } +void EGLImageTextureHost::CreateRenderTexture( + const wr::ExternalImageId& aExternalImageId) { + RefPtr 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& 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& 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, diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index 8e5473c6d075..9ff7cce68104 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -545,6 +545,20 @@ class EGLImageTextureHost final : public TextureHost { 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& 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& aImageKeys) override; + protected: const EGLImage mImage; const EGLSync mSync; diff --git a/gfx/webrender_bindings/RenderEGLImageTextureHost.cpp b/gfx/webrender_bindings/RenderEGLImageTextureHost.cpp new file mode 100644 index 000000000000..6d8a8423460b --- /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 diff --git a/gfx/webrender_bindings/RenderEGLImageTextureHost.h b/gfx/webrender_bindings/RenderEGLImageTextureHost.h new file mode 100644 index 000000000000..2fad29dfb88d --- /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 mGL; + GLenum mTextureTarget; + GLuint mTextureHandle; +}; + +} // namespace wr +} // namespace mozilla + +#endif // MOZILLA_GFX_RENDEREGLIMAGETEXTUREHOSTOGL_H diff --git a/gfx/webrender_bindings/moz.build b/gfx/webrender_bindings/moz.build index be1d8f15e247..81ea5bbf4232 100644 --- a/gfx/webrender_bindings/moz.build +++ b/gfx/webrender_bindings/moz.build @@ -11,6 +11,7 @@ EXPORTS.mozilla.webrender += [ 'RenderBufferTextureHost.h', 'RenderCompositor.h', 'RenderCompositorOGL.h', + 'RenderEGLImageTextureHost.h', 'RendererOGL.h', 'RendererScreenshotGrabber.h', 'RenderSharedSurfaceTextureHost.h', @@ -28,6 +29,7 @@ UNIFIED_SOURCES += [ 'RenderBufferTextureHost.cpp', 'RenderCompositor.cpp', 'RenderCompositorOGL.cpp', + 'RenderEGLImageTextureHost.cpp', 'RendererOGL.cpp', 'RendererScreenshotGrabber.cpp', 'RenderSharedSurfaceTextureHost.cpp',