Bug 1649088 - Add SharedSurface support with AHardwareBuffer support on android r=jgilbert

AHardwareBuffer could remove several limitations of android::SurfaceTexture.

File descriptor usage of current implementation is not efficient. It is going to be addressed by Bug 1663381.

Differential Revision: https://phabricator.services.mozilla.com/D89232
This commit is contained in:
sotaro 2020-09-11 03:11:45 +00:00
Родитель cc286890ec
Коммит 872ccfe115
9 изменённых файлов: 289 добавлений и 4 удалений

Просмотреть файл

@ -67,6 +67,7 @@ class gfxVarReceiver;
_(DwmCompositionEnabled, bool, true) \
_(FxREmbedded, bool, false) \
_(UseAHardwareBufferContent, bool, false) \
_(UseAHardwareBufferSharedSurface, bool, false) \
_(UseEGL, bool, false)
/* Add new entries above this line. */

Просмотреть файл

@ -41,6 +41,10 @@
# include "SharedSurfaceDMABUF.h"
#endif
#ifdef MOZ_WIDGET_ANDROID
# include "SharedSurfaceAndroidHardwareBuffer.h"
#endif
namespace mozilla {
namespace gl {
@ -115,9 +119,6 @@ UniquePtr<SurfaceFactory> SurfaceFactory::Create(
#endif
return nullptr;
case layers::TextureType::AndroidHardwareBuffer:
return nullptr;
case layers::TextureType::AndroidNativeWindow:
#ifdef MOZ_WIDGET_ANDROID
if (XRE_IsParentProcess() && !StaticPrefs::webgl_enable_surface_texture())
@ -127,6 +128,13 @@ UniquePtr<SurfaceFactory> SurfaceFactory::Create(
return nullptr;
#endif
case layers::TextureType::AndroidHardwareBuffer:
#ifdef MOZ_WIDGET_ANDROID
return SurfaceFactory_AndroidHardwareBuffer::Create(gl);
#else
return nullptr;
#endif
case layers::TextureType::EGLImage:
#ifdef MOZ_WIDGET_ANDROID
if (XRE_IsParentProcess()) {

Просмотреть файл

@ -0,0 +1,187 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
/* 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 "SharedSurfaceAndroidHardwareBuffer.h"
#include "GLBlitHelper.h"
#include "GLContextEGL.h"
#include "GLContextProvider.h"
#include "GLLibraryEGL.h"
#include "GLReadTexImageHelper.h"
#include "MozFramebuffer.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
#include "mozilla/layers/AndroidHardwareBuffer.h"
#include "ScopedGLHelpers.h"
#include "SharedSurface.h"
namespace mozilla {
namespace gl {
/*static*/
UniquePtr<SharedSurface_AndroidHardwareBuffer>
SharedSurface_AndroidHardwareBuffer::Create(const SharedSurfaceDesc& desc) {
const auto& gle = GLContextEGL::Cast(desc.gl);
const auto& egl = gle->mEgl;
RefPtr<layers::AndroidHardwareBuffer> buffer =
layers::AndroidHardwareBuffer::Create(desc.size,
gfx::SurfaceFormat::R8G8B8A8);
if (!buffer) {
return nullptr;
}
const EGLint attrs[] = {
LOCAL_EGL_IMAGE_PRESERVED,
LOCAL_EGL_TRUE,
LOCAL_EGL_NONE,
LOCAL_EGL_NONE,
};
EGLClientBuffer clientBuffer =
egl->mLib->fGetNativeClientBufferANDROID(buffer->GetNativeBuffer());
const auto image = egl->fCreateImage(
EGL_NO_CONTEXT, LOCAL_EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
if (!image) {
return nullptr;
}
auto tex = MakeUnique<Texture>(*desc.gl);
{
ScopedBindTexture texture(gle, tex->name, LOCAL_GL_TEXTURE_2D);
gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER,
LOCAL_GL_LINEAR);
gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER,
LOCAL_GL_LINEAR);
gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S,
LOCAL_GL_CLAMP_TO_EDGE);
gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T,
LOCAL_GL_CLAMP_TO_EDGE);
gle->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image);
egl->fDestroyImage(image);
}
const GLenum target = LOCAL_GL_TEXTURE_2D;
auto fb = MozFramebuffer::CreateForBacking(desc.gl, desc.size, 0, false,
target, tex->name);
if (!fb) {
return nullptr;
}
return AsUnique(new SharedSurface_AndroidHardwareBuffer(
desc, std::move(fb), std::move(tex), buffer));
}
SharedSurface_AndroidHardwareBuffer::SharedSurface_AndroidHardwareBuffer(
const SharedSurfaceDesc& desc, UniquePtr<MozFramebuffer> fb,
UniquePtr<Texture> tex, RefPtr<layers::AndroidHardwareBuffer> buffer)
: SharedSurface(desc, std::move(fb)),
mTex(std::move(tex)),
mAndroidHardwareBuffer(buffer) {}
SharedSurface_AndroidHardwareBuffer::~SharedSurface_AndroidHardwareBuffer() {
const auto& gl = mDesc.gl;
if (!gl || !gl->MakeCurrent()) {
return;
}
const auto& gle = GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
if (mSync) {
egl->fDestroySync(mSync);
mSync = 0;
}
}
void SharedSurface_AndroidHardwareBuffer::ProducerReleaseImpl() {
const auto& gl = mDesc.gl;
if (!gl || !gl->MakeCurrent()) {
return;
}
const auto& gle = GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
if (mSync) {
MOZ_ALWAYS_TRUE(egl->fDestroySync(mSync));
mSync = 0;
}
mSync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
MOZ_ASSERT(mSync);
int rawFd = egl->fDupNativeFenceFDANDROID(mSync);
if (rawFd >= 0) {
auto fenceFd = ipc::FileDescriptor(UniqueFileHandle(rawFd));
mAndroidHardwareBuffer->SetAcquireFence(std::move(fenceFd));
}
gl->fFlush();
}
Maybe<layers::SurfaceDescriptor>
SharedSurface_AndroidHardwareBuffer::ToSurfaceDescriptor() {
// XXX File descriptor usage is not efficient. This function is called for
// each WebGL rendering. See Bug 1663381.
int fd[2] = {};
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd) != 0) {
return Nothing();
}
UniqueFileHandle readerFd(fd[0]);
UniqueFileHandle writerFd(fd[1]);
// Send the AHardwareBuffer to an AF_UNIX socket. It does not acquire or
// retain a reference to the buffer object. The caller is therefore
// responsible for ensuring that the buffer remains alive through the lifetime
// of this file descriptor.
int ret = mAndroidHardwareBuffer->SendHandleToUnixSocket(writerFd.get());
if (ret < 0) {
return Nothing();
}
return Some(layers::SurfaceDescriptorAndroidHardwareBuffer(
ipc::FileDescriptor(readerFd.release()), mAndroidHardwareBuffer->mId,
mAndroidHardwareBuffer->mSize, mAndroidHardwareBuffer->mFormat));
}
void SharedSurface_AndroidHardwareBuffer::WaitForBufferOwnership() {
mAndroidHardwareBuffer->WaitForBufferOwnership();
ipc::FileDescriptor fenceFd =
mAndroidHardwareBuffer->GetAndResetReleaseFence();
if (!fenceFd.IsValid()) {
return;
}
const auto& gle = GLContextEGL::Cast(mDesc.gl);
const auto& egl = gle->mEgl;
auto rawFD = fenceFd.TakePlatformHandle();
const EGLint attribs[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID, rawFD.get(),
LOCAL_EGL_NONE};
EGLSync sync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
if (!sync) {
gfxCriticalNote << "Failed to create EGLSync from fd";
return;
}
egl->fClientWaitSync(sync, 0, LOCAL_EGL_FOREVER);
egl->fDestroySync(sync);
}
/*static*/
UniquePtr<SurfaceFactory_AndroidHardwareBuffer>
SurfaceFactory_AndroidHardwareBuffer::Create(GLContext& gl) {
const auto partialDesc = PartialSharedSurfaceDesc{
&gl,
SharedSurfaceType::AndroidHardwareBuffer,
layers::TextureType::AndroidHardwareBuffer,
true,
};
return AsUnique(new SurfaceFactory_AndroidHardwareBuffer(partialDesc));
}
} // namespace gl
} /* namespace mozilla */

