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
3 // found in the LICENSE file.
5 #include "cc/animation/layer_animation_controller.h"
9 #include "cc/animation/animation.h"
10 #include "cc/animation/animation_registrar.h"
11 #include "cc/animation/keyframed_animation_curve.h"
12 #include "cc/animation/layer_animation_value_observer.h"
13 #include "cc/base/scoped_ptr_algorithm.h"
14 #include "third_party/WebKit/Source/Platform/chromium/public/WebAnimationDelegate.h"
15 #include "ui/gfx/transform.h"
19 LayerAnimationController::LayerAnimationController(int id
)
25 layer_animation_delegate_(NULL
) {}
27 LayerAnimationController::~LayerAnimationController() {
29 registrar_
->UnregisterAnimationController(this);
32 scoped_refptr
<LayerAnimationController
> LayerAnimationController::Create(
34 return make_scoped_refptr(new LayerAnimationController(id
));
37 void LayerAnimationController::PauseAnimation(int animation_id
,
39 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
40 if (active_animations_
[i
]->id() == animation_id
) {
41 active_animations_
[i
]->SetRunState(
42 Animation::Paused
, time_offset
+ active_animations_
[i
]->start_time());
47 struct HasAnimationId
{
48 explicit HasAnimationId(int id
) : id_(id
) {}
49 bool operator()(Animation
* animation
) const {
50 return animation
->id() == id_
;
57 void LayerAnimationController::RemoveAnimation(int animation_id
) {
58 ScopedPtrVector
<Animation
>& animations
= active_animations_
;
59 animations
.erase(cc::remove_if(&animations
,
62 HasAnimationId(animation_id
)),
64 UpdateActivation(NormalActivation
);
67 struct HasAnimationIdAndProperty
{
68 HasAnimationIdAndProperty(int id
, Animation::TargetProperty target_property
)
69 : id_(id
), target_property_(target_property
) {}
70 bool operator()(Animation
* animation
) const {
71 return animation
->id() == id_
&&
72 animation
->target_property() == target_property_
;
77 Animation::TargetProperty target_property_
;
80 void LayerAnimationController::RemoveAnimation(
82 Animation::TargetProperty target_property
) {
83 ScopedPtrVector
<Animation
>& animations
= active_animations_
;
84 animations
.erase(cc::remove_if(&animations
,
87 HasAnimationIdAndProperty(animation_id
,
90 UpdateActivation(NormalActivation
);
93 // According to render layer backing, these are for testing only.
94 void LayerAnimationController::SuspendAnimations(double monotonic_time
) {
95 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
96 if (!active_animations_
[i
]->is_finished())
97 active_animations_
[i
]->SetRunState(Animation::Paused
, monotonic_time
);
101 // Looking at GraphicsLayerCA, this appears to be the analog to
102 // SuspendAnimations, which is for testing.
103 void LayerAnimationController::ResumeAnimations(double monotonic_time
) {
104 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
105 if (active_animations_
[i
]->run_state() == Animation::Paused
)
106 active_animations_
[i
]->SetRunState(Animation::Running
, monotonic_time
);
110 // Ensures that the list of active animations on the main thread and the impl
111 // thread are kept in sync.
112 void LayerAnimationController::PushAnimationUpdatesTo(
113 LayerAnimationController
* controller_impl
) {
114 DCHECK(this != controller_impl
);
116 ReplaceImplThreadAnimations(controller_impl
);
119 PurgeAnimationsMarkedForDeletion();
120 PushNewAnimationsToImplThread(controller_impl
);
122 // Remove finished impl side animations only after pushing,
123 // and only after the animations are deleted on the main thread
124 // this insures we will never push an animation twice.
125 RemoveAnimationsCompletedOnMainThread(controller_impl
);
127 PushPropertiesToImplThread(controller_impl
);
129 controller_impl
->UpdateActivation(NormalActivation
);
130 UpdateActivation(NormalActivation
);
133 void LayerAnimationController::TransferAnimationsTo(
134 LayerAnimationController
* other_controller
) {
135 other_controller
->active_animations_
.clear();
136 active_animations_
.swap(other_controller
->active_animations_
);
137 UpdateActivation(NormalActivation
);
139 other_controller
->UpdateActivation(NormalActivation
);
140 other_controller
->set_force_sync();
141 other_controller
->SetAnimationRegistrar(registrar_
);
144 void LayerAnimationController::Animate(double monotonic_time
) {
145 if (!HasActiveValueObserver())
148 StartAnimationsWaitingForNextTick(monotonic_time
);
149 StartAnimationsWaitingForStartTime(monotonic_time
);
150 StartAnimationsWaitingForTargetAvailability(monotonic_time
);
151 ResolveConflicts(monotonic_time
);
152 TickAnimations(monotonic_time
);
153 last_tick_time_
= monotonic_time
;
156 void LayerAnimationController::AccumulatePropertyUpdates(
157 double monotonic_time
,
158 AnimationEventsVector
* events
) {
162 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
163 Animation
* animation
= active_animations_
[i
];
164 if (!animation
->is_impl_only())
167 if (animation
->target_property() == Animation::Opacity
) {
168 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
173 event
.opacity
= animation
->curve()->ToFloatAnimationCurve()->GetValue(
176 events
->push_back(event
);
177 } else if (animation
->target_property() == Animation::Transform
) {
178 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
181 Animation::Transform
,
184 animation
->curve()->ToTransformAnimationCurve()->GetValue(
186 events
->push_back(event
);
191 void LayerAnimationController::UpdateState(bool start_ready_animations
,
192 AnimationEventsVector
* events
) {
193 if (!HasActiveValueObserver())
196 if (start_ready_animations
)
197 PromoteStartedAnimations(last_tick_time_
, events
);
199 MarkFinishedAnimations(last_tick_time_
);
200 MarkAnimationsForDeletion(last_tick_time_
, events
);
202 if (start_ready_animations
) {
203 StartAnimationsWaitingForTargetAvailability(last_tick_time_
);
204 PromoteStartedAnimations(last_tick_time_
, events
);
207 AccumulatePropertyUpdates(last_tick_time_
, events
);
209 UpdateActivation(NormalActivation
);
212 void LayerAnimationController::AddAnimation(scoped_ptr
<Animation
> animation
) {
213 active_animations_
.push_back(animation
.Pass());
214 UpdateActivation(NormalActivation
);
217 Animation
* LayerAnimationController::GetAnimation(
219 Animation::TargetProperty target_property
) const {
220 for (size_t i
= 0; i
< active_animations_
.size(); ++i
)
221 if (active_animations_
[i
]->group() == group_id
&&
222 active_animations_
[i
]->target_property() == target_property
)
223 return active_animations_
[i
];
227 Animation
* LayerAnimationController::GetAnimation(
228 Animation::TargetProperty target_property
) const {
229 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
230 size_t index
= active_animations_
.size() - i
- 1;
231 if (active_animations_
[index
]->target_property() == target_property
)
232 return active_animations_
[index
];
237 bool LayerAnimationController::HasActiveAnimation() const {
238 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
239 if (!active_animations_
[i
]->is_finished())
245 bool LayerAnimationController::IsAnimatingProperty(
246 Animation::TargetProperty target_property
) const {
247 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
248 if (!active_animations_
[i
]->is_finished() &&
249 active_animations_
[i
]->target_property() == target_property
)
255 void LayerAnimationController::SetAnimationRegistrar(
256 AnimationRegistrar
* registrar
) {
257 if (registrar_
== registrar
)
261 registrar_
->UnregisterAnimationController(this);
263 registrar_
= registrar
;
265 registrar_
->RegisterAnimationController(this);
267 UpdateActivation(ForceActivation
);
270 void LayerAnimationController::NotifyAnimationStarted(
271 const AnimationEvent
& event
,
272 double wall_clock_time
) {
273 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
274 if (active_animations_
[i
]->group() == event
.group_id
&&
275 active_animations_
[i
]->target_property() == event
.target_property
&&
276 active_animations_
[i
]->needs_synchronized_start_time()) {
277 active_animations_
[i
]->set_needs_synchronized_start_time(false);
278 active_animations_
[i
]->set_start_time(event
.monotonic_time
);
280 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
281 OnAnimationStarted(event
));
282 if (layer_animation_delegate_
)
283 layer_animation_delegate_
->notifyAnimationStarted(wall_clock_time
);
290 void LayerAnimationController::NotifyAnimationFinished(
291 const AnimationEvent
& event
,
292 double wall_clock_time
) {
293 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
294 if (active_animations_
[i
]->group() == event
.group_id
&&
295 active_animations_
[i
]->target_property() == event
.target_property
) {
296 active_animations_
[i
]->set_received_finished_event(true);
297 if (layer_animation_delegate_
)
298 layer_animation_delegate_
->notifyAnimationFinished(wall_clock_time
);
305 void LayerAnimationController::NotifyAnimationPropertyUpdate(
306 const AnimationEvent
& event
) {
307 switch (event
.target_property
) {
308 case Animation::Opacity
:
309 NotifyObserversOpacityAnimated(event
.opacity
);
311 case Animation::Transform
:
312 NotifyObserversTransformAnimated(event
.transform
);
319 void LayerAnimationController::AddValueObserver(
320 LayerAnimationValueObserver
* observer
) {
321 if (!value_observers_
.HasObserver(observer
))
322 value_observers_
.AddObserver(observer
);
325 void LayerAnimationController::RemoveValueObserver(
326 LayerAnimationValueObserver
* observer
) {
327 value_observers_
.RemoveObserver(observer
);
330 void LayerAnimationController::AddEventObserver(
331 LayerAnimationEventObserver
* observer
) {
332 if (!event_observers_
.HasObserver(observer
))
333 event_observers_
.AddObserver(observer
);
336 void LayerAnimationController::RemoveEventObserver(
337 LayerAnimationEventObserver
* observer
) {
338 event_observers_
.RemoveObserver(observer
);
341 void LayerAnimationController::PushNewAnimationsToImplThread(
342 LayerAnimationController
* controller_impl
) const {
343 // Any new animations owned by the main thread's controller are cloned and
344 // add to the impl thread's controller.
345 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
346 // If the animation is already running on the impl thread, there is no
347 // need to copy it over.
348 if (controller_impl
->GetAnimation(active_animations_
[i
]->group(),
349 active_animations_
[i
]->target_property()))
352 // If the animation is not running on the impl thread, it does not
353 // necessarily mean that it needs to be copied over and started; it may
354 // have already finished. In this case, the impl thread animation will
355 // have already notified that it has started and the main thread animation
356 // will no longer need
357 // a synchronized start time.
358 if (!active_animations_
[i
]->needs_synchronized_start_time())
361 // The new animation should be set to run as soon as possible.
362 Animation::RunState initial_run_state
=
363 Animation::WaitingForTargetAvailability
;
364 double start_time
= 0;
365 scoped_ptr
<Animation
> to_add(active_animations_
[i
]->CloneAndInitialize(
366 Animation::ControllingInstance
, initial_run_state
, start_time
));
367 DCHECK(!to_add
->needs_synchronized_start_time());
368 controller_impl
->AddAnimation(to_add
.Pass());
373 explicit IsCompleted(const LayerAnimationController
& main_thread_controller
)
374 : main_thread_controller_(main_thread_controller
) {}
375 bool operator()(Animation
* animation
) const {
376 if (animation
->is_impl_only()) {
377 return (animation
->run_state() == Animation::WaitingForDeletion
);
379 return !main_thread_controller_
.GetAnimation(
381 animation
->target_property());
386 const LayerAnimationController
& main_thread_controller_
;
389 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
390 LayerAnimationController
* controller_impl
) const {
391 // Delete all impl thread animations for which there is no corresponding
392 // main thread animation. Each iteration,
393 // controller->active_animations_.size() is decremented or i is incremented
394 // guaranteeing progress towards loop termination.
395 ScopedPtrVector
<Animation
>& animations
=
396 controller_impl
->active_animations_
;
397 animations
.erase(cc::remove_if(&animations
,
404 void LayerAnimationController::PushPropertiesToImplThread(
405 LayerAnimationController
* controller_impl
) const {
406 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
407 Animation
* current_impl
=
408 controller_impl
->GetAnimation(
409 active_animations_
[i
]->group(),
410 active_animations_
[i
]->target_property());
412 active_animations_
[i
]->PushPropertiesTo(current_impl
);
416 void LayerAnimationController::StartAnimationsWaitingForNextTick(
417 double monotonic_time
) {
418 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
419 if (active_animations_
[i
]->run_state() == Animation::WaitingForNextTick
)
420 active_animations_
[i
]->SetRunState(Animation::Starting
, monotonic_time
);
424 void LayerAnimationController::StartAnimationsWaitingForStartTime(
425 double monotonic_time
) {
426 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
427 if (active_animations_
[i
]->run_state() == Animation::WaitingForStartTime
&&
428 active_animations_
[i
]->start_time() <= monotonic_time
)
429 active_animations_
[i
]->SetRunState(Animation::Starting
, monotonic_time
);
433 void LayerAnimationController::StartAnimationsWaitingForTargetAvailability(
434 double monotonic_time
) {
435 // First collect running properties.
436 TargetProperties blocked_properties
;
437 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
438 if (active_animations_
[i
]->run_state() == Animation::Starting
||
439 active_animations_
[i
]->run_state() == Animation::Running
)
440 blocked_properties
.insert(active_animations_
[i
]->target_property());
443 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
444 if (active_animations_
[i
]->run_state() ==
445 Animation::WaitingForTargetAvailability
) {
446 // Collect all properties for animations with the same group id (they
447 // should all also be in the list of animations).
448 TargetProperties enqueued_properties
;
449 enqueued_properties
.insert(active_animations_
[i
]->target_property());
450 for (size_t j
= i
+ 1; j
< active_animations_
.size(); ++j
) {
451 if (active_animations_
[i
]->group() == active_animations_
[j
]->group())
452 enqueued_properties
.insert(active_animations_
[j
]->target_property());
455 // Check to see if intersection of the list of properties affected by
456 // the group and the list of currently blocked properties is null. In
457 // any case, the group's target properties need to be added to the list
458 // of blocked properties.
459 bool null_intersection
= true;
460 for (TargetProperties::iterator p_iter
= enqueued_properties
.begin();
461 p_iter
!= enqueued_properties
.end();
463 if (!blocked_properties
.insert(*p_iter
).second
)
464 null_intersection
= false;
467 // If the intersection is null, then we are free to start the animations
469 if (null_intersection
) {
470 active_animations_
[i
]->SetRunState(
471 Animation::Starting
, monotonic_time
);
472 for (size_t j
= i
+ 1; j
< active_animations_
.size(); ++j
) {
473 if (active_animations_
[i
]->group() ==
474 active_animations_
[j
]->group()) {
475 active_animations_
[j
]->SetRunState(
476 Animation::Starting
, monotonic_time
);
484 void LayerAnimationController::PromoteStartedAnimations(
485 double monotonic_time
,
486 AnimationEventsVector
* events
) {
487 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
488 if (active_animations_
[i
]->run_state() == Animation::Starting
) {
489 active_animations_
[i
]->SetRunState(Animation::Running
, monotonic_time
);
490 if (!active_animations_
[i
]->has_set_start_time())
491 active_animations_
[i
]->set_start_time(monotonic_time
);
493 events
->push_back(AnimationEvent(
494 AnimationEvent::Started
,
496 active_animations_
[i
]->group(),
497 active_animations_
[i
]->target_property(),
504 void LayerAnimationController::MarkFinishedAnimations(double monotonic_time
) {
505 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
506 if (active_animations_
[i
]->IsFinishedAt(monotonic_time
) &&
507 active_animations_
[i
]->run_state() != Animation::WaitingForDeletion
)
508 active_animations_
[i
]->SetRunState(Animation::Finished
, monotonic_time
);
512 void LayerAnimationController::ResolveConflicts(double monotonic_time
) {
513 // Find any animations that are animating the same property and resolve the
514 // confict. We could eventually blend, but for now we'll just abort the
515 // previous animation (where 'previous' means: (1) has a prior start time or
516 // (2) has an equal start time, but was added to the queue earlier, i.e.,
517 // has a lower index in active_animations_).
518 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
519 if (active_animations_
[i
]->run_state() == Animation::Starting
||
520 active_animations_
[i
]->run_state() == Animation::Running
) {
521 for (size_t j
= i
+ 1; j
< active_animations_
.size(); ++j
) {
522 if ((active_animations_
[j
]->run_state() == Animation::Starting
||
523 active_animations_
[j
]->run_state() == Animation::Running
) &&
524 active_animations_
[i
]->target_property() ==
525 active_animations_
[j
]->target_property()) {
526 if (active_animations_
[i
]->start_time() >
527 active_animations_
[j
]->start_time()) {
528 active_animations_
[j
]->SetRunState(Animation::Aborted
,
531 active_animations_
[i
]->SetRunState(Animation::Aborted
,
540 void LayerAnimationController::MarkAnimationsForDeletion(
541 double monotonic_time
, AnimationEventsVector
* events
) {
542 // Non-aborted animations are marked for deletion after a corresponding
543 // AnimationEvent::Finished event is sent or received. This means that if
544 // we don't have an events vector, we must ensure that non-aborted animations
545 // have received a finished event before marking them for deletion.
546 for (size_t i
= 0; i
< active_animations_
.size(); i
++) {
547 int group_id
= active_animations_
[i
]->group();
548 bool all_anims_with_same_id_are_finished
= false;
550 // Since deleting an animation on the main thread leads to its deletion
551 // on the impl thread, we only mark a Finished main thread animation for
552 // deletion once it has received a Finished event from the impl thread.
553 bool animation_i_will_send_or_has_received_finish_event
=
554 events
|| active_animations_
[i
]->received_finished_event();
555 // If an animation is finished, and not already marked for deletion,
556 // find out if all other animations in the same group are also finished.
557 if (active_animations_
[i
]->run_state() == Animation::Aborted
||
558 (active_animations_
[i
]->run_state() == Animation::Finished
&&
559 animation_i_will_send_or_has_received_finish_event
)) {
560 all_anims_with_same_id_are_finished
= true;
561 for (size_t j
= 0; j
< active_animations_
.size(); ++j
) {
562 bool animation_j_will_send_or_has_received_finish_event
=
563 events
|| active_animations_
[j
]->received_finished_event();
564 if (group_id
== active_animations_
[j
]->group() &&
565 (!active_animations_
[j
]->is_finished() ||
566 (active_animations_
[j
]->run_state() == Animation::Finished
&&
567 !animation_j_will_send_or_has_received_finish_event
))) {
568 all_anims_with_same_id_are_finished
= false;
573 if (all_anims_with_same_id_are_finished
) {
574 // We now need to remove all animations with the same group id as
575 // group_id (and send along animation finished notifications, if
577 for (size_t j
= i
; j
< active_animations_
.size(); j
++) {
578 if (group_id
== active_animations_
[j
]->group()) {
580 events
->push_back(AnimationEvent(
581 AnimationEvent::Finished
,
583 active_animations_
[j
]->group(),
584 active_animations_
[j
]->target_property(),
587 active_animations_
[j
]->SetRunState(Animation::WaitingForDeletion
,
595 static bool IsWaitingForDeletion(Animation
* animation
) {
596 return animation
->run_state() == Animation::WaitingForDeletion
;
599 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
600 ScopedPtrVector
<Animation
>& animations
= active_animations_
;
601 animations
.erase(cc::remove_if(&animations
,
604 IsWaitingForDeletion
),
608 void LayerAnimationController::ReplaceImplThreadAnimations(
609 LayerAnimationController
* controller_impl
) const {
610 controller_impl
->active_animations_
.clear();
611 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
612 scoped_ptr
<Animation
> to_add
;
613 if (active_animations_
[i
]->needs_synchronized_start_time()) {
614 // We haven't received an animation started notification yet, so it
615 // is important that we add it in a 'waiting' and not 'running' state.
616 Animation::RunState initial_run_state
=
617 Animation::WaitingForTargetAvailability
;
618 double start_time
= 0;
619 to_add
= active_animations_
[i
]->CloneAndInitialize(
620 Animation::ControllingInstance
,
621 initial_run_state
, start_time
).Pass();
623 to_add
= active_animations_
[i
]->Clone(
624 Animation::ControllingInstance
).Pass();
627 controller_impl
->AddAnimation(to_add
.Pass());
631 void LayerAnimationController::TickAnimations(double monotonic_time
) {
632 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
633 if (active_animations_
[i
]->run_state() == Animation::Starting
||
634 active_animations_
[i
]->run_state() == Animation::Running
||
635 active_animations_
[i
]->run_state() == Animation::Paused
) {
637 active_animations_
[i
]->TrimTimeToCurrentIteration(monotonic_time
);
639 // Animation assumes its initial value until it gets the synchronized
640 // start time from the impl thread and can start ticking.
641 if (active_animations_
[i
]->needs_synchronized_start_time())
644 // A just-started animation assumes its initial value.
645 if (active_animations_
[i
]->run_state() == Animation::Starting
&&
646 !active_animations_
[i
]->has_set_start_time())
649 switch (active_animations_
[i
]->target_property()) {
650 case Animation::Transform
: {
651 const TransformAnimationCurve
* transform_animation_curve
=
652 active_animations_
[i
]->curve()->ToTransformAnimationCurve();
653 const gfx::Transform transform
=
654 transform_animation_curve
->GetValue(trimmed
);
655 NotifyObserversTransformAnimated(transform
);
659 case Animation::Opacity
: {
660 const FloatAnimationCurve
* float_animation_curve
=
661 active_animations_
[i
]->curve()->ToFloatAnimationCurve();
662 const float opacity
= float_animation_curve
->GetValue(trimmed
);
663 NotifyObserversOpacityAnimated(opacity
);
667 // Do nothing for sentinel value.
668 case Animation::TargetPropertyEnumSize
:
675 void LayerAnimationController::UpdateActivation(UpdateActivationType type
) {
676 bool force
= type
== ForceActivation
;
678 if (!active_animations_
.empty() && (!is_active_
|| force
))
679 registrar_
->DidActivateAnimationController(this);
680 else if (active_animations_
.empty() && (is_active_
|| force
))
681 registrar_
->DidDeactivateAnimationController(this);
682 is_active_
= !active_animations_
.empty();
686 void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity
) {
687 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
689 OnOpacityAnimated(opacity
));
692 void LayerAnimationController::NotifyObserversTransformAnimated(
693 const gfx::Transform
& transform
) {
694 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
696 OnTransformAnimated(transform
));
699 bool LayerAnimationController::HasActiveValueObserver() {
700 if (value_observers_
.might_have_observers()) {
701 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
703 LayerAnimationValueObserver
* obs
;
704 while ((obs
= it
.GetNext()) != NULL
)