Commit 08e1cc53 authored by Adithya Srinivasan's avatar Adithya Srinivasan Committed by Commit Bot

Make ScrollOffsetAnimationCurve::UpdateTarget use TimeDelta

Makes the method use TimeDelta instead of double to represent
duration.

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: Id95aface04fa2b72bc919fd4ab52af062908f8df
Bug: 763980
Reviewed-on: https://chromium-review.googlesource.com/1140355Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarStephen McGruer <smcgruer@chromium.org>
Commit-Queue: Adithya Srinivasan <adithyas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577928}
parent bffc6249
...@@ -171,35 +171,37 @@ ScrollOffsetAnimationCurve::CloneToScrollOffsetAnimationCurve() const { ...@@ -171,35 +171,37 @@ ScrollOffsetAnimationCurve::CloneToScrollOffsetAnimationCurve() const {
return curve_clone; return curve_clone;
} }
static double VelocityBasedDurationBound(gfx::Vector2dF old_delta, static base::TimeDelta VelocityBasedDurationBound(
double old_normalized_velocity, gfx::Vector2dF old_delta,
double old_duration, double old_normalized_velocity,
gfx::Vector2dF new_delta) { base::TimeDelta old_duration,
gfx::Vector2dF new_delta) {
double old_delta_max_dimension = MaximumDimension(old_delta); double old_delta_max_dimension = MaximumDimension(old_delta);
double new_delta_max_dimension = MaximumDimension(new_delta); double new_delta_max_dimension = MaximumDimension(new_delta);
// If we are already at the target, stop animating. // If we are already at the target, stop animating.
if (std::abs(new_delta_max_dimension) < kEpsilon) if (std::abs(new_delta_max_dimension) < kEpsilon)
return 0; return base::TimeDelta();
// Guard against division by zero. // Guard against division by zero.
if (std::abs(old_delta_max_dimension) < kEpsilon || if (std::abs(old_delta_max_dimension) < kEpsilon ||
std::abs(old_normalized_velocity) < kEpsilon) { std::abs(old_normalized_velocity) < kEpsilon) {
return std::numeric_limits<double>::infinity(); return base::TimeDelta::Max();
} }
// Estimate how long it will take to reach the new target at our present // Estimate how long it will take to reach the new target at our present
// velocity, with some fudge factor to account for the "ease out". // velocity, with some fudge factor to account for the "ease out".
double old_true_velocity = double old_true_velocity = old_normalized_velocity * old_delta_max_dimension /
old_normalized_velocity * old_delta_max_dimension / old_duration; old_duration.InSecondsF();
double bound = (new_delta_max_dimension / old_true_velocity) * 2.5f; double bound = (new_delta_max_dimension / old_true_velocity) * 2.5f;
// If bound < 0 we are moving in the opposite direction. // If bound < 0 we are moving in the opposite direction.
return bound < 0 ? std::numeric_limits<double>::infinity() : bound; return bound < 0 ? base::TimeDelta::Max()
: base::TimeDelta::FromSecondsD(bound);
} }
void ScrollOffsetAnimationCurve::UpdateTarget( void ScrollOffsetAnimationCurve::UpdateTarget(
double t, base::TimeDelta t,
const gfx::ScrollOffset& new_target) { const gfx::ScrollOffset& new_target) {
if (std::abs(MaximumDimension(target_value_.DeltaFrom(new_target))) < if (std::abs(MaximumDimension(target_value_.DeltaFrom(new_target))) <
kEpsilon) { kEpsilon) {
...@@ -207,41 +209,38 @@ void ScrollOffsetAnimationCurve::UpdateTarget( ...@@ -207,41 +209,38 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
return; return;
} }
base::TimeDelta delayed_by = base::TimeDelta::FromSecondsD( base::TimeDelta delayed_by = std::max(base::TimeDelta(), last_retarget_ - t);
std::max(0.0, last_retarget_.InSecondsF() - t)); t = std::max(t, last_retarget_);
t = std::max(t, last_retarget_.InSecondsF());
gfx::ScrollOffset current_position = gfx::ScrollOffset current_position = GetValue(t);
GetValue(base::TimeDelta::FromSecondsD(t));
gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_); gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_);
gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position); gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position);
// The last segement was of zero duration. // The last segement was of zero duration.
if ((total_animation_duration_ - last_retarget_).is_zero()) { if ((total_animation_duration_ - last_retarget_).is_zero()) {
DCHECK_EQ(t, last_retarget_.InSecondsF()); DCHECK_EQ(t, last_retarget_);
total_animation_duration_ = total_animation_duration_ =
SegmentDuration(new_delta, duration_behavior_, delayed_by); SegmentDuration(new_delta, duration_behavior_, delayed_by);
target_value_ = new_target; target_value_ = new_target;
return; return;
} }
double old_duration = base::TimeDelta old_duration = total_animation_duration_ - last_retarget_;
(total_animation_duration_ - last_retarget_).InSecondsF();
double old_normalized_velocity = timing_function_->Velocity( double old_normalized_velocity = timing_function_->Velocity(
(t - last_retarget_.InSecondsF()) / old_duration); ((t - last_retarget_).InSecondsF()) / old_duration.InSecondsF());
// Use the velocity-based duration bound when it is less than the constant // Use the velocity-based duration bound when it is less than the constant
// segment duration. This minimizes the "rubber-band" bouncing effect when // segment duration. This minimizes the "rubber-band" bouncing effect when
// old_normalized_velocity is large and new_delta is small. // old_normalized_velocity is large and new_delta is small.
double new_duration = std::min( base::TimeDelta new_duration =
SegmentDuration(new_delta, duration_behavior_, delayed_by).InSecondsF(), std::min(SegmentDuration(new_delta, duration_behavior_, delayed_by),
VelocityBasedDurationBound(old_delta, old_normalized_velocity, VelocityBasedDurationBound(old_delta, old_normalized_velocity,
old_duration, new_delta)); old_duration, new_delta));
if (new_duration < kEpsilon) { if (new_duration.InSecondsF() < kEpsilon) {
// We are already at or very close to the new target. Stop animating. // We are already at or very close to the new target. Stop animating.
target_value_ = new_target; target_value_ = new_target;
total_animation_duration_ = base::TimeDelta::FromSecondsD(t); total_animation_duration_ = t;
return; return;
} }
...@@ -249,13 +248,14 @@ void ScrollOffsetAnimationCurve::UpdateTarget( ...@@ -249,13 +248,14 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
// To match the "true" velocity in px/sec we must adjust this slope for // To match the "true" velocity in px/sec we must adjust this slope for
// differences in duration and scroll delta between old and new curves. // differences in duration and scroll delta between old and new curves.
double new_normalized_velocity = double new_normalized_velocity =
old_normalized_velocity * (new_duration / old_duration) * old_normalized_velocity *
(new_duration.InSecondsF() / old_duration.InSecondsF()) *
(MaximumDimension(old_delta) / MaximumDimension(new_delta)); (MaximumDimension(old_delta) / MaximumDimension(new_delta));
initial_value_ = current_position; initial_value_ = current_position;
target_value_ = new_target; target_value_ = new_target;
total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration); total_animation_duration_ = t + new_duration;
last_retarget_ = base::TimeDelta::FromSecondsD(t); last_retarget_ = t;
timing_function_ = EaseOutWithInitialVelocity(new_normalized_velocity); timing_function_ = EaseOutWithInitialVelocity(new_normalized_velocity);
} }
......
...@@ -59,7 +59,7 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve : public AnimationCurve { ...@@ -59,7 +59,7 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve : public AnimationCurve {
// relative to the start of the animation. The duration is recomputed based // relative to the start of the animation. The duration is recomputed based
// on the DurationBehavior the curve was constructed with. The timing // on the DurationBehavior the curve was constructed with. The timing
// function is an ease-in-out cubic bezier modified to preserve velocity at t. // function is an ease-in-out cubic bezier modified to preserve velocity at t.
void UpdateTarget(double t, const gfx::ScrollOffset& new_target); void UpdateTarget(base::TimeDelta t, const gfx::ScrollOffset& new_target);
// Shifts the entire curve by a delta without affecting its shape or timing. // Shifts the entire curve by a delta without affecting its shape or timing.
// Used for scroll anchoring adjustments that happen during scroll animations // Used for scroll anchoring adjustments that happen during scroll animations
......
...@@ -148,7 +148,8 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTarget) { ...@@ -148,7 +148,8 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTarget) {
curve->GetValue(base::TimeDelta::FromSecondsD(duration)).y(), curve->GetValue(base::TimeDelta::FromSecondsD(duration)).y(),
0.0002f); 0.0002f);
curve->UpdateTarget(duration / 2, gfx::ScrollOffset(0.0, 9900.0)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(duration / 2),
gfx::ScrollOffset(0.0, 9900.0));
EXPECT_NEAR(duration * 1.5, curve->Duration().InSecondsF(), 0.0002f); EXPECT_NEAR(duration * 1.5, curve->Duration().InSecondsF(), 0.0002f);
EXPECT_NEAR( EXPECT_NEAR(
...@@ -163,7 +164,8 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTarget) { ...@@ -163,7 +164,8 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTarget) {
curve->GetValue(base::TimeDelta::FromSecondsD(duration * 1.5)).y(), curve->GetValue(base::TimeDelta::FromSecondsD(duration * 1.5)).y(),
0.0002f); 0.0002f);
curve->UpdateTarget(duration, gfx::ScrollOffset(0.0, 7200.0)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(duration),
gfx::ScrollOffset(0.0, 7200.0));
// A closer target at high velocity reduces the duration. // A closer target at high velocity reduces the duration.
EXPECT_NEAR(duration * 1.0794, curve->Duration().InSecondsF(), 0.0002f); EXPECT_NEAR(duration * 1.0794, curve->Duration().InSecondsF(), 0.0002f);
...@@ -187,16 +189,19 @@ TEST(ScrollOffsetAnimationCurveTest, InverseDeltaDuration) { ...@@ -187,16 +189,19 @@ TEST(ScrollOffsetAnimationCurveTest, InverseDeltaDuration) {
curve->SetInitialValue(gfx::ScrollOffset()); curve->SetInitialValue(gfx::ScrollOffset());
double smallDeltaDuration = curve->Duration().InSecondsF(); double smallDeltaDuration = curve->Duration().InSecondsF();
curve->UpdateTarget(0.01f, gfx::ScrollOffset(0.f, 300.f)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(0.01f),
gfx::ScrollOffset(0.f, 300.f));
double mediumDeltaDuration = curve->Duration().InSecondsF(); double mediumDeltaDuration = curve->Duration().InSecondsF();
curve->UpdateTarget(0.01f, gfx::ScrollOffset(0.f, 500.f)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(0.01f),
gfx::ScrollOffset(0.f, 500.f));
double largeDeltaDuration = curve->Duration().InSecondsF(); double largeDeltaDuration = curve->Duration().InSecondsF();
EXPECT_GT(smallDeltaDuration, mediumDeltaDuration); EXPECT_GT(smallDeltaDuration, mediumDeltaDuration);
EXPECT_GT(mediumDeltaDuration, largeDeltaDuration); EXPECT_GT(mediumDeltaDuration, largeDeltaDuration);
curve->UpdateTarget(0.01f, gfx::ScrollOffset(0.f, 5000.f)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(0.01f),
gfx::ScrollOffset(0.f, 5000.f));
EXPECT_EQ(largeDeltaDuration, curve->Duration().InSecondsF()); EXPECT_EQ(largeDeltaDuration, curve->Duration().InSecondsF());
} }
...@@ -215,7 +220,8 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithDelay) { ...@@ -215,7 +220,8 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithDelay) {
base::TimeDelta::FromSecondsD(delay_in_seconds)); base::TimeDelta::FromSecondsD(delay_in_seconds));
EXPECT_NEAR(curve_duration, curve->Duration().InSecondsF(), 0.0002f); EXPECT_NEAR(curve_duration, curve->Duration().InSecondsF(), 0.0002f);
curve->UpdateTarget(0.01f, gfx::ScrollOffset(0.f, 500.f)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(0.01f),
gfx::ScrollOffset(0.f, 500.f));
EXPECT_GT(curve_duration, curve->Duration().InSecondsF()); EXPECT_GT(curve_duration, curve->Duration().InSecondsF());
EXPECT_EQ(gfx::ScrollOffset(0.f, 500.f), curve->target_value()); EXPECT_EQ(gfx::ScrollOffset(0.f, 500.f), curve->target_value());
} }
...@@ -232,7 +238,8 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithLargeDelay) { ...@@ -232,7 +238,8 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithLargeDelay) {
EXPECT_EQ(0.f, curve->Duration().InSecondsF()); EXPECT_EQ(0.f, curve->Duration().InSecondsF());
// Re-targeting when animation duration is 0. // Re-targeting when animation duration is 0.
curve->UpdateTarget(-0.01, gfx::ScrollOffset(0.f, 300.f)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(-0.01),
gfx::ScrollOffset(0.f, 300.f));
double duration = double duration =
ScrollOffsetAnimationCurve::SegmentDuration( ScrollOffsetAnimationCurve::SegmentDuration(
gfx::Vector2dF(0.f, 200.f), gfx::Vector2dF(0.f, 200.f),
...@@ -243,7 +250,8 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithLargeDelay) { ...@@ -243,7 +250,8 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithLargeDelay) {
// Re-targeting before last_retarget_, the difference should be accounted for // Re-targeting before last_retarget_, the difference should be accounted for
// in duration. // in duration.
curve->UpdateTarget(-0.01, gfx::ScrollOffset(0.f, 500.f)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(-0.01),
gfx::ScrollOffset(0.f, 500.f));
duration = ScrollOffsetAnimationCurve::SegmentDuration( duration = ScrollOffsetAnimationCurve::SegmentDuration(
gfx::Vector2dF(0.f, 500.f), gfx::Vector2dF(0.f, 500.f),
ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA, ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA,
...@@ -283,13 +291,15 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTargetZeroLastSegmentDuration) { ...@@ -283,13 +291,15 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTargetZeroLastSegmentDuration) {
base::TimeDelta()) base::TimeDelta())
.InSecondsF() + .InSecondsF() +
0.05; 0.05;
curve->UpdateTarget(0.05, gfx::ScrollOffset(0.f, 200.f)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(0.05),
gfx::ScrollOffset(0.f, 200.f));
EXPECT_NEAR(expected_duration, curve->Duration().InSecondsF(), 0.0002f); EXPECT_NEAR(expected_duration, curve->Duration().InSecondsF(), 0.0002f);
// Re-target 2, this should set total_animation_duration to t, which is // Re-target 2, this should set total_animation_duration to t, which is
// last_retarget_. This is what would cause the DCHECK failure in // last_retarget_. This is what would cause the DCHECK failure in
// crbug.com/645317. // crbug.com/645317.
curve->UpdateTarget(-0.145, gfx::ScrollOffset(0.f, 300.f)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(-0.145),
gfx::ScrollOffset(0.f, 300.f));
EXPECT_NEAR(0.05, curve->Duration().InSecondsF(), 0.0002f); EXPECT_NEAR(0.05, curve->Duration().InSecondsF(), 0.0002f);
// Re-target 3, this should set total_animation_duration based on new_delta. // Re-target 3, this should set total_animation_duration based on new_delta.
...@@ -301,7 +311,8 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTargetZeroLastSegmentDuration) { ...@@ -301,7 +311,8 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTargetZeroLastSegmentDuration) {
ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA, ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA,
base::TimeDelta::FromSecondsD(0.15)) base::TimeDelta::FromSecondsD(0.15))
.InSecondsF(); .InSecondsF();
curve->UpdateTarget(-0.1, gfx::ScrollOffset(0.f, 500.f)); curve->UpdateTarget(base::TimeDelta::FromSecondsD(-0.1),
gfx::ScrollOffset(0.f, 500.f));
EXPECT_NEAR(expected_duration, curve->Duration().InSecondsF(), 0.0002f); EXPECT_NEAR(expected_duration, curve->Duration().InSecondsF(), 0.0002f);
} }
......
...@@ -110,7 +110,7 @@ bool ScrollOffsetAnimationsImpl::ScrollAnimationUpdateTarget( ...@@ -110,7 +110,7 @@ bool ScrollOffsetAnimationsImpl::ScrollAnimationUpdateTarget(
// t = -delayed_by. // t = -delayed_by.
trimmed -= delayed_by; trimmed -= delayed_by;
curve->UpdateTarget(trimmed.InSecondsF(), new_target); curve->UpdateTarget(trimmed, new_target);
TRACE_EVENT_INSTANT1("cc", "ScrollAnimationUpdateTarget", TRACE_EVENT_INSTANT1("cc", "ScrollAnimationUpdateTarget",
TRACE_EVENT_SCOPE_THREAD, "UpdatedDuration", TRACE_EVENT_SCOPE_THREAD, "UpdatedDuration",
curve->Duration().InMillisecondsF()); curve->Duration().InMillisecondsF());
......
...@@ -72,7 +72,7 @@ FloatPoint CompositorScrollOffsetAnimationCurve::TargetValue() const { ...@@ -72,7 +72,7 @@ FloatPoint CompositorScrollOffsetAnimationCurve::TargetValue() const {
return FloatPoint(target.x(), target.y()); return FloatPoint(target.x(), target.y());
} }
void CompositorScrollOffsetAnimationCurve::UpdateTarget(double time, void CompositorScrollOffsetAnimationCurve::UpdateTarget(TimeDelta time,
FloatPoint new_target) { FloatPoint new_target) {
curve_->UpdateTarget(time, gfx::ScrollOffset(new_target.X(), new_target.Y())); curve_->UpdateTarget(time, gfx::ScrollOffset(new_target.X(), new_target.Y()));
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/platform/geometry/float_point.h" #include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h" #include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace cc { namespace cc {
class ScrollOffsetAnimationCurve; class ScrollOffsetAnimationCurve;
...@@ -49,7 +50,7 @@ class PLATFORM_EXPORT CompositorScrollOffsetAnimationCurve ...@@ -49,7 +50,7 @@ class PLATFORM_EXPORT CompositorScrollOffsetAnimationCurve
double Duration() const; double Duration() const;
FloatPoint TargetValue() const; FloatPoint TargetValue() const;
void ApplyAdjustment(IntSize); void ApplyAdjustment(IntSize);
void UpdateTarget(double time, FloatPoint new_target); void UpdateTarget(TimeDelta time, FloatPoint new_target);
// CompositorAnimationCurve implementation. // CompositorAnimationCurve implementation.
std::unique_ptr<cc::AnimationCurve> CloneToAnimationCurve() const override; std::unique_ptr<cc::AnimationCurve> CloneToAnimationCurve() const override;
......
...@@ -169,7 +169,7 @@ bool ScrollAnimator::WillAnimateToOffset(const ScrollOffset& target_offset) { ...@@ -169,7 +169,7 @@ bool ScrollAnimator::WillAnimateToOffset(const ScrollOffset& target_offset) {
// of sending to the compositor. // of sending to the compositor.
if (run_state_ == RunState::kRunningOnMainThread) { if (run_state_ == RunState::kRunningOnMainThread) {
animation_curve_->UpdateTarget( animation_curve_->UpdateTarget(
time_function_() - start_time_, TimeDelta::FromSecondsD(time_function_() - start_time_),
CompositorOffsetFromBlinkOffset(target_offset)); CompositorOffsetFromBlinkOffset(target_offset));
return true; return true;
} }
...@@ -329,7 +329,7 @@ void ScrollAnimator::UpdateCompositorAnimations() { ...@@ -329,7 +329,7 @@ void ScrollAnimator::UpdateCompositorAnimations() {
// ::adjustScrollOffsetAnimation should have made the necessary // ::adjustScrollOffsetAnimation should have made the necessary
// adjustment to the curve. // adjustment to the curve.
animation_curve_->UpdateTarget( animation_curve_->UpdateTarget(
time_function_() - start_time_, TimeDelta::FromSecondsD(time_function_() - start_time_),
CompositorOffsetFromBlinkOffset(target_offset_)); CompositorOffsetFromBlinkOffset(target_offset_));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment