Bug 1402498 - Separate out ScrollAnimationBezierPhysics and make ScrollAnimationPhysics an interface. r=rhunt
authorMarkus Stange <mstange@themasta.com>
Fri, 29 Sep 2017 18:37:14 -0400
changeset 383859 884587d3b510a8268ab420adc469f45b8b568dac
parent 383858 c63987a3b9ded6a00ba370c676a55be888320a9d
child 383860 9c91a596243be462ad80d6f5e9c83833d59bf5f5
push id32607
push userarchaeopteryx@coole-files.de
push dateSat, 30 Sep 2017 23:00:11 +0000
treeherdermozilla-central@6d95cee536bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrhunt
bugs1402498
milestone58.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 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