Bug 1402498 - Rename AsyncScrollBase to ScrollAnimationPhysics and use composition instead of inheritance. r=rhunt
authorMarkus Stange <mstange@themasta.com>
Fri, 22 Sep 2017 13:42:29 -0400
changeset 383857 8f20a445bc31ff987c994e6ca1dbf013edbd3f69
parent 383856 ddf078fad9f44e690bb43f61058e766f5dbf9e62
child 383858 c63987a3b9ded6a00ba370c676a55be888320a9d
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 - Rename AsyncScrollBase to ScrollAnimationPhysics and use composition instead of inheritance. r=rhunt MozReview-Commit-ID: 7UFf0mZsrEr
dom/events/WheelHandlingHelper.cpp
gfx/layers/apz/src/GenericScrollAnimation.cpp
gfx/layers/apz/src/GenericScrollAnimation.h
gfx/layers/apz/src/InputBlockState.cpp
gfx/layers/apz/src/KeyboardScrollAnimation.cpp
gfx/layers/apz/src/WheelScrollAnimation.cpp
layout/generic/AsyncScrollBase.cpp
layout/generic/AsyncScrollBase.h
layout/generic/ScrollAnimationPhysics.cpp
layout/generic/ScrollAnimationPhysics.h
layout/generic/moz.build
layout/generic/nsGfxScrollFrame.cpp
--- a/dom/events/WheelHandlingHelper.cpp
+++ b/dom/events/WheelHandlingHelper.cpp
@@ -16,17 +16,17 @@
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsIScrollableFrame.h"
 #include "nsITimer.h"
 #include "nsPluginFrame.h"
 #include "nsPresContext.h"
 #include "prtime.h"
 #include "Units.h"
