Bug 1417519 - Add a mechanism for APZ to get the WebRenderAPI instance. r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 17 Nov 2017 10:54:24 -0500
changeset 437090 f9e128e8c8a67e7ca248b4b13ecd7a86714021d9
parent 437089 273eac46d15c3a11eebfb89b412e4752d319b68a
child 437091 ff8e0f72dd9d5d18b7456c224148a3f309e28a8a
push id117
push userfmarier@mozilla.com
push dateTue, 28 Nov 2017 20:17:16 +0000
reviewersbotond
bugs1417519
milestone59.0a1
Bug 1417519 - Add a mechanism for APZ to get the WebRenderAPI instance. r=botond MozReview-Commit-ID: FhdQhKIfQbw
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
gfx/layers/apz/test/gtest/APZTestCommon.h
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -212,18 +212,19 @@ private:
 APZCTreeManager::CalculatePendingDisplayPort(
   const FrameMetrics& aFrameMetrics,
   const ParentLayerPoint& aVelocity)
 {
   return AsyncPanZoomController::CalculatePendingDisplayPort(
     aFrameMetrics, aVelocity);
 }
 
-APZCTreeManager::APZCTreeManager()
+APZCTreeManager::APZCTreeManager(uint64_t aRootLayersId)
     : mInputQueue(new InputQueue()),
+      mRootLayersId(aRootLayersId),
       mTreeLock("APZCTreeLock"),
       mHitResultForInputBlock(HitNothing),
       mRetainedTouchIdentifier(-1),
       mInScrollbarTouchDrag(false),
       mApzcTreeLog("apzctree")
 {
   RefPtr<APZCTreeManager> self(this);
   NS_DispatchToMainThread(
@@ -448,16 +449,17 @@ APZCTreeManager::UpdateHitTestingTree(ui
 
 bool
 APZCTreeManager::PushStateToWR(wr::WebRenderAPI* aWrApi,
                                const TimeStamp& aSampleTime,
                                nsTArray<wr::WrTransformProperty>& aTransformArray)
 {
   APZThreadUtils::AssertOnCompositorThread();
   MOZ_ASSERT(aWrApi);
+  MOZ_ASSERT(aWrApi == RefPtr<wr::WebRenderAPI>(GetWebRenderAPI()).get());
 
   MutexAutoLock lock(mTreeLock);
 
   // During the first pass through the tree, we build a cache of guid->HTTN so
   // that we can find the relevant APZC instances quickly in subsequent passes,
   // such as the one below to generate scrollbar transforms. Without this, perf
   // could end up being O(n^2) instead of O(n log n) because we'd have to search
   // the tree to find the corresponding APZC every time we hit a thumb node.
@@ -2732,16 +2734,28 @@ APZCTreeManager::ComputeTransformForNode
               nullptr);
         });
     }
   }
   // Otherwise, the node does not have an async transform.
   return aNode->GetTransform() * AsyncTransformMatrix();
 }
 
+already_AddRefed<wr::WebRenderAPI>
+APZCTreeManager::GetWebRenderAPI() const
+{
+  RefPtr<wr::WebRenderAPI> api;
+  if (LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(mRootLayersId)) {
+    if (state->mWrBridge) {
+      api = state->mWrBridge->GetWebRenderAPI();
+    }
+  }
+  return api.forget();
+}
+
 #if defined(MOZ_WIDGET_ANDROID)
 void
 APZCTreeManager::InitializeDynamicToolbarAnimator(const int64_t& aRootLayerTreeId)
 {
   MOZ_ASSERT(mToolbarAnimator);
   mToolbarAnimator->Initialize(aRootLayerTreeId);
 }
 
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -99,17 +99,17 @@ class APZCTreeManager : public IAPZCTree
 
   // Helper struct to hold some state while we build the hit-testing tree. The
   // sole purpose of this struct is to shorten the argument list to
   // UpdateHitTestingTree. All the state that we don't need to
   // push on the stack during recursion and pop on unwind is stored here.
   struct TreeBuildingState;
 
 public:
-  APZCTreeManager();
+  explicit APZCTreeManager(uint64_t aRootLayersId);
 
   /**
    * Initializes the global state used in AsyncPanZoomController.
    * This is normally called when it is first needed in the constructor
    * of APZCTreeManager, but can be called manually to force it to be
    * initialized earlier.
    */
   static void InitializeGlobalState();
@@ -606,23 +606,30 @@ private:
                      const AsyncPanZoomController* apzc);
 
   void NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const;
   void NotifyAutoscrollRejected(const ScrollableLayerGuid& aGuid) const;
 
   // Requires the caller to hold mTreeLock.
   LayerToParentLayerMatrix4x4 ComputeTransformForNode(const HitTestingTreeNode* aNode) const;
 
