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

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: Remove unused plumbing 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 td = base::TimeDelta::FromMicroseconds(
tdresser 2016/08/25 15:55:54 td -> time_delta https://google.github.io/stylegu
ymalik 2016/08/29 14:52:05 Great, thanks!
66 duration / kDurationDivisor * base::Time::kMicrosecondsPerSecond);
67
68 td = td - delayed_by;
69 if (td >= base::TimeDelta())
tdresser 2016/08/25 15:55:54 operator> is comparing unsigned integers, so this
tdresser 2016/08/29 14:31:33 Whoops, nevermind, this looks fine.
ymalik 2016/08/29 14:52:05 Acknowledged.
70 return td;
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 (has_set_initial_value_ && duration == base::TimeDelta())
tdresser 2016/08/25 15:55:54 duration_.is_zero()
ymalik 2016/08/29 14:52:05 Done.
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 if (t == 0) {
tdresser 2016/08/25 15:55:54 Should this be combined with the clause above?
ymalik 2016/08/29 14:52:05 I think this is more clear in communicating that t
tdresser 2016/08/29 15:28:28 Acknowledged.
210 // Just update the target since the animation hasn't started yet.
211 target_value_ = new_target;
212 return;
213 }
214
197 gfx::ScrollOffset current_position = 215 gfx::ScrollOffset current_position =
198 GetValue(base::TimeDelta::FromSecondsD(t)); 216 GetValue(base::TimeDelta::FromSecondsD(t));
199 gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_); 217 gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_);
200 gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position); 218 gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position);
201 219
202 double old_duration = 220 double old_duration =
203 (total_animation_duration_ - last_retarget_).InSecondsF(); 221 (total_animation_duration_ - last_retarget_).InSecondsF();
204 double old_normalized_velocity = timing_function_->Velocity( 222 double old_normalized_velocity = timing_function_->Velocity(
205 (t - last_retarget_.InSecondsF()) / old_duration); 223 (t - last_retarget_.InSecondsF()) / old_duration);
206 224
207 // Use the velocity-based duration bound when it is less than the constant 225 // Use the velocity-based duration bound when it is less than the constant
208 // segment duration. This minimizes the "rubber-band" bouncing effect when 226 // segment duration. This minimizes the "rubber-band" bouncing effect when
209 // old_normalized_velocity is large and new_delta is small. 227 // old_normalized_velocity is large and new_delta is small.
210 double new_duration = 228 double new_duration =
211 std::min(SegmentDuration(new_delta, duration_behavior_).InSecondsF(), 229 std::min(SegmentDuration(new_delta, duration_behavior_, base::TimeDelta())
230 .InSecondsF(),
212 VelocityBasedDurationBound(old_delta, old_normalized_velocity, 231 VelocityBasedDurationBound(old_delta, old_normalized_velocity,
213 old_duration, new_delta)); 232 old_duration, new_delta));
214 233
215 if (new_duration < kEpsilon) { 234 if (new_duration < kEpsilon) {
216 // We are already at or very close to the new target. Stop animating. 235 // We are already at or very close to the new target. Stop animating.
217 target_value_ = new_target; 236 target_value_ = new_target;
218 total_animation_duration_ = base::TimeDelta::FromSecondsD(t); 237 total_animation_duration_ = base::TimeDelta::FromSecondsD(t);
219 return; 238 return;
220 } 239 }
221 240
222 // TimingFunction::Velocity gives the slope of the curve from 0 to 1. 241 // 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 242 // 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. 243 // differences in duration and scroll delta between old and new curves.
225 double new_normalized_velocity = 244 double new_normalized_velocity =
226 old_normalized_velocity * (new_duration / old_duration) * 245 old_normalized_velocity * (new_duration / old_duration) *
227 (MaximumDimension(old_delta) / MaximumDimension(new_delta)); 246 (MaximumDimension(old_delta) / MaximumDimension(new_delta));
228 247
229 initial_value_ = current_position; 248 initial_value_ = current_position;
230 target_value_ = new_target; 249 target_value_ = new_target;
231 total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration); 250 total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration);
232 last_retarget_ = base::TimeDelta::FromSecondsD(t); 251 last_retarget_ = base::TimeDelta::FromSecondsD(t);
233 timing_function_ = EaseOutWithInitialVelocity(new_normalized_velocity); 252 timing_function_ = EaseOutWithInitialVelocity(new_normalized_velocity);
234 } 253 }
235 254
236 } // namespace cc 255 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698