Bug 1649354 - Add android Fence handling to Compositor r=jnicol

AHardwareBuffer requests to handle android fences. There are 2 type of fences, release fence and acquire fence. Some ideas were borrowed from b2g's FenceHandle implementation.

The release fence is a fence that is used for waiting until usage/composite of AHardwareBuffer is ended. It needs to be delivered from host side to client side. It is delivered via ImageBridge, since some TextureClientd str recycled without recycle callback.

The acquire fence is a fence that is used for waiting until rendering to its AHardwareBuffer is completed. It is delivered from client side to host side.

Differential Revision: https://phabricator.services.mozilla.com/D87298
This commit is contained in:
sotaro
2020-08-24 09:34:51 +00:00
parent 0a7b9948c9
commit 6c0bd3b522
22 changed files with 795 additions and 47 deletions

View File

@@ -727,8 +727,8 @@ AndroidHardwareBufferTextureHost::Create(
TextureFlags aFlags, const SurfaceDescriptorAndroidHardwareBuffer& aDesc) {
RefPtr<AndroidHardwareBuffer> buffer =
AndroidHardwareBuffer::FromFileDescriptor(
const_cast<ipc::FileDescriptor&>(aDesc.handle()), aDesc.size(),
aDesc.format());
const_cast<ipc::FileDescriptor&>(aDesc.handle()), aDesc.bufferId(),
aDesc.size(), aDesc.format());
if (!buffer) {
return nullptr;
}
@@ -852,6 +852,29 @@ gl::GLContext* AndroidHardwareBufferTextureHost::gl() const {
}
bool AndroidHardwareBufferTextureHost::Lock() {
if (!mAndroidHardwareBuffer) {
return false;
}
auto fenceFd = mAndroidHardwareBuffer->GetAndResetAcquireFence();
if (fenceFd.IsValid()) {
const auto& gle = gl::GLContextEGL::Cast(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) {
egl->fClientWaitSync(sync, 0, LOCAL_EGL_FOREVER);
egl->fDestroySync(sync);
} else {
gfxCriticalNote << "Failed to create EGLSync from acquire fence fd";
}
}
return mTextureSource && mTextureSource->IsValid();
}
@@ -896,6 +919,30 @@ void AndroidHardwareBufferTextureHost::DeallocateDeviceData() {
DestroyEGLImage();
}
void AndroidHardwareBufferTextureHost::SetAcquireFence(
mozilla::ipc::FileDescriptor&& aFenceFd) {
if (!mAndroidHardwareBuffer) {
return;
}
mAndroidHardwareBuffer->SetAcquireFence(std::move(aFenceFd));
}
void AndroidHardwareBufferTextureHost::SetReleaseFence(
mozilla::ipc::FileDescriptor&& aFenceFd) {
if (!mAndroidHardwareBuffer) {
return;
}
mAndroidHardwareBuffer->SetReleaseFence(std::move(aFenceFd));
}
mozilla::ipc::FileDescriptor
AndroidHardwareBufferTextureHost::GetAndResetReleaseFence() {
if (!mAndroidHardwareBuffer) {
return mozilla::ipc::FileDescriptor();
}
return mAndroidHardwareBuffer->GetAndResetReleaseFence();
}
void AndroidHardwareBufferTextureHost::CreateRenderTexture(
const wr::ExternalImageId& aExternalImageId) {
RefPtr<wr::RenderTextureHost> texture =
@@ -1065,6 +1112,7 @@ bool EGLImageTextureHost::Lock() {
if (mSync) {
MOZ_ASSERT(egl->IsExtensionSupported(EGLExtension::KHR_fence_sync));
// XXX eglWaitSyncKHR() is better api. Bug 1660434 is going to fix it.
status = egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER);
}