Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Unified Diff: cc/animation/scroll_offset_animation_curve.cc

Issue 2040543002: Take MT jank into account when animating the scroll offset on CC (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add test + apply suggested improvement Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: cc/animation/scroll_offset_animation_curve.cc
diff --git a/cc/animation/scroll_offset_animation_curve.cc b/cc/animation/scroll_offset_animation_curve.cc
index b207994c092a327a70c753d99b7c93f4446bf4c2..a3831432897b6f8b3b71295254768597d06f2e8e 100644
--- a/cc/animation/scroll_offset_animation_curve.cc
+++ b/cc/animation/scroll_offset_animation_curve.cc
@@ -40,30 +40,6 @@ static float MaximumDimension(const gfx::Vector2dF& delta) {
return std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y();
}
-static base::TimeDelta SegmentDuration(const gfx::Vector2dF& delta,
- DurationBehavior behavior) {
- double duration = kConstantDuration;
- switch (behavior) {
- case DurationBehavior::CONSTANT:
- duration = kConstantDuration;
- break;
- case DurationBehavior::DELTA_BASED:
- duration = std::sqrt(std::abs(MaximumDimension(delta)));
- break;
- case DurationBehavior::INVERSE_DELTA:
- duration = std::min(
- std::max(kInverseDeltaOffset +
- std::abs(MaximumDimension(delta)) * kInverseDeltaSlope,
- kInverseDeltaMinDuration),
- kInverseDeltaMaxDuration);
- break;
- default:
- NOTREACHED();
- }
- return base::TimeDelta::FromMicroseconds(duration / kDurationDivisor *
- base::Time::kMicrosecondsPerSecond);
-}
-
static std::unique_ptr<TimingFunction> EaseOutWithInitialVelocity(
double velocity) {
// Clamp velocity to a sane value.
@@ -97,12 +73,45 @@ ScrollOffsetAnimationCurve::ScrollOffsetAnimationCurve(
ScrollOffsetAnimationCurve::~ScrollOffsetAnimationCurve() {}
+base::TimeDelta ScrollOffsetAnimationCurve::SegmentDuration(
+ const gfx::Vector2dF& delta,
+ DurationBehavior behavior,
+ base::TimeDelta delayed_by) {
+ double duration = kConstantDuration;
+ switch (behavior) {
+ case DurationBehavior::CONSTANT:
+ duration = kConstantDuration;
+ break;
+ case DurationBehavior::DELTA_BASED:
+ duration = std::sqrt(std::abs(MaximumDimension(delta)));
+ break;
+ case DurationBehavior::INVERSE_DELTA:
+ duration = std::min(
+ std::max(kInverseDeltaOffset +
+ std::abs(MaximumDimension(delta)) * kInverseDeltaSlope,
+ kInverseDeltaMinDuration),
+ kInverseDeltaMaxDuration);
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ base::TimeDelta time_delta = base::TimeDelta::FromMicroseconds(
+ duration / kDurationDivisor * base::Time::kMicrosecondsPerSecond);
+
+ time_delta -= delayed_by;
+ if (time_delta >= base::TimeDelta())
+ return time_delta;
+ return base::TimeDelta();
+}
+
void ScrollOffsetAnimationCurve::SetInitialValue(
- const gfx::ScrollOffset& initial_value) {
+ const gfx::ScrollOffset& initial_value,
+ base::TimeDelta delayed_by) {
initial_value_ = initial_value;
has_set_initial_value_ = true;
total_animation_duration_ = SegmentDuration(
- target_value_.DeltaFrom(initial_value_), duration_behavior_);
+ target_value_.DeltaFrom(initial_value_), duration_behavior_, delayed_by);
}
bool ScrollOffsetAnimationCurve::HasSetInitialValue() const {
@@ -120,6 +129,9 @@ gfx::ScrollOffset ScrollOffsetAnimationCurve::GetValue(
base::TimeDelta duration = total_animation_duration_ - last_retarget_;
t -= last_retarget_;
+ if (duration.is_zero())
+ return target_value_;
+
if (t <= base::TimeDelta())
return initial_value_;
@@ -194,6 +206,23 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
target_value_ = new_target;
return;
}
+
+ // The total_animation_duration_ is zero because of the delay that we
+ // accounted for when the animation was created. The new duration should
+ // also take the delay into account.
+ if (total_animation_duration_.is_zero()) {
+ DCHECK_LE(t, 0);
+ total_animation_duration_ =
+ SegmentDuration(new_target.DeltaFrom(initial_value_),
+ duration_behavior_, base::TimeDelta::FromSecondsD(-t));
+ target_value_ = new_target;
+ return;
+ }
+
+ base::TimeDelta delayed_by = base::TimeDelta::FromSecondsD(
+ std::max(0.0, last_retarget_.InSecondsF() - t));
+ t = std::max(t, last_retarget_.InSecondsF());
+
gfx::ScrollOffset current_position =
GetValue(base::TimeDelta::FromSecondsD(t));
gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_);
@@ -207,10 +236,10 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
// 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_).InSecondsF(),
- VelocityBasedDurationBound(old_delta, old_normalized_velocity,
- old_duration, new_delta));
+ double new_duration = std::min(
+ SegmentDuration(new_delta, duration_behavior_, delayed_by).InSecondsF(),
+ VelocityBasedDurationBound(old_delta, old_normalized_velocity,
+ old_duration, new_delta));
if (new_duration < kEpsilon) {
// We are already at or very close to the new target. Stop animating.
« no previous file with comments | « cc/animation/scroll_offset_animation_curve.h ('k') | cc/animation/scroll_offset_animation_curve_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698