diff --git a/widget/gtk/DMABufSurface.h b/widget/gtk/DMABufSurface.h --- a/widget/gtk/DMABufSurface.h +++ b/widget/gtk/DMABufSurface.h @@ -173,13 +173,13 @@ SurfaceType mSurfaceType; uint64_t mBufferModifiers[DMABUF_BUFFER_PLANES]; int mBufferPlaneCount; int mDmabufFds[DMABUF_BUFFER_PLANES]; - uint32_t mDrmFormats[DMABUF_BUFFER_PLANES]; - uint32_t mStrides[DMABUF_BUFFER_PLANES]; - uint32_t mOffsets[DMABUF_BUFFER_PLANES]; + int32_t mDrmFormats[DMABUF_BUFFER_PLANES]; + int32_t mStrides[DMABUF_BUFFER_PLANES]; + int32_t mOffsets[DMABUF_BUFFER_PLANES]; struct gbm_bo* mGbmBufferObject[DMABUF_BUFFER_PLANES]; void* mMappedRegion[DMABUF_BUFFER_PLANES]; void* mMappedRegionData[DMABUF_BUFFER_PLANES]; uint32_t mMappedRegionStride[DMABUF_BUFFER_PLANES]; @@ -198,10 +198,14 @@ class DMABufSurfaceRGBA : public DMABufSurface { public: static already_AddRefed CreateDMABufSurface( int aWidth, int aHeight, int aDMABufSurfaceFlags); + static already_AddRefed CreateDMABufSurface( + mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage, + int aWidth, int aHeight); + bool Serialize(mozilla::layers::SurfaceDescriptor& aOutDescriptor); DMABufSurfaceRGBA* GetAsDMABufSurfaceRGBA() { return this; } void Clear(); @@ -247,10 +251,12 @@ private: ~DMABufSurfaceRGBA(); bool Create(int aWidth, int aHeight, int aDMABufSurfaceFlags); bool Create(const mozilla::layers::SurfaceDescriptor& aDesc); + bool Create(mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage, + int aWidth, int aHeight); bool ImportSurfaceDescriptor(const mozilla::layers::SurfaceDescriptor& aDesc); bool OpenFileDescriptorForPlane(const mozilla::MutexAutoLock& aProofOfLock, int aPlane); diff --git a/widget/gtk/DMABufSurface.cpp b/widget/gtk/DMABufSurface.cpp --- a/widget/gtk/DMABufSurface.cpp +++ b/widget/gtk/DMABufSurface.cpp @@ -204,10 +204,12 @@ } } void DMABufSurface::FenceSet() { if (!mGL || !mGL->MakeCurrent()) { + MOZ_DIAGNOSTIC_ASSERT(mGL, + "DMABufSurface::FenceSet(): missing GL context!"); return; } const auto& gle = gl::GLContextEGL::Cast(mGL); const auto& egl = gle->mEgl; @@ -228,21 +230,23 @@ mGL->fFinish(); } void DMABufSurface::FenceWait() { if (!mGL || mSyncFd < 0) { + MOZ_DIAGNOSTIC_ASSERT(mGL, + "DMABufSurface::FenceWait() missing GL context!"); return; } const auto& gle = gl::GLContextEGL::Cast(mGL); const auto& egl = gle->mEgl; const EGLint attribs[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID, mSyncFd, LOCAL_EGL_NONE}; EGLSync sync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); if (!sync) { - MOZ_ASSERT(false, "Failed to create GLFence!"); + MOZ_ASSERT(false, "DMABufSurface::FenceWait(): Failed to create GLFence!"); // We failed to create GLFence so clear mSyncFd to avoid another try. close(mSyncFd); mSyncFd = -1; return; } @@ -338,17 +342,18 @@ mGmbFormat = GetDMABufDevice()->GetGbmFormat(mSurfaceFlags & DMABUF_ALPHA); if (!mGmbFormat) { // Requested DRM format is not supported. return false; } + mDrmFormats[0] = mGmbFormat->mFormat; bool useModifiers = (aDMABufSurfaceFlags & DMABUF_USE_MODIFIERS) && mGmbFormat->mModifiersCount > 0; if (useModifiers) { LOGDMABUF((" Creating with modifiers\n")); mGbmBufferObject[0] = nsGbmLib::CreateWithModifiers( - GetDMABufDevice()->GetGbmDevice(), mWidth, mHeight, mGmbFormat->mFormat, + GetDMABufDevice()->GetGbmDevice(), mWidth, mHeight, mDrmFormats[0], mGmbFormat->mModifiers, mGmbFormat->mModifiersCount); if (mGbmBufferObject[0]) { mBufferModifiers[0] = nsGbmLib::GetModifier(mGbmBufferObject[0]); } } @@ -356,11 +361,11 @@ if (!mGbmBufferObject[0]) { LOGDMABUF((" Creating without modifiers\n")); mGbmBufferFlags = GBM_BO_USE_LINEAR; mGbmBufferObject[0] = nsGbmLib::Create(GetDMABufDevice()->GetGbmDevice(), mWidth, mHeight, - mGmbFormat->mFormat, mGbmBufferFlags); + mDrmFormats[0], mGbmBufferFlags); mBufferModifiers[0] = DRM_FORMAT_MOD_INVALID; } if (!mGbmBufferObject[0]) { LOGDMABUF((" Failed to create GbmBufferObject\n")); @@ -386,22 +391,51 @@ LOGDMABUF((" Success\n")); return true; } +bool DMABufSurfaceRGBA::Create(mozilla::gl::GLContext* aGLContext, + const EGLImageKHR aEGLImage, int aWidth, + int aHeight) { + LOGDMABUF(("DMABufSurfaceRGBA::Create() from EGLImage UID = %d\n", mUID)); + if (!aGLContext) { + return false; + } + const auto& gle = gl::GLContextEGL::Cast(aGLContext); + const auto& egl = gle->mEgl; + + mGL = aGLContext; + mWidth = aWidth; + mHeight = aHeight; + mEGLImage = aEGLImage; + if (!egl->fExportDMABUFImageQuery(mEGLImage, mDrmFormats, &mBufferPlaneCount, + mBufferModifiers)) { + LOGDMABUF((" ExportDMABUFImageQueryMESA failed, quit\n")); + return false; + } + if (mBufferPlaneCount > DMABUF_BUFFER_PLANES) { + LOGDMABUF((" wrong plane count %d, quit\n", mBufferPlaneCount)); + return false; + } + if (!egl->fExportDMABUFImage(mEGLImage, mDmabufFds, mStrides, mOffsets)) { + LOGDMABUF((" ExportDMABUFImageMESA failed, quit\n")); + return false; + } + + LOGDMABUF((" imported size %d x %d format %x planes %d", mWidth, mHeight, + mDrmFormats[0], mBufferPlaneCount)); + return true; +} + bool DMABufSurfaceRGBA::ImportSurfaceDescriptor( const SurfaceDescriptor& aDesc) { const SurfaceDescriptorDMABuf& desc = aDesc.get_SurfaceDescriptorDMABuf(); mWidth = desc.width()[0]; mHeight = desc.height()[0]; mBufferModifiers[0] = desc.modifier()[0]; - if (mBufferModifiers[0] != DRM_FORMAT_MOD_INVALID) { - mGmbFormat = GetDMABufDevice()->GetExactGbmFormat(desc.format()[0]); - } else { - mDrmFormats[0] = desc.format()[0]; - } + mDrmFormats[0] = desc.format()[0]; mBufferPlaneCount = desc.fds().Length(); mGbmBufferFlags = desc.flags(); MOZ_RELEASE_ASSERT(mBufferPlaneCount <= DMABUF_BUFFER_PLANES); mUID = desc.uid(); @@ -431,10 +465,12 @@ if (desc.refCount().Length() > 0) { GlobalRefCountImport(desc.refCount()[0].ClonePlatformHandle().release()); } + LOGDMABUF((" imported size %d x %d format %x planes %d", mWidth, mHeight, + mDrmFormats[0], mBufferPlaneCount)); return true; } bool DMABufSurfaceRGBA::Create(const SurfaceDescriptor& aDesc) { return ImportSurfaceDescriptor(aDesc); @@ -460,11 +496,11 @@ return false; } width.AppendElement(mWidth); height.AppendElement(mHeight); - format.AppendElement(mGmbFormat->mFormat); + format.AppendElement(mDrmFormats[0]); modifiers.AppendElement(mBufferModifiers[0]); for (int i = 0; i < mBufferPlaneCount; i++) { fds.AppendElement(ipc::FileDescriptor(mDmabufFds[i])); strides.AppendElement(mStrides[i]); offsets.AppendElement(mOffsets[i]); @@ -486,23 +522,20 @@ fenceFDs, mUID, refCountFDs); return true; } bool DMABufSurfaceRGBA::CreateTexture(GLContext* aGLContext, int aPlane) { + LOGDMABUF(("DMABufSurfaceRGBA::CreateTexture() UID %d\n", mUID)); MOZ_ASSERT(!mEGLImage && !mTexture, "EGLImage is already created!"); nsTArray attribs; attribs.AppendElement(LOCAL_EGL_WIDTH); attribs.AppendElement(mWidth); attribs.AppendElement(LOCAL_EGL_HEIGHT); attribs.AppendElement(mHeight); attribs.AppendElement(LOCAL_EGL_LINUX_DRM_FOURCC_EXT); - if (mGmbFormat) { - attribs.AppendElement(mGmbFormat->mFormat); - } else { - attribs.AppendElement(mDrmFormats[0]); - } + attribs.AppendElement(mDrmFormats[0]); #define ADD_PLANE_ATTRIBS(plane_idx) \ { \ attribs.AppendElement(LOCAL_EGL_DMA_BUF_PLANE##plane_idx##_FD_EXT); \ attribs.AppendElement(mDmabufFds[plane_idx]); \ attribs.AppendElement(LOCAL_EGL_DMA_BUF_PLANE##plane_idx##_OFFSET_EXT); \ @@ -560,10 +593,11 @@ return true; } void DMABufSurfaceRGBA::ReleaseTextures() { + LOGDMABUF(("DMABufSurfaceRGBA::ReleaseTextures() UID %d\n", mUID)); FenceDelete(); if (!mTexture) { return; } @@ -618,11 +652,11 @@ zwp_linux_buffer_params_v1_add(params, mDmabufFds[0], 0, mOffsets[0], mStrides[0], mBufferModifiers[0] >> 32, mBufferModifiers[0] & 0xffffffff); mWlBuffer = zwp_linux_buffer_params_v1_create_immed( - params, GetWidth(), GetHeight(), mGmbFormat->mFormat, 0); + params, GetWidth(), GetHeight(), mDrmFormats[0], 0); CloseFileDescriptors(lockFD); return mWlBuffer != nullptr; } @@ -806,10 +840,20 @@ return nullptr; } return surf.forget(); } +already_AddRefed DMABufSurfaceRGBA::CreateDMABufSurface( + mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage, int aWidth, + int aHeight) { + RefPtr surf = new DMABufSurfaceRGBA(); + if (!surf->Create(aGLContext, aEGLImage, aWidth, aHeight)) { + return nullptr; + } + return surf.forget(); +} + already_AddRefed DMABufSurfaceYUV::CreateYUVSurface( const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth, int aHeight) { RefPtr surf = new DMABufSurfaceYUV(); LOGDMABUF(("DMABufSurfaceYUV::CreateYUVSurface() UID %d from desc\n", surf->GetUID()));