Bug 1506767 - Remove redundant iteration in CompositorBridgeParent::NotifyPipelineRendered() r=mattwoodrow
authorsotaro <sotaro.ikeda.g@gmail.com>
Sat, 17 Nov 2018 12:27:54 +0900
changeset 446907 896d672ed0abaece6317543d2d14783044c2709a
parent 446906 241738774bb1b1f998770af0e0dd82c6ba8de36d
child 446908 8abb8992a558885e973d5c308c11fd7a9e6ed7bb
push id35053
push userapavel@mozilla.com
push dateSat, 17 Nov 2018 11:27:54 +0000
treeherdermozilla-central@e4deec61fc8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1506767
milestone65.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 1506767 - Remove redundant iteration in CompositorBridgeParent::NotifyPipelineRendered() r=mattwoodrow
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/wr/AsyncImagePipelineManager.cpp
gfx/layers/wr/AsyncImagePipelineManager.h
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -2206,17 +2206,17 @@ CompositorBridgeParent::DidComposite(Tim
 
 void
 CompositorBridgeParent::NotifyPipelineRendered(const wr::PipelineId& aPipelineId,
                                                const wr::Epoch& aEpoch,
                                                TimeStamp& aCompositeStart,
                                                TimeStamp& aCompositeEnd,
                                                wr::RendererStats* aStats)
 {
-  if (!mWrBridge) {
+  if (!mWrBridge || !mAsyncImageManager) {
     return;
   }
 
   RefPtr<UiCompositorControllerParent> uiController =
     UiCompositorControllerParent::GetFromRootLayerTreeId(mRootLayerTreeID);
 
   if (mWrBridge->PipelineId() == aPipelineId) {
     mWrBridge->RemoveEpochDataPriorTo(aEpoch);
@@ -2229,31 +2229,25 @@ CompositorBridgeParent::NotifyPipelineRe
       mWrBridge->ExtractImageCompositeNotifications(&notifications);
       if (!notifications.IsEmpty()) {
         Unused << ImageBridgeParent::NotifyImageComposites(notifications);
       }
     }
     return;
   }
 
-  MonitorAutoLock lock(*sIndirectLayerTreesLock);
-  ForEachIndirectLayerTree([&] (LayerTreeState* lts, const LayersId& aLayersId) -> void {
-    if (lts->mCrossProcessParent &&
-        lts->mWrBridge &&
-        lts->mWrBridge->PipelineId() == aPipelineId) {
-
-      lts->mWrBridge->RemoveEpochDataPriorTo(aEpoch);
-
+  auto wrBridge = mAsyncImageManager->GetWrBridge(aPipelineId);
+  if (wrBridge && wrBridge->GetCompositorBridge()) {
+      MOZ_ASSERT(!wrBridge->IsRootWebRenderBridgeParent());
+      wrBridge->RemoveEpochDataPriorTo(aEpoch);
       if (!mPaused) {
-        CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
-        TransactionId transactionId = lts->mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd, uiController, aStats);
-        Unused << cpcp->SendDidComposite(aLayersId, transactionId, aCompositeStart, aCompositeEnd);
+        TransactionId transactionId = wrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd, uiController, aStats);
+        Unused << wrBridge->GetCompositorBridge()->SendDidComposite(wrBridge->GetLayersId(), transactionId, aCompositeStart, aCompositeEnd);
       }
-    }
-  });
+  }
 }
 
 RefPtr<AsyncImagePipelineManager>
 CompositorBridgeParent::GetAsyncImagePipelineManager() const
 {
   return mAsyncImageManager;
 }
 
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -96,50 +96,72 @@ AsyncImagePipelineManager::GetNextExtern
   ++sNextId;
   MOZ_RELEASE_ASSERT(sNextId != UINT32_MAX);
   // gecko allocates external image id as (IdNamespace:32bit + ResourceId:32bit).
   // And AsyncImagePipelineManager uses IdNamespace = 0.
   return wr::ToExternalImageId((uint64_t)sNextId);
 }
 
 void
