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 {
return curve_clone;
}
static double VelocityBasedDurationBound(gfx::Vector2dF old_delta,
double old_normalized_velocity,
double old_duration,
gfx::Vector2dF new_delta) {
static base::TimeDelta VelocityBasedDurationBound(
gfx::Vector2dF old_delta,
double old_normalized_velocity,
base::TimeDelta old_duration,
gfx::Vector2dF new_delta) {
double old_delta_max_dimension = MaximumDimension(old_delta);
double new_delta_max_dimension = MaximumDimension(new_delta);
// If we are already at the target, stop animating.
if (std::abs(new_delta_max_dimension) < kEpsilon)
return 0;
return base::TimeDelta();
// Guard against division by zero.
if (std::abs(old_delta_max_dimension) < 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
// velocity, with some fudge factor to account for the "ease out".
double old_true_velocity =
old_normalized_velocity * old_delta_max_dimension / old_duration;
double old_true_velocity = old_normalized_velocity * old_delta_max_dimension /
old_duration.InSecondsF();
double bound = (new_delta_max_dimension / old_true_velocity) * 2.5f;
// 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(
double t,
base::TimeDelta t,
const gfx::ScrollOffset& new_target) {
if (std::abs(MaximumDimension(target_value_.DeltaFrom(new_target))) <
kEpsilon) {
......@@ -207,41 +209,38 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
return;
}
base::TimeDelta delayed_by = base::TimeDelta::FromSecondsD(
std::max(0.0, last_retarget_.InSecondsF() - t));
t = std::max(t, last_retarget_.InSecondsF());
base::TimeDelta delayed_by = std::max(base::TimeDelta(), last_retarget_ - t);
t = std::max(t, last_retarget_);
gfx::ScrollOffset current_position =
GetValue(base::TimeDelta::FromSecondsD(t));
gfx::ScrollOffset current_position = GetValue(t);
gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_);
gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position);
// The last segement was of zero duration.
if ((total_animation_duration_ - last_retarget_).is_zero()) {
DCHECK_EQ(t, last_retarget_.InSecondsF());
DCHECK_EQ(t, last_retarget_);
total_animation_duration_ =
SegmentDuration(new_delta, duration_behavior_, delayed_by);
target_value_ = new_target;
return;
}
double old_duration =
(total_animation_duration_ - last_retarget_).InSecondsF();
base::TimeDelta old_duration = total_animation_duration_ - last_retarget_;
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
// segment duration. This minimizes the "rubber-band" bouncing effect when
// old_normalized_velocity is large and new_delta is small.
double new_duration = std::min(
SegmentDuration(new_delta, duration_behavior_, delayed_by).InSecondsF(),
VelocityBasedDurationBound(old_delta, old_normalized_velocity,
old_duration, new_delta));
base::TimeDelta new_duration =
std::min(SegmentDuration(new_delta, duration_behavior_, delayed_by),
VelocityBasedDurationBound(old_delta, old_normalized_velocity,
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.
target_value_ = new_target;
total_animation_duration_ = base::TimeDelta::FromSecondsD(t);
total_animation_duration_ = t;
return;
}
......@@ -249,13 +248,14 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
// 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.
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));
initial_value_ = current_position;
target_value_ = new_target;
total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration);
last_retarget_ = base::TimeDelta::FromSecondsD(t);
total_animation_duration_ = t + new_duration;
last_retarget_ = t;
timing_function_ = EaseOutWithInitialVelocity(new_normalized_velocity);
}
......
......@@ -59,7 +59,7 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve : public AnimationCurve {
// relative to the start of the animation. The duration is recomputed based
// on the DurationBehavior the curve was constructed with. The timing
// 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.
// Used for scroll anchoring adjustments that happen during scroll animations
......
......@@ -148,7 +148,8 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTarget) {
curve->GetValue(base::TimeDelta::FromSecondsD(duration)).y(),
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(
......@@ -163,7 +164,8 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTarget) {
curve->GetValue(base::TimeDelta::FromSecondsD(duration * 1.5)).y(),
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.
EXPECT_NEAR(duration * 1.0794, curve->Duration().InSecondsF(), 0.0002f);
......@@ -187,16 +189,19 @@ TEST(ScrollOffsetAnimationCurveTest, InverseDeltaDuration) {
curve->SetInitialValue(gfx::ScrollOffset());
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();
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();
EXPECT_GT(smallDeltaDuration, mediumDeltaDuration);
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());
}
......@@ -215,7 +220,8 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithDelay) {
base::TimeDelta::FromSecondsD(delay_in_seconds));
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_EQ(gfx::ScrollOffset(0.f, 500.f), curve->target_value());
}
......@@ -232,7 +238,8 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithLargeDelay) {
EXPECT_EQ(0.f, curve->Duration().InSecondsF());
// 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 =
ScrollOffsetAnimationCurve::SegmentDuration(
gfx::Vector2dF(0.f, 200.f),
......@@ -243,7 +250,8 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithLargeDelay) {
// Re-targeting before last_retarget_, the difference should be accounted for
// 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(
gfx::Vector2dF(0.f, 500.f),
ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA,
......@@ -283,13 +291,15 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTargetZeroLastSegmentDuration) {
base::TimeDelta())
.InSecondsF() +
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);
// Re-target 2, this should set total_animation_duration to t, which is
// last_retarget_. This is what would cause the DCHECK failure in
// 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);
// Re-target 3, this should set total_animation_duration based on new_delta.
......@@ -301,7 +311,8 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTargetZeroLastSegmentDuration) {
ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA,
base::TimeDelta::FromSecondsD(0.15))
.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);
}
......
......@@ -110,7 +110,7 @@ bool ScrollOffsetAnimationsImpl::ScrollAnimationUpdateTarget(
// t = -delayed_by.
trimmed -= delayed_by;
curve->UpdateTarget(trimmed.InSecondsF(), new_target);
curve->UpdateTarget(trimmed, new_target);
TRACE_EVENT_INSTANT1("cc", "ScrollAnimationUpdateTarget",
TRACE_EVENT_SCOPE_THREAD, "UpdatedDuration",
curve->Duration().InMillisecondsF());
......
......@@ -72,7 +72,7 @@ FloatPoint CompositorScrollOffsetAnimationCurve::TargetValue() const {
return FloatPoint(target.x(), target.y());
}
void CompositorScrollOffsetAnimationCurve::UpdateTarget(double time,
void CompositorScrollOffsetAnimationCurve::UpdateTarget(TimeDelta time,
FloatPoint new_target) {
curve_->UpdateTarget(time, gfx::ScrollOffset(new_target.X(), new_target.Y()));
}
......
......@@ -12,6 +12,7 @@
#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/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace cc {
class ScrollOffsetAnimationCurve;
......@@ -49,7 +50,7 @@ class PLATFORM_EXPORT CompositorScrollOffsetAnimationCurve
double Duration() const;
FloatPoint TargetValue() const;
void ApplyAdjustment(IntSize);
void UpdateTarget(double time, FloatPoint new_target);
void UpdateTarget(TimeDelta time, FloatPoint new_target);
// CompositorAnimationCurve implementation.
std::unique_ptr<cc::AnimationCurve> CloneToAnimationCurve() const override;
......
......@@ -169,7 +169,7 @@ bool ScrollAnimator::WillAnimateToOffset(const ScrollOffset& target_offset) {
// of sending to the compositor.
if (run_state_ == RunState::kRunningOnMainThread) {
animation_curve_->UpdateTarget(
time_function_() - start_time_,
TimeDelta::FromSecondsD(time_function_() - start_time_),
CompositorOffsetFromBlinkOffset(target_offset));
return true;
}
......@@ -329,7 +329,7 @@ void ScrollAnimator::UpdateCompositorAnimations() {
// ::adjustScrollOffsetAnimation should have made the necessary
// adjustment to the curve.
animation_curve_->UpdateTarget(
time_function_() - start_time_,
TimeDelta::FromSecondsD(time_function_() - start_time_),
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