Bug 1402498 - Separate out ScrollAnimationBezierPhysics and make ScrollAnimationPhysics an interface. r?rhunt draft
authorMarkus Stange <mstange@themasta.com>
Fri, 29 Sep 2017 18:37:14 -0400
changeset 672908 d2b8c4f1811f4b86719379154ac8e52e9f2e08a4
parent 672907 81237dbc3a41424bbaaad2e3c94c0aa1b41f1dd4
child 672909 9ea693749cf82995d46f52be50eca490c0d8ba04
push id82420
push userbmo:mstange@themasta.com
push dateFri, 29 Sep 2017 22:38:50 +0000
reviewersrhunt
bugs1402498
milestone58.0a1
Bug 1402498 - Separate out ScrollAnimationBezierPhysics and make ScrollAnimationPhysics an interface. r?rhunt MozReview-Commit-ID: K3b8vjY5xaO
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/GenericScrollAnimation.cpp
gfx/layers/apz/src/GenericScrollAnimation.h
gfx/layers/apz/src/KeyboardScrollAnimation.cpp
gfx/layers/apz/src/WheelScrollAnimation.cpp
layout/generic/ScrollAnimationBezierPhysics.cpp
layout/generic/ScrollAnimationBezierPhysics.h
layout/generic/ScrollAnimationPhysics.cpp
layout/generic/ScrollAnimationPhysics.h
layout/generic/moz.build
layout/generic/nsGfxScrollFrame.cpp
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -72,16 +72,17 @@
 #include "nsStyleConsts.h"
 #include "nsStyleStruct.h"              // for nsTimingFunction
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl, etc
 #include "nsThreadUtils.h"              // for NS_IsMainThread
 #include "nsViewportInfo.h"             // for kViewportMinScale, kViewportMaxScale
 #include "prsystem.h"                   // for PR_GetPhysicalMemorySize
 #include "SharedMemoryBasic.h"          // for SharedMemoryBasic
 #include "ScrollSnap.h"                 // for ScrollSnapUtils
+#include "ScrollAnimationPhysics.h"     // for ComputeAcceleratedWheelDelta
 #include "WheelScrollAnimation.h"
 #include "KeyboardScrollAnimation.h"
 #if defined(MOZ_WIDGET_ANDROID)
 #include "AndroidAPZ.h"
 #include "mozilla/layers/AndroidDynamicToolbarAnimator.h"
 #endif // defined(MOZ_WIDGET_ANDROID)
 
 #define ENABLE_APZC_LOGGING 0
--- a/gfx/layers/apz/src/GenericScrollAnimation.cpp
+++ b/gfx/layers/apz/src/GenericScrollAnimation.cpp
@@ -4,25 +4,27 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GenericScrollAnimation.h"
 
 #include "AsyncPanZoomController.h"
 #include "gfxPrefs.h"
 #include "nsPoint.h"
+#include "ScrollAnimationPhysics.h"
+#include "ScrollAnimationBezierPhysics.h"
 
 namespace mozilla {
 namespace layers {
 
 GenericScrollAnimation::GenericScrollAnimation(AsyncPanZoomController& aApzc,
                                                const nsPoint& aInitialPosition,
-                                               const ScrollAnimationPhysicsSettings& aSettings)
+                                               const ScrollAnimationBezierPhysicsSettings& aSettings)
   : mApzc(aApzc)
-  , mAnimationPhysics(MakeUnique<ScrollAnimationPhysics>(aInitialPosition, aSettings))
+  , mAnimationPhysics(MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, aSettings))
   , mFinalDestination(aInitialPosition)
   , mForceVerticalOverscroll(false)
 {
 }
 
 void
 GenericScrollAnimation::UpdateDelta(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity)
 {
--- a/gfx/layers/apz/src/GenericScrollAnimation.h
+++ b/gfx/layers/apz/src/GenericScrollAnimation.h
@@ -3,30 +3,33 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_GenericScrollAnimation_h_
 #define mozilla_layers_GenericScrollAnimation_h_
 
 #include "AsyncPanZoomAnimation.h"
-#include "ScrollAnimationPhysics.h"
 
 namespace mozilla {
+
+struct ScrollAnimationBezierPhysicsSettings;
+class ScrollAnimationPhysics;
+
 namespace layers {
 
 class AsyncPanZoomController;
 
 class GenericScrollAnimation
   : public AsyncPanZoomAnimation
 {
 public:
   GenericScrollAnimation(AsyncPanZoomController& aApzc,
                          const nsPoint& aInitialPosition,
-                         const ScrollAnimationPhysicsSettings& aSettings);
+                         const ScrollAnimationBezierPhysicsSettings& aSettings);
 
   bool DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) override;
 
   void UpdateDelta(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity);
   void UpdateDestination(TimeStamp aTime, nsPoint aDestination, const nsSize& aCurrentVelocity);
 
   CSSPoint GetDestination() const {
     return CSSPoint::FromAppUnits(mFinalDestination);
--- a/gfx/layers/apz/src/KeyboardScrollAnimation.cpp
+++ b/gfx/layers/apz/src/KeyboardScrollAnimation.cpp
@@ -1,22 +1,23 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "KeyboardScrollAnimation.h"
+#include "ScrollAnimationBezierPhysics.h"
 
 #include "gfxPrefs.h"
 
 namespace mozilla {
 namespace layers {
 
-static ScrollAnimationPhysicsSettings
+static ScrollAnimationBezierPhysicsSettings
 SettingsForType(KeyboardScrollAction::KeyboardScrollActionType aType)
 {
   int32_t minMS = 0;
   int32_t maxMS = 0;
 
   switch (aType) {
     case KeyboardScrollAction::eScrollCharacter:
     case KeyboardScrollAction::eScrollLine: {
@@ -34,17 +35,17 @@ SettingsForType(KeyboardScrollAction::Ke
       minMS = clamped(gfxPrefs::OtherSmoothScrollMinDurationMs(), 0, maxMS);
       break;
     }
   }
 
   // The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
   double intervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
   intervalRatio = std::max(1.0, intervalRatio);
-  return ScrollAnimationPhysicsSettings { minMS, maxMS, intervalRatio };
+  return ScrollAnimationBezierPhysicsSettings { minMS, maxMS, intervalRatio };
 }
 
 KeyboardScrollAnimation::KeyboardScrollAnimation(AsyncPanZoomController& aApzc,
                                                  const nsPoint& aInitialPosition,
                                                  KeyboardScrollAction::KeyboardScrollActionType aType)
   : GenericScrollAnimation(aApzc, aInitialPosition, SettingsForType(aType))
 {
 }
--- a/gfx/layers/apz/src/WheelScrollAnimation.cpp
+++ b/gfx/layers/apz/src/WheelScrollAnimation.cpp
@@ -1,24 +1,25 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WheelScrollAnimation.h"
+#include "ScrollAnimationBezierPhysics.h"
 
 #include "AsyncPanZoomController.h"
 #include "gfxPrefs.h"
 #include "nsPoint.h"
 
 namespace mozilla {
 namespace layers {
 
-static ScrollAnimationPhysicsSettings
+static ScrollAnimationBezierPhysicsSettings
 SettingsForDeltaType(ScrollWheelInput::ScrollDeltaType aDeltaType)
 {
   int32_t minMS = 0;
   int32_t maxMS = 0;
 
   switch (aDeltaType) {
     case ScrollWheelInput::SCROLLDELTA_PAGE:
       maxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
@@ -32,17 +33,17 @@ SettingsForDeltaType(ScrollWheelInput::S
       maxMS = clamped(gfxPrefs::WheelSmoothScrollMaxDurationMs(), 0, 10000);
       minMS = clamped(gfxPrefs::WheelSmoothScrollMinDurationMs(), 0, maxMS);
       break;
   }
 
   // The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
   double intervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
   intervalRatio = std::max(1.0, intervalRatio);
-  return ScrollAnimationPhysicsSettings { minMS, maxMS, intervalRatio };
+  return ScrollAnimationBezierPhysicsSettings { minMS, maxMS, intervalRatio };
 }
 
 WheelScrollAnimation::WheelScrollAnimation(AsyncPanZoomController& aApzc,
                                            const nsPoint& aInitialPosition,
                                            ScrollWheelInput::ScrollDeltaType aDeltaType)
   : GenericScrollAnimation(aApzc, aInitialPosition, SettingsForDeltaType(aDeltaType))
 {
   mForceVerticalOverscroll = !mApzc.mScrollMetadata.AllowVerticalScrollWithWheel();
rename from layout/generic/ScrollAnimationPhysics.cpp
rename to layout/generic/ScrollAnimationBezierPhysics.cpp
--- a/layout/generic/ScrollAnimationPhysics.cpp
+++ b/layout/generic/ScrollAnimationBezierPhysics.cpp
@@ -1,30 +1,30 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "ScrollAnimationPhysics.h"
+#include "ScrollAnimationBezierPhysics.h"
 #include "gfxPrefs.h"
 
 using namespace mozilla;
 
-ScrollAnimationPhysics::ScrollAnimationPhysics(nsPoint aStartPos,
-                                const ScrollAnimationPhysicsSettings& aSettings)
+ScrollAnimationBezierPhysics::ScrollAnimationBezierPhysics(const nsPoint& aStartPos,
+                                const ScrollAnimationBezierPhysicsSettings& aSettings)
  : mSettings(aSettings)
  , mStartPos(aStartPos)
  , mIsFirstIteration(true)
 {
 }
 
 void
-ScrollAnimationPhysics::Update(TimeStamp aTime,
-                               nsPoint aDestination,
-                               const nsSize& aCurrentVelocity)
+ScrollAnimationBezierPhysics::Update(const TimeStamp& aTime,
+                                     const nsPoint& aDestination,
+                                     const nsSize& aCurrentVelocity)
 {
   if (mIsFirstIteration) {
     InitializeHistory(aTime);
   }
 
   TimeDuration duration = ComputeDuration(aTime);
   nsSize currentVelocity = aCurrentVelocity;
 
@@ -48,17 +48,17 @@ ScrollAnimationPhysics::Update(TimeStamp
   InitTimingFunction(mTimingFunctionX, mStartPos.x, currentVelocity.width,
                      aDestination.x);
   InitTimingFunction(mTimingFunctionY, mStartPos.y, currentVelocity.height,
                      aDestination.y);
   mIsFirstIteration = false;
 }
 
 TimeDuration
-ScrollAnimationPhysics::ComputeDuration(TimeStamp aTime)
+ScrollAnimationBezierPhysics::ComputeDuration(const TimeStamp& aTime)
 {
   // Average last 3 delta durations (rounding errors up to 2ms are negligible for us)
   int32_t eventsDeltaMs = (aTime - mPrevEventTime[2]).ToMilliseconds() / 3;
   mPrevEventTime[2] = mPrevEventTime[1];
   mPrevEventTime[1] = mPrevEventTime[0];
   mPrevEventTime[0] = aTime;
 
   // Modulate duration according to events rate (quicker events -> shorter durations).
@@ -69,80 +69,80 @@ ScrollAnimationPhysics::ComputeDuration(
   int32_t durationMS =
     clamped<int32_t>(eventsDeltaMs * mSettings.mIntervalRatio,
                      mSettings.mMinMS, mSettings.mMaxMS);
 
   return TimeDuration::FromMilliseconds(durationMS);
 }
 
 void
-ScrollAnimationPhysics::InitializeHistory(TimeStamp aTime)
+ScrollAnimationBezierPhysics::InitializeHistory(const TimeStamp& aTime)
 {
   // Starting a new scroll (i.e. not when extending an existing scroll animation),
   // create imaginary prev timestamps with maximum relevant intervals between them.
 
   // Longest relevant interval (which results in maximum duration)
   TimeDuration maxDelta =
     TimeDuration::FromMilliseconds(mSettings.mMaxMS / mSettings.mIntervalRatio);
   mPrevEventTime[0] = aTime              - maxDelta;
   mPrevEventTime[1] = mPrevEventTime[0]  - maxDelta;
   mPrevEventTime[2] = mPrevEventTime[1]  - maxDelta;
 }
 
 void
-ScrollAnimationPhysics::InitTimingFunction(nsSMILKeySpline& aTimingFunction,
-                                           nscoord aCurrentPos,
-                                           nscoord aCurrentVelocity,
-                                           nscoord aDestination)
+ScrollAnimationBezierPhysics::InitTimingFunction(nsSMILKeySpline& aTimingFunction,
+                                                 nscoord aCurrentPos,
+                                                 nscoord aCurrentVelocity,
+                                                 nscoord aDestination)
 {
   if (aDestination == aCurrentPos || gfxPrefs::SmoothScrollCurrentVelocityWeighting() == 0) {
     aTimingFunction.Init(0, 0, 1 - gfxPrefs::SmoothScrollStopDecelerationWeighting(), 1);
     return;
   }
 
   const TimeDuration oneSecond = TimeDuration::FromSeconds(1);
   double slope = aCurrentVelocity * (mDuration / oneSecond) / (aDestination - aCurrentPos);
   double normalization = sqrt(1.0 + slope * slope);
   double dt = 1.0 / normalization * gfxPrefs::SmoothScrollCurrentVelocityWeighting();
   double dxy = slope / normalization * gfxPrefs::SmoothScrollCurrentVelocityWeighting();
   aTimingFunction.Init(dt, dxy, 1 - gfxPrefs::SmoothScrollStopDecelerationWeighting(), 1);
 }
 
 nsPoint
-ScrollAnimationPhysics::PositionAt(TimeStamp aTime)
+ScrollAnimationBezierPhysics::PositionAt(const TimeStamp& aTime)
 {
   if (IsFinished(aTime)) {
     return mDestination;
   }
 
   double progressX = mTimingFunctionX.GetSplineValue(ProgressAt(aTime));
   double progressY = mTimingFunctionY.GetSplineValue(ProgressAt(aTime));
   return nsPoint(NSToCoordRound((1 - progressX) * mStartPos.x + progressX * mDestination.x),
                  NSToCoordRound((1 - progressY) * mStartPos.y + progressY * mDestination.y));
 }
 
 nsSize
-ScrollAnimationPhysics::VelocityAt(TimeStamp aTime)
+ScrollAnimationBezierPhysics::VelocityAt(const TimeStamp& aTime)
 {
   if (IsFinished(aTime)) {
     return nsSize(0, 0);
   }
 
   double timeProgress = ProgressAt(aTime);
   return nsSize(VelocityComponent(timeProgress, mTimingFunctionX,
                                   mStartPos.x, mDestination.x),
                 VelocityComponent(timeProgress, mTimingFunctionY,
                                   mStartPos.y, mDestination.y));
 }
 
 nscoord
-ScrollAnimationPhysics::VelocityComponent(double aTimeProgress,
-                                          const nsSMILKeySpline& aTimingFunction,
-                                          nscoord aStart,
-                                          nscoord aDestination) const
+ScrollAnimationBezierPhysics::VelocityComponent(double aTimeProgress,
+                                                const nsSMILKeySpline& aTimingFunction,
+                                                nscoord aStart,
+                                                nscoord aDestination) const
 {
   double dt, dxy;
   aTimingFunction.GetSplineDerivativeValues(aTimeProgress, dt, dxy);
   if (dt == 0)
     return dxy >= 0 ? nscoord_MAX : nscoord_MIN;
 
   const TimeDuration oneSecond = TimeDuration::FromSeconds(1);
   double slope = dxy / dt;
new file mode 100644
--- /dev/null
+++ b/layout/generic/ScrollAnimationBezierPhysics.h
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layout_ScrollAnimationBezierPhysics_h_
+#define mozilla_layout_ScrollAnimationBezierPhysics_h_
+
+#include "ScrollAnimationPhysics.h"
+#include "nsSMILKeySpline.h"
+
+namespace mozilla {
+
+struct ScrollAnimationBezierPhysicsSettings
+{
+  // These values are minimum and maximum animation duration per event,
+  // and a global ratio which defines how longer is the animation's duration
+  // compared to the average recent events intervals (such that for a relatively
+  // consistent events rate, the next event arrives before current animation ends)
+  int32_t mMinMS;
+  int32_t mMaxMS;
+  double mIntervalRatio;
+};
+
+// This class implements a cubic bezier timing function and automatically
+// adapts the animation duration based on the scrolling rate.
+class ScrollAnimationBezierPhysics : public ScrollAnimationPhysics
+{
+public:
+  explicit ScrollAnimationBezierPhysics(const nsPoint& aStartPos,
+                                        const ScrollAnimationBezierPhysicsSettings& aSettings);
+
+  void Update(const TimeStamp& aTime,
+              const nsPoint& aDestination,
+              const nsSize& aCurrentVelocity) override;
+
+  // Get the velocity at a point in time in nscoords/sec.
+  nsSize VelocityAt(const TimeStamp& aTime) override;
+
+  // Returns the expected scroll position at a given point in time, in app
+  // units, relative to the scroll frame.
+  nsPoint PositionAt(const TimeStamp& aTime) override;
+
+  bool IsFinished(const TimeStamp& aTime) override {
+    return aTime > mStartTime + mDuration;
+  }
+
+protected:
+  double ProgressAt(const TimeStamp& aTime) const {
+    return clamped((aTime - mStartTime) / mDuration, 0.0, 1.0);
+  }
+
+  nscoord VelocityComponent(double aTimeProgress,
+                            const nsSMILKeySpline& aTimingFunction,
+                            nscoord aStart, nscoord aDestination) const;
+
+  // Calculate duration, possibly dynamically according to events rate and
+  // event origin. (also maintain previous timestamps - which are only used
+  // here).
+  TimeDuration ComputeDuration(const TimeStamp& aTime);
+
+  // Initializes the timing function in such a way that the current velocity is
+  // preserved.
+  void InitTimingFunction(nsSMILKeySpline& aTimingFunction,
+                          nscoord aCurrentPos, nscoord aCurrentVelocity,
+                          nscoord aDestination);
+
+  // Initialize event history.
+  void InitializeHistory(const TimeStamp& aTime);
+
+  // Cached Preferences values.
+  ScrollAnimationBezierPhysicsSettings mSettings;
+
+  // mPrevEventTime holds previous 3 timestamps for intervals averaging (to
+  // reduce duration fluctuations). When AsyncScroll is constructed and no
+  // previous timestamps are available (indicated with mIsFirstIteration),
+  // initialize mPrevEventTime using imaginary previous timestamps with maximum
+  // relevant intervals between them.
+  TimeStamp mPrevEventTime[3];
+
+  TimeStamp mStartTime;
+
+  nsPoint mStartPos;
+  nsPoint mDestination;
+  TimeDuration mDuration;
+  nsSMILKeySpline mTimingFunctionX;
+  nsSMILKeySpline mTimingFunctionY;
+  bool mIsFirstIteration;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_layout_ScrollAnimationBezierPhysics_h_
--- a/layout/generic/ScrollAnimationPhysics.h
+++ b/layout/generic/ScrollAnimationPhysics.h
@@ -3,98 +3,36 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layout_ScrollAnimationPhysics_h_
 #define mozilla_layout_ScrollAnimationPhysics_h_
 
 #include "mozilla/TimeStamp.h"
 #include "nsPoint.h"
-#include "nsSMILKeySpline.h"
 
 namespace mozilla {
 
-struct ScrollAnimationPhysicsSettings
-{
-  // These values are minimum and maximum animation duration per event,
-  // and a global ratio which defines how longer is the animation's duration
-  // compared to the average recent events intervals (such that for a relatively
-  // consistent events rate, the next event arrives before current animation ends)
-  int32_t mMinMS;
-  int32_t mMaxMS;
-  double mIntervalRatio;
-};
-
-// This is the base class for driving scroll wheel animation on both the
-// compositor and main thread.
 class ScrollAnimationPhysics
 {
 public:
-  typedef mozilla::TimeStamp TimeStamp;
-  typedef mozilla::TimeDuration TimeDuration;
-
-  explicit ScrollAnimationPhysics(nsPoint aStartPos,
-                                  const ScrollAnimationPhysicsSettings& aSettings);
-
-  void Update(TimeStamp aTime,
-              nsPoint aDestination,
-              const nsSize& aCurrentVelocity);
+  virtual void Update(const TimeStamp& aTime,
+                      const nsPoint& aDestination,
+                      const nsSize& aCurrentVelocity) = 0;
 
   // Get the velocity at a point in time in nscoords/sec.
-  nsSize VelocityAt(TimeStamp aTime);
+  virtual nsSize VelocityAt(const TimeStamp& aTime) = 0;
 
   // Returns the expected scroll position at a given point in time, in app
   // units, relative to the scroll frame.
-  nsPoint PositionAt(TimeStamp aTime);
-
-  bool IsFinished(TimeStamp aTime) {
-    return aTime > mStartTime + mDuration;
-  }
-
-protected:
-  double ProgressAt(TimeStamp aTime) const {
-    return clamped((aTime - mStartTime) / mDuration, 0.0, 1.0);
-  }
-
-  nscoord VelocityComponent(double aTimeProgress,
-                            const nsSMILKeySpline& aTimingFunction,
-                            nscoord aStart, nscoord aDestination) const;
-
-  // Calculate duration, possibly dynamically according to events rate and
-  // event origin. (also maintain previous timestamps - which are only used
-  // here).
-  TimeDuration ComputeDuration(TimeStamp aTime);
+  virtual nsPoint PositionAt(const TimeStamp& aTime) = 0;
 
-  // Initializes the timing function in such a way that the current velocity is
-  // preserved.
-  void InitTimingFunction(nsSMILKeySpline& aTimingFunction,
-                          nscoord aCurrentPos, nscoord aCurrentVelocity,
-                          nscoord aDestination);
-
-  // Initialize event history.
-  void InitializeHistory(TimeStamp aTime);
-
-  // Cached Preferences values.
-  ScrollAnimationPhysicsSettings mSettings;
+  virtual bool IsFinished(const TimeStamp& aTime) = 0;
 
-  // mPrevEventTime holds previous 3 timestamps for intervals averaging (to
-  // reduce duration fluctuations). When AsyncScroll is constructed and no
-  // previous timestamps are available (indicated with mIsFirstIteration),
-  // initialize mPrevEventTime using imaginary previous timestamps with maximum
-  // relevant intervals between them.
-  TimeStamp mPrevEventTime[3];
-
-  TimeStamp mStartTime;
-
-  nsPoint mStartPos;
-  nsPoint mDestination;
-  TimeDuration mDuration;
-  nsSMILKeySpline mTimingFunctionX;
-  nsSMILKeySpline mTimingFunctionY;
-  bool mIsFirstIteration;
+  virtual ~ScrollAnimationPhysics() {}
 };
 
 // Helper for accelerated wheel deltas. This can be called from the main thread
 // or the APZ Controller thread.
 static inline double
 ComputeAcceleratedWheelDelta(double aDelta, int32_t aCounter, int32_t aFactor)
 {
   if (!aDelta) {
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -95,16 +95,17 @@ EXPORTS += [
     'nsRubyFrame.h',
     'nsRubyTextContainerFrame.h',
     'nsRubyTextFrame.h',
     'nsSplittableFrame.h',
     'nsSubDocumentFrame.h',
     'nsTextFrameUtils.h',
     'nsTextRunTransformations.h',
     'RubyUtils.h',
+    'ScrollAnimationBezierPhysics.h',
     'ScrollAnimationPhysics.h',
     'ScrollbarActivity.h',
     'ScrollSnap.h',
     'TextDrawTarget.h',
     'Visibility.h',
 ]
 
 EXPORTS.mozilla += [
@@ -171,17 +172,17 @@ UNIFIED_SOURCES += [
     'nsSubDocumentFrame.cpp',
     'nsTextFrame.cpp',
     'nsTextFrameUtils.cpp',
     'nsTextRunTransformations.cpp',
     'nsVideoFrame.cpp',
     'ReflowInput.cpp',
     'ReflowOutput.cpp',
     'RubyUtils.cpp',
-    'ScrollAnimationPhysics.cpp',
+    'ScrollAnimationBezierPhysics.cpp',
     'ScrollbarActivity.cpp',
     'ScrollSnap.cpp',
     'ScrollVelocityQueue.cpp',
     'StickyScrollContainer.cpp',
     'TextOverflow.cpp',
     'ViewportFrame.cpp',
 ]
 
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -53,16 +53,17 @@
 #include "nsThemeConstants.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsIScrollPositionListener.h"
 #include "StickyScrollContainer.h"
 #include "nsIFrameInlines.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "ScrollAnimationPhysics.h"
+#include "ScrollAnimationBezierPhysics.h"
 #include "ScrollSnap.h"
 #include "UnitTransforms.h"
 #include "nsPluginFrame.h"
 #include "nsSliderFrame.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include <mozilla/layers/AxisPhysicsModel.h>
 #include <mozilla/layers/AxisPhysicsMSDModel.h>
 #include "mozilla/layers/LayerTransactionChild.h"
@@ -1905,17 +1906,17 @@ private:
     }
   }
 };
 
 /*
  * Calculate duration, possibly dynamically according to events rate and event origin.
  * (also maintain previous timestamps - which are only used here).
  */
-static ScrollAnimationPhysicsSettings
+static ScrollAnimationBezierPhysicsSettings
 ComputeAnimationSettingsForOrigin(nsIAtom *aOrigin)
 {
   int32_t minMS = 0;
   int32_t maxMS = 0;
   bool isOriginSmoothnessEnabled = false;
   double intervalRatio = 1;
 
   // Default values for all preferences are defined in all.js
@@ -1942,17 +1943,17 @@ ComputeAnimationSettingsForOrigin(nsIAto
   //   (to "connect" consecutive scroll animations before the scroll comes to a stop).
   static const double kDefaultDurationToIntervalRatio = 2; // Duplicated at all.js
   intervalRatio = Preferences::GetInt("general.smoothScroll.durationToIntervalRatio",
                                                       kDefaultDurationToIntervalRatio * 100) / 100.0;
 
   // Duration should be at least as long as the intervals -> ratio is at least 1
   intervalRatio = std::max(1.0, intervalRatio);
 
-  return ScrollAnimationPhysicsSettings { minMS, maxMS, intervalRatio };
+  return ScrollAnimationBezierPhysicsSettings { minMS, maxMS, intervalRatio };
 }
 
 void
 ScrollFrameHelper::AsyncScroll::InitSmoothScroll(TimeStamp aTime,
                                                  nsPoint aInitialPosition,
                                                  nsPoint aDestination,
                                                  nsIAtom *aOrigin,
                                                  const nsRect& aRange,
@@ -1966,18 +1967,19 @@ ScrollFrameHelper::AsyncScroll::InitSmoo
   }
   // Likewise we should never get APZ-triggered scrolls here, and if that changes
   // something is likely broken somewhere.
   MOZ_ASSERT(aOrigin != nsGkAtoms::apz);
 
   // Read preferences only on first iteration or for a different event origin.
   if (!mAnimationPhysics || aOrigin != mOrigin) {
     mOrigin = aOrigin;
-    ScrollAnimationPhysicsSettings settings = ComputeAnimationSettingsForOrigin(mOrigin);
-    mAnimationPhysics = MakeUnique<ScrollAnimationPhysics>(aInitialPosition, settings);
+    ScrollAnimationBezierPhysicsSettings settings = ComputeAnimationSettingsForOrigin(mOrigin);
+    mAnimationPhysics =
+      MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, settings);
   }
 
   mRange = aRange;
 
   mAnimationPhysics->Update(aTime, aDestination, aCurrentVelocity);
 }
 
 bool