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

Side by Side 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: apply skobes feedback 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/animation/scroll_offset_animation_curve.h" 5 #include "cc/animation/scroll_offset_animation_curve.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 23 matching lines...) Expand all
34 34
35 namespace { 35 namespace {
36 36
37 const double kEpsilon = 0.01f; 37 const double kEpsilon = 0.01f;
38 38
39 static float MaximumDimension(const gfx::Vector2dF& delta) { 39 static float MaximumDimension(const gfx::Vector2dF& delta) {
40 return std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y(); 40 return std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y();
41 } 41 }
42 42
43 static base::TimeDelta SegmentDuration(const gfx::Vector2dF& delta, 43 static base::TimeDelta SegmentDuration(const gfx::Vector2dF& delta,
44 DurationBehavior behavior) { 44 DurationBehavior behavior,
45 base::TimeDelta delayed_by) {
45 double duration = kConstantDuration; 46 double duration = kConstantDuration;
46 switch (behavior) { 47 switch (behavior) {
47 case DurationBehavior::CONSTANT: 48 case DurationBehavior::CONSTANT:
48 duration = kConstantDuration; 49 duration = kConstantDuration;
49 break; 50 break;
50 case DurationBehavior::DELTA_BASED: 51 case DurationBehavior::DELTA_BASED:
51 duration = std::sqrt(std::abs(MaximumDimension(delta))); 52 duration = std::sqrt(std::abs(MaximumDimension(delta)));
52 break; 53 break;
53 case DurationBehavior::INVERSE_DELTA: 54 case DurationBehavior::INVERSE_DELTA:
54 duration = std::min( 55 duration = std::min(
55 std::max(kInverseDeltaOffset + 56 std::max(kInverseDeltaOffset +
56 std::abs(MaximumDimension(delta)) * kInverseDeltaSlope, 57 std::abs(MaximumDimension(delta)) * kInverseDeltaSlope,
57 kInverseDeltaMinDuration), 58 kInverseDeltaMinDuration),
58 kInverseDeltaMaxDuration); 59 kInverseDeltaMaxDuration);
59 break; 60 break;
60 default: 61 default:
61 NOTREACHED(); 62 NOTREACHED();
62 } 63 }
63 return base::TimeDelta::FromMicroseconds(duration / kDurationDivisor * 64
64 base::Time::kMicrosecondsPerSecond); 65 base::TimeDelta time_delta = base::TimeDelta::FromMicroseconds(
66 duration / kDurationDivisor * base::Time::kMicrosecondsPerSecond);
67
68 time_delta -= delayed_by;
69 if (time_delta >= base::TimeDelta())
70 return time_delta;
71 return base::TimeDelta();
65 } 72 }
66 73
67 static std::unique_ptr<TimingFunction> EaseOutWithInitialVelocity( 74 static std::unique_ptr<TimingFunction> EaseOutWithInitialVelocity(
68 double velocity) { 75 double velocity) {
69 // Clamp velocity to a sane value. 76 // Clamp velocity to a sane value.
70 velocity = std::min(std::max(velocity, -1000.0), 1000.0); 77 velocity = std::min(std::max(velocity, -1000.0), 1000.0);
71 78
72 // Based on CubicBezierTimingFunction::EaseType::EASE_IN_OUT preset 79 // Based on CubicBezierTimingFunction::EaseType::EASE_IN_OUT preset
73 // with first control point scaled. 80 // with first control point scaled.
74 const double x1 = 0.42; 81 const double x1 = 0.42;
(...skipping 16 matching lines...) Expand all
91 std::unique_ptr<TimingFunction> timing_function, 98 std::unique_ptr<TimingFunction> timing_function,
92 DurationBehavior duration_behavior) 99 DurationBehavior duration_behavior)
93 : target_value_(target_value), 100 : target_value_(target_value),
94 timing_function_(std::move(timing_function)), 101 timing_function_(std::move(timing_function)),
95 duration_behavior_(duration_behavior), 102 duration_behavior_(duration_behavior),
96 has_set_initial_value_(false) {} 103 has_set_initial_value_(false) {}
97 104
98 ScrollOffsetAnimationCurve::~ScrollOffsetAnimationCurve() {} 105 ScrollOffsetAnimationCurve::~ScrollOffsetAnimationCurve() {}
99 106
100 void ScrollOffsetAnimationCurve::SetInitialValue( 107 void ScrollOffsetAnimationCurve::SetInitialValue(
101 const gfx::ScrollOffset& initial_value) { 108 const gfx::ScrollOffset& initial_value,
109 base::TimeDelta delayed_by) {
102 initial_value_ = initial_value; 110 initial_value_ = initial_value;
103 has_set_initial_value_ = true; 111 has_set_initial_value_ = true;
104 total_animation_duration_ = SegmentDuration( 112 total_animation_duration_ = SegmentDuration(
105 target_value_.DeltaFrom(initial_value_), duration_behavior_); 113 target_value_.DeltaFrom(initial_value_), duration_behavior_, delayed_by);
106 } 114 }
107 115
108 bool ScrollOffsetAnimationCurve::HasSetInitialValue() const { 116 bool ScrollOffsetAnimationCurve::HasSetInitialValue() const {
109 return has_set_initial_value_; 117 return has_set_initial_value_;
110 } 118 }
111 119
112 void ScrollOffsetAnimationCurve::ApplyAdjustment( 120 void ScrollOffsetAnimationCurve::ApplyAdjustment(
113 const gfx::Vector2dF& adjustment) { 121 const gfx::Vector2dF& adjustment) {
114 initial_value_ = ScrollOffsetWithDelta(initial_value_, adjustment); 122 initial_value_ = ScrollOffsetWithDelta(initial_value_, adjustment);
115 target_value_ = ScrollOffsetWithDelta(target_value_, adjustment); 123 target_value_ = ScrollOffsetWithDelta(target_value_, adjustment);
116 } 124 }
117 125
118 gfx::ScrollOffset ScrollOffsetAnimationCurve::GetValue( 126 gfx::ScrollOffset ScrollOffsetAnimationCurve::GetValue(
119 base::TimeDelta t) const { 127 base::TimeDelta t) const {
120 base::TimeDelta duration = total_animation_duration_ - last_retarget_; 128 base::TimeDelta duration = total_animation_duration_ - last_retarget_;
121 t -= last_retarget_; 129 t -= last_retarget_;
122 130
131 if (duration.is_zero())
132 return target_value_;
133
123 if (t <= base::TimeDelta()) 134 if (t <= base::TimeDelta())
124 return initial_value_; 135 return initial_value_;
125 136
126 if (t >= duration) 137 if (t >= duration)
127 return target_value_; 138 return target_value_;
128 139
129 double progress = timing_function_->GetValue(TimeUtil::Divide(t, duration)); 140 double progress = timing_function_->GetValue(TimeUtil::Divide(t, duration));
130 return gfx::ScrollOffset( 141 return gfx::ScrollOffset(
131 gfx::Tween::FloatValueBetween( 142 gfx::Tween::FloatValueBetween(
132 progress, initial_value_.x(), target_value_.x()), 143 progress, initial_value_.x(), target_value_.x()),
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 } 198 }
188 199
189 void ScrollOffsetAnimationCurve::UpdateTarget( 200 void ScrollOffsetAnimationCurve::UpdateTarget(
190 double t, 201 double t,
191 const gfx::ScrollOffset& new_target) { 202 const gfx::ScrollOffset& new_target) {
192 if (std::abs(MaximumDimension(target_value_.DeltaFrom(new_target))) < 203 if (std::abs(MaximumDimension(target_value_.DeltaFrom(new_target))) <
193 kEpsilon) { 204 kEpsilon) {
194 target_value_ = new_target; 205 target_value_ = new_target;
195 return; 206 return;
196 } 207 }
208
209 // The total_animation_duration_ is zero because of the delay that we
210 // accounted for when the animation was created. The new duration should
211 // also take the delay into account.
212 if (total_animation_duration_.is_zero()) {
213 DCHECK_LE(t, 0);
214 total_animation_duration_ =
215 SegmentDuration(new_target.DeltaFrom(initial_value_),
216 duration_behavior_, base::TimeDelta::FromSecondsD(-t));
217 target_value_ = new_target;
218 return;
219 }
220
221 t = std::max(t, last_retarget_.InSecondsF());
skobes 2016/09/02 01:27:56 Any change in t produced by this line represents j
222
197 gfx::ScrollOffset current_position = 223 gfx::ScrollOffset current_position =
198 GetValue(base::TimeDelta::FromSecondsD(t)); 224 GetValue(base::TimeDelta::FromSecondsD(t));
199 gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_); 225 gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_);
200 gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position); 226 gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position);
201 227
202 double old_duration = 228 double old_duration =
203 (total_animation_duration_ - last_retarget_).InSecondsF(); 229 (total_animation_duration_ - last_retarget_).InSecondsF();
204 double old_normalized_velocity = timing_function_->Velocity( 230 double old_normalized_velocity = timing_function_->Velocity(
205 (t - last_retarget_.InSecondsF()) / old_duration); 231 (t - last_retarget_.InSecondsF()) / old_duration);
206 232
207 // Use the velocity-based duration bound when it is less than the constant 233 // Use the velocity-based duration bound when it is less than the constant
208 // segment duration. This minimizes the "rubber-band" bouncing effect when 234 // segment duration. This minimizes the "rubber-band" bouncing effect when
209 // old_normalized_velocity is large and new_delta is small. 235 // old_normalized_velocity is large and new_delta is small.
210 double new_duration = 236 double new_duration =
211 std::min(SegmentDuration(new_delta, duration_behavior_).InSecondsF(), 237 std::min(SegmentDuration(new_delta, duration_behavior_, base::TimeDelta())
238 .InSecondsF(),
212 VelocityBasedDurationBound(old_delta, old_normalized_velocity, 239 VelocityBasedDurationBound(old_delta, old_normalized_velocity,
213 old_duration, new_delta)); 240 old_duration, new_delta));
214 241
215 if (new_duration < kEpsilon) { 242 if (new_duration < kEpsilon) {
216 // We are already at or very close to the new target. Stop animating. 243 // We are already at or very close to the new target. Stop animating.
217 target_value_ = new_target; 244 target_value_ = new_target;
218 total_animation_duration_ = base::TimeDelta::FromSecondsD(t); 245 total_animation_duration_ = base::TimeDelta::FromSecondsD(t);
219 return; 246 return;
220 } 247 }
221 248
222 // TimingFunction::Velocity gives the slope of the curve from 0 to 1. 249 // TimingFunction::Velocity gives the slope of the curve from 0 to 1.
223 // To match the "true" velocity in px/sec we must adjust this slope for 250 // To match the "true" velocity in px/sec we must adjust this slope for
224 // differences in duration and scroll delta between old and new curves. 251 // differences in duration and scroll delta between old and new curves.
225 double new_normalized_velocity = 252 double new_normalized_velocity =
226 old_normalized_velocity * (new_duration / old_duration) * 253 old_normalized_velocity * (new_duration / old_duration) *
227 (MaximumDimension(old_delta) / MaximumDimension(new_delta)); 254 (MaximumDimension(old_delta) / MaximumDimension(new_delta));
228 255
229 initial_value_ = current_position; 256 initial_value_ = current_position;
230 target_value_ = new_target; 257 target_value_ = new_target;
231 total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration); 258 total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration);
232 last_retarget_ = base::TimeDelta::FromSecondsD(t); 259 last_retarget_ = base::TimeDelta::FromSecondsD(t);
233 timing_function_ = EaseOutWithInitialVelocity(new_normalized_velocity); 260 timing_function_ = EaseOutWithInitialVelocity(new_normalized_velocity);
234 } 261 }
235 262
236 } // namespace cc 263 } // namespace cc
OLDNEW
« 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