-#include "AsyncScrollBase.h"
+#include "ScrollAnimationPhysics.h"
 
 namespace mozilla {
 
 /******************************************************************/
 /* mozilla::DeltaValues                                           */
 /******************************************************************/
 
 DeltaValues::DeltaValues(WidgetWheelEvent* aEvent)
--- a/gfx/layers/apz/src/GenericScrollAnimation.cpp
+++ b/gfx/layers/apz/src/GenericScrollAnimation.cpp
@@ -10,18 +10,18 @@
 #include "gfxPrefs.h"
 #include "nsPoint.h"
 
 namespace mozilla {
 namespace layers {
 
 GenericScrollAnimation::GenericScrollAnimation(AsyncPanZoomController& aApzc,
                                                const nsPoint& aInitialPosition)
-  : AsyncScrollBase(aInitialPosition)
-  , mApzc(aApzc)
+  : mApzc(aApzc)
+  , mAnimationPhysics(aInitialPosition)
   , mFinalDestination(aInitialPosition)
   , mForceVerticalOverscroll(false)
 {
 }
 
 void
 GenericScrollAnimation::UpdateDelta(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity)
 {
@@ -36,51 +36,51 @@ GenericScrollAnimation::UpdateDestinatio
   mFinalDestination = aDestination;
 
   Update(aTime, aCurrentVelocity);
 }
 
 void
 GenericScrollAnimation::Update(TimeStamp aTime, const nsSize& aCurrentVelocity)
 {
-  if (mIsFirstIteration) {
-    InitializeHistory(aTime);
+  if (mAnimationPhysics.mIsFirstIteration) {
+    mAnimationPhysics.InitializeHistory(aTime);
   }
 
   // Clamp the final destination to the scrollable area.
   CSSPoint clamped = CSSPoint::FromAppUnits(mFinalDestination);
   clamped.x = mApzc.mX.ClampOriginToScrollableRect(clamped.x);
   clamped.y = mApzc.mY.ClampOriginToScrollableRect(clamped.y);
   mFinalDestination = CSSPoint::ToAppUnits(clamped);
 
-  AsyncScrollBase::Update(aTime, mFinalDestination, aCurrentVelocity);
+  mAnimationPhysics.Update(aTime, mFinalDestination, aCurrentVelocity);
 }
 
 bool
 GenericScrollAnimation::DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta)
 {
   TimeStamp now = mApzc.GetFrameTime();
   CSSToParentLayerScale2D zoom = aFrameMetrics.GetZoom();
 
   // If the animation is finished, make sure the final position is correct by
   // using one last displacement. Otherwise, compute the delta via the timing
   // function as normal.
-  bool finished = IsFinished(now);
+  bool finished = mAnimationPhysics.IsFinished(now);
   nsPoint sampledDest = finished
-                        ? mDestination
-                        : PositionAt(now);
+                        ? mAnimationPhysics.mDestination
+                        : mAnimationPhysics.PositionAt(now);
   ParentLayerPoint displacement =
     (CSSPoint::FromAppUnits(sampledDest) - aFrameMetrics.GetScrollOffset()) * zoom;
 
   if (finished) {
     mApzc.mX.SetVelocity(0);
     mApzc.mY.SetVelocity(0);
   } else if (!IsZero(displacement)) {
     // Convert velocity from AppUnits/Seconds to ParentLayerCoords/Milliseconds
-    nsSize velocity = VelocityAt(now);
+    nsSize velocity = mAnimationPhysics.VelocityAt(now);
     ParentLayerPoint velocityPL =
       CSSPoint::FromAppUnits(nsPoint(velocity.width, velocity.height)) * zoom;
     mApzc.mX.SetVelocity(velocityPL.x / 1000.0);
     mApzc.mY.SetVelocity(velocityPL.y / 1000.0);
   }
 
   // Note: we ignore overscroll for generic animations.
   ParentLayerPoint adjustedOffset, overscroll;
--- a/gfx/layers/apz/src/GenericScrollAnimation.h
+++ b/gfx/layers/apz/src/GenericScrollAnimation.h
@@ -3,45 +3,45 @@
 /* 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 "AsyncScrollBase.h"
+#include "ScrollAnimationPhysics.h"
 
 namespace mozilla {
 namespace layers {
 
 class AsyncPanZoomController;
 
 class GenericScrollAnimation
-  : public AsyncPanZoomAnimation,
-    public AsyncScrollBase
+  : public AsyncPanZoomAnimation
 {
 public:
   GenericScrollAnimation(AsyncPanZoomController& aApzc,
                          const nsPoint& aInitialPosition);
 
   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);
   }
 
 private:
   void Update(TimeStamp aTime, const nsSize& aCurrentVelocity);
-
+ 
 protected:
   AsyncPanZoomController& mApzc;
+  ScrollAnimationPhysics mAnimationPhysics;
   nsPoint mFinalDestination;
   bool mForceVerticalOverscroll;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_GenericScrollAnimation_h_
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -1,17 +1,17 @@
 /* -*- 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 "InputBlockState.h"
 #include "AsyncPanZoomController.h"         // for AsyncPanZoomController
-#include "AsyncScrollBase.h"                // for kScrollSeriesTimeoutMs
+#include "ScrollAnimationPhysics.h"         // for kScrollSeriesTimeoutMs
 #include "gfxPrefs.h"                       // for gfxPrefs
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Telemetry.h"              // for Telemetry
 #include "mozilla/layers/APZCTreeManager.h" // for AllowedTouchBehavior
 #include "OverscrollHandoffState.h"
 #include "QueuedInput.h"
 
 #define TBS_LOG(...)
--- a/gfx/layers/apz/src/KeyboardScrollAnimation.cpp
+++ b/gfx/layers/apz/src/KeyboardScrollAnimation.cpp
@@ -14,31 +14,31 @@ namespace layers {
 KeyboardScrollAnimation::KeyboardScrollAnimation(AsyncPanZoomController& aApzc,
                                                  const nsPoint& aInitialPosition,
                                                  KeyboardScrollAction::KeyboardScrollActionType aType)
   : GenericScrollAnimation(aApzc, aInitialPosition)
 {
   switch (aType) {
     case KeyboardScrollAction::eScrollCharacter:
     case KeyboardScrollAction::eScrollLine: {
-      mOriginMaxMS = clamped(gfxPrefs::LineSmoothScrollMaxDurationMs(), 0, 10000);
-      mOriginMinMS = clamped(gfxPrefs::LineSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+      mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::LineSmoothScrollMaxDurationMs(), 0, 10000);
+      mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::LineSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
       break;
     }
     case KeyboardScrollAction::eScrollPage: {
-      mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
-      mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+      mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
+      mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
       break;
     }
     case KeyboardScrollAction::eScrollComplete: {
-      mOriginMaxMS = clamped(gfxPrefs::OtherSmoothScrollMaxDurationMs(), 0, 10000);
-      mOriginMinMS = clamped(gfxPrefs::OtherSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+      mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::OtherSmoothScrollMaxDurationMs(), 0, 10000);
+      mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::OtherSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
       break;
     }
   }
 
   // The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
-  mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
-  mIntervalRatio = std::max(1.0, mIntervalRatio);
+  mAnimationPhysics.mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
+  mAnimationPhysics.mIntervalRatio = std::max(1.0, mAnimationPhysics.mIntervalRatio);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/apz/src/WheelScrollAnimation.cpp
+++ b/gfx/layers/apz/src/WheelScrollAnimation.cpp
@@ -17,28 +17,28 @@ WheelScrollAnimation::WheelScrollAnimati
                                            const nsPoint& aInitialPosition,
                                            ScrollWheelInput::ScrollDeltaType aDeltaType)
   : GenericScrollAnimation(aApzc, aInitialPosition)
 {
   mForceVerticalOverscroll = !mApzc.mScrollMetadata.AllowVerticalScrollWithWheel();
 
   switch (aDeltaType) {
   case ScrollWheelInput::SCROLLDELTA_PAGE:
-    mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
-    mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+    mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
+    mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
     break;
   case ScrollWheelInput::SCROLLDELTA_PIXEL:
-    mOriginMaxMS = clamped(gfxPrefs::PixelSmoothScrollMaxDurationMs(), 0, 10000);
-    mOriginMinMS = clamped(gfxPrefs::PixelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+    mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::PixelSmoothScrollMaxDurationMs(), 0, 10000);
+    mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::PixelSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
     break;
   case ScrollWheelInput::SCROLLDELTA_LINE:
-    mOriginMaxMS = clamped(gfxPrefs::WheelSmoothScrollMaxDurationMs(), 0, 10000);
-    mOriginMinMS = clamped(gfxPrefs::WheelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+    mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::WheelSmoothScrollMaxDurationMs(), 0, 10000);
+    mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::WheelSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
     break;
   }
 
   // The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
-  mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
-  mIntervalRatio = std::max(1.0, mIntervalRatio);
+  mAnimationPhysics.mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
+  mAnimationPhysics.mIntervalRatio = std::max(1.0, mAnimationPhysics.mIntervalRatio);
 }
 
 } // namespace layers
 } // namespace mozilla
rename from layout/generic/AsyncScrollBase.cpp
rename to layout/generic/ScrollAnimationPhysics.cpp
--- a/layout/generic/AsyncScrollBase.cpp
+++ b/layout/generic/ScrollAnimationPhysics.cpp
@@ -1,28 +1,28 @@
 /* -*- 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 "AsyncScrollBase.h"
+#include "ScrollAnimationPhysics.h"
 #include "gfxPrefs.h"
 
 using namespace mozilla;
 
-AsyncScrollBase::AsyncScrollBase(nsPoint aStartPos)
+ScrollAnimationPhysics::ScrollAnimationPhysics(nsPoint aStartPos)
  : mIsFirstIteration(true)
  , mStartPos(aStartPos)
 {
 }
 
 void
-AsyncScrollBase::Update(TimeStamp aTime,
-                        nsPoint aDestination,
-                        const nsSize& aCurrentVelocity)
+ScrollAnimationPhysics::Update(TimeStamp aTime,
+                               nsPoint aDestination,
+                               const nsSize& aCurrentVelocity)
 {
   TimeDuration duration = ComputeDuration(aTime);
   nsSize currentVelocity = aCurrentVelocity;
 
   if (!mIsFirstIteration) {
     // If an additional event has not changed the destination, then do not let
     // another minimum duration reset slow things down.  If it would then
     // instead continue with the existing timing function.
@@ -42,17 +42,17 @@ AsyncScrollBase::Update(TimeStamp aTime,
   InitTimingFunction(mTimingFunctionX, mStartPos.x, currentVelocity.width,
                      aDestination.x);
   InitTimingFunction(mTimingFunctionY, mStartPos.y, currentVelocity.height,
                      aDestination.y);
   mIsFirstIteration = false;
 }
 
 TimeDuration
-AsyncScrollBase::ComputeDuration(TimeStamp aTime)
+ScrollAnimationPhysics::ComputeDuration(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).
@@ -61,71 +61,71 @@ AsyncScrollBase::ComputeDuration(TimeSta
   // scrolling quickly. To reduce fluctuations of the duration, we average event
   // intervals using the recent 4 timestamps (now + three prev -> 3 intervals).
   int32_t durationMS = clamped<int32_t>(eventsDeltaMs * mIntervalRatio, mOriginMinMS, mOriginMaxMS);
 
   return TimeDuration::FromMilliseconds(durationMS);
 }
 
 void
-AsyncScrollBase::InitializeHistory(TimeStamp aTime)
+ScrollAnimationPhysics::InitializeHistory(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(mOriginMaxMS / mIntervalRatio);
   mPrevEventTime[0] = aTime              - maxDelta;
   mPrevEventTime[1] = mPrevEventTime[0]  - maxDelta;
   mPrevEventTime[2] = mPrevEventTime[1]  - maxDelta;
 }
 
 void
-AsyncScrollBase::InitTimingFunction(nsSMILKeySpline& aTimingFunction,
-                                    nscoord aCurrentPos,
-                                    nscoord aCurrentVelocity,
-                                    nscoord aDestination)
+ScrollAnimationPhysics::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
-AsyncScrollBase::PositionAt(TimeStamp aTime) const
+ScrollAnimationPhysics::PositionAt(TimeStamp aTime) const
 {
   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
-AsyncScrollBase::VelocityAt(TimeStamp aTime) const
+ScrollAnimationPhysics::VelocityAt(TimeStamp aTime) const
 {
   double timeProgress = ProgressAt(aTime);
   return nsSize(VelocityComponent(timeProgress, mTimingFunctionX,
                                   mStartPos.x, mDestination.x),
                 VelocityComponent(timeProgress, mTimingFunctionY,
                                   mStartPos.y, mDestination.y));
 }
 
 nscoord
-AsyncScrollBase::VelocityComponent(double aTimeProgress,
-                                   const nsSMILKeySpline& aTimingFunction,
-                                   nscoord aStart,
-                                   nscoord aDestination) const
+ScrollAnimationPhysics::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;
rename from layout/generic/AsyncScrollBase.h
rename to layout/generic/ScrollAnimationPhysics.h
--- a/layout/generic/AsyncScrollBase.h
+++ b/layout/generic/ScrollAnimationPhysics.h
@@ -1,93 +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_AsyncScrollBase_h_
-#define mozilla_layout_AsyncScrollBase_h_
+#ifndef mozilla_layout_ScrollAnimationPhysics_h_
+#define mozilla_layout_ScrollAnimationPhysics_h_
 
 #include "mozilla/TimeStamp.h"
 #include "nsPoint.h"
 #include "nsSMILKeySpline.h"
 
 namespace mozilla {
 
 // This is the base class for driving scroll wheel animation on both the
 // compositor and main thread.
-class AsyncScrollBase
+class ScrollAnimationPhysics
 {
 public:
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
 
-  explicit AsyncScrollBase(nsPoint aStartPos);
+  explicit ScrollAnimationPhysics(nsPoint aStartPos);
 
   void Update(TimeStamp aTime,
               nsPoint aDestination,
               const nsSize& aCurrentVelocity);
 
   // Get the velocity at a point in time in nscoords/sec.
   nsSize VelocityAt(TimeStamp aTime) const;
 
   // Returns the expected scroll position at a given point in time, in app
   // units, relative to the scroll frame.
   nsPoint PositionAt(TimeStamp aTime) const;
 
   bool IsFinished(TimeStamp aTime) {
     return aTime > mStartTime + mDuration;
   }
 
+  // Initialize event history.
+  void InitializeHistory(TimeStamp aTime);
+
+  // Cached Preferences value.
+  //
+  // These values are minimum and maximum animation duration per event origin,
+  // 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 mOriginMinMS;
+  int32_t mOriginMaxMS;
+  double mIntervalRatio;
+  nsPoint mDestination;
+  bool mIsFirstIteration;
+
 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);
 
-  // Initialize event history.
-  void InitializeHistory(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);
 
   // 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];
-  bool mIsFirstIteration;
 
   TimeStamp mStartTime;
 
-  // Cached Preferences value.
-  //
-  // These values are minimum and maximum animation duration per event origin,
-  // 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 mOriginMinMS;
-  int32_t mOriginMaxMS;
-  double mIntervalRatio;
-
   nsPoint mStartPos;
   TimeDuration mDuration;
-  nsPoint mDestination;
   nsSMILKeySpline mTimingFunctionX;
   nsSMILKeySpline mTimingFunctionY;
 };
 
 // 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)
@@ -97,9 +97,9 @@ ComputeAcceleratedWheelDelta(double aDel
   }
   return (aDelta * aCounter * double(aFactor) / 10);
 }
 
 static const uint32_t kScrollSeriesTimeoutMs = 80; // in milliseconds
 
 } // namespace mozilla
 
-#endif // mozilla_layout_AsyncScrollBase_h_
+#endif // mozilla_layout_ScrollAnimationPhysics_h_
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -63,17 +63,16 @@ with Files('Sticky*'):
 
 with Files('nsPluginFrame.*'):
     BUG_COMPONENT = ('Core', 'Plug-ins')
 
 with Files('nsVideoFrame.*'):
     BUG_COMPONENT = ('Core', 'Audio/Video')
 
 EXPORTS += [
-    'AsyncScrollBase.h',
     'nsCanvasFrame.h',
     'nsContainerFrame.h',
     'nsDirection.h',
     'nsFrame.h',
     'nsFrameIdList.h',
     'nsFrameList.h',
     'nsFrameSelection.h',
     'nsFrameState.h',
@@ -96,16 +95,17 @@ EXPORTS += [
     'nsRubyFrame.h',
     'nsRubyTextContainerFrame.h',
     'nsRubyTextFrame.h',
     'nsSplittableFrame.h',
     'nsSubDocumentFrame.h',
     'nsTextFrameUtils.h',
     'nsTextRunTransformations.h',
     'RubyUtils.h',
+    'ScrollAnimationPhysics.h',
     'ScrollbarActivity.h',
     'ScrollSnap.h',
     'TextDrawTarget.h',
     'Visibility.h',
 ]
 
 EXPORTS.mozilla += [
     'CSSAlignUtils.h',
@@ -117,17 +117,16 @@ EXPORTS.mozilla += [
     'WritingModes.h',
 ]
 
 EXPORTS.mozilla.layout += [
     'FrameChildList.h',
 ]
 
 UNIFIED_SOURCES += [
-    'AsyncScrollBase.cpp',
     'BlockReflowInput.cpp',
     'BRFrame.cpp',
     'CSSAlignUtils.cpp',
     'CSSOrderAwareFrameIterator.cpp',
     'DetailsFrame.cpp',
     'FrameChildList.cpp',
     'MathMLTextRunFactory.cpp',
     'nsAbsoluteContainingBlock.cpp',
@@ -172,16 +171,17 @@ UNIFIED_SOURCES += [
     'nsSubDocumentFrame.cpp',
     'nsTextFrame.cpp',
     'nsTextFrameUtils.cpp',
     'nsTextRunTransformations.cpp',
     'nsVideoFrame.cpp',
     'ReflowInput.cpp',
     'ReflowOutput.cpp',
     'RubyUtils.cpp',
+    'ScrollAnimationPhysics.cpp',
     'ScrollbarActivity.cpp',
     'ScrollSnap.cpp',
     'ScrollVelocityQueue.cpp',
     'StickyScrollContainer.cpp',
     'TextOverflow.cpp',
     'ViewportFrame.cpp',
 ]
 
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -52,17 +52,17 @@
 #include "nsRefreshDriver.h"
 #include "nsThemeConstants.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsIScrollPositionListener.h"
 #include "StickyScrollContainer.h"
 #include "nsIFrameInlines.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
-#include "AsyncScrollBase.h"
+#include "ScrollAnimationPhysics.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"
@@ -1794,25 +1794,24 @@ private:
   nsRect mRange;
   mozilla::TimeStamp mLastRefreshTime;
   ScrollFrameHelper *mCallee;
   nscoord mOneDevicePixelInAppUnits;
 };
 
 // AsyncScroll has ref counting.
 class ScrollFrameHelper::AsyncScroll final
-  : public nsARefreshObserver,
-    public AsyncScrollBase
+  : public nsARefreshObserver
 {
 public:
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
 
   explicit AsyncScroll(nsPoint aStartPos)
-    : AsyncScrollBase(aStartPos)
+    : mAnimationPhysics(aStartPos)
     , mCallee(nullptr)
   {
     Telemetry::SetHistogramRecordingEnabled(
       Telemetry::FX_REFRESH_DRIVER_SYNC_SCROLL_FRAME_DELAY_MS, true);
   }
 
 private:
   // Private destructor, to discourage deletion outside of Release():
@@ -1825,16 +1824,18 @@ private:
 public:
   void InitSmoothScroll(TimeStamp aTime, nsPoint aDestination,
                         nsIAtom *aOrigin, const nsRect& aRange,
                         const nsSize& aCurrentVelocity);
   void Init(const nsRect& aRange) {
     mRange = aRange;
   }
 
+  ScrollAnimationPhysics mAnimationPhysics;
+
   // Most recent scroll origin.
   RefPtr<nsIAtom> mOrigin;
 
   // Allowed destination positions around mDestination
   nsRect mRange;
   bool mIsSmoothScroll;
 
 private:
@@ -1901,70 +1902,70 @@ ScrollFrameHelper::AsyncScroll::InitPref
     // changes we should never have aOrigin == nsGkAtoms::restore here.
     aOrigin = nsGkAtoms::other;
   }
   // 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 (!mIsFirstIteration && aOrigin == mOrigin) {
+  if (!mAnimationPhysics.mIsFirstIteration && aOrigin == mOrigin) {
     return;
   }
 
   mOrigin = aOrigin;
-  mOriginMinMS = mOriginMaxMS = 0;
+  mAnimationPhysics.mOriginMinMS = mAnimationPhysics.mOriginMaxMS = 0;
   bool isOriginSmoothnessEnabled = false;
-  mIntervalRatio = 1;
+  mAnimationPhysics.mIntervalRatio = 1;
 
   // Default values for all preferences are defined in all.js
   static const int32_t kDefaultMinMS = 150, kDefaultMaxMS = 150;
   static const bool kDefaultIsSmoothEnabled = true;
 
   nsAutoCString originName;
   aOrigin->ToUTF8String(originName);
   nsAutoCString prefBase = NS_LITERAL_CSTRING("general.smoothScroll.") + originName;
 
   isOriginSmoothnessEnabled = Preferences::GetBool(prefBase.get(), kDefaultIsSmoothEnabled);
   if (isOriginSmoothnessEnabled) {
     nsAutoCString prefMin = prefBase + NS_LITERAL_CSTRING(".durationMinMS");
     nsAutoCString prefMax = prefBase + NS_LITERAL_CSTRING(".durationMaxMS");
-    mOriginMinMS = Preferences::GetInt(prefMin.get(), kDefaultMinMS);
-    mOriginMaxMS = Preferences::GetInt(prefMax.get(), kDefaultMaxMS);
+    mAnimationPhysics.mOriginMinMS = Preferences::GetInt(prefMin.get(), kDefaultMinMS);
+    mAnimationPhysics.mOriginMaxMS = Preferences::GetInt(prefMax.get(), kDefaultMaxMS);
 
     static const int32_t kSmoothScrollMaxAllowedAnimationDurationMS = 10000;
-    mOriginMaxMS = clamped(mOriginMaxMS, 0, kSmoothScrollMaxAllowedAnimationDurationMS);
-    mOriginMinMS = clamped(mOriginMinMS, 0, mOriginMaxMS);
+    mAnimationPhysics.mOriginMaxMS = clamped(mAnimationPhysics.mOriginMaxMS, 0, kSmoothScrollMaxAllowedAnimationDurationMS);
+    mAnimationPhysics.mOriginMinMS = clamped(mAnimationPhysics.mOriginMinMS, 0, mAnimationPhysics.mOriginMaxMS);
   }
 
   // Keep the animation duration longer than the average event intervals
   //   (to "connect" consecutive scroll animations before the scroll comes to a stop).
   static const double kDefaultDurationToIntervalRatio = 2; // Duplicated at all.js
-  mIntervalRatio = Preferences::GetInt("general.smoothScroll.durationToIntervalRatio",
-                                       kDefaultDurationToIntervalRatio * 100) / 100.0;
+  mAnimationPhysics.mIntervalRatio = Preferences::GetInt("general.smoothScroll.durationToIntervalRatio",
+                                                      kDefaultDurationToIntervalRatio * 100) / 100.0;
 
   // Duration should be at least as long as the intervals -> ratio is at least 1
-  mIntervalRatio = std::max(1.0, mIntervalRatio);
-
-  if (mIsFirstIteration) {
-    InitializeHistory(aTime);
+  mAnimationPhysics.mIntervalRatio = std::max(1.0, mAnimationPhysics.mIntervalRatio);
+
+  if (mAnimationPhysics.mIsFirstIteration) {
+    mAnimationPhysics.InitializeHistory(aTime);
   }
 }
 
 void
 ScrollFrameHelper::AsyncScroll::InitSmoothScroll(TimeStamp aTime,
                                                  nsPoint aDestination,
                                                  nsIAtom *aOrigin,
                                                  const nsRect& aRange,
                                                  const nsSize& aCurrentVelocity)
 {
   InitPreferences(aTime, aOrigin);
   mRange = aRange;
 
-  Update(aTime, aDestination, aCurrentVelocity);
+  mAnimationPhysics.Update(aTime, aDestination, aCurrentVelocity);
 }
 
 bool
 ScrollFrameHelper::IsSmoothScrollingEnabled()
 {
   return Preferences::GetBool(SMOOTH_SCROLL_PREF_NAME, false);
 }
 
@@ -2123,18 +2124,18 @@ ScrollFrameHelper::AsyncScrollCallback(S
     "Did not expect AsyncScrollCallback without an active async scroll.");
 
   if (!aInstance || !aInstance->mAsyncScroll) {
     return;  // XXX wallpaper bug 1107353 for now.
   }
 
   nsRect range = aInstance->mAsyncScroll->mRange;
   if (aInstance->mAsyncScroll->mIsSmoothScroll) {
-    if (!aInstance->mAsyncScroll->IsFinished(aTime)) {
-      nsPoint destination = aInstance->mAsyncScroll->PositionAt(aTime);
+    if (!aInstance->mAsyncScroll->mAnimationPhysics.IsFinished(aTime)) {
+      nsPoint destination = aInstance->mAsyncScroll->mAnimationPhysics.PositionAt(aTime);
       // Allow this scroll operation to land on any pixel boundary between the
       // current position and the final allowed range.  (We don't want
       // intermediate steps to be more constrained than the final step!)
       nsRect intermediateRange =
         nsRect(aInstance->GetScrollPosition(), nsSize()).UnionEdges(range);
       aInstance->ScrollToImpl(destination, intermediateRange);
       // 'aInstance' might be destroyed here
       return;
@@ -2287,17 +2288,17 @@ ScrollFrameHelper::ScrollToWithOrigin(ns
     if (aMode == nsIScrollableFrame::SMOOTH_MSD) {
       mIgnoreMomentumScroll = true;
       if (!mAsyncSmoothMSDScroll) {
         nsPoint sv = mVelocityQueue.GetVelocity();
         currentVelocity.width = sv.x;
         currentVelocity.height = sv.y;
         if (mAsyncScroll) {
           if (mAsyncScroll->mIsSmoothScroll) {
-            currentVelocity = mAsyncScroll->VelocityAt(now);
+            currentVelocity = mAsyncScroll->mAnimationPhysics.VelocityAt(now);
           }
           mAsyncScroll = nullptr;
         }
 
         if (nsLayoutUtils::AsyncPanZoomEnabled(mOuter) && WantAsyncScroll()) {
           if (mApzSmoothScrollDestination == Some(mDestination) &&
               mScrollGeneration == sScrollGenerationCounter) {
             // If we already sent APZ a smooth-scroll request to this