+  // Returns a pointer to the WebRenderAPI for the root layers id this APZCTreeManager
+  // is for. This might be null (for example, if WebRender is not enabled).
+  already_AddRefed<wr::WebRenderAPI> GetWebRenderAPI() const;
+
 protected:
   /* The input queue where input events are held until we know enough to
    * figure out where they're going. Protected so gtests can access it.
    */
   RefPtr<InputQueue> mInputQueue;
 
 private:
+  /* Layers id for the root CompositorBridgeParent that owns this APZCTreeManager. */
+  uint64_t mRootLayersId;
+
   /* Whenever walking or mutating the tree rooted at mRootNode, mTreeLock must be held.
    * This lock does not need to be held while manipulating a single APZC instance in
    * isolation (that is, if its tree pointers are not being accessed or mutated). The
    * lock also needs to be held when accessing the mRootNode instance variable, as that
    * is considered part of the APZC tree management state.
    * Finally, the lock needs to be held when accessing mZoomConstraints.
    * IMPORTANT: See the note about lock ordering at the top of this file. */
   mutable mozilla::Mutex mTreeLock;
--- a/gfx/layers/apz/test/gtest/APZTestCommon.h
+++ b/gfx/layers/apz/test/gtest/APZTestCommon.h
@@ -167,17 +167,20 @@ private:
   // The following array is sorted by timestamp (tasks are inserted in order by
   // timestamp).
   nsTArray<std::pair<RefPtr<Runnable>, TimeStamp>> mTaskQueue;
   TimeStamp mTime;
 };
 
 class TestAPZCTreeManager : public APZCTreeManager {
 public:
-  explicit TestAPZCTreeManager(MockContentControllerDelayed* aMcc) : mcc(aMcc) {}
+  explicit TestAPZCTreeManager(MockContentControllerDelayed* aMcc)
+    : APZCTreeManager(0)
+    , mcc(aMcc)
+  {}
 
   RefPtr<InputQueue> GetInputQueue() const {
     return mInputQueue;
   }
 
   void ClearContentController() {
     mcc = nullptr;
   }
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -351,17 +351,17 @@ CompositorBridgeParent::InitSameProcess(
                                         const uint64_t& aLayerTreeId)
 {
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(NS_IsMainThread());
 
   mWidget = aWidget;
   mRootLayerTreeID = aLayerTreeId;
   if (mOptions.UseAPZ()) {
-    mApzcTreeManager = new APZCTreeManager();
+    mApzcTreeManager = new APZCTreeManager(mRootLayerTreeID);
   }
 
   Initialize();
 }
 
 mozilla::ipc::IPCResult
 CompositorBridgeParent::RecvInitialize(const uint64_t& aRootLayerTreeId)
 {
@@ -1122,17 +1122,17 @@ CompositorBridgeParent::AllocPAPZCTreeMa
   // We should only ever get this if APZ is enabled in this compositor.
   MOZ_ASSERT(mOptions.UseAPZ());
 
   // The main process should pass in 0 because we assume mRootLayerTreeID
   MOZ_ASSERT(aLayersId == 0);
 
   // This message doubles as initialization
   MOZ_ASSERT(!mApzcTreeManager);
-  mApzcTreeManager = new APZCTreeManager();
+  mApzcTreeManager = new APZCTreeManager(mRootLayerTreeID);
 
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[mRootLayerTreeID];
   MOZ_ASSERT(state.mParent);
   MOZ_ASSERT(!state.mApzcTreeManagerParent);
   state.mApzcTreeManagerParent = new APZCTreeManagerParent(mRootLayerTreeID, state.mParent->GetAPZCTreeManager());
 
   return state.mApzcTreeManagerParent;
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -126,17 +126,17 @@ CrossProcessCompositorBridgeParent::Allo
   CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[aLayersId];
 
   // If the widget has shutdown its compositor, we may not have had a chance yet
   // to unmap our layers id, and we could get here without a parent compositor.
   // In this case return an empty APZCTM.
   if (!state.mParent) {
     // Note: we immediately call ClearTree since otherwise the APZCTM will
     // retain a reference to itself, through the checkerboard observer.
-    RefPtr<APZCTreeManager> temp = new APZCTreeManager();
+    RefPtr<APZCTreeManager> temp = new APZCTreeManager(0);
     temp->ClearTree();
     return new APZCTreeManagerParent(aLayersId, temp);
   }
 
   MOZ_ASSERT(!state.mApzcTreeManagerParent);
   state.mApzcTreeManagerParent = new APZCTreeManagerParent(aLayersId, state.mParent->GetAPZCTreeManager());
 
   return state.mApzcTreeManagerParent;