Bug 1449982 - Maintain a map from WrWindowId to APZUpdater. r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 10 Apr 2018 12:29:55 -0400
changeset 412679 c40aa91bc0b6e9d8d5b525fa86a8be73c8d31cae
parent 412678 7af325560dfa213ba0c34b24f497443138c9c601
child 412680 7b83f46b5fb38df3311a6b4659d32b6e75b9c275
push id101981
push useraiakab@mozilla.com
push dateTue, 10 Apr 2018 22:18:59 +0000
treeherdermozilla-inbound@9ad2b8aabfae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1449982
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1449982 - Maintain a map from WrWindowId to APZUpdater. r=botond This will allow callbacks from rust code to get a handle to the necessary APZUpdater instance on which to invoke functions. MozReview-Commit-ID: 13XdzZrrtI5
gfx/layers/apz/public/APZUpdater.h
gfx/layers/apz/src/APZUpdater.cpp
gfx/layers/ipc/CompositorBridgeParent.cpp
--- a/gfx/layers/apz/public/APZUpdater.h
+++ b/gfx/layers/apz/public/APZUpdater.h
@@ -2,22 +2,30 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_APZUpdater_h
 #define mozilla_layers_APZUpdater_h
 
+#include <unordered_map>
+
 #include "LayersTypes.h"
 #include "mozilla/layers/APZTestData.h"
+#include "mozilla/StaticMutex.h"
 #include "nsThreadUtils.h"
 #include "Units.h"
 
 namespace mozilla {
+
+namespace wr {
+struct WrWindowId;
+} // namespace wr
+
 namespace layers {
 
 class APZCTreeManager;
 class FocusTarget;
 class Layer;
 class WebRenderScrollData;
 
 /**
@@ -29,16 +37,17 @@ class WebRenderScrollData;
  */
 class APZUpdater {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZUpdater)
 
 public:
   explicit APZUpdater(const RefPtr<APZCTreeManager>& aApz);
 
   bool HasTreeManager(const RefPtr<APZCTreeManager>& aApz);
+  void SetWebRenderWindowId(const wr::WindowId& aWindowId);
 
   void ClearTree();
   void UpdateFocusState(LayersId aRootLayerTreeId,
                         LayersId aOriginatingLayersId,
                         const FocusTarget& aFocusTarget);
   void UpdateHitTestingTree(LayersId aRootLayerTreeId,
                             Layer* aRoot,
                             bool aIsFirstPaint,
@@ -92,14 +101,21 @@ public:
    */
   void RunOnControllerThread(already_AddRefed<Runnable> aTask);
 
 protected:
   virtual ~APZUpdater();
 
 private:
   RefPtr<APZCTreeManager> mApz;
+
+  // Used to manage the mapping from a WR window id to APZUpdater. These are only
+  // used if WebRender is enabled. Both sWindowIdMap and mWindowId should only
+  // be used while holding the sWindowIdLock.
+  static StaticMutex sWindowIdLock;
+  static std::unordered_map<uint64_t, APZUpdater*> sWindowIdMap;
+  Maybe<wr::WrWindowId> mWindowId;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_APZUpdater_h
--- a/gfx/layers/apz/src/APZUpdater.cpp
+++ b/gfx/layers/apz/src/APZUpdater.cpp
@@ -8,46 +8,78 @@
 
 #include "APZCTreeManager.h"
 #include "AsyncPanZoomController.h"
 #include "base/task.h"
 #include "mozilla/layers/APZThreadUtils.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/SynchronousTask.h"
 #include "mozilla/layers/WebRenderScrollData.h"
+#include "mozilla/webrender/WebRenderTypes.h"
 
 namespace mozilla {
 namespace layers {
 
+StaticMutex APZUpdater::sWindowIdLock;
+std::unordered_map<uint64_t, APZUpdater*> APZUpdater::sWindowIdMap;
+
+
 APZUpdater::APZUpdater(const RefPtr<APZCTreeManager>& aApz)
   : mApz(aApz)
 {
   MOZ_ASSERT(aApz);
   mApz->SetUpdater(this);
 }
 
 APZUpdater::~APZUpdater()
 {
   mApz->SetUpdater(nullptr);
+
+  StaticMutexAutoLock lock(sWindowIdLock);
+  if (mWindowId) {
+    // Ensure that ClearTree was called and the task got run
+    MOZ_ASSERT(sWindowIdMap.find(wr::AsUint64(*mWindowId)) == sWindowIdMap.end());
+  }
 }
 
 bool
 APZUpdater::HasTreeManager(const RefPtr<APZCTreeManager>& aApz)
 {
   return aApz.get() == mApz.get();
 }
 
 void
+APZUpdater::SetWebRenderWindowId(const wr::WindowId& aWindowId)
+{
+  StaticMutexAutoLock lock(sWindowIdLock);
+  MOZ_ASSERT(!mWindowId);
+  mWindowId = Some(aWindowId);
+  sWindowIdMap[wr::AsUint64(aWindowId)] = this;
+}
+
+void
 APZUpdater::ClearTree()
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  RunOnUpdaterThread(NewRunnableMethod(
-      "APZUpdater::ClearTree",
-      mApz,
-      &APZCTreeManager::ClearTree));
+  RefPtr<APZUpdater> self = this;
+  RunOnUpdaterThread(NS_NewRunnableFunction(
+    "APZUpdater::ClearTree",
+    [=]() {
+      self->mApz->ClearTree();
+
+      // Once ClearTree is called on the APZCTreeManager, we are in a shutdown
+      // phase. After this point it's ok if WebRender cannot get a hold of the
+      // updater via the window id, and it's a good point to remove the mapping
+      // and avoid leaving a dangling pointer to this object.
+      StaticMutexAutoLock lock(sWindowIdLock);
+      if (self->mWindowId) {
+        sWindowIdMap.erase(wr::AsUint64(*(self->mWindowId)));
+      }
+    }
+  ));
 }
 
 void
 APZUpdater::UpdateFocusState(LayersId aRootLayerTreeId,
                              LayersId aOriginatingLayersId,
                              const FocusTarget& aFocusTarget)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1762,16 +1762,22 @@ CompositorBridgeParent::AllocPWebRenderB
   MOZ_ASSERT(wr::AsLayersId(aPipelineId) == mRootLayerTreeID);
   MOZ_ASSERT(!mWrBridge);
   MOZ_ASSERT(!mCompositor);
   MOZ_ASSERT(!mCompositorScheduler);
   MOZ_ASSERT(mWidget);
 
   RefPtr<widget::CompositorWidget> widget = mWidget;
   wr::WrWindowId windowId = wr::NewWindowId();
+  if (mApzUpdater) {
+    // If APZ is enabled, we need to register the APZ updater with the window id
+    // before the updater thread is created in WebRenderAPI::Create, so
+    // that the callback from the updater thread can find the right APZUpdater.
+    mApzUpdater->SetWebRenderWindowId(windowId);
+  }
   RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(this, Move(widget), windowId, aSize);
   if (!api) {
     mWrBridge = WebRenderBridgeParent::CreateDestroyed(aPipelineId);
     mWrBridge.get()->AddRef(); // IPDL reference
     *aIdNamespace = mWrBridge->GetIdNamespace();
     *aTextureFactoryIdentifier = TextureFactoryIdentifier(LayersBackend::LAYERS_NONE);
     return mWrBridge;
   }