Fix compilation error triggered with -Werror=sign-compare
[chromium-blink-merge.git] / ui / compositor / layer_animator.cc
blob39585a7c946e5a7656d46f02739826e1754e8a69
1 // Copyright (c) 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 "ui/compositor/layer_animator.h"
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "cc/animation/animation_id_provider.h"
11 #include "cc/output/begin_frame_args.h"
12 #include "ui/compositor/compositor.h"
13 #include "ui/compositor/layer.h"
14 #include "ui/compositor/layer_animation_delegate.h"
15 #include "ui/compositor/layer_animation_observer.h"
16 #include "ui/compositor/layer_animation_sequence.h"
17 #include "ui/compositor/layer_animator_collection.h"
18 #include "ui/gfx/frame_time.h"
20 #define SAFE_INVOKE_VOID(function, running_anim, ...) \
21 if (running_anim.is_sequence_alive()) \
22 function(running_anim.sequence(), ##__VA_ARGS__)
23 #define SAFE_INVOKE_BOOL(function, running_anim) \
24 ((running_anim.is_sequence_alive()) \
25 ? function(running_anim.sequence()) \
26 : false)
27 #define SAFE_INVOKE_PTR(function, running_anim) \
28 ((running_anim.is_sequence_alive()) \
29 ? function(running_anim.sequence()) \
30 : NULL)
32 namespace ui {
34 namespace {
36 const int kDefaultTransitionDurationMs = 120;
38 } // namespace
40 // LayerAnimator public --------------------------------------------------------
42 LayerAnimator::LayerAnimator(base::TimeDelta transition_duration)
43 : delegate_(NULL),
44 preemption_strategy_(IMMEDIATELY_SET_NEW_TARGET),
45 is_transition_duration_locked_(false),
46 transition_duration_(transition_duration),
47 tween_type_(gfx::Tween::LINEAR),
48 is_started_(false),
49 disable_timer_for_test_(false),
50 adding_animations_(false) {
53 LayerAnimator::~LayerAnimator() {
54 for (size_t i = 0; i < running_animations_.size(); ++i) {
55 if (running_animations_[i].is_sequence_alive())
56 running_animations_[i].sequence()->OnAnimatorDestroyed();
58 ClearAnimationsInternal();
59 delegate_ = NULL;
62 // static
63 LayerAnimator* LayerAnimator::CreateDefaultAnimator() {
64 return new LayerAnimator(base::TimeDelta::FromMilliseconds(0));
67 // static
68 LayerAnimator* LayerAnimator::CreateImplicitAnimator() {
69 return new LayerAnimator(
70 base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs));
73 // This macro provides the implementation for the setter and getter (well,
74 // the getter of the target value) for an animated property. For example,
75 // it is used for the implementations of SetTransform and GetTargetTransform.
76 // It is worth noting that SetFoo avoids invoking the usual animation machinery
77 // if the transition duration is zero -- in this case we just set the property
78 // on the layer animation delegate immediately.
79 #define ANIMATED_PROPERTY(type, property, name, member_type, member) \
80 void LayerAnimator::Set##name(type value) { \
81 base::TimeDelta duration = GetTransitionDuration(); \
82 if (duration == base::TimeDelta() && delegate() && \
83 (preemption_strategy_ != ENQUEUE_NEW_ANIMATION)) { \
84 StopAnimatingProperty(LayerAnimationElement::property); \
85 delegate()->Set##name##FromAnimation(value); \
86 return; \
87 } \
88 scoped_ptr<LayerAnimationElement> element( \
89 LayerAnimationElement::Create##name##Element(value, duration)); \
90 element->set_tween_type(tween_type_); \
91 StartAnimation(new LayerAnimationSequence(element.release())); \
92 } \
94 member_type LayerAnimator::GetTarget##name() const { \
95 LayerAnimationElement::TargetValue target(delegate()); \
96 GetTargetValue(&target); \
97 return target.member; \
100 ANIMATED_PROPERTY(
101 const gfx::Transform&, TRANSFORM, Transform, gfx::Transform, transform);
102 ANIMATED_PROPERTY(const gfx::Rect&, BOUNDS, Bounds, gfx::Rect, bounds);
103 ANIMATED_PROPERTY(float, OPACITY, Opacity, float, opacity);
104 ANIMATED_PROPERTY(bool, VISIBILITY, Visibility, bool, visibility);
105 ANIMATED_PROPERTY(float, BRIGHTNESS, Brightness, float, brightness);
106 ANIMATED_PROPERTY(float, GRAYSCALE, Grayscale, float, grayscale);
107 ANIMATED_PROPERTY(SkColor, COLOR, Color, SkColor, color);
109 base::TimeDelta LayerAnimator::GetTransitionDuration() const {
110 return transition_duration_;
113 void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) {
114 if (delegate_ && is_started_) {
115 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
116 if (collection)
117 collection->StopAnimator(this);
119 delegate_ = delegate;
120 if (delegate_ && is_started_) {
121 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
122 if (collection)
123 collection->StartAnimator(this);
127 void LayerAnimator::StartAnimation(LayerAnimationSequence* animation) {
128 scoped_refptr<LayerAnimator> retain(this);
129 OnScheduled(animation);
130 if (!StartSequenceImmediately(animation)) {
131 // Attempt to preempt a running animation.
132 switch (preemption_strategy_) {
133 case IMMEDIATELY_SET_NEW_TARGET:
134 ImmediatelySetNewTarget(animation);
135 break;
136 case IMMEDIATELY_ANIMATE_TO_NEW_TARGET:
137 ImmediatelyAnimateToNewTarget(animation);
138 break;
139 case ENQUEUE_NEW_ANIMATION:
140 EnqueueNewAnimation(animation);
141 break;
142 case REPLACE_QUEUED_ANIMATIONS:
143 ReplaceQueuedAnimations(animation);
144 break;
145 case BLEND_WITH_CURRENT_ANIMATION: {
146 // TODO(vollick) Add support for blended sequences and use them here.
147 NOTIMPLEMENTED();
148 break;
152 FinishAnyAnimationWithZeroDuration();
153 UpdateAnimationState();
156 void LayerAnimator::ScheduleAnimation(LayerAnimationSequence* animation) {
157 scoped_refptr<LayerAnimator> retain(this);
158 OnScheduled(animation);
159 if (is_animating()) {
160 animation_queue_.push_back(make_linked_ptr(animation));
161 ProcessQueue();
162 } else {
163 StartSequenceImmediately(animation);
165 UpdateAnimationState();
168 void LayerAnimator::StartTogether(
169 const std::vector<LayerAnimationSequence*>& animations) {
170 scoped_refptr<LayerAnimator> retain(this);
171 if (preemption_strategy_ == IMMEDIATELY_SET_NEW_TARGET) {
172 std::vector<LayerAnimationSequence*>::const_iterator iter;
173 for (iter = animations.begin(); iter != animations.end(); ++iter) {
174 StartAnimation(*iter);
176 return;
179 adding_animations_ = true;
180 if (!is_animating()) {
181 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
182 if (collection && collection->HasActiveAnimators())
183 last_step_time_ = collection->last_tick_time();
184 else
185 last_step_time_ = gfx::FrameTime::Now();
188 // Collect all the affected properties.
189 LayerAnimationElement::AnimatableProperties animated_properties =
190 LayerAnimationElement::UNKNOWN;
192 std::vector<LayerAnimationSequence*>::const_iterator iter;
193 for (iter = animations.begin(); iter != animations.end(); ++iter)
194 animated_properties |= (*iter)->properties();
196 // Starting a zero duration pause that affects all the animated properties
197 // will prevent any of the sequences from animating until there are no
198 // running animations that affect any of these properties, as well as
199 // handle preemption strategy.
200 StartAnimation(new LayerAnimationSequence(
201 LayerAnimationElement::CreatePauseElement(animated_properties,
202 base::TimeDelta())));
204 bool wait_for_group_start = false;
205 for (iter = animations.begin(); iter != animations.end(); ++iter)
206 wait_for_group_start |= (*iter)->IsFirstElementThreaded();
208 int group_id = cc::AnimationIdProvider::NextGroupId();
210 // These animations (provided they don't animate any common properties) will
211 // now animate together if trivially scheduled.
212 for (iter = animations.begin(); iter != animations.end(); ++iter) {
213 (*iter)->set_animation_group_id(group_id);
214 (*iter)->set_waiting_for_group_start(wait_for_group_start);
215 ScheduleAnimation(*iter);
218 adding_animations_ = false;
219 UpdateAnimationState();
223 void LayerAnimator::ScheduleTogether(
224 const std::vector<LayerAnimationSequence*>& animations) {
225 scoped_refptr<LayerAnimator> retain(this);
227 // Collect all the affected properties.
228 LayerAnimationElement::AnimatableProperties animated_properties =
229 LayerAnimationElement::UNKNOWN;
231 std::vector<LayerAnimationSequence*>::const_iterator iter;
232 for (iter = animations.begin(); iter != animations.end(); ++iter)
233 animated_properties |= (*iter)->properties();
235 // Scheduling a zero duration pause that affects all the animated properties
236 // will prevent any of the sequences from animating until there are no
237 // running animations that affect any of these properties.
238 ScheduleAnimation(new LayerAnimationSequence(
239 LayerAnimationElement::CreatePauseElement(animated_properties,
240 base::TimeDelta())));
242 bool wait_for_group_start = false;
243 for (iter = animations.begin(); iter != animations.end(); ++iter)
244 wait_for_group_start |= (*iter)->IsFirstElementThreaded();
246 int group_id = cc::AnimationIdProvider::NextGroupId();
248 // These animations (provided they don't animate any common properties) will
249 // now animate together if trivially scheduled.
250 for (iter = animations.begin(); iter != animations.end(); ++iter) {
251 (*iter)->set_animation_group_id(group_id);
252 (*iter)->set_waiting_for_group_start(wait_for_group_start);
253 ScheduleAnimation(*iter);
256 UpdateAnimationState();
259 void LayerAnimator::SchedulePauseForProperties(
260 base::TimeDelta duration,
261 LayerAnimationElement::AnimatableProperties properties_to_pause) {
262 ScheduleAnimation(new ui::LayerAnimationSequence(
263 ui::LayerAnimationElement::CreatePauseElement(
264 properties_to_pause, duration)));
267 bool LayerAnimator::IsAnimatingProperty(
268 LayerAnimationElement::AnimatableProperty property) const {
269 for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin();
270 queue_iter != animation_queue_.end(); ++queue_iter) {
271 if ((*queue_iter)->properties() & property)
272 return true;
274 return false;
277 void LayerAnimator::StopAnimatingProperty(
278 LayerAnimationElement::AnimatableProperty property) {
279 scoped_refptr<LayerAnimator> retain(this);
280 while (true) {
281 // GetRunningAnimation purges deleted animations before searching, so we are
282 // guaranteed to find a live animation if any is returned at all.
283 RunningAnimation* running = GetRunningAnimation(property);
284 if (!running)
285 break;
286 // As was mentioned above, this sequence must be alive.
287 DCHECK(running->is_sequence_alive());
288 FinishAnimation(running->sequence(), false);
292 void LayerAnimator::AddObserver(LayerAnimationObserver* observer) {
293 if (!observers_.HasObserver(observer))
294 observers_.AddObserver(observer);
297 void LayerAnimator::RemoveObserver(LayerAnimationObserver* observer) {
298 observers_.RemoveObserver(observer);
299 // Remove the observer from all sequences as well.
300 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
301 queue_iter != animation_queue_.end(); ++queue_iter) {
302 (*queue_iter)->RemoveObserver(observer);
306 void LayerAnimator::OnThreadedAnimationStarted(
307 const cc::AnimationEvent& event) {
308 LayerAnimationElement::AnimatableProperty property =
309 LayerAnimationElement::ToAnimatableProperty(event.target_property);
311 RunningAnimation* running = GetRunningAnimation(property);
312 if (!running)
313 return;
314 DCHECK(running->is_sequence_alive());
316 if (running->sequence()->animation_group_id() != event.group_id)
317 return;
319 running->sequence()->OnThreadedAnimationStarted(event);
320 if (!running->sequence()->waiting_for_group_start())
321 return;
323 base::TimeTicks start_time = event.monotonic_time;
325 running->sequence()->set_waiting_for_group_start(false);
327 // The call to GetRunningAnimation made above already purged deleted
328 // animations, so we are guaranteed that all the animations we iterate
329 // over now are alive.
330 for (RunningAnimations::iterator iter = running_animations_.begin();
331 iter != running_animations_.end(); ++iter) {
332 // Ensure that each sequence is only Started once, regardless of the
333 // number of sequences in the group that have threaded first elements.
334 if (((*iter).sequence()->animation_group_id() == event.group_id) &&
335 !(*iter).sequence()->IsFirstElementThreaded() &&
336 (*iter).sequence()->waiting_for_group_start()) {
337 (*iter).sequence()->set_start_time(start_time);
338 (*iter).sequence()->set_waiting_for_group_start(false);
339 (*iter).sequence()->Start(delegate());
344 void LayerAnimator::AddToCollection(LayerAnimatorCollection* collection) {
345 if (is_animating() && !is_started_) {
346 collection->StartAnimator(this);
347 is_started_ = true;
351 void LayerAnimator::RemoveFromCollection(LayerAnimatorCollection* collection) {
352 if (is_animating() && is_started_) {
353 collection->StopAnimator(this);
354 is_started_ = false;
358 // LayerAnimator protected -----------------------------------------------------
360 void LayerAnimator::ProgressAnimation(LayerAnimationSequence* sequence,
361 base::TimeTicks now) {
362 if (!delegate() || sequence->waiting_for_group_start())
363 return;
365 sequence->Progress(now, delegate());
368 void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence* sequence) {
369 if (!delegate())
370 return;
372 sequence->ProgressToEnd(delegate());
375 bool LayerAnimator::HasAnimation(LayerAnimationSequence* sequence) const {
376 for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin();
377 queue_iter != animation_queue_.end(); ++queue_iter) {
378 if ((*queue_iter).get() == sequence)
379 return true;
381 return false;
384 // LayerAnimator private -------------------------------------------------------
386 void LayerAnimator::Step(base::TimeTicks now) {
387 TRACE_EVENT0("ui", "LayerAnimator::Step");
388 scoped_refptr<LayerAnimator> retain(this);
390 last_step_time_ = now;
392 PurgeDeletedAnimations();
394 // We need to make a copy of the running animations because progressing them
395 // and finishing them may indirectly affect the collection of running
396 // animations.
397 RunningAnimations running_animations_copy = running_animations_;
398 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
399 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
400 continue;
402 if (running_animations_copy[i].sequence()->IsFinished(now)) {
403 SAFE_INVOKE_VOID(FinishAnimation, running_animations_copy[i], false);
404 } else {
405 SAFE_INVOKE_VOID(ProgressAnimation, running_animations_copy[i], now);
410 void LayerAnimator::StopAnimatingInternal(bool abort) {
411 scoped_refptr<LayerAnimator> retain(this);
412 while (is_animating()) {
413 // We're going to attempt to finish the first running animation. Let's
414 // ensure that it's valid.
415 PurgeDeletedAnimations();
417 // If we've purged all running animations, attempt to start one up.
418 if (running_animations_.empty())
419 ProcessQueue();
421 DCHECK(!running_animations_.empty());
423 // Still no luck, let's just bail and clear all animations.
424 if (running_animations_.empty()) {
425 ClearAnimationsInternal();
426 break;
429 SAFE_INVOKE_VOID(FinishAnimation, running_animations_[0], abort);
433 void LayerAnimator::UpdateAnimationState() {
434 if (disable_timer_for_test_)
435 return;
437 const bool should_start = is_animating();
438 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
439 if (collection) {
440 if (should_start && !is_started_)
441 collection->StartAnimator(this);
442 else if (!should_start && is_started_)
443 collection->StopAnimator(this);
444 is_started_ = should_start;
445 } else {
446 is_started_ = false;
450 LayerAnimationSequence* LayerAnimator::RemoveAnimation(
451 LayerAnimationSequence* sequence) {
452 linked_ptr<LayerAnimationSequence> to_return;
454 bool is_running = false;
456 // First remove from running animations
457 for (RunningAnimations::iterator iter = running_animations_.begin();
458 iter != running_animations_.end(); ++iter) {
459 if ((*iter).sequence() == sequence) {
460 running_animations_.erase(iter);
461 is_running = true;
462 break;
466 // Then remove from the queue
467 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
468 queue_iter != animation_queue_.end(); ++queue_iter) {
469 if ((*queue_iter) == sequence) {
470 to_return = *queue_iter;
471 animation_queue_.erase(queue_iter);
472 break;
476 if (!to_return.get() ||
477 !to_return->waiting_for_group_start() ||
478 !to_return->IsFirstElementThreaded())
479 return to_return.release();
481 // The removed sequence may have been responsible for making other sequences
482 // wait for a group start. If no other sequences in the group have a
483 // threaded first element, the group no longer needs the additional wait.
484 bool is_wait_still_needed = false;
485 int group_id = to_return->animation_group_id();
486 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
487 queue_iter != animation_queue_.end(); ++queue_iter) {
488 if (((*queue_iter)->animation_group_id() == group_id) &&
489 (*queue_iter)->IsFirstElementThreaded()) {
490 is_wait_still_needed = true;
491 break;
495 if (is_wait_still_needed)
496 return to_return.release();
498 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
499 queue_iter != animation_queue_.end(); ++queue_iter) {
500 if ((*queue_iter)->animation_group_id() == group_id &&
501 (*queue_iter)->waiting_for_group_start()) {
502 (*queue_iter)->set_waiting_for_group_start(false);
503 if (is_running) {
504 (*queue_iter)->set_start_time(last_step_time_);
505 (*queue_iter)->Start(delegate());
509 return to_return.release();
512 void LayerAnimator::FinishAnimation(
513 LayerAnimationSequence* sequence, bool abort) {
514 scoped_refptr<LayerAnimator> retain(this);
515 scoped_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence));
516 if (abort)
517 sequence->Abort(delegate());
518 else
519 ProgressAnimationToEnd(sequence);
520 ProcessQueue();
521 UpdateAnimationState();
524 void LayerAnimator::FinishAnyAnimationWithZeroDuration() {
525 scoped_refptr<LayerAnimator> retain(this);
526 // Special case: if we've started a 0 duration animation, just finish it now
527 // and get rid of it. We need to make a copy because Progress may indirectly
528 // cause new animations to start running.
529 RunningAnimations running_animations_copy = running_animations_;
530 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
531 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
532 continue;
534 if (running_animations_copy[i].sequence()->IsFinished(
535 running_animations_copy[i].sequence()->start_time())) {
536 SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
537 scoped_ptr<LayerAnimationSequence> removed(
538 SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
541 ProcessQueue();
542 UpdateAnimationState();
545 void LayerAnimator::ClearAnimations() {
546 scoped_refptr<LayerAnimator> retain(this);
547 ClearAnimationsInternal();
550 LayerAnimator::RunningAnimation* LayerAnimator::GetRunningAnimation(
551 LayerAnimationElement::AnimatableProperty property) {
552 PurgeDeletedAnimations();
553 for (RunningAnimations::iterator iter = running_animations_.begin();
554 iter != running_animations_.end(); ++iter) {
555 if ((*iter).sequence()->properties() & property)
556 return &(*iter);
558 return NULL;
561 void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence* animation) {
562 // If we don't have the animation in the queue yet, add it.
563 bool found_sequence = false;
564 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
565 queue_iter != animation_queue_.end(); ++queue_iter) {
566 if ((*queue_iter) == animation) {
567 found_sequence = true;
568 break;
572 if (!found_sequence)
573 animation_queue_.push_front(make_linked_ptr(animation));
576 void LayerAnimator::RemoveAllAnimationsWithACommonProperty(
577 LayerAnimationSequence* sequence, bool abort) {
578 // For all the running animations, if they animate the same property,
579 // progress them to the end and remove them. Note, Aborting or Progressing
580 // animations may affect the collection of running animations, so we need to
581 // operate on a copy.
582 RunningAnimations running_animations_copy = running_animations_;
583 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
584 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
585 continue;
587 if (running_animations_copy[i].sequence()->HasConflictingProperty(
588 sequence->properties())) {
589 scoped_ptr<LayerAnimationSequence> removed(
590 SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
591 if (abort)
592 running_animations_copy[i].sequence()->Abort(delegate());
593 else
594 SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
598 // Same for the queued animations that haven't been started. Again, we'll
599 // need to operate on a copy.
600 std::vector<base::WeakPtr<LayerAnimationSequence> > sequences;
601 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
602 queue_iter != animation_queue_.end(); ++queue_iter)
603 sequences.push_back((*queue_iter)->AsWeakPtr());
605 for (size_t i = 0; i < sequences.size(); ++i) {
606 if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
607 continue;
609 if (sequences[i]->HasConflictingProperty(sequence->properties())) {
610 scoped_ptr<LayerAnimationSequence> removed(
611 RemoveAnimation(sequences[i].get()));
612 if (abort)
613 sequences[i]->Abort(delegate());
614 else
615 ProgressAnimationToEnd(sequences[i].get());
620 void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence* sequence) {
621 // Need to detect if our sequence gets destroyed.
622 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
623 sequence->AsWeakPtr();
625 const bool abort = false;
626 RemoveAllAnimationsWithACommonProperty(sequence, abort);
627 if (!weak_sequence_ptr.get())
628 return;
630 LayerAnimationSequence* removed = RemoveAnimation(sequence);
631 DCHECK(removed == NULL || removed == sequence);
632 if (!weak_sequence_ptr.get())
633 return;
635 ProgressAnimationToEnd(sequence);
636 if (!weak_sequence_ptr.get())
637 return;
639 delete sequence;
642 void LayerAnimator::ImmediatelyAnimateToNewTarget(
643 LayerAnimationSequence* sequence) {
644 // Need to detect if our sequence gets destroyed.
645 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
646 sequence->AsWeakPtr();
648 const bool abort = true;
649 RemoveAllAnimationsWithACommonProperty(sequence, abort);
650 if (!weak_sequence_ptr.get())
651 return;
653 AddToQueueIfNotPresent(sequence);
654 if (!weak_sequence_ptr.get())
655 return;
657 StartSequenceImmediately(sequence);
660 void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence* sequence) {
661 // It is assumed that if there was no conflicting animation, we would
662 // not have been called. No need to check for a collision; just
663 // add to the queue.
664 animation_queue_.push_back(make_linked_ptr(sequence));
665 ProcessQueue();
668 void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence* sequence) {
669 // Need to detect if our sequence gets destroyed.
670 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
671 sequence->AsWeakPtr();
673 // Remove all animations that aren't running. Note: at each iteration i is
674 // incremented or an element is removed from the queue, so
675 // animation_queue_.size() - i is always decreasing and we are always making
676 // progress towards the loop terminating.
677 for (size_t i = 0; i < animation_queue_.size();) {
678 if (!weak_sequence_ptr.get())
679 break;
681 PurgeDeletedAnimations();
683 bool is_running = false;
684 for (RunningAnimations::const_iterator iter = running_animations_.begin();
685 iter != running_animations_.end(); ++iter) {
686 if ((*iter).sequence() == animation_queue_[i].get()) {
687 is_running = true;
688 break;
692 if (!is_running)
693 delete RemoveAnimation(animation_queue_[i].get());
694 else
695 ++i;
697 animation_queue_.push_back(make_linked_ptr(sequence));
698 ProcessQueue();
701 void LayerAnimator::ProcessQueue() {
702 bool started_sequence = false;
703 do {
704 started_sequence = false;
705 // Build a list of all currently animated properties.
706 LayerAnimationElement::AnimatableProperties animated =
707 LayerAnimationElement::UNKNOWN;
708 for (RunningAnimations::const_iterator iter = running_animations_.begin();
709 iter != running_animations_.end(); ++iter) {
710 if (!(*iter).is_sequence_alive())
711 continue;
713 animated |= (*iter).sequence()->properties();
716 // Try to find an animation that doesn't conflict with an animated
717 // property or a property that will be animated before it. Note: starting
718 // the animation may indirectly cause more animations to be started, so we
719 // need to operate on a copy.
720 std::vector<base::WeakPtr<LayerAnimationSequence> > sequences;
721 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
722 queue_iter != animation_queue_.end(); ++queue_iter)
723 sequences.push_back((*queue_iter)->AsWeakPtr());
725 for (size_t i = 0; i < sequences.size(); ++i) {
726 if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
727 continue;
729 if (!sequences[i]->HasConflictingProperty(animated)) {
730 StartSequenceImmediately(sequences[i].get());
731 started_sequence = true;
732 break;
735 // Animation couldn't be started. Add its properties to the collection so
736 // that we don't start a conflicting animation. For example, if our queue
737 // has the elements { {T,B}, {B} } (that is, an element that animates both
738 // the transform and the bounds followed by an element that animates the
739 // bounds), and we're currently animating the transform, we can't start
740 // the first element because it animates the transform, too. We cannot
741 // start the second element, either, because the first element animates
742 // bounds too, and needs to go first.
743 animated |= sequences[i]->properties();
746 // If we started a sequence, try again. We may be able to start several.
747 } while (started_sequence);
750 bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) {
751 PurgeDeletedAnimations();
753 // Ensure that no one is animating one of the sequence's properties already.
754 for (RunningAnimations::const_iterator iter = running_animations_.begin();
755 iter != running_animations_.end(); ++iter) {
756 if ((*iter).sequence()->HasConflictingProperty(sequence->properties()))
757 return false;
760 // All clear, actually start the sequence. Note: base::TimeTicks::Now has
761 // a resolution that can be as bad as 15ms. If this causes glitches in the
762 // animations, this can be switched to HighResNow() (animation uses Now()
763 // internally).
764 // All LayerAnimators share the same LayerAnimatorCollection. Use the
765 // last_tick_time() from there to ensure animations started during the same
766 // event complete at the same time.
767 base::TimeTicks start_time;
768 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
769 if (is_animating() || adding_animations_)
770 start_time = last_step_time_;
771 else if (collection && collection->HasActiveAnimators())
772 start_time = collection->last_tick_time();
773 else
774 start_time = gfx::FrameTime::Now();
776 if (!sequence->animation_group_id())
777 sequence->set_animation_group_id(cc::AnimationIdProvider::NextGroupId());
778 if (!sequence->waiting_for_group_start() ||
779 sequence->IsFirstElementThreaded()) {
780 sequence->set_start_time(start_time);
781 sequence->Start(delegate());
783 running_animations_.push_back(
784 RunningAnimation(sequence->AsWeakPtr()));
786 // Need to keep a reference to the animation.
787 AddToQueueIfNotPresent(sequence);
789 // Ensure that animations get stepped at their start time.
790 Step(start_time);
792 return true;
795 void LayerAnimator::GetTargetValue(
796 LayerAnimationElement::TargetValue* target) const {
797 for (AnimationQueue::const_iterator iter = animation_queue_.begin();
798 iter != animation_queue_.end(); ++iter) {
799 (*iter)->GetTargetValue(target);
803 void LayerAnimator::OnScheduled(LayerAnimationSequence* sequence) {
804 if (observers_.might_have_observers()) {
805 ObserverListBase<LayerAnimationObserver>::Iterator it(observers_);
806 LayerAnimationObserver* obs;
807 while ((obs = it.GetNext()) != NULL) {
808 sequence->AddObserver(obs);
811 sequence->OnScheduled();
814 void LayerAnimator::SetTransitionDuration(base::TimeDelta duration) {
815 if (is_transition_duration_locked_)
816 return;
817 transition_duration_ = duration;
820 void LayerAnimator::ClearAnimationsInternal() {
821 PurgeDeletedAnimations();
823 // Abort should never affect the set of running animations, but just in case
824 // clients are badly behaved, we will use a copy of the running animations.
825 RunningAnimations running_animations_copy = running_animations_;
826 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
827 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
828 continue;
830 scoped_ptr<LayerAnimationSequence> removed(
831 RemoveAnimation(running_animations_copy[i].sequence()));
832 if (removed.get())
833 removed->Abort(delegate());
835 // This *should* have cleared the list of running animations.
836 DCHECK(running_animations_.empty());
837 running_animations_.clear();
838 animation_queue_.clear();
839 UpdateAnimationState();
842 void LayerAnimator::PurgeDeletedAnimations() {
843 for (size_t i = 0; i < running_animations_.size();) {
844 if (!running_animations_[i].is_sequence_alive())
845 running_animations_.erase(running_animations_.begin() + i);
846 else
847 i++;
851 LayerAnimatorCollection* LayerAnimator::GetLayerAnimatorCollection() {
852 return delegate_ ? delegate_->GetLayerAnimatorCollection() : NULL;
855 LayerAnimator::RunningAnimation::RunningAnimation(
856 const base::WeakPtr<LayerAnimationSequence>& sequence)
857 : sequence_(sequence) {
860 LayerAnimator::RunningAnimation::~RunningAnimation() { }
862 } // namespace ui