Bug 1056381 - When a layer transaction comes in, only update the hit testing tree when necessary. r=botond
authorbd339 <bd339@tuta.io>
Mon, 16 May 2016 20:53:44 +0200
changeset 298353 ae0dd17a0c862a9b504eb37fce84c980525085d1
parent 298352 d2b250ce1693ce8691329f8ac8d447e254a8ea14
child 298354 a640e6fa8ab9977fb6c5bcf63dc4daca6699477b
push id77131
push userbballo@mozilla.com
push dateSat, 21 May 2016 22:08:10 +0000
treeherdermozilla-inbound@ae0dd17a0c86 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1056381
milestone49.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 1056381 - When a layer transaction comes in, only update the hit testing tree when necessary. r=botond MozReview-Commit-ID: KdLNEMxqtDU
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/CompositorBridgeParent.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayersMessages.ipdlh
gfx/layers/ipc/ShadowLayersManager.h
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1038,25 +1038,28 @@ CompositorBridgeParent::ScheduleTask(alr
   } else {
     MessageLoop::current()->PostDelayedTask(Move(task), time);
   }
 }
 
 void
 CompositorBridgeParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint,
     bool aScheduleComposite, uint32_t aPaintSequenceNumber,
-    bool aIsRepeatTransaction)
+    bool aIsRepeatTransaction, bool aHitTestUpdate)
 {
   if (mApzcTreeManager &&
       !aIsRepeatTransaction &&
       mLayerManager &&
       mLayerManager->GetRoot()) {
     AutoResolveRefLayers resolve(mCompositionManager);
-    mApzcTreeManager->UpdateHitTestingTree(this, mLayerManager->GetRoot(),
-        aIsFirstPaint, aId, aPaintSequenceNumber);
+
+    if (aHitTestUpdate) {
+      mApzcTreeManager->UpdateHitTestingTree(this, mLayerManager->GetRoot(),
+          aIsFirstPaint, aId, aPaintSequenceNumber);
+    }
 
     mLayerManager->NotifyShadowTreeTransaction();
   }
   if (aScheduleComposite) {
     ScheduleComposition();
   }
 }
 
@@ -1285,33 +1288,35 @@ void
 CompositorBridgeParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
                                             const uint64_t& aTransactionId,
                                             const TargetConfig& aTargetConfig,
                                             const InfallibleTArray<PluginWindowData>& aUnused,
                                             bool aIsFirstPaint,
                                             bool aScheduleComposite,
                                             uint32_t aPaintSequenceNumber,
                                             bool aIsRepeatTransaction,
-                                            int32_t aPaintSyncId)
+                                            int32_t aPaintSyncId,
+                                            bool aHitTestUpdate)
 {
   ScheduleRotationOnCompositorThread(aTargetConfig, aIsFirstPaint);
 
   // Instruct the LayerManager to update its render bounds now. Since all the orientation
   // change, dimension change would be done at the stage, update the size here is free of
   // race condition.
   mLayerManager->UpdateRenderBounds(aTargetConfig.naturalBounds());
   mLayerManager->SetRegionToClear(aTargetConfig.clearRegion());
   mLayerManager->GetCompositor()->SetScreenRotation(aTargetConfig.rotation());
 
   mCompositionManager->Updated(aIsFirstPaint, aTargetConfig, aPaintSyncId);
   Layer* root = aLayerTree->GetRoot();
   mLayerManager->SetRoot(root);
 
-  if (mApzcTreeManager && !aIsRepeatTransaction) {
+  if (mApzcTreeManager && !aIsRepeatTransaction && aHitTestUpdate) {
     AutoResolveRefLayers resolve(mCompositionManager);
+
     mApzcTreeManager->UpdateHitTestingTree(this, root, aIsFirstPaint,
         mRootLayerTreeID, aPaintSequenceNumber);
   }
 
   // The transaction ID might get reset to 1 if the page gets reloaded, see
   // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
   // Otherwise, it should be continually increasing.
   MOZ_ASSERT(aTransactionId == 1 || aTransactionId > mPendingTransaction);
@@ -1915,17 +1920,18 @@ public:
   virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
                                    const uint64_t& aTransactionId,
                                    const TargetConfig& aTargetConfig,
                                    const InfallibleTArray<PluginWindowData>& aPlugins,
                                    bool aIsFirstPaint,
                                    bool aScheduleComposite,
                                    uint32_t aPaintSequenceNumber,
                                    bool aIsRepeatTransaction,
-                                   int32_t /*aPaintSyncId: unused*/) override;
+                                   int32_t /*aPaintSyncId: unused*/,
+                                   bool aHitTestUpdate) override;
   virtual void ForceComposite(LayerTransactionParent* aLayerTree) override;
   virtual void NotifyClearCachedResources(LayerTransactionParent* aLayerTree) override;
   virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree,
                                  const TimeStamp& aTime) override;
   virtual void LeaveTestMode(LayerTransactionParent* aLayerTree) override;
   virtual void ApplyAsyncProperties(LayerTransactionParent* aLayerTree)
                override;
   virtual void FlushApzRepaints(const LayerTransactionParent* aLayerTree) override;