Просмотреть файл

@ -0,0 +1,70 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
/* 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 SHARED_SURFACE_ANDROID_HARDWARE_BUFFER_H_
#define SHARED_SURFACE_ANDROID_HARDWARE_BUFFER_H_
#include "mozilla/Attributes.h"
#include "mozilla/Mutex.h"
#include "CompositorTypes.h"
#include "SharedSurface.h"
namespace mozilla {
namespace layers {
class AndroidHardwareBuffer;
} // namespace layers
namespace gl {
class SharedSurface_AndroidHardwareBuffer final : public SharedSurface {
public:
const UniquePtr<Texture> mTex;
const RefPtr<layers::AndroidHardwareBuffer> mAndroidHardwareBuffer;
EGLSync mSync = 0;
static UniquePtr<SharedSurface_AndroidHardwareBuffer> Create(
const SharedSurfaceDesc&);
protected:
SharedSurface_AndroidHardwareBuffer(
const SharedSurfaceDesc&, UniquePtr<MozFramebuffer>, UniquePtr<Texture>,
RefPtr<layers::AndroidHardwareBuffer> buffer);
public:
virtual ~SharedSurface_AndroidHardwareBuffer();
void LockProdImpl() override {}
void UnlockProdImpl() override {}
void ProducerAcquireImpl() override {}
void ProducerReleaseImpl() override;
Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
void WaitForBufferOwnership() override;
};
class SurfaceFactory_AndroidHardwareBuffer final : public SurfaceFactory {
public:
static UniquePtr<SurfaceFactory_AndroidHardwareBuffer> Create(GLContext&);
private:
explicit SurfaceFactory_AndroidHardwareBuffer(
const PartialSharedSurfaceDesc& desc)
: SurfaceFactory(desc) {}
public:
virtual UniquePtr<SharedSurface> CreateSharedImpl(
const SharedSurfaceDesc& desc) override {
return SharedSurface_AndroidHardwareBuffer::Create(desc);
}
};
} // namespace gl
} /* namespace mozilla */
#endif /* SHARED_SURFACE_ANDROID_HARDWARE_BUFFER_H_ */

