diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh --- a/gfx/layers/ipc/LayersSurfaces.ipdlh +++ b/gfx/layers/ipc/LayersSurfaces.ipdlh @@ -71,6 +71,8 @@ uint32_t[] offsets; YUVColorSpace yUVColorSpace; FileDescriptor[] fence; + uint32_t uid; + FileDescriptor[] refCount; }; struct SurfaceTextureDescriptor { diff --git a/widget/gtk/WaylandDMABufSurface.h b/widget/gtk/WaylandDMABufSurface.h --- a/widget/gtk/WaylandDMABufSurface.h +++ b/widget/gtk/WaylandDMABufSurface.h @@ -40,6 +40,23 @@ class WaylandDMABufSurfaceRGBA; +class DMABufRefcount { + public: + DMABufRefcount(); + DMABufRefcount(int aFd); + + bool Created() { return mFd > 0; }; + int GetFD() { return mFd; } + uint64_t GetRefcount(); + void RefAdd(); + void Release(); + + ~DMABufRefcount(); + + private: + int mFd; +}; + class WaylandDMABufSurface { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WaylandDMABufSurface) @@ -82,6 +99,14 @@ void FenceWait(); void FenceDelete(); + void SetUID(uint32_t aUID) { mUID = aUID; }; + uint32_t GetUID() { return mUID; }; + + void GlobalRefCountCreate(); + bool IsGlobalRefSet(); + void GlobalRefAdd(); + void GlobalRefRelease(); + WaylandDMABufSurface(SurfaceType aSurfaceType); protected: @@ -89,6 +114,8 @@ virtual void ReleaseSurface() = 0; bool FenceCreate(int aFd); + bool GlobalRefCountImport(int aFd); + virtual ~WaylandDMABufSurface() { FenceDelete(); }; SurfaceType mSurfaceType; @@ -102,6 +129,9 @@ EGLSyncKHR mSync; RefPtr mGL; + + mozilla::UniquePtr mGlobalRefCount; + uint32_t mUID; }; class WaylandDMABufSurfaceRGBA : public WaylandDMABufSurface { diff --git a/widget/gtk/WaylandDMABufSurface.cpp b/widget/gtk/WaylandDMABufSurface.cpp --- a/widget/gtk/WaylandDMABufSurface.cpp +++ b/widget/gtk/WaylandDMABufSurface.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "mozilla/widget/gbm.h" #include "mozilla/widget/va_drmcommon.h" @@ -57,6 +59,73 @@ # define VA_FOURCC_NV12 0x3231564E #endif +void DMABufRefcount::RefAdd() { + uint64_t counter; + read(mFd, &counter, sizeof(counter)); + counter++; + write(mFd, &counter, sizeof(counter)); +} + +void DMABufRefcount::Release() { + uint64_t counter; + read(mFd, &counter, sizeof(counter)); + counter--; + write(mFd, &counter, sizeof(counter)); +} + +uint64_t DMABufRefcount::GetRefcount() { + uint64_t counter; + read(mFd, &counter, sizeof(counter)); + write(mFd, &counter, sizeof(counter)); + return counter; +} + +DMABufRefcount::DMABufRefcount() + : mFd(eventfd(1, EFD_CLOEXEC | EFD_NONBLOCK)) {} + +DMABufRefcount::DMABufRefcount(int aFd) : mFd(aFd) {} + +DMABufRefcount::~DMABufRefcount() { + if (mFd > 0) { + close(mFd); + } +} + +void WaylandDMABufSurface::GlobalRefCountCreate() { + MOZ_ASSERT(!mGlobalRefCount); + mGlobalRefCount = MakeUnique(); + if (!mGlobalRefCount->Created()) { + NS_WARNING("Failed to create dmabuf global ref count!"); + mGlobalRefCount = nullptr; + } +} + +bool WaylandDMABufSurface::GlobalRefCountImport(int aFd) { + MOZ_ASSERT(!mGlobalRefCount); + mGlobalRefCount = MakeUnique(aFd); + if (!mGlobalRefCount->Created()) { + NS_WARNING("Failed to import dmabuf global ref count!"); + mGlobalRefCount = nullptr; + return false; + } + return true; +} + +bool WaylandDMABufSurface::IsGlobalRefSet() { + MOZ_ASSERT(mGlobalRefCount); + return mGlobalRefCount->GetRefcount() > 1; +} + +void WaylandDMABufSurface::GlobalRefAdd() { + MOZ_ASSERT(mGlobalRefCount); + mGlobalRefCount->RefAdd(); +} + +void WaylandDMABufSurface::GlobalRefRelease() { + MOZ_ASSERT(mGlobalRefCount); + mGlobalRefCount->Release(); +} + WaylandDMABufSurface::WaylandDMABufSurface(SurfaceType aSurfaceType) : mSurfaceType(aSurfaceType), mBufferModifier(DRM_FORMAT_MOD_INVALID), @@ -64,7 +133,9 @@ mDrmFormats(), mStrides(), mOffsets(), - mSync(0) { + mSync(0), + mGlobalRefCount(nullptr), + mUID(0) { for (auto& slot : mDmabufFds) { slot = -1; } @@ -316,6 +387,7 @@ mBufferPlaneCount = desc.fds().Length(); mGbmBufferFlags = desc.flags(); MOZ_RELEASE_ASSERT(mBufferPlaneCount <= DMABUF_BUFFER_PLANES); + mUID = desc.uid(); for (int i = 0; i < mBufferPlaneCount; i++) { mDmabufFds[i] = desc.fds()[i].ClonePlatformHandle().release(); @@ -329,6 +401,13 @@ close(fd); } } + + if (desc.refCount().Length() > 0) { + int fd = desc.refCount()[0].ClonePlatformHandle().release(); + if (!GlobalRefCountImport(fd)) { + close(fd); + } + } } bool WaylandDMABufSurfaceRGBA::Create(const SurfaceDescriptor& aDesc) { @@ -346,6 +425,7 @@ AutoTArray offsets; AutoTArray images; AutoTArray fenceFDs; + AutoTArray refCountFDs; width.AppendElement(mWidth); height.AppendElement(mHeight); @@ -362,9 +442,14 @@ egl->fDupNativeFenceFDANDROID(egl->Display(), mSync))); } - aOutDescriptor = SurfaceDescriptorDMABuf( - mSurfaceType, mBufferModifier, mGbmBufferFlags, fds, width, height, - format, strides, offsets, GetYUVColorSpace(), fenceFDs); + if (mGlobalRefCount) { + refCountFDs.AppendElement(ipc::FileDescriptor(mGlobalRefCount->GetFD())); + } + + aOutDescriptor = + SurfaceDescriptorDMABuf(mSurfaceType, mBufferModifier, mGbmBufferFlags, + fds, width, height, format, strides, offsets, + GetYUVColorSpace(), fenceFDs, mUID, refCountFDs); return true; } @@ -693,6 +778,7 @@ mBufferPlaneCount = aDesc.fds().Length(); mBufferModifier = aDesc.modifier(); mColorSpace = aDesc.yUVColorSpace(); + mUID = aDesc.uid(); MOZ_RELEASE_ASSERT(mBufferPlaneCount <= DMABUF_BUFFER_PLANES); for (int i = 0; i < mBufferPlaneCount; i++) { @@ -710,6 +796,13 @@ close(fd); } } + + if (aDesc.refCount().Length() > 0) { + int fd = aDesc.refCount()[0].ClonePlatformHandle().release(); + if (!GlobalRefCountImport(fd)) { + close(fd); + } + } } bool WaylandDMABufSurfaceNV12::Serialize( @@ -721,6 +814,7 @@ AutoTArray strides; AutoTArray offsets; AutoTArray fenceFDs; + AutoTArray refCountFDs; for (int i = 0; i < mBufferPlaneCount; i++) { width.AppendElement(mWidth[i]); @@ -737,9 +831,13 @@ egl->fDupNativeFenceFDANDROID(egl->Display(), mSync))); } + if (mGlobalRefCount) { + refCountFDs.AppendElement(ipc::FileDescriptor(mGlobalRefCount->GetFD())); + } + aOutDescriptor = SurfaceDescriptorDMABuf( mSurfaceType, mBufferModifier, 0, fds, width, height, format, strides, - offsets, GetYUVColorSpace(), fenceFDs); + offsets, GetYUVColorSpace(), fenceFDs, mUID, refCountFDs); return true; } diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h --- a/widget/gtk/WindowSurfaceWayland.h +++ b/widget/gtk/WindowSurfaceWayland.h @@ -36,8 +36,6 @@ int aImageDataSize); private: - int CreateTemporaryFile(int aSize); - wl_shm_pool* mShmPool; int mShmPoolFd; int mAllocatedSize; diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp --- a/widget/gtk/WindowSurfaceWayland.cpp +++ b/widget/gtk/WindowSurfaceWayland.cpp @@ -206,42 +206,25 @@ return mWindowSurfaceWayland->GetWaylandDisplay(); } -int WaylandShmPool::CreateTemporaryFile(int aSize) { - const char* tmppath = getenv("XDG_RUNTIME_DIR"); - MOZ_RELEASE_ASSERT(tmppath, "Missing XDG_RUNTIME_DIR env variable."); - - nsPrintfCString tmpname("%s/mozilla-shared-XXXXXX", tmppath); - - char* filename; - int fd = -1; - int ret = 0; - - if (tmpname.GetMutableData(&filename)) { - fd = mkstemp(filename); - if (fd >= 0) { - int flags = fcntl(fd, F_GETFD); - if (flags >= 0) { - fcntl(fd, F_SETFD, flags | FD_CLOEXEC); - } - } - } - +static int WaylandAllocateShmMemory(int aSize) { + static int counter = 0; + nsPrintfCString shmName("/wayland.mozilla.ipc.%d", counter++); + int fd = shm_open(shmName.get(), O_CREAT | O_RDWR | O_EXCL, 0600); if (fd >= 0) { - unlink(tmpname.get()); + shm_unlink(shmName.get()); } else { - printf_stderr("Unable to create mapping file %s\n", filename); + printf_stderr("Unable to SHM memory segment\n"); MOZ_CRASH(); } + int ret = 0; #ifdef HAVE_POSIX_FALLOCATE do { ret = posix_fallocate(fd, 0, aSize); } while (ret == EINTR); if (ret != 0) { close(fd); - MOZ_CRASH_UNSAFE_PRINTF( - "posix_fallocate() fails on %s size %d error code %d\n", filename, - aSize, ret); + MOZ_CRASH("posix_fallocate() fails to allocate shm memory"); } #else do { @@ -249,8 +232,7 @@ } while (ret < 0 && errno == EINTR); if (ret < 0) { close(fd); - MOZ_CRASH_UNSAFE_PRINTF("ftruncate() fails on %s size %d error code %d\n", - filename, aSize, ret); + MOZ_CRASH("ftruncate() fails to allocate shm memory"); } #endif @@ -259,7 +241,7 @@ WaylandShmPool::WaylandShmPool(nsWaylandDisplay* aWaylandDisplay, int aSize) : mAllocatedSize(aSize) { - mShmPoolFd = CreateTemporaryFile(mAllocatedSize); + mShmPoolFd = WaylandAllocateShmMemory(mAllocatedSize); mImageData = mmap(nullptr, mAllocatedSize, PROT_READ | PROT_WRITE, MAP_SHARED, mShmPoolFd, 0); MOZ_RELEASE_ASSERT(mImageData != MAP_FAILED,