зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
cc286890ec
Коммит
872ccfe115
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче