• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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