Bug 1152051 - Ensure that destroying an overscroll animation always clears the state Axis tracks about it. r=Cwiiis
authorBotond Ballo <botond@mozilla.com>
Wed, 29 Apr 2015 18:54:10 -0400
changeset 273476 c7b25a8722359af4b8f1d29ddc522f7900c5d969
parent 273475 d2a6230fee214ad5f23c1b9474ab96875865642a
child 273477 e1b56bd22b3a87979022e26d234ac2c282dc5f3f
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersCwiiis
bugs1152051
milestone40.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 1152051 - Ensure that destroying an overscroll animation always clears the state Axis tracks about it. r=Cwiiis
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/Axis.cpp
gfx/layers/apz/src/Axis.h
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -642,18 +642,23 @@ private:
 };
 
 class OverscrollAnimation: public AsyncPanZoomAnimation {
 public:
   explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ParentLayerPoint& aVelocity)
     : AsyncPanZoomAnimation(TimeDuration::Forever())
     , mApzc(aApzc)
   {
-    mApzc.mX.SetVelocity(aVelocity.x);
-    mApzc.mY.SetVelocity(aVelocity.y);
+    mApzc.mX.StartOverscrollAnimation(aVelocity.x);
+    mApzc.mY.StartOverscrollAnimation(aVelocity.y);
+  }
+  ~OverscrollAnimation()
+  {
+    mApzc.mX.EndOverscrollAnimation();
+    mApzc.mY.EndOverscrollAnimation();
   }
 
   virtual bool DoSample(FrameMetrics& aFrameMetrics,
                         const TimeDuration& aDelta) override
   {
     // Can't inline these variables due to short-circuit evaluation.
     bool continueX = mApzc.mX.SampleOverscrollAnimation(aDelta);
     bool continueY = mApzc.mY.SampleOverscrollAnimation(aDelta);
--- a/gfx/layers/apz/src/Axis.cpp
+++ b/gfx/layers/apz/src/Axis.cpp
@@ -135,17 +135,17 @@ bool Axis::AdjustDisplacement(ParentLaye
     return false;
   }
   if (forceOverscroll) {
     aOverscrollAmountOut = aDisplacement;
     aDisplacementOut = 0;
     return false;
   }
 
-  StopSamplingOverscrollAnimation();
+  ClearOverscrollAnimationState();
 
   ParentLayerCoord displacement = aDisplacement;
 
   // First consume any overscroll in the opposite direction along this axis.
   ParentLayerCoord consumedOverscroll = 0;
   if (mOverscroll > 0 && aDisplacement < 0) {
     consumedOverscroll = std::min(mOverscroll, -aDisplacement);
   } else if (mOverscroll < 0 && aDisplacement > 0) {
@@ -177,17 +177,17 @@ ParentLayerCoord Axis::ApplyResistance(P
   // factor; this should prevent overscrolling by more than the composition
   // length.
   float resistanceFactor = 1 - fabsf(GetOverscroll()) / GetCompositionLength();
   return resistanceFactor < 0 ? ParentLayerCoord(0) : aRequestedOverscroll * resistanceFactor;
 }
 
 void Axis::OverscrollBy(ParentLayerCoord aOverscroll) {
   MOZ_ASSERT(CanScroll());
-  StopSamplingOverscrollAnimation();
+  ClearOverscrollAnimationState();
   aOverscroll = ApplyResistance(aOverscroll);
   if (aOverscroll > 0) {
 #ifdef DEBUG
     if (!FuzzyEqualsCoordinate(GetCompositionEnd().value, GetPageEnd().value)) {
       nsPrintfCString message("composition end (%f) is not equal (within error) to page end (%f)\n",
                               GetCompositionEnd().value, GetPageEnd().value);
       NS_ASSERTION(false, message.get());
       MOZ_CRASH();
@@ -219,20 +219,33 @@ ParentLayerCoord Axis::GetOverscroll() c
     NS_ASSERTION(false, message.get());
     MOZ_CRASH();
   }
 #endif
 
   return result;
 }
 
-void Axis::StopSamplingOverscrollAnimation() {
-  ParentLayerCoord overscroll = GetOverscroll();
-  ClearOverscroll();
-  mOverscroll = overscroll;
+void Axis::StartOverscrollAnimation(float aVelocity) {
+  // Make sure any state from a previous animation has been cleared.
+  MOZ_ASSERT(mFirstOverscrollAnimationSample == 0 &&
+             mLastOverscrollPeak == 0 &&
+             mOverscrollScale == 1);
+
+  SetVelocity(aVelocity);
+}
+
+void Axis::EndOverscrollAnimation() {
+  ClearOverscrollAnimationState();
+}
+
+void Axis::ClearOverscrollAnimationState() {
+  mFirstOverscrollAnimationSample = 0;
+  mLastOverscrollPeak = 0;
+  mOverscrollScale = 1.0f;
 }
 
 void Axis::StepOverscrollAnimation(double aStepDurationMilliseconds) {
   // Apply spring physics to the overscroll as time goes on.
   // Note: this method of sampling isn't perfectly smooth, as it assumes
   // a constant velocity over 'aDelta', instead of an accelerating velocity.
   // (The way we applying friction to flings has the same issue.)
   // Hooke's law with damping:
@@ -342,20 +355,18 @@ bool Axis::SampleOverscrollAnimation(con
   return true;
 }
 
 bool Axis::IsOverscrolled() const {
   return mOverscroll != 0.f;
 }
 
 void Axis::ClearOverscroll() {
+  ClearOverscrollAnimationState();
   mOverscroll = 0;
-  mFirstOverscrollAnimationSample = 0;
-  mLastOverscrollPeak = 0;
-  mOverscrollScale = 1.0f;
 }
 
 ParentLayerCoord Axis::PanStart() const {
   return mStartPos;
 }
 
 ParentLayerCoord Axis::PanDistance() const {
   return fabs(mPos - mStartPos);
--- a/gfx/layers/apz/src/Axis.h
+++ b/gfx/layers/apz/src/Axis.h
@@ -101,22 +101,32 @@ public:
    * mAsyncPanZoomController->mFrameMetrics.mScrollOffset must be at its
    * extreme allowed value in the relevant direction (that is, it must be at
    * its maximum value if we are overscrolled at our composition length, and
    * at its minimum value if we are overscrolled at the origin).
    */
   ParentLayerCoord GetOverscroll() const;
 
   /**
+   * Start an overscroll animation with the given initial velocity.
+   */
+  void StartOverscrollAnimation(float aVelocity);
+
+  /**
    * Sample the snap-back animation to relieve overscroll.
    * |aDelta| is the time since the last sample.
    */
   bool SampleOverscrollAnimation(const TimeDuration& aDelta);
 
   /**
+   * Stop an overscroll animation.
+   */
+  void EndOverscrollAnimation();
+
+  /**
    * Return whether this axis is overscrolled in either direction.
    */
   bool IsOverscrolled() const;
 
   /**
    * Clear any overscroll amount on this axis.
    */
   void ClearOverscroll();
@@ -270,19 +280,18 @@ protected:
   nsTArray<std::pair<uint32_t, float> > mVelocityQueue;
 
   const FrameMetrics& GetFrameMetrics() const;
 
   // Adjust a requested overscroll amount for resistance, yielding a smaller
   // actual overscroll amount.
   ParentLayerCoord ApplyResistance(ParentLayerCoord aOverscroll) const;
 
-  // Helper function to disable overscroll transformations triggered by
-  // SampleOverscrollAnimation().
-  void StopSamplingOverscrollAnimation();
+  // Clear the state associated with an overscroll animation.
+  void ClearOverscrollAnimationState();
 
   // Helper function for SampleOverscrollAnimation().
   void StepOverscrollAnimation(double aStepDurationMilliseconds);
 
   // Convert a velocity from global inches/ms into ParentLayerCoords/ms.
   float ToLocalVelocity(float aVelocityInchesPerMs) const;
 };