Blob Blame History Raw
diff -up firefox-82.0/widget/gtk/WindowSurfaceWayland.cpp.1656727 firefox-82.0/widget/gtk/WindowSurfaceWayland.cpp
--- firefox-82.0/widget/gtk/WindowSurfaceWayland.cpp.1656727	2020-10-15 16:16:53.522050159 +0200
+++ firefox-82.0/widget/gtk/WindowSurfaceWayland.cpp	2020-10-15 16:18:24.956289348 +0200
@@ -158,7 +158,6 @@ We allocate shared memory (shm) by mmap(
 between us and wayland compositor. We draw our graphics data to the shm and
 handle to wayland compositor by WindowBackBuffer/WindowSurfaceWayland
 (wl_buffer/wl_surface).
-
 */
 
 #define EVENT_LOOP_DELAY (1000 / 240)
@@ -166,6 +165,44 @@ handle to wayland compositor by WindowBa
 #define BUFFER_BPP 4
 gfx::SurfaceFormat WindowBackBuffer::mFormat = gfx::SurfaceFormat::B8G8R8A8;
 
+static mozilla::Mutex* gDelayedCommitLock = nullptr;
+static GList* gDelayedCommits = nullptr;
+
+static void DelayedCommitsEnsureMutext() {
+  if (!gDelayedCommitLock) {
+    gDelayedCommitLock = new mozilla::Mutex("DelayedCommit lock");
+  }
+}
+
+static bool DelayedCommitsCheckAndRemoveSurface(
+    WindowSurfaceWayland* aSurface) {
+  MutexAutoLock lock(*gDelayedCommitLock);
+  GList* foundCommit = g_list_find(gDelayedCommits, aSurface);
+  if (foundCommit) {
+    gDelayedCommits = g_list_delete_link(gDelayedCommits, foundCommit);
+  }
+  return foundCommit != nullptr;
+}
+
+static bool DelayedCommitsCheckAndAddSurface(WindowSurfaceWayland* aSurface) {
+  MutexAutoLock lock(*gDelayedCommitLock);
+  GList* foundCommit = g_list_find(gDelayedCommits, aSurface);
+  if (!foundCommit) {
+    gDelayedCommits = g_list_prepend(gDelayedCommits, aSurface);
+  }
+  return foundCommit == nullptr;
+}
+
+// When a new window is created we may not have a valid wl_surface
+// for drawing (Gtk haven't created it yet). All commits are queued
+// and CommitWaylandBuffer() is called by timer when wl_surface is ready
+// for drawing.
+static void WaylandBufferDelayCommitHandler(WindowSurfaceWayland* aSurface) {
+  if (DelayedCommitsCheckAndRemoveSurface(aSurface)) {
+    aSurface->CommitWaylandBuffer();
+  }
+}
+
 RefPtr<nsWaylandDisplay> WindowBackBuffer::GetWaylandDisplay() {
   return mWindowSurfaceWayland->GetWaylandDisplay();
 }
@@ -399,7 +436,6 @@ WindowSurfaceWayland::WindowSurfaceWayla
       mWaylandFullscreenDamage(false),
       mFrameCallback(nullptr),
       mLastCommittedSurface(nullptr),
-      mDelayedCommitHandle(nullptr),
       mLastCommitTime(0),
       mDrawToWaylandBufferDirectly(true),
       mCanSwitchWaylandBuffer(true),
@@ -411,6 +447,7 @@ WindowSurfaceWayland::WindowSurfaceWayla
   for (int i = 0; i < BACK_BUFFER_NUM; i++) {
     mShmBackupBuffer[i] = nullptr;
   }
+  DelayedCommitsEnsureMutext();
 }
 
 WindowSurfaceWayland::~WindowSurfaceWayland() {
@@ -418,12 +455,9 @@ WindowSurfaceWayland::~WindowSurfaceWayl
     NS_WARNING("Deleted WindowSurfaceWayland with a pending commit!");
   }
 
-  if (mDelayedCommitHandle) {
-    // Delete reference to this to prevent WaylandBufferDelayCommitHandler()
-    // operate on released this. mDelayedCommitHandle itself will
-    // be released at WaylandBufferDelayCommitHandler().
-    *mDelayedCommitHandle = nullptr;
-  }
+  // Delete reference to this to prevent WaylandBufferDelayCommitHandler()
+  // operate on released this.
+  DelayedCommitsCheckAndRemoveSurface(this);
 
   if (mFrameCallback) {
     wl_callback_destroy(mFrameCallback);
@@ -864,23 +898,11 @@ bool WindowSurfaceWayland::CommitImageCa
   return true;
 }
 
