Bug 824511 - Remove Axis.cpp?mark=76,79,82#73 dead code and make Axis less sensitive to random move events distance. r=drs
authorTatiana Meshkova <tanya.meshkova@gmail.com>
Wed, 20 Feb 2013 14:59:15 -0800
changeset 122693 5f2c0e6e56a576a84189c0ff07ef7e6eaa78649e
parent 122692 8ae71ffcc43d1f04bdf28ae9f079413c3056ed46
child 122694 4e5f82315a798ea1f96a7a8e55e1731877b516a1
push id24356
push usergszorc@mozilla.com
push dateSun, 24 Feb 2013 01:00:12 +0000
treeherdermozilla-central@195e706140d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdrs
bugs824511
milestone22.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 824511 - Remove Axis.cpp?mark=76,79,82#73 dead code and make Axis less sensitive to random move events distance. r=drs
gfx/layers/ipc/Axis.cpp
gfx/layers/ipc/Axis.h
--- a/gfx/layers/ipc/Axis.cpp
+++ b/gfx/layers/ipc/Axis.cpp
@@ -46,23 +46,31 @@ static float gAccelerationMultiplier = 1
 
 /**
  * When flinging, if the velocity goes below this number, we just stop the
  * animation completely. This is to prevent asymptotically approaching 0
  * velocity and rerendering unnecessarily.
  */
 static float gFlingStoppedThreshold = 0.01f;
 
+/**
+ * Maximum size of velocity queue. The queue contains last N velocity records.
+ * On touch end we calculate the average velocity in order to compensate
+ * touch/mouse drivers misbehaviour.
+ */
+static int gMaxVelocityQueueSize = 5;
+
 static void ReadAxisPrefs()
 {
   Preferences::AddFloatVarCache(&gMaxEventAcceleration, "gfx.axis.max_event_acceleration", gMaxEventAcceleration);
   Preferences::AddFloatVarCache(&gFlingFriction, "gfx.axis.fling_friction", gFlingFriction);
   Preferences::AddFloatVarCache(&gVelocityThreshold, "gfx.axis.velocity_threshold", gVelocityThreshold);
   Preferences::AddFloatVarCache(&gAccelerationMultiplier, "gfx.axis.acceleration_multiplier", gAccelerationMultiplier);
   Preferences::AddFloatVarCache(&gFlingStoppedThreshold, "gfx.axis.fling_stopped_threshold", gFlingStoppedThreshold);
+  Preferences::AddIntVarCache(&gMaxVelocityQueueSize, "gfx.axis.max_velocity_queue_size", gMaxVelocityQueueSize);
 }
 
 class ReadAxisPref MOZ_FINAL : public nsRunnable {
 public:
   NS_IMETHOD Run()
   {
     ReadAxisPrefs();
     return NS_OK;
@@ -89,39 +97,40 @@ Axis::Axis(AsyncPanZoomController* aAsyn
     mVelocity(0.0f),
     mAcceleration(0),
     mAsyncPanZoomController(aAsyncPanZoomController)
 {
   InitAxisPrefs();
 }
 
 void Axis::UpdateWithTouchAtDevicePoint(int32_t aPos, const TimeDuration& aTimeDelta) {
+  if (mPos == aPos) {
+    // Does not make sense to calculate velocity when distance is 0
+    return;
+  }
+
   float newVelocity = (mPos - aPos) / aTimeDelta.ToMilliseconds();
 
-  bool curVelocityIsLow = fabsf(newVelocity) < 0.01f;
   bool curVelocityBelowThreshold = fabsf(newVelocity) < gVelocityThreshold;
   bool directionChange = (mVelocity > 0) != (newVelocity > 0);
 
   // If we've changed directions, or the current velocity threshold, stop any
   // acceleration we've accumulated.
   if (directionChange || curVelocityBelowThreshold) {
     mAcceleration = 0;
   }
 
-  // If a direction change has happened, or the current velocity due to this new
-  // touch is relatively low, then just apply it. If not, throttle it.
-  if (curVelocityIsLow || (directionChange && fabs(newVelocity) - EPSILON <= 0.0f)) {
-    mVelocity = newVelocity;
-  } else {
-    float maxChange = fabsf(mVelocity * aTimeDelta.ToMilliseconds() * gMaxEventAcceleration);
-    mVelocity = std::min(mVelocity + maxChange, std::max(mVelocity - maxChange, newVelocity));
-  }
-
   mVelocity = newVelocity;
   mPos = aPos;
+
+  // Keep last gMaxVelocityQueueSize or less velocities in the queue.
+  mVelocityQueue.AppendElement(mVelocity);
+  if (mVelocityQueue.Length() > gMaxVelocityQueueSize) {
+    mVelocityQueue.RemoveElementAt(0);
+  }
 }
 
 void Axis::StartTouch(int32_t aPos) {
   mStartPos = aPos;
   mPos = aPos;
 }
 
 float Axis::GetDisplacementForDuration(float aScale, const TimeDuration& aDelta) {
@@ -144,21 +153,35 @@ float Axis::GetDisplacementForDuration(f
 }
 
 float Axis::PanDistance() {
   return fabsf(mPos - mStartPos);
 }
 
 void Axis::EndTouch() {
   mAcceleration++;
+
+  // Calculate the mean velocity and empty the queue.
+  int count = mVelocityQueue.Length();
+  if (count) {
+    mVelocity = 0;
+    while (!mVelocityQueue.IsEmpty()) {
+      mVelocity += mVelocityQueue[0];
+      mVelocityQueue.RemoveElementAt(0);
+    }
+    mVelocity /= count;
+  }
 }
 
 void Axis::CancelTouch() {
   mVelocity = 0.0f;
   mAcceleration = 0;
+  while (!mVelocityQueue.IsEmpty()) {
+    mVelocityQueue.RemoveElementAt(0);
+  }
 }
 
 bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta) {
   if (fabsf(mVelocity) <= gFlingStoppedThreshold) {
     // If the velocity is very low, just set it to 0 and stop the fling,
     // otherwise we'll just asymptotically approach 0 and the user won't
     // actually see any changes.
     mVelocity = 0.0f;
--- a/gfx/layers/ipc/Axis.h
+++ b/gfx/layers/ipc/Axis.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_Axis_h
 #define mozilla_layers_Axis_h
 
 #include "nsGUIEvent.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/gfx/2D.h"
+#include "nsTArray.h"
 
 namespace mozilla {
 namespace layers {
 
 class AsyncPanZoomController;
 
 /**
  * Helper class to maintain each axis of movement (X,Y) for panning and zooming.
@@ -179,16 +180,17 @@ protected:
   float mVelocity;
   // Acceleration is represented by an int, which is the power we raise a
   // constant to and then multiply the velocity by whenever it is sampled. We do
   // this only when we detect that the user wants to do a fast fling; that is,
   // they are flinging multiple times in a row very quickly, probably trying to
   // reach one of the extremes of the page.
   int32_t mAcceleration;
   AsyncPanZoomController* mAsyncPanZoomController;
+  nsTArray<float> mVelocityQueue;
 };
 
 class AxisX : public Axis {
 public:
   AxisX(AsyncPanZoomController* mAsyncPanZoomController);
   virtual float GetPointOffset(const gfx::Point& aPoint);
   virtual float GetRectLength(const gfx::Rect& aRect);
   virtual float GetRectOffset(const gfx::Rect& aRect);