File 1999029-Wayland-buffer-transaction-locking.patch of Package firefox-kde

diff --git a/widget/gtk/WaylandBuffer.h b/widget/gtk/WaylandBuffer.h
--- a/widget/gtk/WaylandBuffer.h
+++ b/widget/gtk/WaylandBuffer.h
@@ -60,14 +60,14 @@
   LayoutDeviceIntSize GetSize() const { return mSize; };
   bool IsMatchingSize(const LayoutDeviceIntSize& aSize) const {
     return aSize == mSize;
   }
 
-  bool IsAttached() const;
-
+  bool IsAttached(const WaylandSurfaceLock& aSurfaceLock) const;
   BufferTransaction* GetTransaction(const WaylandSurfaceLock& aSurfaceLock);
-  void RemoveTransaction(RefPtr<BufferTransaction> aTransaction);
+  void RemoveTransaction(const WaylandSurfaceLock& aSurfaceLock,
+                         RefPtr<BufferTransaction> aTransaction);
 
 #ifdef MOZ_LOGGING
   virtual void DumpToFile(const char* aHint) = 0;
 #endif
 
diff --git a/widget/gtk/WaylandBuffer.cpp b/widget/gtk/WaylandBuffer.cpp
--- a/widget/gtk/WaylandBuffer.cpp
+++ b/widget/gtk/WaylandBuffer.cpp
@@ -88,11 +88,11 @@
   MozClearPointer(mShmPool, wl_shm_pool_destroy);
 }
 
 WaylandBuffer::WaylandBuffer(const LayoutDeviceIntSize& aSize) : mSize(aSize) {}
 
