diff --git a/gfx/layers/NativeLayerWayland.cpp b/gfx/layers/NativeLayerWayland.cpp index c8f95908ca42..c3429ae826d2 100644 --- a/gfx/layers/NativeLayerWayland.cpp +++ b/gfx/layers/NativeLayerWayland.cpp @@ -513,6 +513,32 @@ GdkWindow* NativeLayerRootWayland::GetGdkWindow() const { return mSurface->GetGdkWindow(); } +// Try to match stored wl_buffer with provided DMABufSurface or create +// a new one. +RefPtr NativeLayerRootWayland::BorrowExternalBuffer( + RefPtr aDMABufSurface) { + LOG("NativeLayerRootWayland::BorrowExternalBuffer() WaylandSurface [%p] UID " + "%d PID %d", + aDMABufSurface.get(), aDMABufSurface->GetUID(), aDMABufSurface->GetPID()); + + RefPtr waylandBuffer = + widget::WaylandBufferDMABUF::CreateExternal(aDMABufSurface); + for (auto& b : mExternalBuffers) { + if (b.Matches(aDMABufSurface)) { + waylandBuffer->SetExternalWLBuffer(b.GetWLBuffer()); + return waylandBuffer.forget(); + } + } + + wl_buffer* wlbuffer = waylandBuffer->CreateAndTakeWLBuffer(); + if (!wlbuffer) { + return nullptr; + } + + mExternalBuffers.EmplaceBack(aDMABufSurface, wlbuffer); + return waylandBuffer.forget(); +} + NativeLayerWayland::NativeLayerWayland(NativeLayerRootWayland* aRootLayer, const IntSize& aSize, bool aIsOpaque) : mMutex("NativeLayerWayland"), @@ -1008,9 +1034,12 @@ void NativeLayerWaylandExternal::AttachExternalImage( mSize = texture->GetSize(0); mDisplayRect = IntRect(IntPoint{}, mSize); mBufferInvalided = true; - mFrontBuffer = - widget::WaylandBufferDMABUF::CreateExternal(mTextureHost->GetSurface()); - mIsHDR = mTextureHost->GetSurface()->IsHDRSurface(); + + auto surface = mTextureHost->GetSurface(); + mFrontBuffer = surface->CanRecycle() + ? mRootLayer->BorrowExternalBuffer(surface) + : widget::WaylandBufferDMABUF::CreateExternal(surface); + mIsHDR = surface->IsHDRSurface(); LOG("NativeLayerWaylandExternal::AttachExternalImage() host [%p] " "DMABufSurface [%p] DMABuf UID %d [%d x %d] HDR %d Opaque %d", diff --git a/gfx/layers/NativeLayerWayland.h b/gfx/layers/NativeLayerWayland.h index 3fa78789bcf5..e8078e151663 100644 --- a/gfx/layers/NativeLayerWayland.h +++ b/gfx/layers/NativeLayerWayland.h @@ -61,6 +61,9 @@ class NativeLayerRootWayland final : public NativeLayerRoot { void FrameCallbackHandler(uint32_t aTime); + RefPtr BorrowExternalBuffer( + RefPtr aDMABufSurface); + #ifdef MOZ_LOGGING nsAutoCString GetDebugTag() const; void* GetLoggingWidget() const; @@ -119,6 +122,10 @@ class NativeLayerRootWayland final : public NativeLayerRoot { // they have been added or removed. nsTArray> mMainThreadUpdateSublayers; + // External buffers (DMABuf) used by the layers. + // We want to cache and reuse wl_buffer of external images. + nsTArray mExternalBuffers; + // We're between CompositorBeginFrame() / CompositorEndFrame() calls. mozilla::Atomic mFrameInProcess{false};