Bug 1289432 - Stop relying on the mEvents array inside the SetConfirmedTargetApzc implementations. r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 14 Sep 2016 07:54:37 -0400
changeset 357434 868e5e9845acedf0bcf69c01ace18e8107f3c94c
parent 357433 b40d59513ee6954ab7fff73689fa834727b4a0fa
child 357435 8ff1c50ceb8b129e6a75cbee08fe849a2e355062
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1289432
milestone51.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 1289432 - Stop relying on the mEvents array inside the SetConfirmedTargetApzc implementations. r=botond MozReview-Commit-ID: BG7BmQPa6g9
gfx/layers/apz/src/InputBlockState.cpp
gfx/layers/apz/src/InputBlockState.h
gfx/layers/apz/src/InputQueue.cpp
gfx/layers/apz/src/InputQueue.h
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -33,17 +33,18 @@ InputBlockState::InputBlockState(const R
 {
   // We should never be constructed with a nullptr target.
   MOZ_ASSERT(mTargetApzc);
   mOverscrollHandoffChain = mTargetApzc->BuildOverscrollHandoffChain();
 }
 
 bool
 InputBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
-                                        TargetConfirmationState aState)
+                                        TargetConfirmationState aState,
+                                        InputData* aFirstInput)
 {
   MOZ_ASSERT(aState == TargetConfirmationState::eConfirmed
           || aState == TargetConfirmationState::eTimedOut);
 
   if (mTargetConfirmed == TargetConfirmationState::eTimedOut &&
       aState == TargetConfirmationState::eConfirmed) {
     // The main thread finally responded. We had already timed out the
     // confirmation, but we want to update the state internally so that we
@@ -377,28 +378,28 @@ WheelBlockState::SetContentResponse(bool
   if (aPreventDefault) {
     EndTransaction();
   }
   return CancelableBlockState::SetContentResponse(aPreventDefault);
 }
 
 bool
 WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
-                                        TargetConfirmationState aState)
+                                        TargetConfirmationState aState,
+                                        InputData* aFirstInput)
 {
   // The APZC that we find via APZCCallbackHelpers may not be the same APZC
   // ESM or OverscrollHandoff would have computed. Make sure we get the right
   // one by looking for the first apzc the next pending event can scroll.
   RefPtr<AsyncPanZoomController> apzc = aTargetApzc;
-  if (apzc && mEvents.Length() > 0) {
-    const ScrollWheelInput& event = mEvents.ElementAt(0);
-    apzc = apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(event);
+  if (apzc && aFirstInput) {
+    apzc = apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(*aFirstInput);
   }
 
-  InputBlockState::SetConfirmedTargetApzc(apzc, aState);
+  InputBlockState::SetConfirmedTargetApzc(apzc, aState, aFirstInput);
   return true;
 }
 
 void
 WheelBlockState::Update(ScrollWheelInput& aEvent)
 {
   // We might not be in a transaction if the block never started in a
   // transaction - for example, if nothing was scrollable.
@@ -632,32 +633,32 @@ PanGestureBlockState::PanGestureBlockSta
     if (apzc && apzc != GetTargetApzc()) {
       UpdateTargetApzc(apzc);
     }
   }
 }
 
 bool
 PanGestureBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
-                                             TargetConfirmationState aState)
+                                             TargetConfirmationState aState,
+                                             InputData* aFirstInput)
 {
   // The APZC that we find via APZCCallbackHelpers may not be the same APZC
   // ESM or OverscrollHandoff would have computed. Make sure we get the right
   // one by looking for the first apzc the next pending event can scroll.
   RefPtr<AsyncPanZoomController> apzc = aTargetApzc;
-  if (apzc && mEvents.Length() > 0) {
-    const PanGestureInput& event = mEvents.ElementAt(0);
+  if (apzc && aFirstInput) {
     RefPtr<AsyncPanZoomController> scrollableApzc =
-      apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(event);
+      apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(*aFirstInput);
     if (scrollableApzc) {
       apzc = scrollableApzc;
     }
   }
 
-  InputBlockState::SetConfirmedTargetApzc(apzc, aState);
+  InputBlockState::SetConfirmedTargetApzc(apzc, aState, aFirstInput);
   return true;
 }
 
 void
 PanGestureBlockState::AddEvent(const PanGestureInput& aEvent)
 {
   mEvents.AppendElement(aEvent);
 }
--- a/gfx/layers/apz/src/InputBlockState.h
+++ b/gfx/layers/apz/src/InputBlockState.h
@@ -50,17 +50,18 @@ public:
   };
 
   explicit InputBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
                            bool aTargetConfirmed);
   virtual ~InputBlockState()
   {}
 
   virtual bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
-                                      TargetConfirmationState aState);
+                                      TargetConfirmationState aState,
+                                      InputData* aFirstInput);
   const RefPtr<AsyncPanZoomController>& GetTargetApzc() const;
   const RefPtr<const OverscrollHandoffChain>& GetOverscrollHandoffChain() const;
   uint64_t GetBlockId() const;
 
   bool IsTargetConfirmed() const;
   bool HasReceivedRealConfirmedTarget() const;
 
   void SetScrolledApzc(AsyncPanZoomController* aApzc);
