mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
Bug 1614568 [Wayland] Implement fence sync to dmabuf surfaces for WebGL rendering, r=jgilbert
Use ANDROID_native_fence_sync to synchronize WebGL renderin. It's similar to KHR_fence_sync but it the fence can be exported to file descriptor and shared among processes so we can create the fence by WebGL producer and then wait in renderer. Use glFinish() as a fallback when ANDROID_native_fence_sync is not available. Differential Revision: https://phabricator.services.mozilla.com/D62712 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
fd033029ab
commit
905e0e97e8
@ -45,11 +45,7 @@ SharedSurface_DMABUF::~SharedSurface_DMABUF() {
|
||||
mSurface->ReleaseTextures();
|
||||
}
|
||||
|
||||
void SharedSurface_DMABUF::ProducerReleaseImpl() {
|
||||
mGL->MakeCurrent();
|
||||
// We don't have a better sync mechanism here so use glFinish() at least.
|
||||
mGL->fFinish();
|
||||
}
|
||||
void SharedSurface_DMABUF::ProducerReleaseImpl() { mSurface->FenceSet(); }
|
||||
|
||||
bool SharedSurface_DMABUF::ToSurfaceDescriptor(
|
||||
layers::SurfaceDescriptor* const out_descriptor) {
|
||||
|
@ -70,6 +70,7 @@ struct SurfaceDescriptorDMABuf {
|
||||
uint32_t[] strides;
|
||||
uint32_t[] offsets;
|
||||
YUVColorSpace yUVColorSpace;
|
||||
FileDescriptor fence;
|
||||
};
|
||||
|
||||
struct SurfaceTextureDescriptor {
|
||||
|
@ -59,6 +59,8 @@ bool WaylandDMABUFTextureHostOGL::Lock() {
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
|
||||
mSurface->FenceWait();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -57,17 +57,6 @@ using namespace mozilla::layers;
|
||||
# define VA_FOURCC_NV12 0x3231564E
|
||||
#endif
|
||||
|
||||
WaylandDMABufSurface::WaylandDMABufSurface(SurfaceType aSurfaceType)
|
||||
: mSurfaceType(aSurfaceType),
|
||||
mBufferModifier(0),
|
||||
mBufferPlaneCount(0),
|
||||
mStrides(),
|
||||
mOffsets() {
|
||||
for (int i = 0; i < DMABUF_BUFFER_PLANES; i++) {
|
||||
mDmabufFds[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<WaylandDMABufSurface>
|
||||
WaylandDMABufSurface::CreateDMABufSurface(
|
||||
const mozilla::layers::SurfaceDescriptor& aDesc) {
|
||||
@ -91,6 +80,69 @@ WaylandDMABufSurface::CreateDMABufSurface(
|
||||
return surf.forget();
|
||||
}
|
||||
|
||||
void WaylandDMABufSurface::FenceDelete() {
|
||||
auto* egl = gl::GLLibraryEGL::Get();
|
||||
|
||||
if (mSync) {
|
||||
// We can't call this unless we have the ext, but we will always have
|
||||
// the ext if we have something to destroy.
|
||||
egl->fDestroySync(egl->Display(), mSync);
|
||||
mSync = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandDMABufSurface::FenceSet() {
|
||||
if (!mGL || !mGL->MakeCurrent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* egl = gl::GLLibraryEGL::Get();
|
||||
if (egl->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync) &&
|
||||
egl->IsExtensionSupported(GLLibraryEGL::ANDROID_native_fence_sync)) {
|
||||
if (mSync) {
|
||||
MOZ_ALWAYS_TRUE(egl->fDestroySync(egl->Display(), mSync));
|
||||
mSync = nullptr;
|
||||
}
|
||||
|
||||
mSync = egl->fCreateSync(egl->Display(),
|
||||
LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
|
||||
if (mSync) {
|
||||
mGL->fFlush();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ANDROID_native_fence_sync may not be supported so call glFinish()
|
||||
// as a slow path.
|
||||
mGL->fFinish();
|
||||
}
|
||||
|
||||
void WaylandDMABufSurface::FenceWait() {
|
||||
auto* egl = gl::GLLibraryEGL::Get();
|
||||
|
||||
// Wait on the fence, because presumably we're going to want to read this
|
||||
// surface
|
||||
if (mSync) {
|
||||
egl->fClientWaitSync(egl->Display(), mSync, 0, LOCAL_EGL_FOREVER);
|
||||
}
|
||||
}
|
||||
|
||||
bool WaylandDMABufSurface::FenceCreate(int aFd) {
|
||||
MOZ_ASSERT(aFd > 0);
|
||||
|
||||
auto* egl = gl::GLLibraryEGL::Get();
|
||||
const EGLint attribs[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID, aFd,
|
||||
LOCAL_EGL_NONE};
|
||||
mSync = egl->fCreateSync(egl->Display(), LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID,
|
||||
attribs);
|
||||
if (!mSync) {
|
||||
MOZ_ASSERT(false, "Failed to create GLFence!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaylandDMABufSurfaceRGBA::SetWLBuffer(struct wl_buffer* aWLBuffer) {
|
||||
MOZ_ASSERT(mWLBuffer == nullptr, "WLBuffer already assigned!");
|
||||
mWLBuffer = aWLBuffer;
|
||||
@ -275,6 +327,13 @@ void WaylandDMABufSurfaceRGBA::ImportSurfaceDescriptor(
|
||||
mStrides[i] = desc.strides()[i];
|
||||
mOffsets[i] = desc.offsets()[i];
|
||||
}
|
||||
|
||||
int fd = desc.fence().ClonePlatformHandle().release();
|
||||
if (fd > 0) {
|
||||
if (!FenceCreate(fd)) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WaylandDMABufSurfaceRGBA::Create(const SurfaceDescriptor& aDesc) {
|
||||
@ -314,6 +373,7 @@ bool WaylandDMABufSurfaceRGBA::Serialize(
|
||||
AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> strides;
|
||||
AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> offsets;
|
||||
AutoTArray<uintptr_t, DMABUF_BUFFER_PLANES> images;
|
||||
ipc::FileDescriptor fenceFD;
|
||||
|
||||
width.AppendElement(mWidth);
|
||||
height.AppendElement(mHeight);
|
||||
@ -324,9 +384,15 @@ bool WaylandDMABufSurfaceRGBA::Serialize(
|
||||
offsets.AppendElement(mOffsets[i]);
|
||||
}
|
||||
|
||||
if (mSync) {
|
||||
auto* egl = gl::GLLibraryEGL::Get();
|
||||
fenceFD = ipc::FileDescriptor(
|
||||
egl->fDupNativeFenceFDANDROID(egl->Display(), mSync));
|
||||
}
|
||||
|
||||
aOutDescriptor = SurfaceDescriptorDMABuf(
|
||||
mSurfaceType, mBufferModifier, mGbmBufferFlags, fds, width, height,
|
||||
format, strides, offsets, GetYUVColorSpace());
|
||||
format, strides, offsets, GetYUVColorSpace(), fenceFD);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -420,6 +486,8 @@ bool WaylandDMABufSurfaceRGBA::CreateTexture(GLContext* aGLContext,
|
||||
}
|
||||
|
||||
void WaylandDMABufSurfaceRGBA::ReleaseTextures() {
|
||||
FenceDelete();
|
||||
|
||||
if (mTexture && mGL->MakeCurrent()) {
|
||||
mGL->fDeleteTextures(1, &mTexture);
|
||||
mTexture = 0;
|
||||
@ -639,6 +707,13 @@ void WaylandDMABufSurfaceNV12::ImportSurfaceDescriptor(
|
||||
mStrides[i] = aDesc.strides()[i];
|
||||
mOffsets[i] = aDesc.offsets()[i];
|
||||
}
|
||||
|
||||
int fd = aDesc.fence().ClonePlatformHandle().release();
|
||||
if (fd > 0) {
|
||||
if (!FenceCreate(fd)) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WaylandDMABufSurfaceNV12::Serialize(
|
||||
@ -649,6 +724,7 @@ bool WaylandDMABufSurfaceNV12::Serialize(
|
||||
AutoTArray<ipc::FileDescriptor, DMABUF_BUFFER_PLANES> fds;
|
||||
AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> strides;
|
||||
AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> offsets;
|
||||
ipc::FileDescriptor fenceFD;
|
||||
|
||||
for (int i = 0; i < mBufferPlaneCount; i++) {
|
||||
width.AppendElement(mWidth[i]);
|
||||
@ -659,10 +735,15 @@ bool WaylandDMABufSurfaceNV12::Serialize(
|
||||
offsets.AppendElement(mOffsets[i]);
|
||||
}
|
||||
|
||||
aOutDescriptor =
|
||||
SurfaceDescriptorDMABuf(mSurfaceType, mBufferModifier, 0, fds, width,
|
||||
height, format, strides, offsets, mColorSpace);
|
||||
if (mSync) {
|
||||
auto* egl = gl::GLLibraryEGL::Get();
|
||||
fenceFD = ipc::FileDescriptor(
|
||||
egl->fDupNativeFenceFDANDROID(egl->Display(), mSync));
|
||||
}
|
||||
|
||||
aOutDescriptor = SurfaceDescriptorDMABuf(mSurfaceType, mBufferModifier, 0,
|
||||
fds, width, height, format, strides,
|
||||
offsets, mColorSpace, fenceFD);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -743,6 +824,8 @@ bool WaylandDMABufSurfaceNV12::CreateTexture(GLContext* aGLContext,
|
||||
}
|
||||
|
||||
void WaylandDMABufSurfaceNV12::ReleaseTextures() {
|
||||
FenceDelete();
|
||||
|
||||
if (mGL->MakeCurrent()) {
|
||||
for (int i = 0; i < mBufferPlaneCount; i++) {
|
||||
if (mTexture[i]) {
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/widget/nsWaylandDisplay.h"
|
||||
|
||||
typedef void* EGLImageKHR;
|
||||
typedef void* EGLSyncKHR;
|
||||
|
||||
#define DMABUF_BUFFER_PLANES 4
|
||||
|
||||
@ -77,13 +78,28 @@ class WaylandDMABufSurface {
|
||||
};
|
||||
virtual bool IsFullRange() { return false; };
|
||||
|
||||
WaylandDMABufSurface(SurfaceType aSurfaceType);
|
||||
void FenceSet();
|
||||
void FenceWait();
|
||||
void FenceDelete();
|
||||
|
||||
WaylandDMABufSurface(SurfaceType aSurfaceType)
|
||||
: mSurfaceType(aSurfaceType),
|
||||
mBufferModifier(0),
|
||||
mBufferPlaneCount(0),
|
||||
mStrides(),
|
||||
mOffsets(),
|
||||
mSync(0) {
|
||||
for (auto& slot : mDmabufFds) {
|
||||
slot = -1;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool Create(const mozilla::layers::SurfaceDescriptor& aDesc) = 0;
|
||||
virtual void ReleaseSurface() = 0;
|
||||
bool FenceCreate(int aFd);
|
||||
|
||||
virtual ~WaylandDMABufSurface(){};
|
||||
virtual ~WaylandDMABufSurface() { FenceDelete(); };
|
||||
|
||||
SurfaceType mSurfaceType;
|
||||
uint64_t mBufferModifier;
|
||||
@ -93,6 +109,7 @@ class WaylandDMABufSurface {
|
||||
uint32_t mStrides[DMABUF_BUFFER_PLANES];
|
||||
uint32_t mOffsets[DMABUF_BUFFER_PLANES];
|
||||
|
||||
EGLSyncKHR mSync;
|
||||
RefPtr<mozilla::gl::GLContext> mGL;
|
||||
};
|
||||
|
||||
@ -172,7 +189,6 @@ class WaylandDMABufSurfaceRGBA : public WaylandDMABufSurface {
|
||||
struct gbm_bo* mGbmBufferObject;
|
||||
uint32_t mGbmBufferFlags;
|
||||
|
||||
RefPtr<mozilla::gl::GLContext> mGL;
|
||||
EGLImageKHR mEGLImage;
|
||||
GLuint mTexture;
|
||||
|
||||
@ -227,7 +243,6 @@ class WaylandDMABufSurfaceNV12 : public WaylandDMABufSurface {
|
||||
EGLImageKHR mEGLImage[DMABUF_BUFFER_PLANES];
|
||||
GLuint mTexture[DMABUF_BUFFER_PLANES];
|
||||
mozilla::gfx::YUVColorSpace mColorSpace;
|
||||
RefPtr<mozilla::gl::GLContext> mGL;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user