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.
4
5 #include "ui/compositor/layer_animator.h"
6
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/gfx/animation/animation_container.h"
18 #include "ui/gfx/frame_time.h"
19
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)
31
32 namespace ui {
33
34 class LayerAnimator;
35
36 namespace {
37
38 const int kDefaultTransitionDurationMs = 120;
39 const int kTimerIntervalMs = 10;
40
41 // Returns the AnimationContainer we're added to.
GetAnimationContainer()42 gfx::AnimationContainer* GetAnimationContainer() {
43 static gfx::AnimationContainer* container = NULL;
44 if (!container) {
45 container = new gfx::AnimationContainer();
46 container->AddRef();
47 }
48 return container;
49 }
50
51 } // namespace
52
53 // LayerAnimator public --------------------------------------------------------
54
LayerAnimator(base::TimeDelta transition_duration)55 LayerAnimator::LayerAnimator(base::TimeDelta transition_duration)
56 : delegate_(NULL),
57 preemption_strategy_(IMMEDIATELY_SET_NEW_TARGET),
58 is_transition_duration_locked_(false),
59 transition_duration_(transition_duration),
60 tween_type_(gfx::Tween::LINEAR),
61 is_started_(false),
62 disable_timer_for_test_(false),
63 adding_animations_(false) {
64 }
65
~LayerAnimator()66 LayerAnimator::~LayerAnimator() {
67 for (size_t i = 0; i < running_animations_.size(); ++i) {
68 if (running_animations_[i].is_sequence_alive())
69 running_animations_[i].sequence()->OnAnimatorDestroyed();
70 }
71 ClearAnimationsInternal();
72 delegate_ = NULL;
73 }
74
75 // static
CreateDefaultAnimator()76 LayerAnimator* LayerAnimator::CreateDefaultAnimator() {
77 return new LayerAnimator(base::TimeDelta::FromMilliseconds(0));
78 }
79
80 // static
CreateImplicitAnimator()81 LayerAnimator* LayerAnimator::CreateImplicitAnimator() {
82 return new LayerAnimator(
83 base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs));
84 }
85
86 // This macro provides the implementation for the setter and getter (well,
87 // the getter of the target value) for an animated property. For example,
88 // it is used for the implementations of SetTransform and GetTargetTransform.
89 // It is worth noting that SetFoo avoids invoking the usual animation machinery
90 // if the transition duration is zero -- in this case we just set the property
91 // on the layer animation delegate immediately.
92 #define ANIMATED_PROPERTY(type, property, name, member_type, member) \
93 void LayerAnimator::Set##name(type value) { \
94 base::TimeDelta duration = GetTransitionDuration(); \
95 if (duration == base::TimeDelta() && delegate() && \
96 (preemption_strategy_ != ENQUEUE_NEW_ANIMATION)) { \
97 StopAnimatingProperty(LayerAnimationElement::property); \
98 delegate()->Set##name##FromAnimation(value); \
99 return; \
100 } \
101 scoped_ptr<LayerAnimationElement> element( \
102 LayerAnimationElement::Create##name##Element(value, duration)); \
103 element->set_tween_type(tween_type_); \
104 StartAnimation(new LayerAnimationSequence(element.release())); \
105 } \
106 \
107 member_type LayerAnimator::GetTarget##name() const { \
108 LayerAnimationElement::TargetValue target(delegate()); \
109 GetTargetValue(&target); \
110 return target.member; \
111 }
112
113 ANIMATED_PROPERTY(
114 const gfx::Transform&, TRANSFORM, Transform, gfx::Transform, transform);
115 ANIMATED_PROPERTY(const gfx::Rect&, BOUNDS, Bounds, gfx::Rect, bounds);
116 ANIMATED_PROPERTY(float, OPACITY, Opacity, float, opacity);
117 ANIMATED_PROPERTY(bool, VISIBILITY, Visibility, bool, visibility);
118 ANIMATED_PROPERTY(float, BRIGHTNESS, Brightness, float, brightness);
119 ANIMATED_PROPERTY(float, GRAYSCALE, Grayscale, float, grayscale);
120 ANIMATED_PROPERTY(SkColor, COLOR, Color, SkColor, color);
121
GetTransitionDuration() const122 base::TimeDelta LayerAnimator::GetTransitionDuration() const {
123 return transition_duration_;
124 }
125
SetDelegate(LayerAnimationDelegate * delegate)126 void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) {
127 delegate_ = delegate;
128 }
129
StartAnimation(LayerAnimationSequence * animation)130 void LayerAnimator::StartAnimation(LayerAnimationSequence* animation) {
131 scoped_refptr<LayerAnimator> retain(this);
132 OnScheduled(animation);
133 if (!StartSequenceImmediately(animation)) {
134 // Attempt to preempt a running animation.
135 switch (preemption_strategy_) {
136 case IMMEDIATELY_SET_NEW_TARGET:
137 ImmediatelySetNewTarget(animation);
138 break;
139 case IMMEDIATELY_ANIMATE_TO_NEW_TARGET:
140 ImmediatelyAnimateToNewTarget(animation);
141 break;
142 case ENQUEUE_NEW_ANIMATION:
143 EnqueueNewAnimation(animation);
144 break;
145 case REPLACE_QUEUED_ANIMATIONS:
146 ReplaceQueuedAnimations(animation);
147 break;
148 case BLEND_WITH_CURRENT_ANIMATION: {
149 // TODO(vollick) Add support for blended sequences and use them here.
150 NOTIMPLEMENTED();
151 break;
152 }
153 }
154 }
155 FinishAnyAnimationWithZeroDuration();
156 UpdateAnimationState();
157 }
158
ScheduleAnimation(LayerAnimationSequence * animation)159 void LayerAnimator::ScheduleAnimation(LayerAnimationSequence* animation) {
160 scoped_refptr<LayerAnimator> retain(this);
161 OnScheduled(animation);
162 if (is_animating()) {
163 animation_queue_.push_back(make_linked_ptr(animation));
164 ProcessQueue();
165 } else {
166 StartSequenceImmediately(animation);
167 }
168 UpdateAnimationState();
169 }
170
StartTogether(const std::vector<LayerAnimationSequence * > & animations)171 void LayerAnimator::StartTogether(
172 const std::vector<LayerAnimationSequence*>& animations) {
173 scoped_refptr<LayerAnimator> retain(this);
174 if (preemption_strategy_ == IMMEDIATELY_SET_NEW_TARGET) {
175 std::vector<LayerAnimationSequence*>::const_iterator iter;
176 for (iter = animations.begin(); iter != animations.end(); ++iter) {
177 StartAnimation(*iter);
178 }
179 return;
180 }
181
182 adding_animations_ = true;
183 if (!is_animating()) {
184 if (GetAnimationContainer()->is_running())
185 last_step_time_ = GetAnimationContainer()->last_tick_time();
186 else
187 last_step_time_ = gfx::FrameTime::Now();
188 }
189
190 // Collect all the affected properties.
191 LayerAnimationElement::AnimatableProperties animated_properties;
192 std::vector<LayerAnimationSequence*>::const_iterator iter;
193 for (iter = animations.begin(); iter != animations.end(); ++iter) {
194 animated_properties.insert((*iter)->properties().begin(),
195 (*iter)->properties().end());
196 }
197
198 // Starting a zero duration pause that affects all the animated properties
199 // will prevent any of the sequences from animating until there are no
200 // running animations that affect any of these properties, as well as
201 // handle preemption strategy.
202 StartAnimation(new LayerAnimationSequence(
203 LayerAnimationElement::CreatePauseElement(animated_properties,
204 base::TimeDelta())));
205
206 bool wait_for_group_start = false;
207 for (iter = animations.begin(); iter != animations.end(); ++iter)
208 wait_for_group_start |= (*iter)->IsFirstElementThreaded();
209
210 int group_id = cc::AnimationIdProvider::NextGroupId();
211
212 // These animations (provided they don't animate any common properties) will
213 // now animate together if trivially scheduled.
214 for (iter = animations.begin(); iter != animations.end(); ++iter) {
215 (*iter)->set_animation_group_id(group_id);
216 (*iter)->set_waiting_for_group_start(wait_for_group_start);
217 ScheduleAnimation(*iter);
218 }
219
220 adding_animations_ = false;
221 UpdateAnimationState();
222 }
223
224
ScheduleTogether(const std::vector<LayerAnimationSequence * > & animations)225 void LayerAnimator::ScheduleTogether(
226 const std::vector<LayerAnimationSequence*>& animations) {
227 scoped_refptr<LayerAnimator> retain(this);
228
229 // Collect all the affected properties.
230 LayerAnimationElement::AnimatableProperties animated_properties;
231 std::vector<LayerAnimationSequence*>::const_iterator iter;
232 for (iter = animations.begin(); iter != animations.end(); ++iter) {
233 animated_properties.insert((*iter)->properties().begin(),
234 (*iter)->properties().end());
235 }
236
237 // Scheduling a zero duration pause that affects all the animated properties
238 // will prevent any of the sequences from animating until there are no
239 // running animations that affect any of these properties.
240 ScheduleAnimation(new LayerAnimationSequence(
241 LayerAnimationElement::CreatePauseElement(animated_properties,
242 base::TimeDelta())));
243
244 bool wait_for_group_start = false;
245 for (iter = animations.begin(); iter != animations.end(); ++iter)
246 wait_for_group_start |= (*iter)->IsFirstElementThreaded();
247
248 int group_id = cc::AnimationIdProvider::NextGroupId();
249
250 // These animations (provided they don't animate any common properties) will
251 // now animate together if trivially scheduled.
252 for (iter = animations.begin(); iter != animations.end(); ++iter) {
253 (*iter)->set_animation_group_id(group_id);
254 (*iter)->set_waiting_for_group_start(wait_for_group_start);
255 ScheduleAnimation(*iter);
256 }
257
258 UpdateAnimationState();
259 }
260
SchedulePauseForProperties(base::TimeDelta duration,LayerAnimationElement::AnimatableProperty property,...)261 void LayerAnimator::SchedulePauseForProperties(
262 base::TimeDelta duration,
263 LayerAnimationElement::AnimatableProperty property,
264 ...) {
265 ui::LayerAnimationElement::AnimatableProperties properties_to_pause;
266 va_list marker;
267 va_start(marker, property);
268 for (int p = static_cast<int>(property); p != -1; p = va_arg(marker, int)) {
269 properties_to_pause.insert(
270 static_cast<LayerAnimationElement::AnimatableProperty>(p));
271 }
272 va_end(marker);
273 ScheduleAnimation(new ui::LayerAnimationSequence(
274 ui::LayerAnimationElement::CreatePauseElement(
275 properties_to_pause, duration)));
276 }
277
IsAnimatingProperty(LayerAnimationElement::AnimatableProperty property) const278 bool LayerAnimator::IsAnimatingProperty(
279 LayerAnimationElement::AnimatableProperty property) const {
280 for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin();
281 queue_iter != animation_queue_.end(); ++queue_iter) {
282 if ((*queue_iter)->properties().find(property) !=
283 (*queue_iter)->properties().end()) {
284 return true;
285 }
286 }
287 return false;
288 }
289
StopAnimatingProperty(LayerAnimationElement::AnimatableProperty property)290 void LayerAnimator::StopAnimatingProperty(
291 LayerAnimationElement::AnimatableProperty property) {
292 scoped_refptr<LayerAnimator> retain(this);
293 while (true) {
294 // GetRunningAnimation purges deleted animations before searching, so we are
295 // guaranteed to find a live animation if any is returned at all.
296 RunningAnimation* running = GetRunningAnimation(property);
297 if (!running)
298 break;
299 // As was mentioned above, this sequence must be alive.
300 DCHECK(running->is_sequence_alive());
301 FinishAnimation(running->sequence(), false);
302 }
303 }
304
AddObserver(LayerAnimationObserver * observer)305 void LayerAnimator::AddObserver(LayerAnimationObserver* observer) {
306 if (!observers_.HasObserver(observer))
307 observers_.AddObserver(observer);
308 }
309
RemoveObserver(LayerAnimationObserver * observer)310 void LayerAnimator::RemoveObserver(LayerAnimationObserver* observer) {
311 observers_.RemoveObserver(observer);
312 // Remove the observer from all sequences as well.
313 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
314 queue_iter != animation_queue_.end(); ++queue_iter) {
315 (*queue_iter)->RemoveObserver(observer);
316 }
317 }
318
OnThreadedAnimationStarted(const cc::AnimationEvent & event)319 void LayerAnimator::OnThreadedAnimationStarted(
320 const cc::AnimationEvent& event) {
321 LayerAnimationElement::AnimatableProperty property =
322 LayerAnimationElement::ToAnimatableProperty(event.target_property);
323
324 RunningAnimation* running = GetRunningAnimation(property);
325 if (!running)
326 return;
327 DCHECK(running->is_sequence_alive());
328
329 if (running->sequence()->animation_group_id() != event.group_id)
330 return;
331
332 running->sequence()->OnThreadedAnimationStarted(event);
333 if (!running->sequence()->waiting_for_group_start())
334 return;
335
336 base::TimeTicks start_time = base::TimeTicks::FromInternalValue(
337 event.monotonic_time * base::Time::kMicrosecondsPerSecond);
338
339 running->sequence()->set_waiting_for_group_start(false);
340
341 // The call to GetRunningAnimation made above already purged deleted
342 // animations, so we are guaranteed that all the animations we iterate
343 // over now are alive.
344 for (RunningAnimations::iterator iter = running_animations_.begin();
345 iter != running_animations_.end(); ++iter) {
346 // Ensure that each sequence is only Started once, regardless of the
347 // number of sequences in the group that have threaded first elements.
348 if (((*iter).sequence()->animation_group_id() == event.group_id) &&
349 !(*iter).sequence()->IsFirstElementThreaded() &&
350 (*iter).sequence()->waiting_for_group_start()) {
351 (*iter).sequence()->set_start_time(start_time);
352 (*iter).sequence()->set_waiting_for_group_start(false);
353 (*iter).sequence()->Start(delegate());
354 }
355 }
356 }
357
358 // LayerAnimator protected -----------------------------------------------------
359
ProgressAnimation(LayerAnimationSequence * sequence,base::TimeTicks now)360 void LayerAnimator::ProgressAnimation(LayerAnimationSequence* sequence,
361 base::TimeTicks now) {
362 if (!delegate() || sequence->waiting_for_group_start())
363 return;
364
365 sequence->Progress(now, delegate());
366 }
367
ProgressAnimationToEnd(LayerAnimationSequence * sequence)368 void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence* sequence) {
369 if (!delegate())
370 return;
371
372 sequence->ProgressToEnd(delegate());
373 }
374
HasAnimation(LayerAnimationSequence * sequence) const375 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;
380 }
381 return false;
382 }
383
384 // LayerAnimator private -------------------------------------------------------
385
Step(base::TimeTicks now)386 void LayerAnimator::Step(base::TimeTicks now) {
387 TRACE_EVENT0("ui", "LayerAnimator::Step");
388 scoped_refptr<LayerAnimator> retain(this);
389
390 last_step_time_ = now;
391
392 PurgeDeletedAnimations();
393
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;
401
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);
406 }
407 }
408 }
409
SetStartTime(base::TimeTicks start_time)410 void LayerAnimator::SetStartTime(base::TimeTicks start_time) {
411 // Do nothing.
412 }
413
GetTimerInterval() const414 base::TimeDelta LayerAnimator::GetTimerInterval() const {
415 return base::TimeDelta::FromMilliseconds(kTimerIntervalMs);
416 }
417
StopAnimatingInternal(bool abort)418 void LayerAnimator::StopAnimatingInternal(bool abort) {
419 scoped_refptr<LayerAnimator> retain(this);
420 while (is_animating()) {
421 // We're going to attempt to finish the first running animation. Let's
422 // ensure that it's valid.
423 PurgeDeletedAnimations();
424
425 // If we've purged all running animations, attempt to start one up.
426 if (running_animations_.empty())
427 ProcessQueue();
428
429 DCHECK(!running_animations_.empty());
430
431 // Still no luck, let's just bail and clear all animations.
432 if (running_animations_.empty()) {
433 ClearAnimationsInternal();
434 break;
435 }
436
437 SAFE_INVOKE_VOID(FinishAnimation, running_animations_[0], abort);
438 }
439 }
440
UpdateAnimationState()441 void LayerAnimator::UpdateAnimationState() {
442 if (disable_timer_for_test_)
443 return;
444
445 const bool should_start = is_animating();
446 if (should_start && !is_started_)
447 GetAnimationContainer()->Start(this);
448 else if (!should_start && is_started_)
449 GetAnimationContainer()->Stop(this);
450
451 is_started_ = should_start;
452 }
453
RemoveAnimation(LayerAnimationSequence * sequence)454 LayerAnimationSequence* LayerAnimator::RemoveAnimation(
455 LayerAnimationSequence* sequence) {
456 linked_ptr<LayerAnimationSequence> to_return;
457
458 bool is_running = false;
459
460 // First remove from running animations
461 for (RunningAnimations::iterator iter = running_animations_.begin();
462 iter != running_animations_.end(); ++iter) {
463 if ((*iter).sequence() == sequence) {
464 running_animations_.erase(iter);
465 is_running = true;
466 break;
467 }
468 }
469
470 // Then remove from the queue
471 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
472 queue_iter != animation_queue_.end(); ++queue_iter) {
473 if ((*queue_iter) == sequence) {
474 to_return = *queue_iter;
475 animation_queue_.erase(queue_iter);
476 break;
477 }
478 }
479
480 if (!to_return.get() ||
481 !to_return->waiting_for_group_start() ||
482 !to_return->IsFirstElementThreaded())
483 return to_return.release();
484
485 // The removed sequence may have been responsible for making other sequences
486 // wait for a group start. If no other sequences in the group have a
487 // threaded first element, the group no longer needs the additional wait.
488 bool is_wait_still_needed = false;
489 int group_id = to_return->animation_group_id();
490 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
491 queue_iter != animation_queue_.end(); ++queue_iter) {
492 if (((*queue_iter)->animation_group_id() == group_id) &&
493 (*queue_iter)->IsFirstElementThreaded()) {
494 is_wait_still_needed = true;
495 break;
496 }
497 }
498
499 if (is_wait_still_needed)
500 return to_return.release();
501
502 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
503 queue_iter != animation_queue_.end(); ++queue_iter) {
504 if ((*queue_iter)->animation_group_id() == group_id &&
505 (*queue_iter)->waiting_for_group_start()) {
506 (*queue_iter)->set_waiting_for_group_start(false);
507 if (is_running) {
508 (*queue_iter)->set_start_time(last_step_time_);
509 (*queue_iter)->Start(delegate());
510 }
511 }
512 }
513 return to_return.release();
514 }
515
FinishAnimation(LayerAnimationSequence * sequence,bool abort)516 void LayerAnimator::FinishAnimation(
517 LayerAnimationSequence* sequence, bool abort) {
518 scoped_refptr<LayerAnimator> retain(this);
519 scoped_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence));
520 if (abort)
521 sequence->Abort(delegate());
522 else
523 ProgressAnimationToEnd(sequence);
524 ProcessQueue();
525 UpdateAnimationState();
526 }
527
FinishAnyAnimationWithZeroDuration()528 void LayerAnimator::FinishAnyAnimationWithZeroDuration() {
529 scoped_refptr<LayerAnimator> retain(this);
530 // Special case: if we've started a 0 duration animation, just finish it now
531 // and get rid of it. We need to make a copy because Progress may indirectly
532 // cause new animations to start running.
533 RunningAnimations running_animations_copy = running_animations_;
534 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
535 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
536 continue;
537
538 if (running_animations_copy[i].sequence()->IsFinished(
539 running_animations_copy[i].sequence()->start_time())) {
540 SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
541 scoped_ptr<LayerAnimationSequence> removed(
542 SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
543 }
544 }
545 ProcessQueue();
546 UpdateAnimationState();
547 }
548
ClearAnimations()549 void LayerAnimator::ClearAnimations() {
550 scoped_refptr<LayerAnimator> retain(this);
551 ClearAnimationsInternal();
552 }
553
GetRunningAnimation(LayerAnimationElement::AnimatableProperty property)554 LayerAnimator::RunningAnimation* LayerAnimator::GetRunningAnimation(
555 LayerAnimationElement::AnimatableProperty property) {
556 PurgeDeletedAnimations();
557 for (RunningAnimations::iterator iter = running_animations_.begin();
558 iter != running_animations_.end(); ++iter) {
559 if ((*iter).sequence()->properties().find(property) !=
560 (*iter).sequence()->properties().end())
561 return &(*iter);
562 }
563 return NULL;
564 }
565
AddToQueueIfNotPresent(LayerAnimationSequence * animation)566 void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence* animation) {
567 // If we don't have the animation in the queue yet, add it.
568 bool found_sequence = false;
569 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
570 queue_iter != animation_queue_.end(); ++queue_iter) {
571 if ((*queue_iter) == animation) {
572 found_sequence = true;
573 break;
574 }
575 }
576
577 if (!found_sequence)
578 animation_queue_.push_front(make_linked_ptr(animation));
579 }
580
RemoveAllAnimationsWithACommonProperty(LayerAnimationSequence * sequence,bool abort)581 void LayerAnimator::RemoveAllAnimationsWithACommonProperty(
582 LayerAnimationSequence* sequence, bool abort) {
583 // For all the running animations, if they animate the same property,
584 // progress them to the end and remove them. Note, Aborting or Progressing
585 // animations may affect the collection of running animations, so we need to
586 // operate on a copy.
587 RunningAnimations running_animations_copy = running_animations_;
588 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
589 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
590 continue;
591
592 if (running_animations_copy[i].sequence()->HasConflictingProperty(
593 sequence->properties())) {
594 scoped_ptr<LayerAnimationSequence> removed(
595 SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
596 if (abort)
597 running_animations_copy[i].sequence()->Abort(delegate());
598 else
599 SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
600 }
601 }
602
603 // Same for the queued animations that haven't been started. Again, we'll
604 // need to operate on a copy.
605 std::vector<base::WeakPtr<LayerAnimationSequence> > sequences;
606 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
607 queue_iter != animation_queue_.end(); ++queue_iter)
608 sequences.push_back((*queue_iter)->AsWeakPtr());
609
610 for (size_t i = 0; i < sequences.size(); ++i) {
611 if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
612 continue;
613
614 if (sequences[i]->HasConflictingProperty(sequence->properties())) {
615 scoped_ptr<LayerAnimationSequence> removed(
616 RemoveAnimation(sequences[i].get()));
617 if (abort)
618 sequences[i]->Abort(delegate());
619 else
620 ProgressAnimationToEnd(sequences[i].get());
621 }
622 }
623 }
624
ImmediatelySetNewTarget(LayerAnimationSequence * sequence)625 void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence* sequence) {
626 // Need to detect if our sequence gets destroyed.
627 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
628 sequence->AsWeakPtr();
629
630 const bool abort = false;
631 RemoveAllAnimationsWithACommonProperty(sequence, abort);
632 if (!weak_sequence_ptr.get())
633 return;
634
635 LayerAnimationSequence* removed = RemoveAnimation(sequence);
636 DCHECK(removed == NULL || removed == sequence);
637 if (!weak_sequence_ptr.get())
638 return;
639
640 ProgressAnimationToEnd(sequence);
641 if (!weak_sequence_ptr.get())
642 return;
643
644 delete sequence;
645 }
646
ImmediatelyAnimateToNewTarget(LayerAnimationSequence * sequence)647 void LayerAnimator::ImmediatelyAnimateToNewTarget(
648 LayerAnimationSequence* sequence) {
649 // Need to detect if our sequence gets destroyed.
650 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
651 sequence->AsWeakPtr();
652
653 const bool abort = true;
654 RemoveAllAnimationsWithACommonProperty(sequence, abort);
655 if (!weak_sequence_ptr.get())
656 return;
657
658 AddToQueueIfNotPresent(sequence);
659 if (!weak_sequence_ptr.get())
660 return;
661
662 StartSequenceImmediately(sequence);
663 }
664
EnqueueNewAnimation(LayerAnimationSequence * sequence)665 void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence* sequence) {
666 // It is assumed that if there was no conflicting animation, we would
667 // not have been called. No need to check for a collision; just
668 // add to the queue.
669 animation_queue_.push_back(make_linked_ptr(sequence));
670 ProcessQueue();
671 }
672
ReplaceQueuedAnimations(LayerAnimationSequence * sequence)673 void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence* sequence) {
674 // Need to detect if our sequence gets destroyed.
675 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
676 sequence->AsWeakPtr();
677
678 // Remove all animations that aren't running. Note: at each iteration i is
679 // incremented or an element is removed from the queue, so
680 // animation_queue_.size() - i is always decreasing and we are always making
681 // progress towards the loop terminating.
682 for (size_t i = 0; i < animation_queue_.size();) {
683 if (!weak_sequence_ptr.get())
684 break;
685
686 PurgeDeletedAnimations();
687
688 bool is_running = false;
689 for (RunningAnimations::const_iterator iter = running_animations_.begin();
690 iter != running_animations_.end(); ++iter) {
691 if ((*iter).sequence() == animation_queue_[i].get()) {
692 is_running = true;
693 break;
694 }
695 }
696
697 if (!is_running)
698 delete RemoveAnimation(animation_queue_[i].get());
699 else
700 ++i;
701 }
702 animation_queue_.push_back(make_linked_ptr(sequence));
703 ProcessQueue();
704 }
705
ProcessQueue()706 void LayerAnimator::ProcessQueue() {
707 bool started_sequence = false;
708 do {
709 started_sequence = false;
710 // Build a list of all currently animated properties.
711 LayerAnimationElement::AnimatableProperties animated;
712 for (RunningAnimations::const_iterator iter = running_animations_.begin();
713 iter != running_animations_.end(); ++iter) {
714 if (!(*iter).is_sequence_alive())
715 continue;
716 animated.insert((*iter).sequence()->properties().begin(),
717 (*iter).sequence()->properties().end());
718 }
719
720 // Try to find an animation that doesn't conflict with an animated
721 // property or a property that will be animated before it. Note: starting
722 // the animation may indirectly cause more animations to be started, so we
723 // need to operate on a copy.
724 std::vector<base::WeakPtr<LayerAnimationSequence> > sequences;
725 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
726 queue_iter != animation_queue_.end(); ++queue_iter)
727 sequences.push_back((*queue_iter)->AsWeakPtr());
728
729 for (size_t i = 0; i < sequences.size(); ++i) {
730 if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
731 continue;
732
733 if (!sequences[i]->HasConflictingProperty(animated)) {
734 StartSequenceImmediately(sequences[i].get());
735 started_sequence = true;
736 break;
737 }
738
739 // Animation couldn't be started. Add its properties to the collection so
740 // that we don't start a conflicting animation. For example, if our queue
741 // has the elements { {T,B}, {B} } (that is, an element that animates both
742 // the transform and the bounds followed by an element that animates the
743 // bounds), and we're currently animating the transform, we can't start
744 // the first element because it animates the transform, too. We cannot
745 // start the second element, either, because the first element animates
746 // bounds too, and needs to go first.
747 animated.insert(sequences[i]->properties().begin(),
748 sequences[i]->properties().end());
749 }
750
751 // If we started a sequence, try again. We may be able to start several.
752 } while (started_sequence);
753 }
754
StartSequenceImmediately(LayerAnimationSequence * sequence)755 bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) {
756 PurgeDeletedAnimations();
757
758 // Ensure that no one is animating one of the sequence's properties already.
759 for (RunningAnimations::const_iterator iter = running_animations_.begin();
760 iter != running_animations_.end(); ++iter) {
761 if ((*iter).sequence()->HasConflictingProperty(sequence->properties()))
762 return false;
763 }
764
765 // All clear, actually start the sequence. Note: base::TimeTicks::Now has
766 // a resolution that can be as bad as 15ms. If this causes glitches in the
767 // animations, this can be switched to HighResNow() (animation uses Now()
768 // internally).
769 // All LayerAnimators share the same AnimationContainer. Use the
770 // last_tick_time() from there to ensure animations started during the same
771 // event complete at the same time.
772 base::TimeTicks start_time;
773 if (is_animating() || adding_animations_)
774 start_time = last_step_time_;
775 else if (GetAnimationContainer()->is_running())
776 start_time = GetAnimationContainer()->last_tick_time();
777 else
778 start_time = gfx::FrameTime::Now();
779
780 if (!sequence->animation_group_id())
781 sequence->set_animation_group_id(cc::AnimationIdProvider::NextGroupId());
782 if (!sequence->waiting_for_group_start() ||
783 sequence->IsFirstElementThreaded()) {
784 sequence->set_start_time(start_time);
785 sequence->Start(delegate());
786 }
787 running_animations_.push_back(
788 RunningAnimation(sequence->AsWeakPtr()));
789
790 // Need to keep a reference to the animation.
791 AddToQueueIfNotPresent(sequence);
792
793 // Ensure that animations get stepped at their start time.
794 Step(start_time);
795
796 return true;
797 }
798
GetTargetValue(LayerAnimationElement::TargetValue * target) const799 void LayerAnimator::GetTargetValue(
800 LayerAnimationElement::TargetValue* target) const {
801 for (AnimationQueue::const_iterator iter = animation_queue_.begin();
802 iter != animation_queue_.end(); ++iter) {
803 (*iter)->GetTargetValue(target);
804 }
805 }
806
OnScheduled(LayerAnimationSequence * sequence)807 void LayerAnimator::OnScheduled(LayerAnimationSequence* sequence) {
808 if (observers_.might_have_observers()) {
809 ObserverListBase<LayerAnimationObserver>::Iterator it(observers_);
810 LayerAnimationObserver* obs;
811 while ((obs = it.GetNext()) != NULL) {
812 sequence->AddObserver(obs);
813 }
814 }
815 sequence->OnScheduled();
816 }
817
SetTransitionDuration(base::TimeDelta duration)818 void LayerAnimator::SetTransitionDuration(base::TimeDelta duration) {
819 if (is_transition_duration_locked_)
820 return;
821 transition_duration_ = duration;
822 }
823
ClearAnimationsInternal()824 void LayerAnimator::ClearAnimationsInternal() {
825 PurgeDeletedAnimations();
826
827 // Abort should never affect the set of running animations, but just in case
828 // clients are badly behaved, we will use a copy of the running animations.
829 RunningAnimations running_animations_copy = running_animations_;
830 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
831 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
832 continue;
833
834 scoped_ptr<LayerAnimationSequence> removed(
835 RemoveAnimation(running_animations_copy[i].sequence()));
836 if (removed.get())
837 removed->Abort(delegate());
838 }
839 // This *should* have cleared the list of running animations.
840 DCHECK(running_animations_.empty());
841 running_animations_.clear();
842 animation_queue_.clear();
843 UpdateAnimationState();
844 }
845
PurgeDeletedAnimations()846 void LayerAnimator::PurgeDeletedAnimations() {
847 for (size_t i = 0; i < running_animations_.size();) {
848 if (!running_animations_[i].is_sequence_alive())
849 running_animations_.erase(running_animations_.begin() + i);
850 else
851 i++;
852 }
853 }
854
RunningAnimation(const base::WeakPtr<LayerAnimationSequence> & sequence)855 LayerAnimator::RunningAnimation::RunningAnimation(
856 const base::WeakPtr<LayerAnimationSequence>& sequence)
857 : sequence_(sequence) {
858 }
859
~RunningAnimation()860 LayerAnimator::RunningAnimation::~RunningAnimation() { }
861
862 } // namespace ui
863