@@ -228,17 +229,18 @@ public:
 
   bool SetContentResponse(bool aPreventDefault) override;
   bool HasEvents() const override;
   void DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
   void HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
   bool MustStayActive() override;
   const char* Type() override;
   bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
-                              TargetConfirmationState aState) override;
+                              TargetConfirmationState aState,
+                              InputData* aFirstInput) override;
 
   void AddEvent(const ScrollWheelInput& aEvent);
 
   WheelBlockState *AsWheelBlock() override {
     return this;
   }
 
   /**
@@ -350,17 +352,18 @@ public:
   bool HasReceivedAllContentNotifications() const override;
   bool IsReadyForHandling() const override;
   bool HasEvents() const override;
   void DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
   void HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
   bool MustStayActive() override;
   const char* Type() override;
   bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
-                              TargetConfirmationState aState) override;
+                              TargetConfirmationState aState,
+                              InputData* aFirstInput) override;
 
   void AddEvent(const PanGestureInput& aEvent);
 
   PanGestureBlockState *AsPanGestureBlock() override {
     return this;
   }
 
   /**
--- a/gfx/layers/apz/src/InputQueue.cpp
+++ b/gfx/layers/apz/src/InputQueue.cpp
@@ -99,17 +99,18 @@ InputQueue::ReceiveTouchInput(const RefP
         haveBehaviors) {
       // If we're already in a fast fling, and a single finger goes down, then
       // we want special handling for the touch event, because it shouldn't get
       // delivered to content. Note that we don't set this flag when going
       // from a fast fling to a pinch state (i.e. second finger goes down while
       // the first finger is moving).
       block->SetDuringFastFling();
       block->SetConfirmedTargetApzc(aTarget,
-          InputBlockState::TargetConfirmationState::eConfirmed);
+          InputBlockState::TargetConfirmationState::eConfirmed,
+          nullptr /* the block was just created so it has no events */);
       if (gfxPrefs::TouchActionEnabled()) {
         block->SetAllowedTouchBehaviors(currentBehaviors);
       }
       INPQ_LOG("block %p tagged as fast-motion\n", block);
     }
 
     CancelAnimationsForNewBlock(block);
 
@@ -541,33 +542,65 @@ InputQueue::ScheduleMainThreadTimeout(co
   INPQ_LOG("scheduling main thread timeout for target %p\n", aTarget.get());
   aBlock->StartContentResponseTimer();
   aTarget->PostDelayedTask(NewRunnableMethod<uint64_t>(this,
                                                        &InputQueue::MainThreadTimeout,
                                                        aBlock->GetBlockId()),
                            gfxPrefs::APZContentResponseTimeout());
 }
 
