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

Side by Side Diff: cc/layer_animation_controller.cc

Issue 12517003: cc: Chromify the Animation and LayerAnimationController classes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « cc/layer_animation_controller.h ('k') | cc/layer_animation_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 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/layer_animation_controller.h" 5 #include "cc/layer_animation_controller.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "cc/animation.h" 9 #include "cc/animation.h"
10 #include "cc/animation_registrar.h" 10 #include "cc/animation_registrar.h"
11 #include "cc/keyframed_animation_curve.h" 11 #include "cc/keyframed_animation_curve.h"
12 #include "cc/layer_animation_value_observer.h" 12 #include "cc/layer_animation_value_observer.h"
13 #include "cc/scoped_ptr_algorithm.h" 13 #include "cc/scoped_ptr_algorithm.h"
14 #include "ui/gfx/transform.h" 14 #include "ui/gfx/transform.h"
15 15
16 namespace cc { 16 namespace cc {
17 17
18 LayerAnimationController::LayerAnimationController(int id) 18 LayerAnimationController::LayerAnimationController(int id)
19 : m_forceSync(false) 19 : force_sync_(false),
20 , m_id(id) 20 id_(id),
21 , m_registrar(0) 21 registrar_(0),
22 , m_isActive(false) 22 is_active_(false),
23 , m_lastTickTime(0) 23 last_tick_time_(0) {}
24 { 24
25 } 25 LayerAnimationController::~LayerAnimationController() {
26 26 if (registrar_)
27 LayerAnimationController::~LayerAnimationController() 27 registrar_->UnregisterAnimationController(this);
28 { 28 }
29 if (m_registrar) 29
30 m_registrar->UnregisterAnimationController(this); 30 scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
31 } 31 int id) {
32 32 return make_scoped_refptr(new LayerAnimationController(id));
33 scoped_refptr<LayerAnimationController> LayerAnimationController::create(int id) 33 }
34 { 34
35 return make_scoped_refptr(new LayerAnimationController(id)); 35 void LayerAnimationController::PauseAnimation(int animation_id,
36 } 36 double time_offset) {
37 37 for (size_t i = 0; i < active_animations_.size(); ++i) {
38 void LayerAnimationController::pauseAnimation(int animationId, double timeOffset ) 38 if (active_animations_[i]->id() == animation_id) {
39 { 39 active_animations_[i]->SetRunState(
40 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { 40 Animation::Paused, time_offset + active_animations_[i]->start_time());
41 if (m_activeAnimations[i]->id() == animationId) 41 }
42 m_activeAnimations[i]->setRunState(Animation::Paused, timeOffset + m _activeAnimations[i]->startTime()); 42 }
43 }
44 } 43 }
45 44
46 struct HasAnimationId { 45 struct HasAnimationId {
47 HasAnimationId(int id) : m_id(id) { } 46 HasAnimationId(int id) : id_(id) {}
48 bool operator()(Animation* animation) const { return animation->id() == m_id ; } 47 bool operator()(Animation* animation) const {
49 private: 48 return animation->id() == id_;
50 int m_id; 49 }
50
51 private:
52 int id_;
51 }; 53 };
52 54
53 void LayerAnimationController::removeAnimation(int animationId) 55 void LayerAnimationController::RemoveAnimation(int animation_id) {
54 { 56 ScopedPtrVector<Animation>& animations = active_animations_;
55 ScopedPtrVector<Animation>& animations = m_activeAnimations; 57 animations.erase(cc::remove_if(animations,
56 animations.erase(cc::remove_if(animations, animations.begin(), animations.en d(), HasAnimationId(animationId)), animations.end()); 58 animations.begin(),
57 updateActivation(); 59 animations.end(),
60 HasAnimationId(animation_id)),
61 animations.end());
62 UpdateActivation(NormalActivation);
58 } 63 }
59 64
60 struct HasAnimationIdAndProperty { 65 struct HasAnimationIdAndProperty {
61 HasAnimationIdAndProperty(int id, Animation::TargetProperty targetProperty) : m_id(id), m_targetProperty(targetProperty) { } 66 HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property)
62 bool operator()(Animation* animation) const { return animation->id() == m_id && animation->targetProperty() == m_targetProperty; } 67 : id_(id), target_property_(target_property) {}
63 private: 68 bool operator()(Animation* animation) const {
64 int m_id; 69 return animation->id() == id_ &&
65 Animation::TargetProperty m_targetProperty; 70 animation->target_property() == target_property_;
71 }
72
73 private:
74 int id_;
75 Animation::TargetProperty target_property_;
66 }; 76 };
67 77
68 void LayerAnimationController::removeAnimation(int animationId, Animation::Targe tProperty targetProperty) 78 void LayerAnimationController::RemoveAnimation(
69 { 79 int animation_id,
70 ScopedPtrVector<Animation>& animations = m_activeAnimations; 80 Animation::TargetProperty target_property) {
71 animations.erase(cc::remove_if(animations, animations.begin(), animations.en d(), HasAnimationIdAndProperty(animationId, targetProperty)), animations.end()); 81 ScopedPtrVector<Animation>& animations = active_animations_;
72 updateActivation(); 82 animations.erase(cc::remove_if(animations,
83 animations.begin(),
84 animations.end(),
85 HasAnimationIdAndProperty(animation_id,
86 target_property)),
87 animations.end());
88 UpdateActivation(NormalActivation);
73 } 89 }
74 90
75 // According to render layer backing, these are for testing only. 91 // According to render layer backing, these are for testing only.
76 void LayerAnimationController::suspendAnimations(double monotonicTime) 92 void LayerAnimationController::SuspendAnimations(double monotonic_time) {
77 { 93 for (size_t i = 0; i < active_animations_.size(); ++i) {
78 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { 94 if (!active_animations_[i]->is_finished())
79 if (!m_activeAnimations[i]->isFinished()) 95 active_animations_[i]->SetRunState(Animation::Paused, monotonic_time);
80 m_activeAnimations[i]->setRunState(Animation::Paused, monotonicTime) ; 96 }
81 } 97 }
82 } 98
83 99 // Looking at GraphicsLayerCA, this appears to be the analog to
84 // Looking at GraphicsLayerCA, this appears to be the analog to suspendAnimation s, which is for testing. 100 // suspendAnimations, which is for testing.
85 void LayerAnimationController::resumeAnimations(double monotonicTime) 101 void LayerAnimationController::ResumeAnimations(double monotonic_time) {
86 { 102 for (size_t i = 0; i < active_animations_.size(); ++i) {
87 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { 103 if (active_animations_[i]->run_state() == Animation::Paused)
88 if (m_activeAnimations[i]->runState() == Animation::Paused) 104 active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
89 m_activeAnimations[i]->setRunState(Animation::Running, monotonicTime ); 105 }
90 } 106 }
91 } 107
92 108 // Ensures that the list of active animations on the main thread and the impl
93 // Ensures that the list of active animations on the main thread and the impl th read 109 // thread are kept in sync.
94 // are kept in sync. 110 void LayerAnimationController::PushAnimationUpdatesTo(
95 void LayerAnimationController::pushAnimationUpdatesTo(LayerAnimationController* controllerImpl) 111 LayerAnimationController* controller_impl) {
96 { 112 if (force_sync_) {
97 if (m_forceSync) { 113 ReplaceImplThreadAnimations(controller_impl);
98 replaceImplThreadAnimations(controllerImpl); 114 force_sync_ = false;
99 m_forceSync = false; 115 } else {
116 PurgeAnimationsMarkedForDeletion();
117 PushNewAnimationsToImplThread(controller_impl);
118
119 // Remove finished impl side animations only after pushing,
120 // and only after the animations are deleted on the main thread
121 // this insures we will never push an animation twice.
122 RemoveAnimationsCompletedOnMainThread(controller_impl);
123
124 PushPropertiesToImplThread(controller_impl);
125 }
126 controller_impl->UpdateActivation(NormalActivation);
127 UpdateActivation(NormalActivation);
128 }
129
130 void LayerAnimationController::Animate(double monotonic_time) {
131 if (!HasActiveObserver())
132 return;
133
134 StartAnimationsWaitingForNextTick(monotonic_time);
135 StartAnimationsWaitingForStartTime(monotonic_time);
136 StartAnimationsWaitingForTargetAvailability(monotonic_time);
137 ResolveConflicts(monotonic_time);
138 TickAnimations(monotonic_time);
139 last_tick_time_ = monotonic_time;
140 }
141
142 void LayerAnimationController::AccumulatePropertyUpdates(
143 double monotonic_time,
144 AnimationEventsVector* events) {
145 if (!events)
146 return;
147
148 for (size_t i = 0; i < active_animations_.size(); ++i) {
149 Animation* animation = active_animations_[i];
150 if (!animation->is_impl_only())
151 continue;
152
153 if (animation->target_property() == Animation::Opacity) {
154 AnimationEvent event(AnimationEvent::PropertyUpdate,
155 id_,
156 animation->group(),
157 Animation::Opacity,
158 monotonic_time);
159 event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue(
160 monotonic_time);
161
162 events->push_back(event);
163 }
164 else if (animation->target_property() == Animation::Transform) {
165 AnimationEvent event(AnimationEvent::PropertyUpdate,
166 id_,
167 animation->group(),
168 Animation::Transform,
169 monotonic_time);
170 event.transform =
171 animation->curve()->ToTransformAnimationCurve()->GetValue(
172 monotonic_time);
173 events->push_back(event);
174 }
175 }
176 }
177
178 void LayerAnimationController::UpdateState(AnimationEventsVector* events) {
179 if (!HasActiveObserver())
180 return;
181
182 PromoteStartedAnimations(last_tick_time_, events);
183 MarkFinishedAnimations(last_tick_time_);
184 MarkAnimationsForDeletion(last_tick_time_, events);
185 StartAnimationsWaitingForTargetAvailability(last_tick_time_);
186 PromoteStartedAnimations(last_tick_time_, events);
187
188 AccumulatePropertyUpdates(last_tick_time_, events);
189
190 UpdateActivation(NormalActivation);
191 }
192
193 void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
194 active_animations_.push_back(animation.Pass());
195 UpdateActivation(NormalActivation);
196 }
197
198 Animation* LayerAnimationController::GetAnimation(
199 int group_id,
200 Animation::TargetProperty target_property) const {
201 for (size_t i = 0; i < active_animations_.size(); ++i)
202 if (active_animations_[i]->group() == group_id &&
203 active_animations_[i]->target_property() == target_property)
204 return active_animations_[i];
205 return 0;
206 }
207
208 Animation* LayerAnimationController::GetAnimation(
209 Animation::TargetProperty target_property) const {
210 for (size_t i = 0; i < active_animations_.size(); ++i) {
211 size_t index = active_animations_.size() - i - 1;
212 if (active_animations_[index]->target_property() == target_property)
213 return active_animations_[index];
214 }
215 return 0;
216 }
217
218 bool LayerAnimationController::HasActiveAnimation() const {
219 for (size_t i = 0; i < active_animations_.size(); ++i) {
220 if (!active_animations_[i]->is_finished())
221 return true;
222 }
223 return false;
224 }
225
226 bool LayerAnimationController::IsAnimatingProperty(
227 Animation::TargetProperty target_property) const {
228 for (size_t i = 0; i < active_animations_.size(); ++i) {
229 if (active_animations_[i]->run_state() != Animation::Finished &&
230 active_animations_[i]->run_state() != Animation::Aborted &&
231 active_animations_[i]->target_property() == target_property)
232 return true;
233 }
234 return false;
235 }
236
237 void LayerAnimationController::OnAnimationStarted(
238 const AnimationEvent& event) {
239 for (size_t i = 0; i < active_animations_.size(); ++i) {
240 if (active_animations_[i]->group() == event.group_id &&
241 active_animations_[i]->target_property() == event.target_property &&
242 active_animations_[i]->needs_synchronized_start_time()) {
243 active_animations_[i]->set_needs_synchronized_start_time(false);
244 active_animations_[i]->set_start_time(event.monotonic_time);
245 return;
246 }
247 }
248 }
249
250 void LayerAnimationController::SetAnimationRegistrar(
251 AnimationRegistrar* registrar) {
252 if (registrar_ == registrar)
253 return;
254
255 if (registrar_)
256 registrar_->UnregisterAnimationController(this);
257
258 registrar_ = registrar;
259 if (registrar_)
260 registrar_->RegisterAnimationController(this);
261
262 bool force = true;
263 UpdateActivation(ForceActivation);
264 }
265
266 void LayerAnimationController::AddObserver(
267 LayerAnimationValueObserver* observer) {
268 if (!observers_.HasObserver(observer))
269 observers_.AddObserver(observer);
270 }
271
272 void LayerAnimationController::RemoveObserver(
273 LayerAnimationValueObserver* observer) {
274 observers_.RemoveObserver(observer);
275 }
276
277 void LayerAnimationController::PushNewAnimationsToImplThread(
278 LayerAnimationController* controller_impl) const {
279 // Any new animations owned by the main thread's controller are cloned and
280 // add to the impl thread's controller.
281 for (size_t i = 0; i < active_animations_.size(); ++i) {
282 // If the animation is already running on the impl thread, there is no
283 // need to copy it over.
284 if (controller_impl->GetAnimation(active_animations_[i]->group(),
285 active_animations_[i]->target_property()))
286 continue;
287
288 // If the animation is not running on the impl thread, it does not
289 // necessarily mean that it needs to be copied over and started; it may
290 // have already finished. In this case, the impl thread animation will
291 // have already notified that it has started and the main thread animation
292 // will no longer need
293 // a synchronized start time.
294 if (!active_animations_[i]->needs_synchronized_start_time())
295 continue;
296
297 // The new animation should be set to run as soon as possible.
298 Animation::RunState initial_run_state =
299 Animation::WaitingForTargetAvailability;
300 double start_time = 0;
301 scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize(
302 Animation::ControllingInstance, initial_run_state, start_time));
303 DCHECK(!to_add->needs_synchronized_start_time());
304 controller_impl->AddAnimation(to_add.Pass());
305 }
306 }
307
308 struct IsCompleted {
309 IsCompleted(const LayerAnimationController& main_thread_controller)
310 : main_thread_controller_(main_thread_controller) {}
311 bool operator()(Animation* animation) const {
312 if (animation->is_impl_only())
313 return false;
314 return !main_thread_controller_.GetAnimation(animation->group(),
315 animation->target_property());
316 }
317
318 private:
319 const LayerAnimationController& main_thread_controller_;
320 };
321
322 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
323 LayerAnimationController* controller_impl) const {
324 // Delete all impl thread animations for which there is no corresponding
325 // main thread animation. Each iteration,
326 // controller->active_animations_.size() is decremented or i is incremented
327 // guaranteeing progress towards loop termination.
328 ScopedPtrVector<Animation>& animations =
329 controller_impl->active_animations_;
330 animations.erase(cc::remove_if(animations,
331 animations.begin(),
332 animations.end(),
333 IsCompleted(*this)),
334 animations.end());
335 }
336
337 void LayerAnimationController::PushPropertiesToImplThread(
338 LayerAnimationController* controller_impl) const {
339 for (size_t i = 0; i < active_animations_.size(); ++i) {
340 Animation* current_impl =
341 controller_impl->GetAnimation(
342 active_animations_[i]->group(),
343 active_animations_[i]->target_property());
344 if (current_impl)
345 active_animations_[i]->PushPropertiesTo(current_impl);
346 }
347 }
348
349 void LayerAnimationController::StartAnimationsWaitingForNextTick(
350 double monotonic_time) {
351 for (size_t i = 0; i < active_animations_.size(); ++i) {
352 if (active_animations_[i]->run_state() == Animation::WaitingForNextTick)
353 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
354 }
355 }
356
357 void LayerAnimationController::StartAnimationsWaitingForStartTime(
358 double monotonic_time) {
359 for (size_t i = 0; i < active_animations_.size(); ++i) {
360 if (active_animations_[i]->run_state() == Animation::WaitingForStartTime &&
361 active_animations_[i]->start_time() <= monotonic_time)
362 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
363 }
364 }
365
366 void LayerAnimationController::StartAnimationsWaitingForTargetAvailability(
367 double monotonic_time) {
368 // First collect running properties.
369 TargetProperties blocked_properties;
370 for (size_t i = 0; i < active_animations_.size(); ++i) {
371 if (active_animations_[i]->run_state() == Animation::Starting ||
372 active_animations_[i]->run_state() == Animation::Running ||
373 active_animations_[i]->run_state() == Animation::Finished)
374 blocked_properties.insert(active_animations_[i]->target_property());
375 }
376
377 for (size_t i = 0; i < active_animations_.size(); ++i) {
378 if (active_animations_[i]->run_state() ==
379 Animation::WaitingForTargetAvailability) {
380 // Collect all properties for animations with the same group id (they
381 // should all also be in the list of animations).
382 TargetProperties enqueued_properties;
383 enqueued_properties.insert(active_animations_[i]->target_property());
384 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
385 if (active_animations_[i]->group() == active_animations_[j]->group())
386 enqueued_properties.insert(active_animations_[j]->target_property());
387 }
388
389 // Check to see if intersection of the list of properties affected by
390 // the group and the list of currently blocked properties is null. In
391 // any case, the group's target properties need to be added to the list
392 // of blocked properties.
393 bool null_intersection = true;
394 for (TargetProperties::iterator p_iter = enqueued_properties.begin();
395 p_iter != enqueued_properties.end();
396 ++p_iter) {
397 if (!blocked_properties.insert(*p_iter).second)
398 null_intersection = false;
399 }
400
401 // If the intersection is null, then we are free to start the animations
402 // in the group.
403 if (null_intersection) {
404 active_animations_[i]->SetRunState(
405 Animation::Starting, monotonic_time);
406 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
407 if (active_animations_[i]->group() ==
408 active_animations_[j]->group()) {
409 active_animations_[j]->SetRunState(
410 Animation::Starting, monotonic_time);
411 }
412 }
413 }
414 }
415 }
416 }
417
418 void LayerAnimationController::PromoteStartedAnimations(
419 double monotonic_time,
420 AnimationEventsVector* events) {
421 for (size_t i = 0; i < active_animations_.size(); ++i) {
422 if (active_animations_[i]->run_state() == Animation::Starting) {
423 active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
424 if (!active_animations_[i]->has_set_start_time())
425 active_animations_[i]->set_start_time(monotonic_time);
426 if (events) {
427 events->push_back(AnimationEvent(
428 AnimationEvent::Started,
429 id_,
430 active_animations_[i]->group(),
431 active_animations_[i]->target_property(),
432 monotonic_time));
433 }
434 }
435 }
436 }
437
438 void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) {
439 for (size_t i = 0; i < active_animations_.size(); ++i) {
440 if (active_animations_[i]->IsFinishedAt(monotonic_time))
441 active_animations_[i]->SetRunState(Animation::Finished, monotonic_time);
442 }
443 }
444
445 void LayerAnimationController::ResolveConflicts(double monotonic_time) {
446 // Find any animations that are animating the same property and resolve the
447 // confict. We could eventually blend, but for now we'll just abort the
448 // previous animation (where 'previous' means: (1) has a prior start time or
449 // (2) has an equal start time, but was added to the queue earlier, i.e.,
450 // has a lower index in active_animations_).
451 for (size_t i = 0; i < active_animations_.size(); ++i) {
452 if (active_animations_[i]->run_state() == Animation::Starting ||
453 active_animations_[i]->run_state() == Animation::Running) {
454 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
455 if ((active_animations_[j]->run_state() == Animation::Starting ||
456 active_animations_[j]->run_state() == Animation::Running) &&
457 active_animations_[i]->target_property() ==
458 active_animations_[j]->target_property()) {
459 if (active_animations_[i]->start_time() >
460 active_animations_[j]->start_time()) {
461 active_animations_[j]->SetRunState(Animation::Aborted,
462 monotonic_time);
463 } else {
464 active_animations_[i]->SetRunState(Animation::Aborted,
465 monotonic_time);
466 }
467 }
468 }
469 }
470 }
471 }
472
473 void LayerAnimationController::MarkAnimationsForDeletion(
474 double monotonic_time, AnimationEventsVector* events) {
475 for (size_t i = 0; i < active_animations_.size(); i++) {
476 int group_id = active_animations_[i]->group();
477 bool all_anims_with_same_id_are_finished = false;
478 // If an animation is finished, and not already marked for deletion,
479 // Find out if all other animations in the same group are also finished.
480 if (active_animations_[i]->is_finished() &&
481 active_animations_[i]->run_state() != Animation::WaitingForDeletion) {
482 all_anims_with_same_id_are_finished = true;
483 for (size_t j = 0; j < active_animations_.size(); ++j) {
484 if (group_id == active_animations_[j]->group() &&
485 !active_animations_[j]->is_finished()) {
486 all_anims_with_same_id_are_finished = false;
487 break;
488 }
489 }
490 }
491 if (all_anims_with_same_id_are_finished) {
492 // We now need to remove all animations with the same group id as
493 // group_id (and send along animation finished notifications, if
494 // necessary).
495 for (size_t j = i; j < active_animations_.size(); j++) {
496 if (group_id == active_animations_[j]->group()) {
497 if (events) {
498 events->push_back(AnimationEvent(
499 AnimationEvent::Finished,
500 id_,
501 active_animations_[j]->group(),
502 active_animations_[j]->target_property(),
503 monotonic_time));
504 }
505 active_animations_[j]->SetRunState(Animation::WaitingForDeletion,
506 monotonic_time);
507 }
508 }
509 }
510 }
511 }
512
513 static bool IsWaitingForDeletion(Animation* animation) {
514 return animation->run_state() == Animation::WaitingForDeletion;
515 }
516
517 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
518 ScopedPtrVector<Animation>& animations = active_animations_;
519 animations.erase(cc::remove_if(animations,
520 animations.begin(),
521 animations.end(),
522 IsWaitingForDeletion),
523 animations.end());
524 }
525
526 void LayerAnimationController::ReplaceImplThreadAnimations(
527 LayerAnimationController* controller_impl) const {
528 controller_impl->active_animations_.clear();
529 for (size_t i = 0; i < active_animations_.size(); ++i) {
530 scoped_ptr<Animation> to_add;
531 if (active_animations_[i]->needs_synchronized_start_time()) {
532 // We haven't received an animation started notification yet, so it
533 // is important that we add it in a 'waiting' and not 'running' state.
534 Animation::RunState initial_run_state =
535 Animation::WaitingForTargetAvailability;
536 double start_time = 0;
537 to_add = active_animations_[i]->CloneAndInitialize(
538 Animation::ControllingInstance,
539 initial_run_state, start_time).Pass();
100 } else { 540 } else {
101 purgeAnimationsMarkedForDeletion(); 541 to_add = active_animations_[i]->Clone(
102 pushNewAnimationsToImplThread(controllerImpl); 542 Animation::ControllingInstance).Pass();
103 543 }
104 // Remove finished impl side animations only after pushing, 544
105 // and only after the animations are deleted on the main thread 545 controller_impl->AddAnimation(to_add.Pass());
106 // this insures we will never push an animation twice. 546 }
107 removeAnimationsCompletedOnMainThread(controllerImpl); 547 }
108 548
109 pushPropertiesToImplThread(controllerImpl); 549 void LayerAnimationController::TickAnimations(double monotonic_time) {
110 } 550 for (size_t i = 0; i < active_animations_.size(); ++i) {
111 controllerImpl->updateActivation(); 551 if (active_animations_[i]->run_state() == Animation::Starting ||
112 updateActivation(); 552 active_animations_[i]->run_state() == Animation::Running ||
113 } 553 active_animations_[i]->run_state() == Animation::Paused) {
114 554 double trimmed =
115 void LayerAnimationController::animate(double monotonicTime) 555 active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
116 { 556
117 if (!hasActiveObserver()) 557 // Animation assumes its initial value until it gets the synchronized
118 return; 558 // start time from the impl thread and can start ticking.
119 559 if (active_animations_[i]->needs_synchronized_start_time())
120 startAnimationsWaitingForNextTick(monotonicTime); 560 trimmed = 0;
121 startAnimationsWaitingForStartTime(monotonicTime); 561
122 startAnimationsWaitingForTargetAvailability(monotonicTime); 562 // A just-started animation assumes its initial value.
123 resolveConflicts(monotonicTime); 563 if (active_animations_[i]->run_state() == Animation::Starting &&
124 tickAnimations(monotonicTime); 564 !active_animations_[i]->has_set_start_time())
125 m_lastTickTime = monotonicTime; 565 trimmed = 0;
126 } 566
127 567 switch (active_animations_[i]->target_property()) {
128 void LayerAnimationController::accumulatePropertyUpdates(double monotonicTime, 568
129 AnimationEventsVector* events) 569 case Animation::Transform: {
130 { 570 const TransformAnimationCurve* transform_animation_curve =
131 if (!events) 571 active_animations_[i]->curve()->ToTransformAnimationCurve();
132 return; 572 const gfx::Transform transform =
133 573 transform_animation_curve->GetValue(trimmed);
134 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { 574 NotifyObserversTransformAnimated(transform);
135 Animation* animation = m_activeAnimations[i]; 575 break;
136 if (!animation->isImplOnly())
137 continue;
138
139 if (animation->targetProperty() == Animation::Opacity) {
140 AnimationEvent event(AnimationEvent::PropertyUpdate,
141 m_id, animation->group(),
142 Animation::Opacity, monotonicTime);
143 event.opacity = animation->curve()->toFloatAnimationCurve()->getValu e(monotonicTime);
144
145 events->push_back(event);
146 } 576 }
147 else if (animation->targetProperty() == Animation::Transform) { 577
148 AnimationEvent event(AnimationEvent::PropertyUpdate, 578 case Animation::Opacity: {
149 m_id, animation->group(), 579 const FloatAnimationCurve* float_animation_curve =
150 Animation::Transform, monotonicTime); 580 active_animations_[i]->curve()->ToFloatAnimationCurve();
151 event.transform = animation->curve()->toTransformAnimationCurve()->g etValue(monotonicTime); 581 const float opacity = float_animation_curve->GetValue(trimmed);
152 events->push_back(event); 582 NotifyObserversOpacityAnimated(opacity);
583 break;
153 } 584 }
154 } 585
155 } 586 // Do nothing for sentinel value.
156 587 case Animation::TargetPropertyEnumSize:
157 void LayerAnimationController::updateState(AnimationEventsVector* events) 588 NOTREACHED();
158 { 589 }
159 if (!hasActiveObserver()) 590 }
160 return; 591 }
161 592 }
162 promoteStartedAnimations(m_lastTickTime, events); 593
163 markFinishedAnimations(m_lastTickTime); 594 void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
164 markAnimationsForDeletion(m_lastTickTime, events); 595 bool force = type == ForceActivation;
165 startAnimationsWaitingForTargetAvailability(m_lastTickTime); 596 if (registrar_) {
166 promoteStartedAnimations(m_lastTickTime, events); 597 if (!active_animations_.empty() && (!is_active_ || force))
167 598 registrar_->DidActivateAnimationController(this);
168 accumulatePropertyUpdates(m_lastTickTime, events); 599 else if (active_animations_.empty() && (is_active_ || force))
169 600 registrar_->DidDeactivateAnimationController(this);
170 updateActivation(); 601 is_active_ = !active_animations_.empty();
171 } 602 }
172 603 }
173 void LayerAnimationController::addAnimation(scoped_ptr<Animation> animation) 604
174 { 605 void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) {
175 m_activeAnimations.push_back(animation.Pass()); 606 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
176 updateActivation(); 607 observers_,
177 } 608 OnOpacityAnimated(opacity));
178 609 }
179 Animation* LayerAnimationController::getAnimation(int groupId, Animation::Target Property targetProperty) const 610
180 { 611 void LayerAnimationController::NotifyObserversTransformAnimated(
181 for (size_t i = 0; i < m_activeAnimations.size(); ++i) 612 const gfx::Transform& transform) {
182 if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]-> targetProperty() == targetProperty) 613 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
183 return m_activeAnimations[i]; 614 observers_,
184 return 0; 615 OnTransformAnimated(transform));
185 } 616 }
186 617
187 Animation* LayerAnimationController::getAnimation(Animation::TargetProperty targ etProperty) const 618 bool LayerAnimationController::HasActiveObserver() {
188 { 619 if (observers_.might_have_observers()) {
189 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { 620 ObserverListBase<LayerAnimationValueObserver>::Iterator it(observers_);
190 size_t index = m_activeAnimations.size() - i - 1; 621 LayerAnimationValueObserver* obs;
191 if (m_activeAnimations[index]->targetProperty() == targetProperty) 622 while ((obs = it.GetNext()) != NULL)
192 return m_activeAnimations[index]; 623 if (obs->IsActive())
193 } 624 return true;
194 return 0; 625 }
195 } 626 return false;
196
197 bool LayerAnimationController::hasActiveAnimation() const
198 {
199 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
200 if (!m_activeAnimations[i]->isFinished())
201 return true;
202 }
203 return false;
204 }
205
206 bool LayerAnimationController::isAnimatingProperty(Animation::TargetProperty tar getProperty) const
207 {
208 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
209 if (m_activeAnimations[i]->runState() != Animation::Finished && m_active Animations[i]->runState() != Animation::Aborted && m_activeAnimations[i]->target Property() == targetProperty)
210 return true;
211 }
212 return false;
213 }
214
215 void LayerAnimationController::OnAnimationStarted(const AnimationEvent& event)
216 {
217 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
218 if (m_activeAnimations[i]->group() == event.groupId && m_activeAnimation s[i]->targetProperty() == event.targetProperty && m_activeAnimations[i]->needsSy nchronizedStartTime()) {
219 m_activeAnimations[i]->setNeedsSynchronizedStartTime(false);
220 m_activeAnimations[i]->setStartTime(event.monotonicTime);
221 return;
222 }
223 }
224 }
225
226 void LayerAnimationController::setAnimationRegistrar(AnimationRegistrar* registr ar)
227 {
228 if (m_registrar == registrar)
229 return;
230
231 if (m_registrar)
232 m_registrar->UnregisterAnimationController(this);
233
234 m_registrar = registrar;
235 if (m_registrar)
236 m_registrar->RegisterAnimationController(this);
237
238 bool force = true;
239 updateActivation(force);
240 }
241
242 void LayerAnimationController::addObserver(LayerAnimationValueObserver* observer )
243 {
244 if (!m_observers.HasObserver(observer))
245 m_observers.AddObserver(observer);
246 }
247
248 void LayerAnimationController::removeObserver(LayerAnimationValueObserver* obser ver)
249 {
250 m_observers.RemoveObserver(observer);
251 }
252
253 void LayerAnimationController::pushNewAnimationsToImplThread(LayerAnimationContr oller* controllerImpl) const
254 {
255 // Any new animations owned by the main thread's controller are cloned and a dde to the impl thread's controller.
256 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
257 // If the animation is already running on the impl thread, there is no n eed to copy it over.
258 if (controllerImpl->getAnimation(m_activeAnimations[i]->group(), m_activ eAnimations[i]->targetProperty()))
259 continue;
260
261 // If the animation is not running on the impl thread, it does not neces sarily mean that it needs
262 // to be copied over and started; it may have already finished. In this case, the impl thread animation
263 // will have already notified that it has started and the main thread an imation will no longer need
264 // a synchronized start time.
265 if (!m_activeAnimations[i]->needsSynchronizedStartTime())
266 continue;
267
268 // The new animation should be set to run as soon as possible.
269 Animation::RunState initialRunState = Animation::WaitingForTargetAvailab ility;
270 double startTime = 0;
271 scoped_ptr<Animation> toAdd(m_activeAnimations[i]->cloneAndInitialize(An imation::ControllingInstance, initialRunState, startTime));
272 DCHECK(!toAdd->needsSynchronizedStartTime());
273 controllerImpl->addAnimation(toAdd.Pass());
274 }
275 }
276
277 struct IsCompleted {
278 IsCompleted(const LayerAnimationController& mainThreadController) : m_mainTh readController(mainThreadController) { }
279 bool operator()(Animation* animation) const {
280 if (animation->isImplOnly())
281 return false;
282 return !m_mainThreadController.getAnimation(animation->group(), animatio n->targetProperty()); }
283 private:
284 const LayerAnimationController& m_mainThreadController;
285 };
286
287 void LayerAnimationController::removeAnimationsCompletedOnMainThread(LayerAnimat ionController* controllerImpl) const
288 {
289 // Delete all impl thread animations for which there is no corresponding mai n thread animation.
290 // Each iteration, controller->m_activeAnimations.size() is decremented or i is incremented
291 // guaranteeing progress towards loop termination.
292 ScopedPtrVector<Animation>& animations = controllerImpl->m_activeAnimations;
293 animations.erase(cc::remove_if(animations, animations.begin(), animations.en d(), IsCompleted(*this)), animations.end());
294 }
295
296 void LayerAnimationController::pushPropertiesToImplThread(LayerAnimationControll er* controllerImpl) const
297 {
298 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
299 Animation* currentImpl = controllerImpl->getAnimation(m_activeAnimations [i]->group(), m_activeAnimations[i]->targetProperty());
300 if (currentImpl)
301 m_activeAnimations[i]->pushPropertiesTo(currentImpl);
302 }
303 }
304
305 void LayerAnimationController::startAnimationsWaitingForNextTick(double monotoni cTime)
306 {
307 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
308 if (m_activeAnimations[i]->runState() == Animation::WaitingForNextTick)
309 m_activeAnimations[i]->setRunState(Animation::Starting, monotonicTim e);
310 }
311 }
312
313 void LayerAnimationController::startAnimationsWaitingForStartTime(double monoton icTime)
314 {
315 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
316 if (m_activeAnimations[i]->runState() == Animation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime)
317 m_activeAnimations[i]->setRunState(Animation::Starting, monotonicTim e);
318 }
319 }
320
321 void LayerAnimationController::startAnimationsWaitingForTargetAvailability(doubl e monotonicTime)
322 {
323 // First collect running properties.
324 TargetProperties blockedProperties;
325 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
326 if (m_activeAnimations[i]->runState() == Animation::Starting || m_active Animations[i]->runState() == Animation::Running || m_activeAnimations[i]->runSta te() == Animation::Finished)
327 blockedProperties.insert(m_activeAnimations[i]->targetProperty());
328 }
329
330 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
331 if (m_activeAnimations[i]->runState() == Animation::WaitingForTargetAvai lability) {
332 // Collect all properties for animations with the same group id (the y should all also be in the list of animations).
333 TargetProperties enqueuedProperties;
334 enqueuedProperties.insert(m_activeAnimations[i]->targetProperty());
335 for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
336 if (m_activeAnimations[i]->group() == m_activeAnimations[j]->gro up())
337 enqueuedProperties.insert(m_activeAnimations[j]->targetPrope rty());
338 }
339
340 // Check to see if intersection of the list of properties affected b y the group and the list of currently
341 // blocked properties is null. In any case, the group's target prope rties need to be added to the list
342 // of blocked properties.
343 bool nullIntersection = true;
344 for (TargetProperties::iterator pIter = enqueuedProperties.begin(); pIter != enqueuedProperties.end(); ++pIter) {
345 if (!blockedProperties.insert(*pIter).second)
346 nullIntersection = false;
347 }
348
349 // If the intersection is null, then we are free to start the animat ions in the group.
350 if (nullIntersection) {
351 m_activeAnimations[i]->setRunState(Animation::Starting, monotoni cTime);
352 for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
353 if (m_activeAnimations[i]->group() == m_activeAnimations[j]- >group())
354 m_activeAnimations[j]->setRunState(Animation::Starting, monotonicTime);
355 }
356 }
357 }
358 }
359 }
360
361 void LayerAnimationController::promoteStartedAnimations(double monotonicTime, An imationEventsVector* events)
362 {
363 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
364 if (m_activeAnimations[i]->runState() == Animation::Starting) {
365 m_activeAnimations[i]->setRunState(Animation::Running, monotonicTime );
366 if (!m_activeAnimations[i]->hasSetStartTime())
367 m_activeAnimations[i]->setStartTime(monotonicTime);
368 if (events)
369 events->push_back(AnimationEvent(AnimationEvent::Started, m_id, m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monoton icTime));
370 }
371 }
372 }
373
374 void LayerAnimationController::markFinishedAnimations(double monotonicTime)
375 {
376 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
377 if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
378 m_activeAnimations[i]->setRunState(Animation::Finished, monotonicTim e);
379 }
380 }
381
382 void LayerAnimationController::resolveConflicts(double monotonicTime)
383 {
384 // Find any animations that are animating the same property and resolve the
385 // confict. We could eventually blend, but for now we'll just abort the
386 // previous animation (where 'previous' means: (1) has a prior start time or
387 // (2) has an equal start time, but was added to the queue earlier, i.e.,
388 // has a lower index in m_activeAnimations).
389 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
390 if (m_activeAnimations[i]->runState() == Animation::Starting || m_active Animations[i]->runState() == Animation::Running) {
391 for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
392 if ((m_activeAnimations[j]->runState() == Animation::Starting ||
393 m_activeAnimations[j]->runState() == Animation::Running) &&
394 m_activeAnimations[i]->targetProperty() == m_activeAnimation s[j]->targetProperty()) {
395 if (m_activeAnimations[i]->startTime() > m_activeAnimations[ j]->startTime())
396 m_activeAnimations[j]->setRunState(Animation::Aborted, m onotonicTime);
397 else
398 m_activeAnimations[i]->setRunState(Animation::Aborted, m onotonicTime);
399 }
400 }
401 }
402 }
403 }
404
405 void LayerAnimationController::markAnimationsForDeletion(double monotonicTime, A nimationEventsVector* events)
406 {
407 for (size_t i = 0; i < m_activeAnimations.size(); i++) {
408 int groupId = m_activeAnimations[i]->group();
409 bool allAnimsWithSameIdAreFinished = false;
410 // If an animation is finished, and not already marked for deletion,
411 // Find out if all other animations in the same group are also finished.
412 if (m_activeAnimations[i]->isFinished() && m_activeAnimations[i]->runSta te() != Animation::WaitingForDeletion) {
413 allAnimsWithSameIdAreFinished = true;
414 for (size_t j = 0; j < m_activeAnimations.size(); ++j) {
415 if (groupId == m_activeAnimations[j]->group() && !m_activeAnimat ions[j]->isFinished()) {
416 allAnimsWithSameIdAreFinished = false;
417 break;
418 }
419 }
420 }
421 if (allAnimsWithSameIdAreFinished) {
422 // We now need to remove all animations with the same group id as gr oupId
423 // (and send along animation finished notifications, if necessary).
424 for (size_t j = i; j < m_activeAnimations.size(); j++) {
425 if (groupId == m_activeAnimations[j]->group()) {
426 if (events)
427 events->push_back(AnimationEvent(AnimationEvent::Finishe d, m_id, m_activeAnimations[j]->group(), m_activeAnimations[j]->targetProperty() , monotonicTime));
428 m_activeAnimations[j]->setRunState(Animation::WaitingForDele tion, monotonicTime);
429 }
430 }
431 }
432 }
433 }
434
435 static bool isWaitingForDeletion(Animation* animation) { return animation->runSt ate() == Animation::WaitingForDeletion; }
436
437 void LayerAnimationController::purgeAnimationsMarkedForDeletion()
438 {
439 ScopedPtrVector<Animation>& animations = m_activeAnimations;
440 animations.erase(cc::remove_if(animations, animations.begin(), animations.en d(), isWaitingForDeletion), animations.end());
441 }
442
443 void LayerAnimationController::replaceImplThreadAnimations(LayerAnimationControl ler* controllerImpl) const
444 {
445 controllerImpl->m_activeAnimations.clear();
446 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
447 scoped_ptr<Animation> toAdd;
448 if (m_activeAnimations[i]->needsSynchronizedStartTime()) {
449 // We haven't received an animation started notification yet, so it
450 // is important that we add it in a 'waiting' and not 'running' stat e.
451 Animation::RunState initialRunState = Animation::WaitingForTargetAva ilability;
452 double startTime = 0;
453 toAdd = m_activeAnimations[i]->cloneAndInitialize(Animation::Control lingInstance, initialRunState, startTime).Pass();
454 } else
455 toAdd = m_activeAnimations[i]->clone(Animation::ControllingInstance) .Pass();
456
457 controllerImpl->addAnimation(toAdd.Pass());
458 }
459 }
460
461 void LayerAnimationController::tickAnimations(double monotonicTime)
462 {
463 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
464 if (m_activeAnimations[i]->runState() == Animation::Starting ||
465 m_activeAnimations[i]->runState() == Animation::Running ||
466 m_activeAnimations[i]->runState() == Animation::Paused) {
467 double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(m onotonicTime);
468
469 // Animation assumes its initial value until it gets the synchronize d start time
470 // from the impl thread and can start ticking.
471 if (m_activeAnimations[i]->needsSynchronizedStartTime())
472 trimmed = 0;
473
474 // A just-started animation assumes its initial value.
475 if (m_activeAnimations[i]->runState() == Animation::Starting && !m_a ctiveAnimations[i]->hasSetStartTime())
476 trimmed = 0;
477
478 switch (m_activeAnimations[i]->targetProperty()) {
479
480 case Animation::Transform: {
481 const TransformAnimationCurve* transformAnimationCurve = m_activ eAnimations[i]->curve()->toTransformAnimationCurve();
482 const gfx::Transform transform = transformAnimationCurve->getVal ue(trimmed);
483 notifyObserversTransformAnimated(transform);
484 break;
485 }
486
487 case Animation::Opacity: {
488 const FloatAnimationCurve* floatAnimationCurve = m_activeAnimati ons[i]->curve()->toFloatAnimationCurve();
489 const float opacity = floatAnimationCurve->getValue(trimmed);
490 notifyObserversOpacityAnimated(opacity);
491 break;
492 }
493
494 // Do nothing for sentinel value.
495 case Animation::TargetPropertyEnumSize:
496 NOTREACHED();
497 }
498 }
499 }
500 }
501
502 void LayerAnimationController::updateActivation(bool force)
503 {
504 if (m_registrar) {
505 if (!m_activeAnimations.empty() && (!m_isActive || force))
506 m_registrar->DidActivateAnimationController(this);
507 else if (m_activeAnimations.empty() && (m_isActive || force))
508 m_registrar->DidDeactivateAnimationController(this);
509 m_isActive = !m_activeAnimations.empty();
510 }
511 }
512
513 void LayerAnimationController::notifyObserversOpacityAnimated(float opacity)
514 {
515 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
516 m_observers,
517 OnOpacityAnimated(opacity));
518 }
519
520 void LayerAnimationController::notifyObserversTransformAnimated(const gfx::Trans form& transform)
521 {
522 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
523 m_observers,
524 OnTransformAnimated(transform));
525 }
526
527 bool LayerAnimationController::hasActiveObserver()
528 {
529 if (m_observers.might_have_observers()) {
530 ObserverListBase<LayerAnimationValueObserver>::Iterator it(m_observers);
531 LayerAnimationValueObserver* obs;
532 while ((obs = it.GetNext()) != NULL)
533 if (obs->IsActive())
534 return true;
535 }
536 return false;
537 } 627 }
538 628
539 } // namespace cc 629 } // namespace cc
OLDNEW
« no previous file with comments | « cc/layer_animation_controller.h ('k') | cc/layer_animation_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698