Bug 1402498 - Add ScrollAnimationMSDPhysics, can be enabled using general.smoothScroll.msdPhysics.enabled. r=rhunt

MozReview-Commit-ID: fr8Q9iod5k

--HG--
extra : rebase_source : b9113d40081371872deff6aade13fd226b3e72a9
This commit is contained in:
Markus Stange 2017-09-26 20:55:35 -04:00
Родитель c2ed209689
Коммит 4b4d6f1561
7 изменённых файлов: 208 добавлений и 5 удалений

Просмотреть файл

@ -11,6 +11,7 @@
#include "nsPoint.h"
#include "ScrollAnimationPhysics.h"
#include "ScrollAnimationBezierPhysics.h"
#include "ScrollAnimationMSDPhysics.h"
namespace mozilla {
namespace layers {
@ -19,10 +20,14 @@ GenericScrollAnimation::GenericScrollAnimation(AsyncPanZoomController& aApzc,
const nsPoint& aInitialPosition,
const ScrollAnimationBezierPhysicsSettings& aSettings)
: mApzc(aApzc)
, mAnimationPhysics(MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, aSettings))
, mFinalDestination(aInitialPosition)
, mForceVerticalOverscroll(false)
{
if (gfxPrefs::SmoothScrollMSDPhysicsEnabled()) {
mAnimationPhysics = MakeUnique<ScrollAnimationMSDPhysics>(aInitialPosition);
} else {
mAnimationPhysics = MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, aSettings);
}
}
void

Просмотреть файл

@ -404,6 +404,21 @@ private:
DECL_GFX_PREF(Live, "general.smoothScroll.stopDecelerationWeighting",
SmoothScrollStopDecelerationWeighting, float, 0.4f);
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.enabled",
SmoothScrollMSDPhysicsEnabled, bool, false);
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.continuousMotionMaxDeltaMS",
SmoothScrollMSDPhysicsContinuousMotionMaxDeltaMS, int32_t, 120);
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.motionBeginSpringConstant",
SmoothScrollMSDPhysicsMotionBeginSpringConstant, int32_t, 1250);
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.slowdownMinDeltaMS",
SmoothScrollMSDPhysicsSlowdownMinDeltaMS, int32_t, 12);
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.slowdownMinDeltaRatio",
SmoothScrollMSDPhysicsSlowdownMinDeltaRatio, float, 1.3f);
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.slowdownSpringConstant",
SmoothScrollMSDPhysicsSlowdownSpringConstant, int32_t, 2000);
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.regularSpringConstant",
SmoothScrollMSDPhysicsRegularSpringConstant, int32_t, 1000);
DECL_GFX_PREF(Once, "gfx.android.rgb16.force", AndroidRGB16Force, bool, false);
#if defined(ANDROID)
DECL_GFX_PREF(Once, "gfx.apitrace.enabled", UseApitrace, bool, false);

Просмотреть файл

@ -0,0 +1,109 @@
/* -*- 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 "ScrollAnimationMSDPhysics.h"
#include "gfxPrefs.h"
using namespace mozilla;
ScrollAnimationMSDPhysics::ScrollAnimationMSDPhysics(const nsPoint& aStartPos)
: mStartPos(aStartPos)
, mModelX(0, 0, 0, gfxPrefs::SmoothScrollMSDPhysicsRegularSpringConstant(), 1)
, mModelY(0, 0, 0, gfxPrefs::SmoothScrollMSDPhysicsRegularSpringConstant(), 1)
, mIsFirstIteration(true)
{
}
void
ScrollAnimationMSDPhysics::Update(const TimeStamp& aTime,
const nsPoint& aDestination,
const nsSize& aCurrentVelocity)
{
double springConstant = ComputeSpringConstant(aTime);
// mLastSimulatedTime is the most recent time that this animation has been
// "observed" at. We don't want to update back to a state in the past, so we
// set mStartTime to the more recent of mLastSimulatedTime and aTime.
// aTime can be in the past if we're processing an input event whose internal
// timestamp is in the past.
if (mLastSimulatedTime && aTime < mLastSimulatedTime) {
mStartTime = mLastSimulatedTime;
} else {
mStartTime = aTime;
}
if (!mIsFirstIteration) {
mStartPos = PositionAt(mStartTime);
}
mLastSimulatedTime = mStartTime;
mDestination = aDestination;
mModelX = AxisPhysicsMSDModel(mStartPos.x, aDestination.x,
aCurrentVelocity.width, springConstant, 1);
mModelY = AxisPhysicsMSDModel(mStartPos.y, aDestination.y,
aCurrentVelocity.height, springConstant, 1);
mIsFirstIteration = false;
}
double
ScrollAnimationMSDPhysics::ComputeSpringConstant(const TimeStamp& aTime)
{
if (!mPreviousEventTime) {
mPreviousEventTime = aTime;
mPreviousDelta = TimeDuration();
return gfxPrefs::SmoothScrollMSDPhysicsMotionBeginSpringConstant();
}
TimeDuration delta = aTime - mPreviousEventTime;
TimeDuration previousDelta = mPreviousDelta;
mPreviousEventTime = aTime;
mPreviousDelta = delta;
double deltaMS = delta.ToMilliseconds();
if (deltaMS >= gfxPrefs::SmoothScrollMSDPhysicsContinuousMotionMaxDeltaMS()) {
return gfxPrefs::SmoothScrollMSDPhysicsMotionBeginSpringConstant();
}
if (previousDelta &&
deltaMS >= gfxPrefs::SmoothScrollMSDPhysicsSlowdownMinDeltaMS() &&
deltaMS >= previousDelta.ToMilliseconds() * gfxPrefs::SmoothScrollMSDPhysicsSlowdownMinDeltaRatio()) {
// The rate of events has slowed (the time delta between events has
// increased) enough that we think that the current scroll motion is coming
// to a stop. Use a stiffer spring in order to reach the destination more
// quickly.
return gfxPrefs::SmoothScrollMSDPhysicsSlowdownSpringConstant();
}
return gfxPrefs::SmoothScrollMSDPhysicsRegularSpringConstant();
}
void
ScrollAnimationMSDPhysics::SimulateUntil(const TimeStamp& aTime)
{
if (!mLastSimulatedTime || aTime < mLastSimulatedTime) {
return;
}
TimeDuration delta = aTime - mLastSimulatedTime;
mModelX.Simulate(delta);
mModelY.Simulate(delta);
mLastSimulatedTime = aTime;
}
nsPoint
ScrollAnimationMSDPhysics::PositionAt(const TimeStamp& aTime)
{
SimulateUntil(aTime);
return nsPoint(NSToCoordRound(mModelX.GetPosition()),
NSToCoordRound(mModelY.GetPosition()));
}
nsSize
ScrollAnimationMSDPhysics::VelocityAt(const TimeStamp& aTime)
{
SimulateUntil(aTime);
return nsSize(NSToCoordRound(mModelX.GetVelocity()),
NSToCoordRound(mModelY.GetVelocity()));
}

Просмотреть файл

@ -0,0 +1,58 @@
/* -*- 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_ScrollAnimationMSDPhysics_h_
#define mozilla_layout_ScrollAnimationMSDPhysics_h_
#include "ScrollAnimationPhysics.h"
#include "mozilla/layers/AxisPhysicsMSDModel.h"
namespace mozilla {
// This class implements a cubic MSD timing function and automatically
// adapts the animation duration based on the scrolling rate.
class ScrollAnimationMSDPhysics : public ScrollAnimationPhysics
{
public:
typedef mozilla::layers::AxisPhysicsMSDModel AxisPhysicsMSDModel;
explicit ScrollAnimationMSDPhysics(const nsPoint& aStartPos);
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 {
SimulateUntil(aTime);
return mModelX.IsFinished(1) && mModelY.IsFinished(1);
}
protected:
double ComputeSpringConstant(const TimeStamp& aTime);
void SimulateUntil(const TimeStamp& aTime);
TimeStamp mPreviousEventTime;
TimeDuration mPreviousDelta;
TimeStamp mStartTime;
nsPoint mStartPos;
nsPoint mDestination;
TimeStamp mLastSimulatedTime;
AxisPhysicsMSDModel mModelX;
AxisPhysicsMSDModel mModelY;
bool mIsFirstIteration;
};
} // namespace mozilla
#endif // mozilla_layout_ScrollAnimationMSDPhysics_h_

Просмотреть файл

@ -101,6 +101,7 @@ EXPORTS += [
'nsTextRunTransformations.h',
'RubyUtils.h',
'ScrollAnimationBezierPhysics.h',
'ScrollAnimationMSDPhysics.h',
'ScrollAnimationPhysics.h',
'ScrollbarActivity.h',
'ScrollSnap.h',
@ -178,6 +179,7 @@ UNIFIED_SOURCES += [
'ReflowOutput.cpp',
'RubyUtils.cpp',
'ScrollAnimationBezierPhysics.cpp',
'ScrollAnimationMSDPhysics.cpp',
'ScrollbarActivity.cpp',
'ScrollSnap.cpp',
'ScrollVelocityQueue.cpp',

Просмотреть файл

@ -59,6 +59,7 @@
#include "gfxPrefs.h"
#include "ScrollAnimationPhysics.h"
#include "ScrollAnimationBezierPhysics.h"
#include "ScrollAnimationMSDPhysics.h"
#include "ScrollSnap.h"
#include "UnitTransforms.h"
#include "nsPluginFrame.h"
@ -1912,7 +1913,7 @@ private:
* (also maintain previous timestamps - which are only used here).
*/
static ScrollAnimationBezierPhysicsSettings
ComputeAnimationSettingsForOrigin(nsIAtom *aOrigin)
ComputeBezierAnimationSettingsForOrigin(nsIAtom *aOrigin)
{
int32_t minMS = 0;
int32_t maxMS = 0;
@ -1972,9 +1973,14 @@ ScrollFrameHelper::AsyncScroll::InitSmoothScroll(TimeStamp aTime,
// Read preferences only on first iteration or for a different event origin.
if (!mAnimationPhysics || aOrigin != mOrigin) {
mOrigin = aOrigin;
ScrollAnimationBezierPhysicsSettings settings = ComputeAnimationSettingsForOrigin(mOrigin);
mAnimationPhysics =
MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, settings);
if (gfxPrefs::SmoothScrollMSDPhysicsEnabled()) {
mAnimationPhysics = MakeUnique<ScrollAnimationMSDPhysics>(aInitialPosition);
} else {
ScrollAnimationBezierPhysicsSettings settings =
ComputeBezierAnimationSettingsForOrigin(mOrigin);
mAnimationPhysics =
MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, settings);
}
}
mRange = aRange;

Просмотреть файл

@ -2806,6 +2806,14 @@ pref("general.smoothScroll.durationToIntervalRatio", 200);
// These two prefs determine the timing function.
pref("general.smoothScroll.currentVelocityWeighting", "0.25");
pref("general.smoothScroll.stopDecelerationWeighting", "0.4");
// Alternative smooth scroll physics ("MSD" = Mass-Spring-Damper)
pref("general.smoothScroll.msdPhysics.enabled", false);
pref("general.smoothScroll.msdPhysics.continuousMotionMaxDeltaMS", 120);
pref("general.smoothScroll.msdPhysics.motionBeginSpringConstant", 1250);
pref("general.smoothScroll.msdPhysics.slowdownMinDeltaMS", 12);
pref("general.smoothScroll.msdPhysics.slowdownMinDeltaRatio", "1.3");
pref("general.smoothScroll.msdPhysics.slowdownSpringConstant", 2000);
pref("general.smoothScroll.msdPhysics.regularSpringConstant", 1000);
pref("profile.confirm_automigration",true);
// profile.migration_behavior determines how the profiles root is set