@@ -2333,17 +2339,18 @@ CrossProcessCompositorBridgeParent::Shad
   LayerTransactionParent* aLayerTree,
   const uint64_t& aTransactionId,
   const TargetConfig& aTargetConfig,
   const InfallibleTArray<PluginWindowData>& aPlugins,
   bool aIsFirstPaint,
   bool aScheduleComposite,
   uint32_t aPaintSequenceNumber,
   bool aIsRepeatTransaction,
-  int32_t /*aPaintSyncId: unused*/)
+  int32_t /*aPaintSyncId: unused*/,
+  bool aHitTestUpdate)
 {
   uint64_t id = aLayerTree->GetId();
 
   MOZ_ASSERT(id != 0);
 
   CompositorBridgeParent::LayerTreeState* state =
     CompositorBridgeParent::GetIndirectShadowTree(id);
   if (!state) {
@@ -2358,17 +2365,17 @@ CrossProcessCompositorBridgeParent::Shad
   }
   UpdateIndirectTree(id, shadowRoot, aTargetConfig);
 
   // Cache the plugin data for this remote layer tree
   state->mPluginData = aPlugins;
   state->mUpdatedPluginDataAvailable = true;
 
   state->mParent->NotifyShadowTreeTransaction(id, aIsFirstPaint, aScheduleComposite,
-      aPaintSequenceNumber, aIsRepeatTransaction);
+      aPaintSequenceNumber, aIsRepeatTransaction, aHitTestUpdate);
 
   // Send the 'remote paint ready' message to the content thread if it has already asked.
   if(mNotifyAfterRemotePaint)  {
     Unused << SendRemotePaintIsReady();
     mNotifyAfterRemotePaint = false;
   }
 
   if (state->mLayerTreeReadyObserver) {
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -261,17 +261,18 @@ public:
   virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
                                    const uint64_t& aTransactionId,
                                    const TargetConfig& aTargetConfig,
                                    const InfallibleTArray<PluginWindowData>& aPlugins,
                                    bool aIsFirstPaint,
                                    bool aScheduleComposite,
                                    uint32_t aPaintSequenceNumber,
                                    bool aIsRepeatTransaction,
-                                   int32_t aPaintSyncId) override;
+                                   int32_t aPaintSyncId,
+                                   bool aHitTestUpdate) override;
   virtual void ForceComposite(LayerTransactionParent* aLayerTree) override;
   virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree,
                                  const TimeStamp& aTime) override;
   virtual void LeaveTestMode(LayerTransactionParent* aLayerTree) override;
   virtual void ApplyAsyncProperties(LayerTransactionParent* aLayerTree)
                override;
   virtual void FlushApzRepaints(const LayerTransactionParent* aLayerTree) override;
   virtual void GetAPZTestData(const LayerTransactionParent* aLayerTree,
@@ -343,17 +344,17 @@ public:
    * otherwise.
    */
   bool ScheduleResumeOnCompositorThread();
   bool ScheduleResumeOnCompositorThread(int width, int height);
 
   virtual void ScheduleComposition();
   void NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint,
       bool aScheduleComposite, uint32_t aPaintSequenceNumber,
-      bool aIsRepeatTransaction);
+      bool aIsRepeatTransaction, bool aHitTestUpdate);
 
   /**
    * Check rotation info and schedule a rendering task if needed.
    * Only can be called from compositor thread.
    */
   void ScheduleRotationOnCompositorThread(const TargetConfig& aTargetConfig, bool aIsFirstPaint);
 
   /**
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -260,65 +260,80 @@ LayerTransactionParent::RecvUpdate(Infal
   AutoLayerTransactionParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
   EditReplyVector replyv;
 
   {
     AutoResolveRefLayers resolve(mShadowLayersManager->GetCompositionManager(this));
     layer_manager()->BeginTransaction();
   }
 
+  // not all edits require an update to the hit testing tree
+  bool updateHitTestingTree = false;
+
   for (EditArray::index_type i = 0; i < cset.Length(); ++i) {
     const Edit& edit = cset[i];
 
     switch (edit.type()) {
     // Create* ops
     case Edit::TOpCreatePaintedLayer: {
       MOZ_LAYERS_LOG(("[ParentSide] CreatePaintedLayer"));
 
       RefPtr<PaintedLayerComposite> layer =
         layer_manager()->CreatePaintedLayerComposite();
       AsLayerComposite(edit.get_OpCreatePaintedLayer())->Bind(layer);
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpCreateContainerLayer: {
       MOZ_LAYERS_LOG(("[ParentSide] CreateContainerLayer"));
 
       RefPtr<ContainerLayer> layer = layer_manager()->CreateContainerLayerComposite();
       AsLayerComposite(edit.get_OpCreateContainerLayer())->Bind(layer);
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpCreateImageLayer: {
       MOZ_LAYERS_LOG(("[ParentSide] CreateImageLayer"));
 
       RefPtr<ImageLayerComposite> layer =
         layer_manager()->CreateImageLayerComposite();
       AsLayerComposite(edit.get_OpCreateImageLayer())->Bind(layer);
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpCreateColorLayer: {
       MOZ_LAYERS_LOG(("[ParentSide] CreateColorLayer"));
 
       RefPtr<ColorLayerComposite> layer = layer_manager()->CreateColorLayerComposite();
       AsLayerComposite(edit.get_OpCreateColorLayer())->Bind(layer);
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpCreateCanvasLayer: {
       MOZ_LAYERS_LOG(("[ParentSide] CreateCanvasLayer"));
 
       RefPtr<CanvasLayerComposite> layer =
         layer_manager()->CreateCanvasLayerComposite();
       AsLayerComposite(edit.get_OpCreateCanvasLayer())->Bind(layer);
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpCreateRefLayer: {
       MOZ_LAYERS_LOG(("[ParentSide] CreateRefLayer"));
 
       RefPtr<RefLayerComposite> layer =
         layer_manager()->CreateRefLayerComposite();
       AsLayerComposite(edit.get_OpCreateRefLayer())->Bind(layer);
+
+      updateHitTestingTree = true;
       break;
     }
 
     // Attributes
     case Edit::TOpSetLayerAttributes: {
       MOZ_LAYERS_LOG(("[ParentSide] SetLayerAttributes"));
 
       const OpSetLayerAttributes& osla = edit.get_OpSetLayerAttributes();
@@ -464,16 +479,18 @@ LayerTransactionParent::RecvUpdate(Infal
         const ImageLayerAttributes& attrs = specific.get_ImageLayerAttributes();
         imageLayer->SetFilter(attrs.filter());
         imageLayer->SetScaleToSize(attrs.scaleToSize(), attrs.scaleMode());
         break;
       }
       default:
         NS_RUNTIMEABORT("not reached");
       }
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpSetDiagnosticTypes: {
       mLayerManager->GetCompositor()->SetDiagnosticTypes(
         edit.get_OpSetDiagnosticTypes().diagnostics());
       break;
     }
     case Edit::TOpWindowOverlayChanged: {
@@ -488,96 +505,108 @@ LayerTransactionParent::RecvUpdate(Infal
       if (!newRoot) {
         return false;
       }
       if (newRoot->GetParent()) {
         // newRoot is not a root!
         return false;
       }
       mRoot = newRoot;
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpInsertAfter: {
       MOZ_LAYERS_LOG(("[ParentSide] InsertAfter"));
 
       const OpInsertAfter& oia = edit.get_OpInsertAfter();
       Layer* child = ShadowChild(oia)->AsLayer();
       if (!child) {
         return false;
       }
       ContainerLayerComposite* container = ShadowContainer(oia)->AsContainerLayerComposite();
       if (!container ||
           !container->InsertAfter(child, ShadowAfter(oia)->AsLayer()))
       {
         return false;
       }
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpPrependChild: {
       MOZ_LAYERS_LOG(("[ParentSide] PrependChild"));
 
       const OpPrependChild& oac = edit.get_OpPrependChild();
       Layer* child = ShadowChild(oac)->AsLayer();
       if (!child) {
         return false;
       }
       ContainerLayerComposite* container = ShadowContainer(oac)->AsContainerLayerComposite();
       if (!container ||
           !container->InsertAfter(child, nullptr))
       {
         return false;
       }
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpRemoveChild: {
       MOZ_LAYERS_LOG(("[ParentSide] RemoveChild"));
 
       const OpRemoveChild& orc = edit.get_OpRemoveChild();
       Layer* childLayer = ShadowChild(orc)->AsLayer();
       if (!childLayer) {
         return false;
       }
       ContainerLayerComposite* container = ShadowContainer(orc)->AsContainerLayerComposite();
       if (!container ||
           !container->RemoveChild(childLayer))
       {
         return false;
       }
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpRepositionChild: {
       MOZ_LAYERS_LOG(("[ParentSide] RepositionChild"));
 
       const OpRepositionChild& orc = edit.get_OpRepositionChild();
       Layer* child = ShadowChild(orc)->AsLayer();
       if (!child) {
         return false;
       }
       ContainerLayerComposite* container = ShadowContainer(orc)->AsContainerLayerComposite();
       if (!container ||
           !container->RepositionChild(child, ShadowAfter(orc)->AsLayer()))
       {
         return false;
       }
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TOpRaiseToTopChild: {
       MOZ_LAYERS_LOG(("[ParentSide] RaiseToTopChild"));
 
       const OpRaiseToTopChild& rtc = edit.get_OpRaiseToTopChild();
       Layer* child = ShadowChild(rtc)->AsLayer();
       if (!child) {
         return false;
       }
       ContainerLayerComposite* container = ShadowContainer(rtc)->AsContainerLayerComposite();
       if (!container ||
           !container->RepositionChild(child, nullptr))
       {
         return false;
       }
+
+      updateHitTestingTree = true;
       break;
     }
     case Edit::TCompositableOperation: {
       if (!ReceiveCompositableUpdate(edit.get_CompositableOperation(),
                                 replyv)) {
         return false;
       }
       break;
@@ -618,17 +647,17 @@ LayerTransactionParent::RecvUpdate(Infal
     default:
       NS_RUNTIMEABORT("not reached");
     }
   }
 
   mShadowLayersManager->ShadowLayersUpdated(this, aTransactionId, targetConfig,
                                             aPlugins, isFirstPaint, scheduleComposite,
                                             paintSequenceNumber, isRepeatTransaction,
-                                            aPaintSyncId);
+                                            aPaintSyncId, updateHitTestingTree);
 
   {
     AutoResolveRefLayers resolve(mShadowLayersManager->GetCompositionManager(this));
     layer_manager()->EndTransaction(TimeStamp(), LayerManager::END_NO_IMMEDIATE_REDRAW);
   }
 
   if (reply) {
     reply->SetCapacity(replyv.size());
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -450,16 +450,18 @@ union CompositableOperationDetail {
 };
 
 struct CompositableOperation {
   PCompositable compositable;
   CompositableOperationDetail detail;
 };
 
 // A unit of a changeset; a set of these comprise a changeset
+// If adding a new edit type that requires the hit testing tree to be updated,
+// set the updateHitTestingTree flag to true in RecvUpdate()
 union Edit {
   OpCreatePaintedLayer;
   OpCreateContainerLayer;
   OpCreateImageLayer;
   OpCreateColorLayer;
   OpCreateCanvasLayer;
   OpCreateRefLayer;
 
--- a/gfx/layers/ipc/ShadowLayersManager.h
+++ b/gfx/layers/ipc/ShadowLayersManager.h
@@ -21,17 +21,18 @@ public:
     virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
                                      const uint64_t& aTransactionId,
                                      const TargetConfig& aTargetConfig,
                                      const InfallibleTArray<PluginWindowData>& aPlugins,
                                      bool aIsFirstPaint,
                                      bool aScheduleComposite,
                                      uint32_t aPaintSequenceNumber,
                                      bool aIsRepeatTransaction,
-                                     int32_t aPaintSyncId) = 0;
+                                     int32_t aPaintSyncId,
+                                     bool aHitTestUpdate) = 0;
 
     virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aLayerTree) { return nullptr; }
 
     virtual void NotifyClearCachedResources(LayerTransactionParent* aLayerTree) { }
 
     virtual void ForceComposite(LayerTransactionParent* aLayerTree) { }
     virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree,
                                    const TimeStamp& aTime) { return true; }