-AsyncImagePipelineManager::AddPipeline(const wr::PipelineId& aPipelineId)
+AsyncImagePipelineManager::AddPipeline(const wr::PipelineId& aPipelineId, WebRenderBridgeParent* aWrBridge)
 {
   if (mDestroyed) {
     return;
   }
   uint64_t id = wr::AsUint64(aPipelineId);
 
   PipelineTexturesHolder* holder = mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
   if(holder) {
     // This could happen during tab move between different windows.
     // Previously removed holder could be still alive for waiting destroyed.
     MOZ_ASSERT(holder->mDestroyedEpoch.isSome());
     holder->mDestroyedEpoch = Nothing(); // Revive holder
+    holder->mWrBridge = aWrBridge;
     return;
   }
   holder = new PipelineTexturesHolder();
+  holder->mWrBridge = aWrBridge;
   mPipelineTexturesHolders.Put(id, holder);
 }
 
 void
 AsyncImagePipelineManager::RemovePipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch)
 {
   if (mDestroyed) {
     return;
   }
 
   PipelineTexturesHolder* holder = mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
   MOZ_ASSERT(holder);
   if (!holder) {
     return;
   }
+  holder->mWrBridge = nullptr;
   holder->mDestroyedEpoch = Some(aEpoch);
 }
 
+WebRenderBridgeParent*
+AsyncImagePipelineManager::GetWrBridge(const wr::PipelineId& aPipelineId)
+{
+  if (mDestroyed) {
+    return nullptr;
+  }
+
+  PipelineTexturesHolder* holder = mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
+  if (!holder) {
+    return nullptr;
+  }
+  if (holder->mWrBridge) {
+    MOZ_ASSERT(holder->mDestroyedEpoch.isNothing());
+    return holder->mWrBridge;
+  }
+
+  return nullptr;
+}
+
 void
 AsyncImagePipelineManager::AddAsyncImagePipeline(const wr::PipelineId& aPipelineId, WebRenderImageHost* aImageHost)
 {
   if (mDestroyed) {
     return;
   }
   MOZ_ASSERT(aImageHost);
   uint64_t id = wr::AsUint64(aPipelineId);
--- a/gfx/layers/wr/AsyncImagePipelineManager.h
+++ b/gfx/layers/wr/AsyncImagePipelineManager.h
@@ -42,18 +42,19 @@ public:
   explicit AsyncImagePipelineManager(already_AddRefed<wr::WebRenderAPI>&& aApi);
 
 protected:
   ~AsyncImagePipelineManager();
 
 public:
   void Destroy();
 
-  void AddPipeline(const wr::PipelineId& aPipelineId);
+  void AddPipeline(const wr::PipelineId& aPipelineId, WebRenderBridgeParent* aWrBridge = nullptr);
   void RemovePipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch);
+  WebRenderBridgeParent* GetWrBridge(const wr::PipelineId& aPipelineId);
 
   void HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture);
   void HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHostWrapper* aWrTextureWrapper);
   void HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, const wr::ExternalImageId& aImageId);
 
   // This is called from the Renderer thread to notify this class about the
   // pipelines in the most recently completed render. A copy of the update
   // information is put into mUpdatesQueue.