-bool WaylandBuffer::IsAttached() const {
+bool WaylandBuffer::IsAttached(const WaylandSurfaceLock& aSurfaceLock) const {
   for (const auto& transaction : mBufferTransactions) {
     if (transaction->IsAttached()) {
       return true;
     }
   }
@@ -128,11 +128,12 @@
   auto* transaction = new BufferTransaction(this, buffer, !!mExternalWlBuffer);
   mBufferTransactions.AppendElement(transaction);
   return transaction;
 }
 
-void WaylandBuffer::RemoveTransaction(RefPtr<BufferTransaction> aTransaction) {
+void WaylandBuffer::RemoveTransaction(const WaylandSurfaceLock& aSurfaceLock,
+                                      RefPtr<BufferTransaction> aTransaction) {
   LOGWAYLAND("WaylandBuffer::RemoveTransaction() [%p]", (void*)aTransaction);
   [[maybe_unused]] bool removed =
       mBufferTransactions.RemoveElement(aTransaction);
   MOZ_DIAGNOSTIC_ASSERT(removed);
   MOZ_DIAGNOSTIC_ASSERT(!mBufferTransactions.Contains(aTransaction));
@@ -185,11 +186,11 @@
   LOGWAYLAND("WaylandBufferSHM::WaylandBufferSHM() [%p]\n", (void*)this);
 }
 
 WaylandBufferSHM::~WaylandBufferSHM() {
   LOGWAYLAND("WaylandBufferSHM::~WaylandBufferSHM() [%p]\n", (void*)this);
-  MOZ_RELEASE_ASSERT(!IsAttached());
+  MOZ_RELEASE_ASSERT(mBufferTransactions.IsEmpty());
 }
 
 already_AddRefed<gfx::DrawTarget> WaylandBufferSHM::Lock() {
   LOGWAYLAND("WaylandBufferSHM::lock() [%p]\n", (void*)this);
   return gfxPlatform::CreateDrawTargetForData(
@@ -284,11 +285,11 @@
 }
 
 WaylandBufferDMABUF::~WaylandBufferDMABUF() {
   LOGWAYLAND("WaylandBufferDMABUF::~WaylandBufferDMABUF [%p] UID %d\n",
              (void*)this, mDMABufSurface ? mDMABufSurface->GetUID() : -1);
-  MOZ_RELEASE_ASSERT(!IsAttached());
+  MOZ_RELEASE_ASSERT(mBufferTransactions.IsEmpty());
 }
 
 #ifdef MOZ_LOGGING
 void WaylandBufferDMABUF::DumpToFile(const char* aHint) {
   if (!mDumpSerial) {
@@ -469,11 +470,11 @@
   mSurface->RemoveTransactionLocked(aSurfaceLock, this);
   mSurface = nullptr;
 
   // This can destroy us
   RefPtr grip{this};
-  mBuffer->RemoveTransaction(this);
+  mBuffer->RemoveTransaction(aSurfaceLock, this);
   mBuffer = nullptr;
 }
 
 BufferTransaction::BufferTransaction(WaylandBuffer* aBuffer,
                                      wl_buffer* aWLBuffer,

diff -up firefox-147.0.1/widget/gtk/WindowSurfaceWaylandMultiBuffer.cpp.1999029-2 firefox-147.0.1/widget/gtk/WindowSurfaceWaylandMultiBuffer.cpp
--- firefox-147.0.1/widget/gtk/WindowSurfaceWaylandMultiBuffer.cpp.1999029-2	2026-01-16 10:22:08.000000000 +0100
+++ firefox-147.0.1/widget/gtk/WindowSurfaceWaylandMultiBuffer.cpp	2026-01-20 07:49:45.921278176 +0100
@@ -154,8 +154,8 @@ using gfx::DataSourceSurface;
 
 WindowSurfaceWaylandMB::WindowSurfaceWaylandMB(
     RefPtr<nsWindow> aWindow, GtkCompositorWidget* aCompositorWidget)
-    : mSurfaceLock("WindowSurfaceWayland lock"),
-      mWindow(std::move(aWindow)),
+    : mWindow(std::move(aWindow)),
+      mWaylandSurface(mWindow->GetWaylandSurface()),
       mCompositorWidget(aCompositorWidget) {}
 
 bool WindowSurfaceWaylandMB::MaybeUpdateWindowSize() {
@@ -175,7 +175,7 @@ bool WindowSurfaceWaylandMB::MaybeUpdate
 
 already_AddRefed<DrawTarget> WindowSurfaceWaylandMB::Lock(
     const LayoutDeviceIntRegion& aInvalidRegion) {
-  MutexAutoLock lock(mSurfaceLock);
+  WaylandSurfaceLock lock(mWaylandSurface);
 
 #ifdef MOZ_LOGGING
   gfx::IntRect lockRect = aInvalidRegion.GetBounds().ToUnknownRect();
@@ -205,7 +205,7 @@ already_AddRefed<DrawTarget> WindowSurfa
   }
 
   if (!mInProgressBuffer) {
-    if (mFrontBuffer && !mFrontBuffer->IsAttached()) {
+    if (mFrontBuffer && !mFrontBuffer->IsAttached(lock)) {
       mInProgressBuffer = mFrontBuffer;
     } else {
       mInProgressBuffer = ObtainBufferFromPool(lock, mWindowSize);
@@ -226,7 +226,7 @@ already_AddRefed<DrawTarget> WindowSurfa
 }
 
 void WindowSurfaceWaylandMB::HandlePartialUpdate(
-    const MutexAutoLock& aProofOfLock,
+    const WaylandSurfaceLock& aWaylandSurfaceLock,
     const LayoutDeviceIntRegion& aInvalidRegion) {
   LayoutDeviceIntRegion copyRegion;
   if (mInProgressBuffer->GetBufferAge() == 2) {
@@ -258,12 +258,12 @@ void WindowSurfaceWaylandMB::HandleParti
 
 void WindowSurfaceWaylandMB::Commit(
     const LayoutDeviceIntRegion& aInvalidRegion) {
-  MutexAutoLock lock(mSurfaceLock);
+  WaylandSurfaceLock lock(mWaylandSurface);
   Commit(lock, aInvalidRegion);
 }
 
 void WindowSurfaceWaylandMB::Commit(
-    const MutexAutoLock& aProofOfLock,
+    const WaylandSurfaceLock& aWaylandSurfaceLock,
     const LayoutDeviceIntRegion& aInvalidRegion) {
 #ifdef MOZ_LOGGING
   gfx::IntRect invalidRect = aInvalidRegion.GetBounds().ToUnknownRect();
@@ -274,32 +274,30 @@ void WindowSurfaceWaylandMB::Commit(
       invalidRect.height, mWindowSize.width, mWindowSize.height);
 #endif
 
-  if (!mInProgressBuffer) {
+  if (!mInProgressBuffer || !mWaylandSurface->IsMapped()) {
     // invisible window
     return;
   }
 
-  MozContainer* container = mWindow->GetMozContainer();
-  WaylandSurface* waylandSurface = MOZ_WL_SURFACE(container);
-  WaylandSurfaceLock lock(waylandSurface);
-
-  waylandSurface->InvalidateRegionLocked(lock,
+  auto waylandSurface = aWaylandSurfaceLock.GetWaylandSurface();
+  waylandSurface->InvalidateRegionLocked(aWaylandSurfaceLock,
                                          aInvalidRegion.ToUnknownRegion());
-  waylandSurface->AttachLocked(lock, mInProgressBuffer);
-  waylandSurface->CommitLocked(lock, /* force commit */ true,
-                               /* force flush */ true);
+  waylandSurface->AttachLocked(aWaylandSurfaceLock, mInProgressBuffer);
+  waylandSurface->CommitLocked(aWaylandSurfaceLock, /* force commit */ true,
+                                /* force flush */ true);
 
   mInProgressBuffer->ResetBufferAge();
   mFrontBuffer = mInProgressBuffer;
   mFrontBufferInvalidRegion = aInvalidRegion;
   mInProgressBuffer = nullptr;
 
-  EnforcePoolSizeLimit(aProofOfLock);
-  IncrementBufferAge(aProofOfLock);
+  EnforcePoolSizeLimit(aWaylandSurfaceLock);
+  IncrementBufferAge(aWaylandSurfaceLock);
 }
 
 RefPtr<WaylandBufferSHM> WindowSurfaceWaylandMB::ObtainBufferFromPool(
-    const MutexAutoLock& aProofOfLock, const LayoutDeviceIntSize& aSize) {
+    const WaylandSurfaceLock& aWaylandSurfaceLock,
+    const LayoutDeviceIntSize& aSize) {
   if (!mAvailableBuffers.IsEmpty()) {
     RefPtr<WaylandBufferSHM> buffer = mAvailableBuffers.PopLastElement();
     mInUseBuffers.AppendElement(buffer);
@@ -315,9 +313,9 @@ RefPtr<WaylandBufferSHM> WindowSurfaceWa
 }
 
 void WindowSurfaceWaylandMB::ReturnBufferToPool(
-    const MutexAutoLock& aProofOfLock,
+    const WaylandSurfaceLock& aWaylandSurfaceLock,
     const RefPtr<WaylandBufferSHM>& aBuffer) {
-  if (aBuffer->IsAttached()) {
+  if (aBuffer->IsAttached(aWaylandSurfaceLock)) {
     mPendingBuffers.AppendElement(aBuffer);
   } else if (aBuffer->IsMatchingSize(mWindowSize)) {
     mAvailableBuffers.AppendElement(aBuffer);
@@ -326,7 +324,7 @@ void WindowSurfaceWaylandMB::ReturnBuffe
 }
 
 void WindowSurfaceWaylandMB::EnforcePoolSizeLimit(
-    const MutexAutoLock& aProofOfLock) {
+    const WaylandSurfaceLock& aWaylandSurfaceLock) {
   // Enforce the pool size limit, removing least-recently-used entries as
   // necessary.
   while (mAvailableBuffers.Length() > BACK_BUFFER_NUM) {
@@ -340,9 +338,9 @@ void WindowSurfaceWaylandMB::EnforcePool
 }
 
 void WindowSurfaceWaylandMB::CollectPendingSurfaces(
-    const MutexAutoLock& aProofOfLock) {
+    const WaylandSurfaceLock& aWaylandSurfaceLock) {
   mPendingBuffers.RemoveElementsBy([&](auto& buffer) {
-    if (!buffer->IsAttached()) {
+    if (!buffer->IsAttached(aWaylandSurfaceLock)) {
       if (buffer->IsMatchingSize(mWindowSize)) {
         mAvailableBuffers.AppendElement(std::move(buffer));
       }
@@ -353,7 +351,7 @@ void WindowSurfaceWaylandMB::CollectPend
 }
 
 void WindowSurfaceWaylandMB::IncrementBufferAge(
-    const MutexAutoLock& aProofOfLock) {
+    const WaylandSurfaceLock& aWaylandSurfaceLock) {
   for (const RefPtr<WaylandBufferSHM>& buffer : mInUseBuffers) {
     buffer->IncrementBufferAge();
   }
diff -up firefox-147.0.1/widget/gtk/WindowSurfaceWaylandMultiBuffer.h.1999029-2 firefox-147.0.1/widget/gtk/WindowSurfaceWaylandMultiBuffer.h
--- firefox-147.0.1/widget/gtk/WindowSurfaceWaylandMultiBuffer.h.1999029-2	2026-01-16 09:55:42.000000000 +0100
+++ firefox-147.0.1/widget/gtk/WindowSurfaceWaylandMultiBuffer.h	2026-01-20 07:41:46.720127574 +0100
@@ -43,23 +43,24 @@ class WindowSurfaceWaylandMB : public Wi
   void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final;
 
  private:
-  void Commit(const MutexAutoLock& aProofOfLock,
+  void Commit(const WaylandSurfaceLock& aWaylandSurfaceLock,
               const LayoutDeviceIntRegion& aInvalidRegion);
   RefPtr<WaylandBufferSHM> ObtainBufferFromPool(
-      const MutexAutoLock& aProofOfLock, const LayoutDeviceIntSize& aSize);
-  void ReturnBufferToPool(const MutexAutoLock& aProofOfLock,
+      const WaylandSurfaceLock& aWaylandSurfaceLock,
+      const LayoutDeviceIntSize& aSize);
+  void ReturnBufferToPool(const WaylandSurfaceLock& aWaylandSurfaceLock,
                           const RefPtr<WaylandBufferSHM>& aBuffer);
-  void EnforcePoolSizeLimit(const MutexAutoLock& aProofOfLock);
-  void CollectPendingSurfaces(const MutexAutoLock& aProofOfLock);
-  void HandlePartialUpdate(const MutexAutoLock& aProofOfLock,
+  void EnforcePoolSizeLimit(const WaylandSurfaceLock& aWaylandSurfaceLock);
+  void CollectPendingSurfaces(const WaylandSurfaceLock& aWaylandSurfaceLock);
+  void HandlePartialUpdate(const WaylandSurfaceLock& aWaylandSurfaceLock,
                            const LayoutDeviceIntRegion& aInvalidRegion);
-  void IncrementBufferAge(const MutexAutoLock& aProofOfLock);
+  void IncrementBufferAge(const WaylandSurfaceLock& aWaylandSurfaceLock);
   // Return true if window size was updated.
   bool MaybeUpdateWindowSize();
 
-  mozilla::Mutex mSurfaceLock MOZ_UNANNOTATED;
-
   RefPtr<nsWindow> mWindow;
+  RefPtr<WaylandSurface> mWaylandSurface;
+
   // WindowSurfaceWaylandMB is owned by GtkCompositorWidget so we can't
   // reference it.
   GtkCompositorWidget* mCompositorWidget;
diff --git a/widget/gtk/WaylandSurface.cpp b/widget/gtk/WaylandSurface.cpp
--- a/widget/gtk/WaylandSurface.cpp
+++ b/widget/gtk/WaylandSurface.cpp
@@ -1122,13 +1122,13 @@
                      bufferSize.height == surfaceSize.height;
   LOGWAYLAND(
       "WaylandSurface::AttachLocked() transactions [%d] WaylandBuffer [%p] "
       "attached [%d] buffer size [%d x %d] surface (scaled) size [%d x %d] "
       "fractional scale %f matches %d",
-      (int)mBufferTransactions.Length(), aBuffer.get(), aBuffer->IsAttached(),
-      bufferSize.width, bufferSize.height, surfaceSize.width,
-      surfaceSize.height, scale, sizeMatches);
+      (int)mBufferTransactions.Length(), aBuffer.get(),
+      aBuffer->IsAttached(aSurfaceLock), bufferSize.width, bufferSize.height,
+      surfaceSize.width, surfaceSize.height, scale, sizeMatches);
 
   if (mViewportFollowsSizeChanges) {
     DesktopIntSize viewportSize;
     if (!sizeMatches) {
       viewportSize =

diff --git a/gfx/layers/SurfacePoolWayland.h b/gfx/layers/SurfacePoolWayland.h
--- a/gfx/layers/SurfacePoolWayland.h
+++ b/gfx/layers/SurfacePoolWayland.h
@@ -30,13 +30,15 @@
   friend RefPtr<SurfacePool> SurfacePool::Create(size_t aPoolSizeLimit);
 
   explicit SurfacePoolWayland(size_t aPoolSizeLimit);
 
   RefPtr<widget::WaylandBuffer> ObtainBufferFromPool(
+      const widget::WaylandSurfaceLock& aWaylandSurfaceLock,
       const gfx::IntSize& aSize, gl::GLContext* aGL,
       RefPtr<widget::DRMFormat> aFormat);
-  void ReturnBufferToPool(const RefPtr<widget::WaylandBuffer>& aBuffer);
+  void ReturnBufferToPool(const widget::WaylandSurfaceLock& aWaylandSurfaceLock,
+                          const RefPtr<widget::WaylandBuffer>& aBuffer);
   void EnforcePoolSizeLimit();
   void CollectPendingSurfaces();
   Maybe<GLuint> GetFramebufferForBuffer(
       const RefPtr<widget::WaylandBuffer>& aBuffer, gl::GLContext* aGL,
       bool aNeedsDepthBuffer);
@@ -44,20 +46,23 @@
   struct GLResourcesForBuffer final {
     RefPtr<gl::GLContext> mGL;                   // non-null
     UniquePtr<gl::MozFramebuffer> mFramebuffer;  // non-null
   };
 
+  // Keep mWaylandSurface / mWaylandBuffer in pair as we don't share
+  // mWaylandBuffer among WaylandSurfaces.
   struct SurfacePoolEntry final {
     const gfx::IntSize mSize;
-    const RefPtr<widget::WaylandBuffer> mWaylandBuffer;  // non-null
+    const RefPtr<widget::WaylandSurface> mWaylandSurface;  // non-null
+    const RefPtr<widget::WaylandBuffer> mWaylandBuffer;    // non-null
     Maybe<GLResourcesForBuffer> mGLResources;
   };
 
-  bool CanRecycleSurfaceForRequest(const MutexAutoLock& aProofOfLock,
-                                   const SurfacePoolEntry& aEntry,
-                                   const gfx::IntSize& aSize,
-                                   gl::GLContext* aGL);
+  bool CanRecycleSurfaceForRequest(
+      const MutexAutoLock& aProofOfLock, const SurfacePoolEntry& aEntry,
+      const widget::WaylandSurfaceLock& aWaylandSurfaceLock,
+      const gfx::IntSize& aSize, gl::GLContext* aGL);
 
   RefPtr<gl::DepthAndStencilBuffer> GetDepthBufferForSharing(
       const MutexAutoLock& aProofOfLock, gl::GLContext* aGL,
       const gfx::IntSize& aSize);
   UniquePtr<gl::MozFramebuffer> CreateFramebufferForTexture(
@@ -103,12 +108,14 @@
   SurfacePoolHandleWayland* AsSurfacePoolHandleWayland() override {
     return this;
   }
 
   RefPtr<widget::WaylandBuffer> ObtainBufferFromPool(
+      const widget::WaylandSurfaceLock& aWaylandSurfaceLock,
       const gfx::IntSize& aSize, RefPtr<widget::DRMFormat> aFormat);
-  void ReturnBufferToPool(const RefPtr<widget::WaylandBuffer>& aBuffer);
+  void ReturnBufferToPool(const widget::WaylandSurfaceLock& aWaylandSurfaceLock,
+                          const RefPtr<widget::WaylandBuffer>& aBuffer);
   Maybe<GLuint> GetFramebufferForBuffer(
       const RefPtr<widget::WaylandBuffer>& aBuffer, bool aNeedsDepthBuffer);
   const auto& gl() { return mGL; }
 
   RefPtr<SurfacePool> Pool() override { return mPool; }
diff --git a/gfx/layers/SurfacePoolWayland.cpp b/gfx/layers/SurfacePoolWayland.cpp
--- a/gfx/layers/SurfacePoolWayland.cpp
+++ b/gfx/layers/SurfacePoolWayland.cpp
@@ -71,12 +71,20 @@
       [&](const DepthBufferEntry& entry) { return entry.mGL == aGL; });
 }
 
 bool SurfacePoolWayland::CanRecycleSurfaceForRequest(
     const MutexAutoLock& aProofOfLock, const SurfacePoolEntry& aEntry,
-    const IntSize& aSize, GLContext* aGL) {
-  MOZ_DIAGNOSTIC_ASSERT(!aEntry.mWaylandBuffer->IsAttached());
+    const widget::WaylandSurfaceLock& aWaylandSurfaceLock, const IntSize& aSize,
+    GLContext* aGL) {
+  if (aEntry.mWaylandSurface != aWaylandSurfaceLock.GetWaylandSurface()) {
+    LOGVERBOSE(
+        "SurfacePoolWayland::CanRecycleSurfaceForRequest(): can't recycle due "
+        "to different WaylandSurface.");
+    return false;
+  }
+  MOZ_DIAGNOSTIC_ASSERT(
+      !aEntry.mWaylandBuffer->IsAttached(aWaylandSurfaceLock));
   if (aEntry.mSize != aSize) {
     LOGVERBOSE(
         "SurfacePoolWayland::CanRecycleSurfaceForRequest(): can't recycle due "
         "to different sizes.");
     return false;
@@ -93,18 +101,20 @@
       aGL == nullptr);
   return aGL == nullptr;
 }
 
 RefPtr<WaylandBuffer> SurfacePoolWayland::ObtainBufferFromPool(
-    const IntSize& aSize, GLContext* aGL, RefPtr<widget::DRMFormat> aFormat) {
+    const widget::WaylandSurfaceLock& aWaylandSurfaceLock, const IntSize& aSize,
+    GLContext* aGL, RefPtr<widget::DRMFormat> aFormat) {
   MutexAutoLock lock(mMutex);
 
-  auto iterToRecycle = std::find_if(
-      mAvailableEntries.begin(), mAvailableEntries.end(),
-      [&](const SurfacePoolEntry& aEntry) {
-        return CanRecycleSurfaceForRequest(lock, aEntry, aSize, aGL);
-      });
+  auto iterToRecycle =
+      std::find_if(mAvailableEntries.begin(), mAvailableEntries.end(),
+                   [&](const SurfacePoolEntry& aEntry) {
+                     return CanRecycleSurfaceForRequest(
+                         lock, aEntry, aWaylandSurfaceLock, aSize, aGL);
+                   });
   if (iterToRecycle != mAvailableEntries.end()) {
     RefPtr<WaylandBuffer> buffer = iterToRecycle->mWaylandBuffer;
     mInUseEntries.insert({buffer.get(), std::move(*iterToRecycle)});
     mAvailableEntries.RemoveElementAt(iterToRecycle);
     LOGVERBOSE(
@@ -123,28 +133,32 @@
   } else {
     buffer = widget::WaylandBufferSHM::Create(
         LayoutDeviceIntSize::FromUnknownSize(aSize));
   }
   if (buffer) {
-    mInUseEntries.insert({buffer.get(), SurfacePoolEntry{aSize, buffer, {}}});
+    mInUseEntries.insert(
+        {buffer.get(),
+         SurfacePoolEntry{
+             aSize, aWaylandSurfaceLock.GetWaylandSurface(), buffer, {}}});
   }
   LOGVERBOSE(
       "SurfacePoolWayland::ObtainBufferFromPool() created [%p] U[%d] P[%d] "
       "A[%d]",
       buffer.get(), (int)mInUseEntries.size(), (int)mPendingEntries.Length(),
       (int)mAvailableEntries.Length());
   return buffer;
 }
 
 void SurfacePoolWayland::ReturnBufferToPool(
+    const widget::WaylandSurfaceLock& aWaylandSurfaceLock,
     const RefPtr<WaylandBuffer>& aBuffer) {
   MutexAutoLock lock(mMutex);
 
   auto inUseEntryIter = mInUseEntries.find(aBuffer);
   MOZ_RELEASE_ASSERT(inUseEntryIter != mInUseEntries.end());
 
-  if (aBuffer->IsAttached()) {
+  if (aBuffer->IsAttached(aWaylandSurfaceLock)) {
     mPendingEntries.AppendElement(std::move(inUseEntryIter->second));
   } else {
     mAvailableEntries.AppendElement(std::move(inUseEntryIter->second));
   }
   mInUseEntries.erase(inUseEntryIter);
@@ -177,14 +191,15 @@
 }
 
 void SurfacePoolWayland::CollectPendingSurfaces() {
   MutexAutoLock lock(mMutex);
   mPendingEntries.RemoveElementsBy([&](auto& entry) {
+    widget::WaylandSurfaceLock lock(entry.mWaylandSurface);
     LOGVERBOSE(
         "SurfacePoolWayland::CollectPendingSurfaces() [%p] attached [%d]",
-        entry.mWaylandBuffer.get(), entry.mWaylandBuffer->IsAttached());
-    if (!entry.mWaylandBuffer->IsAttached()) {
+        entry.mWaylandBuffer.get(), entry.mWaylandBuffer->IsAttached(lock));
+    if (!entry.mWaylandBuffer->IsAttached(lock)) {
       mAvailableEntries.AppendElement(std::move(entry));
       return true;
     }
     return false;
   });
@@ -282,17 +297,19 @@
 }
 
 void SurfacePoolHandleWayland::OnEndFrame() { mPool->EnforcePoolSizeLimit(); }
 
 RefPtr<WaylandBuffer> SurfacePoolHandleWayland::ObtainBufferFromPool(
-    const IntSize& aSize, RefPtr<widget::DRMFormat> aFormat) {
-  return mPool->ObtainBufferFromPool(aSize, mGL, aFormat);
+    const widget::WaylandSurfaceLock& aWaylandSurfaceLock, const IntSize& aSize,
+    RefPtr<widget::DRMFormat> aFormat) {
+  return mPool->ObtainBufferFromPool(aWaylandSurfaceLock, aSize, mGL, aFormat);
 }
 
 void SurfacePoolHandleWayland::ReturnBufferToPool(
+    const widget::WaylandSurfaceLock& aProofOfLock,
     const RefPtr<WaylandBuffer>& aBuffer) {
-  mPool->ReturnBufferToPool(aBuffer);
+  mPool->ReturnBufferToPool(aProofOfLock, aBuffer);
 }
 
 Maybe<GLuint> SurfacePoolHandleWayland::GetFramebufferForBuffer(
     const RefPtr<WaylandBuffer>& aBuffer, bool aNeedsDepthBuffer) {
   return mPool->GetFramebufferForBuffer(aBuffer, mGL, aNeedsDepthBuffer);

diff --git a/gfx/layers/NativeLayerWayland.cpp b/gfx/layers/NativeLayerWayland.cpp
--- a/gfx/layers/NativeLayerWayland.cpp
+++ b/gfx/layers/NativeLayerWayland.cpp
@@ -1032,28 +1032,28 @@
     mState.mMutatedPlacement = true;
   }
   mDirtyRegion = aUpdateRegion;
 
   MOZ_DIAGNOSTIC_ASSERT(!mInProgressBuffer);
-  if (mFrontBuffer && !mFrontBuffer->IsAttached()) {
+  if (mFrontBuffer && !mFrontBuffer->IsAttached(lock)) {
     LOGVERBOSE(
         "NativeLayerWaylandRender::NextSurfaceAsDrawTarget(): use front buffer "
         "for rendering");
     // the Wayland compositor released the buffer early, we can reuse it
     mInProgressBuffer = std::move(mFrontBuffer);
   } else {
     LOGVERBOSE(
         "NativeLayerWaylandRender::NextSurfaceAsDrawTarget(): use progress "
         "buffer for rendering");
     mInProgressBuffer = mSurfacePoolHandle->ObtainBufferFromPool(
-        mSize, mRootLayer->GetDRMFormat());
+        lock, mSize, mRootLayer->GetDRMFormat());
     if (mFrontBuffer) {
       LOGVERBOSE(
           "NativeLayerWaylandRender::NextSurfaceAsDrawTarget(): read-back from "
           "front buffer");
       ReadBackFrontBuffer(lock);
-      mSurfacePoolHandle->ReturnBufferToPool(mFrontBuffer);
+      mSurfacePoolHandle->ReturnBufferToPool(lock, mFrontBuffer);
       mFrontBuffer = nullptr;
     }
   }
   MOZ_DIAGNOSTIC_ASSERT(!mFrontBuffer);
 
@@ -1062,11 +1062,11 @@
     wr::RenderThread::Get()->HandleWebRenderError(
         wr::WebRenderError::NEW_SURFACE);
     return nullptr;
   }
 
-  MOZ_DIAGNOSTIC_ASSERT(!mInProgressBuffer->IsAttached(),
+  MOZ_DIAGNOSTIC_ASSERT(!mInProgressBuffer->IsAttached(lock),
                         "Reusing attached buffer!");
 
   return mInProgressBuffer->Lock();
 }
 
@@ -1082,31 +1082,31 @@
     mState.mMutatedPlacement = true;
   }
   mDirtyRegion = IntRegion(aUpdateRegion);
 
   MOZ_DIAGNOSTIC_ASSERT(!mInProgressBuffer);
-  if (mFrontBuffer && !mFrontBuffer->IsAttached()) {
+  if (mFrontBuffer && !mFrontBuffer->IsAttached(lock)) {
     LOGVERBOSE(
         "NativeLayerWaylandRender::NextSurfaceAsFramebuffer(): use front "
         "buffer for rendering");
     // the Wayland compositor released the buffer early, we can reuse it
     mInProgressBuffer = std::move(mFrontBuffer);
   } else {
     LOGVERBOSE(
         "NativeLayerWaylandRender::NextSurfaceAsFramebuffer(): use progress "
         "buffer for rendering");
     mInProgressBuffer = mSurfacePoolHandle->ObtainBufferFromPool(
-        mSize, mRootLayer->GetDRMFormat());
+        lock, mSize, mRootLayer->GetDRMFormat());
   }
 
   MOZ_DIAGNOSTIC_ASSERT(mInProgressBuffer,
                         "NativeLayerWaylandRender: Failed to obtain buffer");
   if (!mInProgressBuffer) {
     return Nothing();
   }
 
-  MOZ_DIAGNOSTIC_ASSERT(!mInProgressBuffer->IsAttached(),
+  MOZ_DIAGNOSTIC_ASSERT(!mInProgressBuffer->IsAttached(lock),
                         "Reusing attached buffer!");
 
   // get the framebuffer before handling partial damage so we don't accidently
   // create one without depth buffer
   Maybe<GLuint> fbo = mSurfacePoolHandle->GetFramebufferForBuffer(
@@ -1120,11 +1120,11 @@
   if (mFrontBuffer) {
     LOGVERBOSE(
         "NativeLayerWaylandRender::NextSurfaceAsFramebuffer(): read-back from "
         "front buffer");
     ReadBackFrontBuffer(lock);
-    mSurfacePoolHandle->ReturnBufferToPool(mFrontBuffer);
+    mSurfacePoolHandle->ReturnBufferToPool(lock, mFrontBuffer);
     mFrontBuffer = nullptr;
   }
 
   return fbo;
 }
@@ -1226,16 +1226,17 @@
     const WaylandSurfaceLock& aProofOfLock, bool aForce) {
   LOGVERBOSE(
       "NativeLayerWaylandRender::DiscardBackbuffersLocked() force %d progress "
       "%p front %p",
       aForce, mInProgressBuffer.get(), mFrontBuffer.get());
-  if (mInProgressBuffer && (!mInProgressBuffer->IsAttached() || aForce)) {
-    mSurfacePoolHandle->ReturnBufferToPool(mInProgressBuffer);
+  if (mInProgressBuffer &&
+      (!mInProgressBuffer->IsAttached(aProofOfLock) || aForce)) {
+    mSurfacePoolHandle->ReturnBufferToPool(aProofOfLock, mInProgressBuffer);
     mInProgressBuffer = nullptr;
   }
-  if (mFrontBuffer && (!mFrontBuffer->IsAttached() || aForce)) {
-    mSurfacePoolHandle->ReturnBufferToPool(mFrontBuffer);
+  if (mFrontBuffer && (!mFrontBuffer->IsAttached(aProofOfLock) || aForce)) {
+    mSurfacePoolHandle->ReturnBufferToPool(aProofOfLock, mFrontBuffer);
     mFrontBuffer = nullptr;
   }
 }
 
 NativeLayerWaylandRender::~NativeLayerWaylandRender() {

openSUSE Build Service is sponsored by