-static void WaylandBufferDelayCommitHandler(WindowSurfaceWayland** aSurface) {
-  if (*aSurface) {
-    (*aSurface)->DelayedCommitHandler();
-  } else {
-    // Referenced WindowSurfaceWayland is already deleted.
-    // Do nothing but just release the mDelayedCommitHandle allocated at
-    // WindowSurfaceWayland::CommitWaylandBuffer().
-    free(aSurface);
-  }
-}
-
 void WindowSurfaceWayland::CommitWaylandBuffer() {
   LOGWAYLAND(("WindowSurfaceWayland::CommitWaylandBuffer [%p]\n", (void*)this));
   LOGWAYLAND(
       ("   mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly));
   LOGWAYLAND(("   mCanSwitchWaylandBuffer = %d\n", mCanSwitchWaylandBuffer));
-  LOGWAYLAND(("   mDelayedCommitHandle = %p\n", mDelayedCommitHandle));
   LOGWAYLAND(("   mFrameCallback = %p\n", mFrameCallback));
   LOGWAYLAND(("   mLastCommittedSurface = %p\n", mLastCommittedSurface));
   LOGWAYLAND(("   mBufferPendingCommit = %d\n", mBufferPendingCommit));
@@ -916,16 +938,10 @@ void WindowSurfaceWayland::CommitWayland
     MOZ_ASSERT(!mFrameCallback || waylandSurface != mLastCommittedSurface,
                "Missing wayland surface at frame callback!");
 
-    // Do nothing if there's already mDelayedCommitHandle pending.
-    if (!mDelayedCommitHandle) {
-      mDelayedCommitHandle = static_cast<WindowSurfaceWayland**>(
-          moz_xmalloc(sizeof(*mDelayedCommitHandle)));
-      *mDelayedCommitHandle = this;
-
+    if (DelayedCommitsCheckAndAddSurface(this)) {
       MessageLoop::current()->PostDelayedTask(
           NewRunnableFunction("WaylandBackBufferCommit",
-                              &WaylandBufferDelayCommitHandler,
-                              mDelayedCommitHandle),
+                              &WaylandBufferDelayCommitHandler, this),
           EVENT_LOOP_DELAY);
     }
     return;
@@ -1037,25 +1053,6 @@ void WindowSurfaceWayland::FrameCallback
 
   CommitWaylandBuffer();
 }
-
-void WindowSurfaceWayland::DelayedCommitHandler() {
-  MOZ_ASSERT(mIsMainThread == NS_IsMainThread());
-  MOZ_ASSERT(mDelayedCommitHandle != nullptr, "Missing mDelayedCommitHandle!");
-
-  LOGWAYLAND(
-      ("WindowSurfaceWayland::DelayedCommitHandler [%p]\n", (void*)this));
-
-  if (!mDelayedCommitHandle) {
-    LOGWAYLAND(("    We're missing mDelayedCommitHandle!\n"));
-    return;
-  }
-
-  *mDelayedCommitHandle = nullptr;
-  free(mDelayedCommitHandle);
-  mDelayedCommitHandle = nullptr;
-
-  CommitWaylandBuffer();
-}
 
 }  // namespace widget
 }  // namespace mozilla
diff -up firefox-82.0/widget/gtk/WindowSurfaceWayland.h.1656727 firefox-82.0/widget/gtk/WindowSurfaceWayland.h
--- firefox-82.0/widget/gtk/WindowSurfaceWayland.h.1656727	2020-10-14 19:20:27.000000000 +0200
+++ firefox-82.0/widget/gtk/WindowSurfaceWayland.h	2020-10-15 16:16:53.528050175 +0200
@@ -161,7 +161,7 @@ class WindowSurfaceWayland : public Wind
   // If we fail (wayland compositor is busy,
   // wl_surface is not created yet) we queue the painting
   // and we send it to wayland compositor in FrameCallbackHandler()/
-  // DelayedCommitHandler/CommitWaylandBuffer().
+  // CommitWaylandBuffer().
   already_AddRefed<gfx::DrawTarget> Lock(
       const LayoutDeviceIntRegion& aRegion) override;
   void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final;
@@ -171,12 +171,6 @@ class WindowSurfaceWayland : public Wind
   // queued commits.
   void FrameCallbackHandler();
 
-  // When a new window is created we may not have a valid wl_surface
-  // for drawing (Gtk haven't created it yet). All commits are queued
-  // and DelayedCommitHandler() is called by timer when wl_surface is ready
-  // for drawing.
-  void DelayedCommitHandler();
-
   // Try to commit all queued drawings to Wayland compositor. This is usually
   // called from other routines but can be used to explicitly flush
   // all drawings as we do when wl_buffer is released
@@ -249,17 +243,14 @@ class WindowSurfaceWayland : public Wind
   wl_callback* mFrameCallback;
   wl_surface* mLastCommittedSurface;
 
-  // Registered reference to pending DelayedCommitHandler() call.
-  WindowSurfaceWayland** mDelayedCommitHandle;
-
   // Cached drawings. If we can't get WaylandBuffer (wl_buffer) at
   // WindowSurfaceWayland::Lock() we direct gecko rendering to
   // mImageSurface.
   // If we can't get WaylandBuffer at WindowSurfaceWayland::Commit()
   // time, mImageSurface is moved to mDelayedImageCommits which
   // holds all cached drawings.
-  // mDelayedImageCommits can be drawn by FrameCallbackHandler(),
-  // DelayedCommitHandler() or when WaylandBuffer is detached.
+  // mDelayedImageCommits can be drawn by FrameCallbackHandler()
+  // or when WaylandBuffer is detached.
   RefPtr<gfxImageSurface> mImageSurface;
   AutoTArray<WindowImageSurface, 30> mDelayedImageCommits;
 
@@ -282,8 +273,8 @@ class WindowSurfaceWayland : public Wind
   // We can't send WaylandBuffer (wl_buffer) to compositor when gecko
   // is rendering into it (i.e. between WindowSurfaceWayland::Lock() /
   // WindowSurfaceWayland::Commit()).
-  // Thus we use mBufferCommitAllowed to disable commit by callbacks
-  // (FrameCallbackHandler(), DelayedCommitHandler())
+  // Thus we use mBufferCommitAllowed to disable commit by
+  // CommitWaylandBuffer().
   bool mBufferCommitAllowed;
 
   // We need to clear WaylandBuffer when entire transparent window is repainted.