@@ -159,16 +160,17 @@ private:
   };
 
   struct PipelineTexturesHolder {
     // Holds forwarding WebRenderTextureHosts.
     std::queue<ForwardingTextureHost> mTextureHosts;
     std::queue<ForwardingTextureHostWrapper> mTextureHostWrappers;
     std::queue<UniquePtr<ForwardingExternalImage>> mExternalImages;
     Maybe<wr::Epoch> mDestroyedEpoch;
+    WebRenderBridgeParent* MOZ_NON_OWNING_REF mWrBridge = nullptr;
   };
 
   struct AsyncImagePipeline {
     AsyncImagePipeline();
     void Update(const LayoutDeviceRect& aScBounds,
                 const gfx::Matrix4x4& aScTransform,
                 const gfx::MaybeIntSize& aScaleToSize,
                 const wr::ImageRendering& aFilter,
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -315,17 +315,17 @@ WebRenderBridgeParent::WebRenderBridgePa
   , mIdNamespace(aApi->GetNamespace())
   , mPaused(false)
   , mDestroyed(false)
   , mReceivedDisplayList(false)
   , mIsFirstPaint(true)
 {
   MOZ_ASSERT(mAsyncImageManager);
   MOZ_ASSERT(mAnimStorage);
-  mAsyncImageManager->AddPipeline(mPipelineId);
+  mAsyncImageManager->AddPipeline(mPipelineId, this);
   if (IsRootWebRenderBridgeParent()) {
     MOZ_ASSERT(!mCompositorScheduler);
     mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
   }
 }
 
 WebRenderBridgeParent::WebRenderBridgeParent(const wr::PipelineId& aPipelineId)
   : mCompositorBridge(nullptr)
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -61,16 +61,17 @@ public:
                         TimeDuration aVsyncRate);
 
   static WebRenderBridgeParent* CreateDestroyed(const wr::PipelineId& aPipelineId);
 
   wr::PipelineId PipelineId() { return mPipelineId; }
   already_AddRefed<wr::WebRenderAPI> GetWebRenderAPI() { return do_AddRef(mApi); }
   AsyncImagePipelineManager* AsyncImageManager() { return mAsyncImageManager; }
   CompositorVsyncScheduler* CompositorScheduler() { return mCompositorScheduler.get(); }
+  CompositorBridgeParentBase* GetCompositorBridge() { return mCompositorBridge; }
 
   mozilla::ipc::IPCResult RecvEnsureConnected(TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                               MaybeIdNamespace* aMaybeIdNamespace) override;
 
   mozilla::ipc::IPCResult RecvNewCompositable(const CompositableHandle& aHandle,
                                               const TextureInfo& aInfo) override;
   mozilla::ipc::IPCResult RecvReleaseCompositable(const CompositableHandle& aHandle) override;
 
@@ -218,16 +219,18 @@ public:
    * display list. This is intended to be called by the widget code when it
    * loses its viewport information (or for whatever reason wants to refresh
    * the viewport information). The message will sent back to the widget code
    * via UiCompositorControllerParent::NotifyFirstPaint() when the corresponding
    * transaction is flushed.
    */
   void ForceIsFirstPaint() { mIsFirstPaint = true; }
 
+  bool IsRootWebRenderBridgeParent() const;
+  LayersId GetLayersId() const;
 private:
   class ScheduleSharedSurfaceRelease;
 
   explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId);
   virtual ~WebRenderBridgeParent();
 
   void UpdateAPZFocusState(const FocusTarget& aFocus);
   void UpdateAPZScrollData(const wr::Epoch& aEpoch, WebRenderScrollData&& aData);
@@ -258,32 +261,29 @@ private:
                                     wr::TransactionBuilder& aTxnForImageBridge);
   void RemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId,
                                        wr::TransactionBuilder& aTxn);
 
   void DeleteImage(const wr::ImageKey& aKey,
                    wr::TransactionBuilder& aUpdates);
   void ReleaseTextureOfImage(const wr::ImageKey& aKey);
 
-  LayersId GetLayersId() const;
   bool ProcessWebRenderParentCommands(const InfallibleTArray<WebRenderParentCommand>& aCommands,
                                       wr::TransactionBuilder& aTxn);
 
   void ClearResources();
   bool ShouldParentObserveEpoch();
   mozilla::ipc::IPCResult HandleShutdown();
 
   // Returns true if there is any animation (including animations in delay
   // phase).
   bool AdvanceAnimations();
   bool SampleAnimations(nsTArray<wr::WrOpacityProperty>& aOpacityArray,
                         nsTArray<wr::WrTransformProperty>& aTransformArray);
 
-  bool IsRootWebRenderBridgeParent() const;
-
   CompositorBridgeParent* GetRootCompositorBridgeParent() const;
 
   RefPtr<WebRenderBridgeParent> GetRootWebRenderBridgeParent() const;
 
   // Tell APZ what the subsequent sampling's timestamp should be.
   void SetAPZSampleTime();
 
   wr::Epoch GetNextWrEpoch();