Bug 1961723 [Linux] Use WaylandBufferDMABUFHolder at NativeLayerWayland to hold wl_buffers for external dmabuf surfaces r=lsalzman

WaylandBufferDMABUFHolder stores wl_buffer for external dmabuf surface and allows us to use existing wl_buffer for dmabuf surface instead of creating
a new one. That saves GPU resources and GPU power (MPV does the same).

In this patch add WaylandBufferDMABUFHolder to NativeLayerRootWayland and cache wl_buffers there for surfaces which can be recycled.

Differential Revision: https://phabricator.services.mozilla.com/D248228
This commit is contained in:
stransky
2025-05-13 08:26:17 +00:00
committed by stransky@redhat.com
parent 388084e23c
commit b0c857d67b
2 changed files with 39 additions and 3 deletions

View File

@@ -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<WaylandBuffer> NativeLayerRootWayland::BorrowExternalBuffer(
RefPtr<DMABufSurface> 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",

View File

@@ -61,6 +61,9 @@ class NativeLayerRootWayland final : public NativeLayerRoot {
void FrameCallbackHandler(uint32_t aTime);
RefPtr<widget::WaylandBuffer> BorrowExternalBuffer(
RefPtr<DMABufSurface> 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<RefPtr<NativeLayerWayland>> mMainThreadUpdateSublayers;
// External buffers (DMABuf) used by the layers.
// We want to cache and reuse wl_buffer of external images.
nsTArray<widget::WaylandBufferDMABUFHolder> mExternalBuffers;
// We're between CompositorBeginFrame() / CompositorEndFrame() calls.
mozilla::Atomic<bool, mozilla::Relaxed> mFrameInProcess{false};