Просмотреть файл

@ -25,6 +25,7 @@ enum class SharedSurfaceType : uint8_t {
GLXDrawable,
SharedGLTexture,
AndroidSurfaceTexture,
AndroidHardwareBuffer,
EGLSurfaceDMABUF,
};

Просмотреть файл

@ -71,6 +71,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
EXPORTS += [
'AndroidNativeWindow.h',
'SharedSurfaceAndroidHardwareBuffer.h',
]
UNIFIED_SOURCES += [
'SharedSurfaceAndroidHardwareBuffer.cpp',
]
if gl_provider == 'CGL':

Просмотреть файл

@ -8,6 +8,7 @@
#include "BuildConstants.h"
#include "ipc/KnowsCompositor.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/StaticPrefs_webgl.h"
#include "nsICanvasRenderingContextInternal.h"
#include "PersistentBufferProvider.h"
@ -116,6 +117,9 @@ TextureType TexTypeForWebgl(KnowsCompositor* const knowsCompositor) {
return TextureType::X11;
}
if (kIsAndroid) {
if (gfx::gfxVars::UseAHardwareBufferSharedSurface()) {
return TextureType::AndroidHardwareBuffer;
}
if (StaticPrefs::webgl_enable_surface_texture()) {
return TextureType::AndroidNativeWindow;
}

Просмотреть файл

@ -16,6 +16,7 @@
#include "mozilla/layers/AndroidHardwareBuffer.h"
#include "mozilla/Preferences.h"
#include "mozilla/StaticPrefs_gfx.h"
#include "mozilla/StaticPrefs_webgl.h"
#include "gfx2DGlue.h"
#include "gfxFT2FontList.h"
@ -113,8 +114,12 @@ void gfxAndroidPlatform::InitAcceleration() {
if (StaticPrefs::gfx_use_ahardwarebuffer_content_AtStartup()) {
gfxVars::SetUseAHardwareBufferContent(true);
}
if (StaticPrefs::webgl_enable_ahardwarebuffer()) {
gfxVars::SetUseAHardwareBufferSharedSurface(true);
}
}
if (gfx::gfxVars::UseAHardwareBufferContent()) {
if (gfx::gfxVars::UseAHardwareBufferContent() ||
gfxVars::UseAHardwareBufferSharedSurface()) {
layers::AndroidHardwareBufferApi::Init();
layers::AndroidHardwareBufferManager::Init();
}

Просмотреть файл

@ -9802,6 +9802,11 @@
value: false
mirror: always
- name: webgl.enable-ahardwarebuffer
type: RelaxedAtomicBool
value: false
mirror: always
- name: webgl.enable-webgl2
type: RelaxedAtomicBool
value: true