+CancelableBlockState*
+InputQueue::FindBlockForId(const uint64_t& aInputBlockId,
+                           InputData** aOutFirstInput)
+{
+  for (size_t i = 0; i < mQueuedInputs.Length(); i++) {
+    if (mQueuedInputs[i]->Block()->GetBlockId() == aInputBlockId) {
+      if (aOutFirstInput) {
+        *aOutFirstInput = mQueuedInputs[i]->Input();
+      }
+      return mQueuedInputs[i]->Block();
+    }
+  }
+
+  CancelableBlockState* block = nullptr;
+  if (mActiveTouchBlock && mActiveTouchBlock->GetBlockId() == aInputBlockId) {
+    block = mActiveTouchBlock.get();
+  } else if (mActiveWheelBlock && mActiveWheelBlock->GetBlockId() == aInputBlockId) {
+    block = mActiveWheelBlock.get();
+  } else if (mActiveDragBlock && mActiveDragBlock->GetBlockId() == aInputBlockId) {
+    block = mActiveDragBlock.get();
+  } else if (mActivePanGestureBlock && mActivePanGestureBlock->GetBlockId() == aInputBlockId) {
+    block = mActivePanGestureBlock.get();
+  }
+  // Since we didn't encounter this block while iterating through mQueuedInputs,
+  // it must have no events associated with it at the moment.
+  MOZ_ASSERT(!block || !block->HasEvents());
+  if (aOutFirstInput) {
+    *aOutFirstInput = nullptr;
+  }
+  return block;
+}
+
 void
 InputQueue::MainThreadTimeout(const uint64_t& aInputBlockId) {
   APZThreadUtils::AssertOnControllerThread();
 
   INPQ_LOG("got a main thread timeout; block=%" PRIu64 "\n", aInputBlockId);
   bool success = false;
-  for (size_t i = 0; i < mInputBlockQueue.Length(); i++) {
-    if (mInputBlockQueue[i]->GetBlockId() == aInputBlockId) {
-      // time out the touch-listener response and also confirm the existing
-      // target apzc in the case where the main thread doesn't get back to us
-      // fast enough.
-      success = mInputBlockQueue[i]->TimeoutContentResponse();
-      success |= mInputBlockQueue[i]->SetConfirmedTargetApzc(
-          mInputBlockQueue[i]->GetTargetApzc(),
-          InputBlockState::TargetConfirmationState::eTimedOut);
-      break;
-    }
+  InputData* firstInput = nullptr;
+  CancelableBlockState* block = FindBlockForId(aInputBlockId, &firstInput);
+  if (block) {
+    // time out the touch-listener response and also confirm the existing
+    // target apzc in the case where the main thread doesn't get back to us
+    // fast enough.
+    success = block->TimeoutContentResponse();
+    success |= block->SetConfirmedTargetApzc(
+        block->GetTargetApzc(),
+        InputBlockState::TargetConfirmationState::eTimedOut,
+        firstInput);
   }
   if (success) {
     ProcessInputBlocks();
   }
 }
 
 void
 InputQueue::ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault) {
@@ -590,48 +623,46 @@ InputQueue::ContentReceivedInputBlock(ui
 
 void
 InputQueue::SetConfirmedTargetApzc(uint64_t aInputBlockId, const RefPtr<AsyncPanZoomController>& aTargetApzc) {
   APZThreadUtils::AssertOnControllerThread();
 
   INPQ_LOG("got a target apzc; block=%" PRIu64 " guid=%s\n",
     aInputBlockId, aTargetApzc ? Stringify(aTargetApzc->GetGuid()).c_str() : "");
   bool success = false;
-  for (size_t i = 0; i < mInputBlockQueue.Length(); i++) {
-    CancelableBlockState* block = mInputBlockQueue[i].get();
-    if (block->GetBlockId() == aInputBlockId) {
-      success = block->SetConfirmedTargetApzc(aTargetApzc,
-          InputBlockState::TargetConfirmationState::eConfirmed);
-      block->RecordContentResponseTime();
-      break;
-    }
+  InputData* firstInput = nullptr;
+  CancelableBlockState* block = FindBlockForId(aInputBlockId, &firstInput);
+  if (block) {
+    success = block->SetConfirmedTargetApzc(aTargetApzc,
+        InputBlockState::TargetConfirmationState::eConfirmed,
+        firstInput);
+    block->RecordContentResponseTime();
   }
   if (success) {
     ProcessInputBlocks();
   }
 }
 
 void
 InputQueue::ConfirmDragBlock(uint64_t aInputBlockId, const RefPtr<AsyncPanZoomController>& aTargetApzc,
                                    const AsyncDragMetrics& aDragMetrics)
 {
   APZThreadUtils::AssertOnControllerThread();
 
   INPQ_LOG("got a target apzc; block=%" PRIu64 " guid=%s\n",
     aInputBlockId, aTargetApzc ? Stringify(aTargetApzc->GetGuid()).c_str() : "");
   bool success = false;
-  for (size_t i = 0; i < mInputBlockQueue.Length(); i++) {
-    DragBlockState* block = mInputBlockQueue[i]->AsDragBlock();
-    if (block && block->GetBlockId() == aInputBlockId) {
-      block->SetDragMetrics(aDragMetrics);
-      success = block->SetConfirmedTargetApzc(aTargetApzc,
-          InputBlockState::TargetConfirmationState::eConfirmed);
-      block->RecordContentResponseTime();
-      break;
-    }
+  InputData* firstInput = nullptr;
+  CancelableBlockState* block = FindBlockForId(aInputBlockId, &firstInput);
+  if (block && block->AsDragBlock()) {
+    block->AsDragBlock()->SetDragMetrics(aDragMetrics);
+    success = block->SetConfirmedTargetApzc(aTargetApzc,
+        InputBlockState::TargetConfirmationState::eConfirmed,
+        firstInput);
+    block->RecordContentResponseTime();
   }
   if (success) {
     ProcessInputBlocks();
   }
 }
 
 void
 InputQueue::SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aBehaviors) {
--- a/gfx/layers/apz/src/InputQueue.h
+++ b/gfx/layers/apz/src/InputQueue.h
@@ -167,16 +167,27 @@ private:
                                         const PanGestureInput& aEvent,
                                         uint64_t* aOutInputBlockId);
 
   /**
    * Remove any blocks that are inactive - not ready, and having no events.
    */
   void SweepDepletedBlocks();
 
+  /**
+   * Helper function that searches mQueuedInputs for the first block matching
+   * the given id, and returns it. If |aOutFirstInput| is non-null, it is
+   * populated with a pointer to the first input in mQueuedInputs that
+   * corresponds to the block, or null if no such input was found. Note that
+   * even if there are no inputs in mQueuedInputs, this function can return
+   * non-null if the block id provided matches one of the depleted-but-still-
+   * active blocks (mActiveTouchBlock, mActiveWheelBlock, etc.).
+   */
+  CancelableBlockState* FindBlockForId(const uint64_t& aInputBlockId,
+                                       InputData** aOutFirstInput);
   void ScheduleMainThreadTimeout(const RefPtr<AsyncPanZoomController>& aTarget,
                                  CancelableBlockState* aBlock);
   void MainThreadTimeout(const uint64_t& aInputBlockId);
   void ProcessInputBlocks();
   void ClearActiveBlock(CancelableBlockState* aBlock);
   void UpdateActiveApzc(const RefPtr<AsyncPanZoomController>& aNewActive);
 
 private: