Bug 1764201 Part 3: Remove screen info stuff from gfxPlatform. r=jgilbert,geckoview...
[gecko.git] / gfx / layers / apz / src / SimpleVelocityTracker.cpp
blob87cae10d51f9fb2e07f9346eeab030d7c596e2f1
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "SimpleVelocityTracker.h"
9 #include "mozilla/ServoStyleConsts.h" // for StyleComputedTimingFunction
10 #include "mozilla/StaticPrefs_apz.h"
11 #include "mozilla/StaticPtr.h" // for StaticAutoPtr
13 static mozilla::LazyLogModule sApzSvtLog("apz.simplevelocitytracker");
14 #define SVT_LOG(...) MOZ_LOG(sApzSvtLog, LogLevel::Debug, (__VA_ARGS__))
16 namespace mozilla {
17 namespace layers {
19 // When we compute the velocity we do so by taking two input events and
20 // dividing the distance delta over the time delta. In some cases the time
21 // delta can be really small, which can make the velocity computation very
22 // volatile. To avoid this we impose a minimum time delta below which we do
23 // not recompute the velocity.
24 const TimeDuration MIN_VELOCITY_SAMPLE_TIME = TimeDuration::FromMilliseconds(5);
26 extern StaticAutoPtr<StyleComputedTimingFunction> gVelocityCurveFunction;
28 SimpleVelocityTracker::SimpleVelocityTracker(Axis* aAxis)
29 : mAxis(aAxis), mVelocitySamplePos(0) {}
31 void SimpleVelocityTracker::StartTracking(ParentLayerCoord aPos,
32 TimeStamp aTimestamp) {
33 Clear();
34 mVelocitySampleTime = aTimestamp;
35 mVelocitySamplePos = aPos;
38 Maybe<float> SimpleVelocityTracker::AddPosition(ParentLayerCoord aPos,
39 TimeStamp aTimestamp) {
40 if (aTimestamp <= mVelocitySampleTime + MIN_VELOCITY_SAMPLE_TIME) {
41 // See also the comment on MIN_VELOCITY_SAMPLE_TIME.
42 // We don't update either mVelocitySampleTime or mVelocitySamplePos so that
43 // eventually when we do get an event with the required time delta we use
44 // the corresponding distance delta as well.
45 SVT_LOG("%p|%s skipping velocity computation for small time delta %f ms\n",
46 mAxis->OpaqueApzcPointer(), mAxis->Name(),
47 (aTimestamp - mVelocitySampleTime).ToMilliseconds());
48 return Nothing();
51 float newVelocity =
52 (float)(mVelocitySamplePos - aPos) /
53 (float)(aTimestamp - mVelocitySampleTime).ToMilliseconds();
55 newVelocity = ApplyFlingCurveToVelocity(newVelocity);
57 SVT_LOG("%p|%s updating velocity to %f with touch\n",
58 mAxis->OpaqueApzcPointer(), mAxis->Name(), newVelocity);
59 mVelocitySampleTime = aTimestamp;
60 mVelocitySamplePos = aPos;
62 AddVelocityToQueue(aTimestamp, newVelocity);
64 return Some(newVelocity);
67 Maybe<float> SimpleVelocityTracker::ComputeVelocity(TimeStamp aTimestamp) {
68 float velocity = 0;
69 int count = 0;
70 for (const auto& e : mVelocityQueue) {
71 TimeDuration timeDelta = (aTimestamp - e.first);
72 if (timeDelta < TimeDuration::FromMilliseconds(
73 StaticPrefs::apz_velocity_relevance_time_ms())) {
74 count++;
75 velocity += e.second;
78 mVelocityQueue.Clear();
79 if (count > 1) {
80 velocity /= count;
82 return Some(velocity);
85 void SimpleVelocityTracker::Clear() { mVelocityQueue.Clear(); }
87 void SimpleVelocityTracker::AddVelocityToQueue(TimeStamp aTimestamp,
88 float aVelocity) {
89 mVelocityQueue.AppendElement(std::make_pair(aTimestamp, aVelocity));
90 if (mVelocityQueue.Length() >
91 StaticPrefs::apz_max_velocity_queue_size_AtStartup()) {
92 mVelocityQueue.RemoveElementAt(0);
96 float SimpleVelocityTracker::ApplyFlingCurveToVelocity(float aVelocity) const {
97 float newVelocity = aVelocity;
98 if (StaticPrefs::apz_max_velocity_inches_per_ms() > 0.0f) {
99 bool velocityIsNegative = (newVelocity < 0);
100 newVelocity = fabs(newVelocity);
102 float maxVelocity =
103 mAxis->ToLocalVelocity(StaticPrefs::apz_max_velocity_inches_per_ms());
104 newVelocity = std::min(newVelocity, maxVelocity);
106 if (StaticPrefs::apz_fling_curve_threshold_inches_per_ms() > 0.0f &&
107 StaticPrefs::apz_fling_curve_threshold_inches_per_ms() <
108 StaticPrefs::apz_max_velocity_inches_per_ms()) {
109 float curveThreshold = mAxis->ToLocalVelocity(
110 StaticPrefs::apz_fling_curve_threshold_inches_per_ms());
111 if (newVelocity > curveThreshold) {
112 // here, 0 < curveThreshold < newVelocity <= maxVelocity, so we apply
113 // the curve
114 float scale = maxVelocity - curveThreshold;
115 float funcInput = (newVelocity - curveThreshold) / scale;
116 float funcOutput =
117 gVelocityCurveFunction->At(funcInput, /* aBeforeFlag = */ false);
118 float curvedVelocity = (funcOutput * scale) + curveThreshold;
119 SVT_LOG("%p|%s curving up velocity from %f to %f\n",
120 mAxis->OpaqueApzcPointer(), mAxis->Name(), newVelocity,
121 curvedVelocity);
122 newVelocity = curvedVelocity;
126 if (velocityIsNegative) {
127 newVelocity = -newVelocity;
131 return newVelocity;
134 } // namespace layers
135 } // namespace mozilla