forked from mirrors/gecko-dev
Bug 1642788 - Use mTimeStamp rather than mTime for APZ velocity computations. r=kats
Differential Revision: https://phabricator.services.mozilla.com/D77979
This commit is contained in:
parent
47b44d078e
commit
a864440a96
8 changed files with 96 additions and 92 deletions
|
|
@ -19,7 +19,8 @@ namespace layers {
|
|||
// stopped moving. Some input devices do not send move events in the
|
||||
// case where a pointer has stopped. We need to detect this case so that we can
|
||||
// accurately predict the velocity after the pointer starts moving again.
|
||||
static const int kAssumePointerMoveStoppedTimeMs = 40;
|
||||
static const TimeDuration kAssumePointerMoveStoppedTime =
|
||||
TimeDuration::FromMilliseconds(40);
|
||||
|
||||
// The degree of the approximation.
|
||||
static const uint8_t kDegree = 2;
|
||||
|
|
@ -31,36 +32,36 @@ static const uint8_t kPolyDegree = kDegree + 1;
|
|||
// Maximum size of position history.
|
||||
static const uint8_t kHistorySize = 20;
|
||||
|
||||
AndroidVelocityTracker::AndroidVelocityTracker() : mLastEventTime(0) {}
|
||||
AndroidVelocityTracker::AndroidVelocityTracker() {}
|
||||
|
||||
void AndroidVelocityTracker::StartTracking(ParentLayerCoord aPos,
|
||||
uint32_t aTimestampMs) {
|
||||
TimeStamp aTimestamp) {
|
||||
Clear();
|
||||
mHistory.AppendElement(std::make_pair(aTimestampMs, aPos));
|
||||
mLastEventTime = aTimestampMs;
|
||||
mHistory.AppendElement(std::make_pair(aTimestamp, aPos));
|
||||
mLastEventTime = aTimestamp;
|
||||
}
|
||||
|
||||
Maybe<float> AndroidVelocityTracker::AddPosition(ParentLayerCoord aPos,
|
||||
uint32_t aTimestampMs) {
|
||||
if ((aTimestampMs - mLastEventTime) >= kAssumePointerMoveStoppedTimeMs) {
|
||||
TimeStamp aTimestamp) {
|
||||
if ((aTimestamp - mLastEventTime) >= kAssumePointerMoveStoppedTime) {
|
||||
Clear();
|
||||
}
|
||||
|
||||
if (aTimestampMs == mLastEventTime) {
|
||||
// If we get a sample with the same timestamp as the previous one,
|
||||
if ((aTimestamp - mLastEventTime).ToMilliseconds() < 1.0) {
|
||||
// If we get a sample within a millisecond of the previous one,
|
||||
// just update its position. Two samples in the history with the
|
||||
// same timestamp can lead to things like infinite velocities.
|
||||
if (mHistory.Length() > 0) {
|
||||
mHistory[mHistory.Length() - 1].second = aPos;
|
||||
}
|
||||
} else {
|
||||
mHistory.AppendElement(std::make_pair(aTimestampMs, aPos));
|
||||
mHistory.AppendElement(std::make_pair(aTimestamp, aPos));
|
||||
if (mHistory.Length() > kHistorySize) {
|
||||
mHistory.RemoveElementAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
mLastEventTime = aTimestampMs;
|
||||
mLastEventTime = aTimestamp;
|
||||
|
||||
if (mHistory.Length() < 2) {
|
||||
return Nothing();
|
||||
|
|
@ -68,7 +69,8 @@ Maybe<float> AndroidVelocityTracker::AddPosition(ParentLayerCoord aPos,
|
|||
|
||||
auto start = mHistory[mHistory.Length() - 2];
|
||||
auto end = mHistory[mHistory.Length() - 1];
|
||||
return Some((end.second - start.second) / (end.first - start.first));
|
||||
return Some((end.second - start.second) /
|
||||
(end.first - start.first).ToMilliseconds());
|
||||
}
|
||||
|
||||
static float VectorDot(const float* a, const float* b, uint32_t m) {
|
||||
|
|
@ -213,7 +215,7 @@ static bool SolveLeastSquares(const float* x, const float* y, const float* w,
|
|||
return true;
|
||||
}
|
||||
|
||||
Maybe<float> AndroidVelocityTracker::ComputeVelocity(uint32_t aTimestampMs) {
|
||||
Maybe<float> AndroidVelocityTracker::ComputeVelocity(TimeStamp aTimestamp) {
|
||||
if (mHistory.IsEmpty()) {
|
||||
return Nothing{};
|
||||
}
|
||||
|
|
@ -230,18 +232,20 @@ Maybe<float> AndroidVelocityTracker::ComputeVelocity(uint32_t aTimestampMs) {
|
|||
float time[kHistorySize];
|
||||
uint32_t m = 0;
|
||||
int index = mHistory.Length() - 1;
|
||||
const uint32_t horizon = StaticPrefs::apz_velocity_relevance_time_ms();
|
||||
const TimeDuration horizon = TimeDuration::FromMilliseconds(
|
||||
StaticPrefs::apz_velocity_relevance_time_ms());
|
||||
const auto& newest_movement = mHistory[index];
|
||||
|
||||
do {
|
||||
const auto& movement = mHistory[index];
|
||||
uint32_t age = newest_movement.first - movement.first;
|
||||
TimeDuration age = newest_movement.first - movement.first;
|
||||
if (age > horizon) break;
|
||||
|
||||
ParentLayerCoord position = movement.second;
|
||||
pos[m] = position;
|
||||
w[m] = 1.0f;
|
||||
time[m] = -static_cast<float>(age) / 1000.0f; // in seconds
|
||||
time[m] =
|
||||
-static_cast<float>(age.ToMilliseconds()) / 1000.0f; // in seconds
|
||||
index--;
|
||||
m++;
|
||||
} while (index >= 0);
|
||||
|
|
|
|||
|
|
@ -21,19 +21,19 @@ namespace layers {
|
|||
class AndroidVelocityTracker : public VelocityTracker {
|
||||
public:
|
||||
explicit AndroidVelocityTracker();
|
||||
void StartTracking(ParentLayerCoord aPos, uint32_t aTimestamp) override;
|
||||
void StartTracking(ParentLayerCoord aPos, TimeStamp aTimestamp) override;
|
||||
Maybe<float> AddPosition(ParentLayerCoord aPos,
|
||||
uint32_t aTimestampMs) override;
|
||||
Maybe<float> ComputeVelocity(uint32_t aTimestampMs) override;
|
||||
TimeStamp aTimestamp) override;
|
||||
Maybe<float> ComputeVelocity(TimeStamp aTimestamp) override;
|
||||
void Clear() override;
|
||||
|
||||
private:
|
||||
// A queue of (timestamp, position) pairs; these are the historical
|
||||
// positions at the given timestamps. Timestamps are in milliseconds.
|
||||
nsTArray<std::pair<uint32_t, ParentLayerCoord>> mHistory;
|
||||
// The last time an event was added to the tracker (in milliseconds),
|
||||
// or zero if no events have been added.
|
||||
uint32_t mLastEventTime;
|
||||
// positions at the given timestamps.
|
||||
nsTArray<std::pair<TimeStamp, ParentLayerCoord>> mHistory;
|
||||
// The last time an event was added to the tracker, or the null moment if no
|
||||
// events have been added.
|
||||
TimeStamp mLastEventTime;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
|||
|
|
@ -120,7 +120,6 @@ typedef GeckoContentController::APZStateChange APZStateChange;
|
|||
typedef GeckoContentController::TapType TapType;
|
||||
typedef mozilla::gfx::Point Point;
|
||||
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
|
||||
using mozilla::gfx::PointTyped;
|
||||
|
||||
// Choose between platform-specific implementations.
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
|
@ -1353,7 +1352,7 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(
|
|||
case NOTHING: {
|
||||
ParentLayerPoint point = GetFirstTouchPoint(aEvent);
|
||||
mStartTouch = GetFirstExternalTouchPoint(aEvent);
|
||||
StartTouch(point, aEvent.mTime);
|
||||
StartTouch(point, aEvent.mTimeStamp);
|
||||
if (RefPtr<GeckoContentController> controller =
|
||||
GetGeckoContentController()) {
|
||||
MOZ_ASSERT(GetCurrentTouchBlock());
|
||||
|
|
@ -1508,7 +1507,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(
|
|||
case PANNING_LOCKED_Y:
|
||||
case PAN_MOMENTUM: {
|
||||
MOZ_ASSERT(GetCurrentTouchBlock());
|
||||
EndTouch(aEvent.mTime);
|
||||
EndTouch(aEvent.mTimeStamp);
|
||||
return HandleEndOfPan();
|
||||
}
|
||||
case PINCHING:
|
||||
|
|
@ -1557,7 +1556,7 @@ nsEventStatus AsyncPanZoomController::OnScaleBegin(
|
|||
// If zooming is not allowed, this is a two-finger pan.
|
||||
// Start tracking panning distance and velocity.
|
||||
if (!mZoomConstraints.mAllowZoom) {
|
||||
StartTouch(aEvent.mLocalFocusPoint, aEvent.mTime);
|
||||
StartTouch(aEvent.mLocalFocusPoint, aEvent.mTimeStamp);
|
||||
}
|
||||
|
||||
// For platforms that don't support APZ zooming, dispatch a message to the
|
||||
|
|
@ -1604,8 +1603,10 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
|
|||
// UpdateWithTouchAtDevicePoint() acquires the tree lock, so
|
||||
// it cannot be called while the mRecursiveMutex lock is held.
|
||||
if (!allowZoom) {
|
||||
mX.UpdateWithTouchAtDevicePoint(aEvent.mLocalFocusPoint.x, aEvent.mTime);
|
||||
mY.UpdateWithTouchAtDevicePoint(aEvent.mLocalFocusPoint.y, aEvent.mTime);
|
||||
mX.UpdateWithTouchAtDevicePoint(aEvent.mLocalFocusPoint.x,
|
||||
aEvent.mTimeStamp);
|
||||
mY.UpdateWithTouchAtDevicePoint(aEvent.mLocalFocusPoint.y,
|
||||
aEvent.mTimeStamp);
|
||||
}
|
||||
|
||||
// FIXME: bug 1525793 -- this may need to handle zooming or not on a
|
||||
|
|
@ -1765,7 +1766,7 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(
|
|||
// One finger is still down, so transition to a TOUCHING state
|
||||
if (mZoomConstraints.mAllowZoom) {
|
||||
mPanDirRestricted = false;
|
||||
StartTouch(aEvent.mLocalFocusPoint, aEvent.mTime);
|
||||
StartTouch(aEvent.mLocalFocusPoint, aEvent.mTimeStamp);
|
||||
SetState(TOUCHING);
|
||||
} else {
|
||||
// If zooming isn't allowed, StartTouch() was already called
|
||||
|
|
@ -1804,7 +1805,7 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(
|
|||
ScrollSnap();
|
||||
} else {
|
||||
// when zoom is not allowed
|
||||
EndTouch(aEvent.mTime);
|
||||
EndTouch(aEvent.mTimeStamp);
|
||||
if (stateWasPinching) {
|
||||
// still pinching
|
||||
if (HasReadyTouchBlock()) {
|
||||
|
|
@ -2466,7 +2467,7 @@ nsEventStatus AsyncPanZoomController::OnPanMayBegin(
|
|||
const PanGestureInput& aEvent) {
|
||||
APZC_LOG("%p got a pan-maybegin in state %d\n", this, mState);
|
||||
|
||||
StartTouch(aEvent.mLocalPanStartPoint, aEvent.mTime);
|
||||
StartTouch(aEvent.mLocalPanStartPoint, aEvent.mTimeStamp);
|
||||
MOZ_ASSERT(GetCurrentPanGestureBlock());
|
||||
GetCurrentPanGestureBlock()->GetOverscrollHandoffChain()->CancelAnimations();
|
||||
|
||||
|
|
@ -2492,7 +2493,7 @@ nsEventStatus AsyncPanZoomController::OnPanBegin(
|
|||
CancelAnimation();
|
||||
}
|
||||
|
||||
StartTouch(aEvent.mLocalPanStartPoint, aEvent.mTime);
|
||||
StartTouch(aEvent.mLocalPanStartPoint, aEvent.mTimeStamp);
|
||||
|
||||
if (GetAxisLockMode() == FREE) {
|
||||
SetState(PANNING);
|
||||
|
|
@ -2620,9 +2621,9 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent,
|
|||
// the only caller of UpdateWithTouchAtDevicePoint() for pan events, so
|
||||
// there is no risk of other calls resetting the position.)
|
||||
mX.UpdateWithTouchAtDevicePoint(mX.GetPos() - logicalPanDisplacement.x,
|
||||
aEvent.mTime);
|
||||
aEvent.mTimeStamp);
|
||||
mY.UpdateWithTouchAtDevicePoint(mY.GetPos() - logicalPanDisplacement.y,
|
||||
aEvent.mTime);
|
||||
aEvent.mTimeStamp);
|
||||
|
||||
HandlePanningUpdate(physicalPanDisplacement);
|
||||
|
||||
|
|
@ -2663,7 +2664,7 @@ nsEventStatus AsyncPanZoomController::OnPanEnd(const PanGestureInput& aEvent) {
|
|||
// Call into OnPan in order to process any delta included in this event.
|
||||
OnPan(aEvent, true);
|
||||
|
||||
EndTouch(aEvent.mTime);
|
||||
EndTouch(aEvent.mTimeStamp);
|
||||
|
||||
// Use HandleEndOfPan for fling on platforms that don't
|
||||
// emit momentum events (Gtk).
|
||||
|
|
@ -3161,8 +3162,8 @@ nsEventStatus AsyncPanZoomController::StartPanning(
|
|||
void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(
|
||||
const MultiTouchInput& aEvent) {
|
||||
ParentLayerPoint point = GetFirstTouchPoint(aEvent);
|
||||
mX.UpdateWithTouchAtDevicePoint(point.x, aEvent.mTime);
|
||||
mY.UpdateWithTouchAtDevicePoint(point.y, aEvent.mTime);
|
||||
mX.UpdateWithTouchAtDevicePoint(point.x, aEvent.mTimeStamp);
|
||||
mY.UpdateWithTouchAtDevicePoint(point.y, aEvent.mTimeStamp);
|
||||
}
|
||||
|
||||
Maybe<CompositionPayload> AsyncPanZoomController::NotifyScrollSampling() {
|
||||
|
|
@ -3540,16 +3541,16 @@ void AsyncPanZoomController::RecordScrollPayload(const TimeStamp& aTimeStamp) {
|
|||
}
|
||||
|
||||
void AsyncPanZoomController::StartTouch(const ParentLayerPoint& aPoint,
|
||||
uint32_t aTimestampMs) {
|
||||
TimeStamp aTimestamp) {
|
||||
RecursiveMutexAutoLock lock(mRecursiveMutex);
|
||||
mX.StartTouch(aPoint.x, aTimestampMs);
|
||||
mY.StartTouch(aPoint.y, aTimestampMs);
|
||||
mX.StartTouch(aPoint.x, aTimestamp);
|
||||
mY.StartTouch(aPoint.y, aTimestamp);
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::EndTouch(uint32_t aTimestampMs) {
|
||||
void AsyncPanZoomController::EndTouch(TimeStamp aTimestamp) {
|
||||
RecursiveMutexAutoLock lock(mRecursiveMutex);
|
||||
mX.EndTouch(aTimestampMs);
|
||||
mY.EndTouch(aTimestampMs);
|
||||
mX.EndTouch(aTimestamp);
|
||||
mY.EndTouch(aTimestamp);
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
|
||||
|
|
|
|||
|
|
@ -805,12 +805,12 @@ class AsyncPanZoomController {
|
|||
* Register the start of a touch or pan gesture at the given position and
|
||||
* time.
|
||||
*/
|
||||
void StartTouch(const ParentLayerPoint& aPoint, uint32_t aTimestampMs);
|
||||
void StartTouch(const ParentLayerPoint& aPoint, TimeStamp aTimestamp);
|
||||
|
||||
/**
|
||||
* Register the end of a touch or pan gesture at the given time.
|
||||
*/
|
||||
void EndTouch(uint32_t aTimestampMs);
|
||||
void EndTouch(TimeStamp aTimestamp);
|
||||
|
||||
/**
|
||||
* Utility function to send updated FrameMetrics to Gecko so that it can paint
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ float Axis::ToLocalVelocity(float aVelocityInchesPerMs) const {
|
|||
}
|
||||
|
||||
void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos,
|
||||
uint32_t aTimestampMs) {
|
||||
TimeStamp aTimestamp) {
|
||||
// mVelocityTracker is controller-thread only
|
||||
APZThreadUtils::AssertOnControllerThread();
|
||||
|
||||
|
|
@ -67,17 +67,17 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos,
|
|||
AXIS_LOG("%p|%s got position %f\n", mAsyncPanZoomController, Name(),
|
||||
mPos.value);
|
||||
if (Maybe<float> newVelocity =
|
||||
mVelocityTracker->AddPosition(aPos, aTimestampMs)) {
|
||||
mVelocityTracker->AddPosition(aPos, aTimestamp)) {
|
||||
mVelocity = mAxisLocked ? 0 : *newVelocity;
|
||||
AXIS_LOG("%p|%s velocity from tracker is %f\n", mAsyncPanZoomController,
|
||||
Name(), mVelocity);
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs) {
|
||||
void Axis::StartTouch(ParentLayerCoord aPos, TimeStamp aTimestamp) {
|
||||
mStartPos = aPos;
|
||||
mPos = aPos;
|
||||
mVelocityTracker->StartTracking(aPos, aTimestampMs);
|
||||
mVelocityTracker->StartTracking(aPos, aTimestamp);
|
||||
mAxisLocked = false;
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +226,7 @@ ParentLayerCoord Axis::PanDistance(ParentLayerCoord aPos) const {
|
|||
return fabs(aPos - mStartPos);
|
||||
}
|
||||
|
||||
void Axis::EndTouch(uint32_t aTimestampMs) {
|
||||
void Axis::EndTouch(TimeStamp aTimestamp) {
|
||||
// mVelocityQueue is controller-thread only
|
||||
APZThreadUtils::AssertOnControllerThread();
|
||||
|
||||
|
|
@ -238,7 +238,7 @@ void Axis::EndTouch(uint32_t aTimestampMs) {
|
|||
if (mAxisLocked) {
|
||||
mVelocity = 0;
|
||||
} else if (Maybe<float> velocity =
|
||||
mVelocityTracker->ComputeVelocity(aTimestampMs)) {
|
||||
mVelocityTracker->ComputeVelocity(aTimestamp)) {
|
||||
mVelocity = *velocity;
|
||||
} else {
|
||||
mVelocity = 0;
|
||||
|
|
|
|||
|
|
@ -46,14 +46,14 @@ class VelocityTracker {
|
|||
* Start tracking velocity along this axis, starting with the given
|
||||
* initial position and corresponding timestamp.
|
||||
*/
|
||||
virtual void StartTracking(ParentLayerCoord aPos, uint32_t aTimestamp) = 0;
|
||||
virtual void StartTracking(ParentLayerCoord aPos, TimeStamp aTimestamp) = 0;
|
||||
/**
|
||||
* Record a new position along this axis, at the given timestamp.
|
||||
* Returns the average velocity between the last sample and this one, or
|
||||
* or Nothing() if a reasonable average cannot be computed.
|
||||
*/
|
||||
virtual Maybe<float> AddPosition(ParentLayerCoord aPos,
|
||||
uint32_t aTimestampMs) = 0;
|
||||
TimeStamp aTimestamp) = 0;
|
||||
/**
|
||||
* Compute an estimate of the axis's current velocity, based on recent
|
||||
* position samples. It's up to implementation how many samples to consider
|
||||
|
|
@ -61,7 +61,7 @@ class VelocityTracker {
|
|||
* If the tracker doesn't have enough samples to compute a result, it
|
||||
* may return Nothing{}.
|
||||
*/
|
||||
virtual Maybe<float> ComputeVelocity(uint32_t aTimestampMs) = 0;
|
||||
virtual Maybe<float> ComputeVelocity(TimeStamp aTimestamp) = 0;
|
||||
/**
|
||||
* Clear all state in the velocity tracker.
|
||||
*/
|
||||
|
|
@ -85,20 +85,20 @@ class Axis {
|
|||
* accumulated displacements over the course of the pan gesture.
|
||||
*/
|
||||
void UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos,
|
||||
uint32_t aTimestampMs);
|
||||
TimeStamp aTimestamp);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Notify this Axis that a touch has begun, i.e. the user has put their finger
|
||||
* on the screen but has not yet tried to pan.
|
||||
*/
|
||||
void StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs);
|
||||
void StartTouch(ParentLayerCoord aPos, TimeStamp aTimestamp);
|
||||
|
||||
/**
|
||||
* Notify this Axis that a touch has ended gracefully. This may perform
|
||||
* recalculations of the axis velocity.
|
||||
*/
|
||||
void EndTouch(uint32_t aTimestampMs);
|
||||
void EndTouch(TimeStamp aTimestamp);
|
||||
|
||||
/**
|
||||
* Notify this Axis that the gesture has ended forcefully. Useful for stopping
|
||||
|
|
|
|||
|
|
@ -21,56 +21,56 @@ namespace layers {
|
|||
// delta can be really small, which can make the velocity computation very
|
||||
// volatile. To avoid this we impose a minimum time delta below which we do
|
||||
// not recompute the velocity.
|
||||
const uint32_t MIN_VELOCITY_SAMPLE_TIME_MS = 5;
|
||||
const TimeDuration MIN_VELOCITY_SAMPLE_TIME = TimeDuration::FromMilliseconds(5);
|
||||
|
||||
extern StaticAutoPtr<ComputedTimingFunction> gVelocityCurveFunction;
|
||||
|
||||
SimpleVelocityTracker::SimpleVelocityTracker(Axis* aAxis)
|
||||
: mAxis(aAxis), mVelocitySampleTimeMs(0), mVelocitySamplePos(0) {}
|
||||
: mAxis(aAxis), mVelocitySamplePos(0) {}
|
||||
|
||||
void SimpleVelocityTracker::StartTracking(ParentLayerCoord aPos,
|
||||
uint32_t aTimestampMs) {
|
||||
TimeStamp aTimestamp) {
|
||||
Clear();
|
||||
mVelocitySampleTimeMs = aTimestampMs;
|
||||
mVelocitySampleTime = aTimestamp;
|
||||
mVelocitySamplePos = aPos;
|
||||
}
|
||||
|
||||
Maybe<float> SimpleVelocityTracker::AddPosition(ParentLayerCoord aPos,
|
||||
uint32_t aTimestampMs) {
|
||||
if (aTimestampMs <= mVelocitySampleTimeMs + MIN_VELOCITY_SAMPLE_TIME_MS) {
|
||||
// See also the comment on MIN_VELOCITY_SAMPLE_TIME_MS.
|
||||
// We still update mPos so that the positioning is correct (and we don't run
|
||||
// into problems like bug 1042734) but the velocity will remain where it
|
||||
// was. In particular we don't update either mVelocitySampleTimeMs or
|
||||
// mVelocitySamplePos so that eventually when we do get an event with the
|
||||
// required time delta we use the corresponding distance delta as well.
|
||||
SVT_LOG("%p|%s skipping velocity computation for small time delta %dms\n",
|
||||
TimeStamp aTimestamp) {
|
||||
if (aTimestamp <= mVelocitySampleTime + MIN_VELOCITY_SAMPLE_TIME) {
|
||||
// See also the comment on MIN_VELOCITY_SAMPLE_TIME.
|
||||
// We don't update either mVelocitySampleTime or mVelocitySamplePos so that
|
||||
// eventually when we do get an event with the required time delta we use
|
||||
// the corresponding distance delta as well.
|
||||
SVT_LOG("%p|%s skipping velocity computation for small time delta %f ms\n",
|
||||
mAxis->OpaqueApzcPointer(), mAxis->Name(),
|
||||
(aTimestampMs - mVelocitySampleTimeMs));
|
||||
(aTimestamp - mVelocitySampleTime).ToMilliseconds());
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
float newVelocity = (float)(mVelocitySamplePos - aPos) /
|
||||
(float)(aTimestampMs - mVelocitySampleTimeMs);
|
||||
float newVelocity =
|
||||
(float)(mVelocitySamplePos - aPos) /
|
||||
(float)(aTimestamp - mVelocitySampleTime).ToMilliseconds();
|
||||
|
||||
newVelocity = ApplyFlingCurveToVelocity(newVelocity);
|
||||
|
||||
SVT_LOG("%p|%s updating velocity to %f with touch\n",
|
||||
mAxis->OpaqueApzcPointer(), mAxis->Name(), newVelocity);
|
||||
mVelocitySampleTimeMs = aTimestampMs;
|
||||
mVelocitySampleTime = aTimestamp;
|
||||
mVelocitySamplePos = aPos;
|
||||
|
||||
AddVelocityToQueue(aTimestampMs, newVelocity);
|
||||
AddVelocityToQueue(aTimestamp, newVelocity);
|
||||
|
||||
return Some(newVelocity);
|
||||
}
|
||||
|
||||
Maybe<float> SimpleVelocityTracker::ComputeVelocity(uint32_t aTimestampMs) {
|
||||
Maybe<float> SimpleVelocityTracker::ComputeVelocity(TimeStamp aTimestamp) {
|
||||
float velocity = 0;
|
||||
int count = 0;
|
||||
for (const auto& e : mVelocityQueue) {
|
||||
uint32_t timeDelta = (aTimestampMs - e.first);
|
||||
if (timeDelta < StaticPrefs::apz_velocity_relevance_time_ms()) {
|
||||
TimeDuration timeDelta = (aTimestamp - e.first);
|
||||
if (timeDelta < TimeDuration::FromMilliseconds(
|
||||
StaticPrefs::apz_velocity_relevance_time_ms())) {
|
||||
count++;
|
||||
velocity += e.second;
|
||||
}
|
||||
|
|
@ -84,9 +84,9 @@ Maybe<float> SimpleVelocityTracker::ComputeVelocity(uint32_t aTimestampMs) {
|
|||
|
||||
void SimpleVelocityTracker::Clear() { mVelocityQueue.Clear(); }
|
||||
|
||||
void SimpleVelocityTracker::AddVelocityToQueue(uint32_t aTimestampMs,
|
||||
void SimpleVelocityTracker::AddVelocityToQueue(TimeStamp aTimestamp,
|
||||
float aVelocity) {
|
||||
mVelocityQueue.AppendElement(std::make_pair(aTimestampMs, aVelocity));
|
||||
mVelocityQueue.AppendElement(std::make_pair(aTimestamp, aVelocity));
|
||||
if (mVelocityQueue.Length() >
|
||||
StaticPrefs::apz_max_velocity_queue_size_AtStartup()) {
|
||||
mVelocityQueue.RemoveElementAt(0);
|
||||
|
|
|
|||
|
|
@ -20,14 +20,14 @@ namespace layers {
|
|||
class SimpleVelocityTracker : public VelocityTracker {
|
||||
public:
|
||||
explicit SimpleVelocityTracker(Axis* aAxis);
|
||||
void StartTracking(ParentLayerCoord aPos, uint32_t aTimestamp) override;
|
||||
void StartTracking(ParentLayerCoord aPos, TimeStamp aTimestamp) override;
|
||||
Maybe<float> AddPosition(ParentLayerCoord aPos,
|
||||
uint32_t aTimestampMs) override;
|
||||
Maybe<float> ComputeVelocity(uint32_t aTimestampMs) override;
|
||||
TimeStamp aTimestamp) override;
|
||||
Maybe<float> ComputeVelocity(TimeStamp aTimestamp) override;
|
||||
void Clear() override;
|
||||
|
||||
private:
|
||||
void AddVelocityToQueue(uint32_t aTimestampMs, float aVelocity);
|
||||
void AddVelocityToQueue(TimeStamp aTimestamp, float aVelocity);
|
||||
float ApplyFlingCurveToVelocity(float aVelocity) const;
|
||||
|
||||
// The Axis that uses this velocity tracker.
|
||||
|
|
@ -36,16 +36,15 @@ class SimpleVelocityTracker : public VelocityTracker {
|
|||
Axis* MOZ_NON_OWNING_REF mAxis;
|
||||
|
||||
// A queue of (timestamp, velocity) pairs; these are the historical
|
||||
// velocities at the given timestamps. Timestamps are in milliseconds,
|
||||
// velocities are in screen pixels per ms. This member can only be
|
||||
// accessed on the controller/UI thread.
|
||||
nsTArray<std::pair<uint32_t, float>> mVelocityQueue;
|
||||
// velocities at the given timestamps. Velocities are in screen pixels per ms.
|
||||
// This member can only be accessed on the controller/UI thread.
|
||||
nsTArray<std::pair<TimeStamp, float>> mVelocityQueue;
|
||||
|
||||
// mVelocitySampleTimeMs and mVelocitySamplePos are the time and position
|
||||
// mVelocitySampleTime and mVelocitySamplePos are the time and position
|
||||
// used in the last velocity sampling. They get updated when a new sample is
|
||||
// taken (which may not happen on every input event, if the time delta is too
|
||||
// small).
|
||||
uint32_t mVelocitySampleTimeMs;
|
||||
TimeStamp mVelocitySampleTime;
|
||||
ParentLayerCoord mVelocitySamplePos;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue