layer_animator.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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/compositor/layer_animator_collection.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
32namespace ui {
33
34namespace {
35
36const int kDefaultTransitionDurationMs = 120;
37
38}  // namespace
39
40// LayerAnimator public --------------------------------------------------------
41
42LayerAnimator::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) {
51}
52
53LayerAnimator::~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();
57  }
58  ClearAnimationsInternal();
59  delegate_ = NULL;
60}
61
62// static
63LayerAnimator* LayerAnimator::CreateDefaultAnimator() {
64  return new LayerAnimator(base::TimeDelta::FromMilliseconds(0));
65}
66
67// static
68LayerAnimator* LayerAnimator::CreateImplicitAnimator() {
69  return new LayerAnimator(
70      base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs));
71}
72
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)  \
80void 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}                                                                     \
93                                                                      \
94member_type LayerAnimator::GetTarget##name() const {                  \
95  LayerAnimationElement::TargetValue target(delegate());              \
96  GetTargetValue(&target);                                            \
97  return target.member;                                               \
98}
99
100ANIMATED_PROPERTY(
101    const gfx::Transform&, TRANSFORM, Transform, gfx::Transform, transform);
102ANIMATED_PROPERTY(const gfx::Rect&, BOUNDS, Bounds, gfx::Rect, bounds);
103ANIMATED_PROPERTY(float, OPACITY, Opacity, float, opacity);
104ANIMATED_PROPERTY(bool, VISIBILITY, Visibility, bool, visibility);
105ANIMATED_PROPERTY(float, BRIGHTNESS, Brightness, float, brightness);
106ANIMATED_PROPERTY(float, GRAYSCALE, Grayscale, float, grayscale);
107ANIMATED_PROPERTY(SkColor, COLOR, Color, SkColor, color);
108
109base::TimeDelta LayerAnimator::GetTransitionDuration() const {
110  return transition_duration_;
111}
112
113void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) {
114  if (delegate_ && is_started_) {
115    LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
116    if (collection)
117      collection->StopAnimator(this);
118  }
119  delegate_ = delegate;
120  if (delegate_ && is_started_) {
121    LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
122    if (collection)
123      collection->StartAnimator(this);
124  }
125}
126
127void 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;
149      }
150    }
151  }
152  FinishAnyAnimationWithZeroDuration();
153  UpdateAnimationState();
154}
155
156void 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);
164  }
165  UpdateAnimationState();
166}
167
168void 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);
175    }
176    return;
177  }
178
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();
186  }
187
188  // Collect all the affected properties.
189  LayerAnimationElement::AnimatableProperties animated_properties =
190      LayerAnimationElement::UNKNOWN;
191
192  std::vector<LayerAnimationSequence*>::const_iterator iter;
193  for (iter = animations.begin(); iter != animations.end(); ++iter)
194    animated_properties |= (*iter)->properties();
195
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())));
203
204  bool wait_for_group_start = false;
205  for (iter = animations.begin(); iter != animations.end(); ++iter)
206    wait_for_group_start |= (*iter)->IsFirstElementThreaded();
207
208  int group_id = cc::AnimationIdProvider::NextGroupId();
209
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);
216  }
217
218  adding_animations_ = false;
219  UpdateAnimationState();
220}
221
222
223void LayerAnimator::ScheduleTogether(
224    const std::vector<LayerAnimationSequence*>& animations) {
225  scoped_refptr<LayerAnimator> retain(this);
226
227  // Collect all the affected properties.
228  LayerAnimationElement::AnimatableProperties animated_properties =
229      LayerAnimationElement::UNKNOWN;
230
231  std::vector<LayerAnimationSequence*>::const_iterator iter;
232  for (iter = animations.begin(); iter != animations.end(); ++iter)
233    animated_properties |= (*iter)->properties();
234
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())));
241
242  bool wait_for_group_start = false;
243  for (iter = animations.begin(); iter != animations.end(); ++iter)
244    wait_for_group_start |= (*iter)->IsFirstElementThreaded();
245
246  int group_id = cc::AnimationIdProvider::NextGroupId();
247
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);
254  }
255
256  UpdateAnimationState();
257}
258
259void 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)));
265}
266
267bool 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;
273  }
274  return false;
275}
276
277void 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);
289  }
290}
291
292void LayerAnimator::AddObserver(LayerAnimationObserver* observer) {
293  if (!observers_.HasObserver(observer))
294    observers_.AddObserver(observer);
295}
296
297void 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);
303  }
304}
305
306void LayerAnimator::OnThreadedAnimationStarted(
307    const cc::AnimationEvent& event) {
308  LayerAnimationElement::AnimatableProperty property =
309    LayerAnimationElement::ToAnimatableProperty(event.target_property);
310
311  RunningAnimation* running = GetRunningAnimation(property);
312  if (!running)
313    return;
314  DCHECK(running->is_sequence_alive());
315
316  if (running->sequence()->animation_group_id() != event.group_id)
317    return;
318
319  running->sequence()->OnThreadedAnimationStarted(event);
320  if (!running->sequence()->waiting_for_group_start())
321    return;
322
323  base::TimeTicks start_time = event.monotonic_time;
324
325  running->sequence()->set_waiting_for_group_start(false);
326
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());
340    }
341  }
342}
343
344void LayerAnimator::AddToCollection(LayerAnimatorCollection* collection) {
345  if (is_animating() && !is_started_) {
346    collection->StartAnimator(this);
347    is_started_ = true;
348  }
349}
350
351void LayerAnimator::RemoveFromCollection(LayerAnimatorCollection* collection) {
352  if (is_animating() && is_started_) {
353    collection->StopAnimator(this);
354    is_started_ = false;
355  }
356}
357
358// LayerAnimator protected -----------------------------------------------------
359
360void 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
368void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence* sequence) {
369  if (!delegate())
370    return;
371
372  sequence->ProgressToEnd(delegate());
373}
374
375bool 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
386void 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
410void 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();
416
417    // If we've purged all running animations, attempt to start one up.
418    if (running_animations_.empty())
419      ProcessQueue();
420
421    DCHECK(!running_animations_.empty());
422
423    // Still no luck, let's just bail and clear all animations.
424    if (running_animations_.empty()) {
425      ClearAnimationsInternal();
426      break;
427    }
428
429    SAFE_INVOKE_VOID(FinishAnimation, running_animations_[0], abort);
430  }
431}
432
433void LayerAnimator::UpdateAnimationState() {
434  if (disable_timer_for_test_)
435    return;
436
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;
447  }
448}
449
450LayerAnimationSequence* LayerAnimator::RemoveAnimation(
451    LayerAnimationSequence* sequence) {
452  linked_ptr<LayerAnimationSequence> to_return;
453
454  bool is_running = false;
455
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;
463    }
464  }
465
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;
473    }
474  }
475
476  if (!to_return.get() ||
477      !to_return->waiting_for_group_start() ||
478      !to_return->IsFirstElementThreaded())
479    return to_return.release();
480
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;
492    }
493  }
494
495  if (is_wait_still_needed)
496    return to_return.release();
497
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());
506      }
507    }
508  }
509  return to_return.release();
510}
511
512void 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();
522}
523
524void 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;
533
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]));
539    }
540  }
541  ProcessQueue();
542  UpdateAnimationState();
543}
544
545void LayerAnimator::ClearAnimations() {
546  scoped_refptr<LayerAnimator> retain(this);
547  ClearAnimationsInternal();
548}
549
550LayerAnimator::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);
557  }
558  return NULL;
559}
560
561void 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;
569    }
570  }
571
572  if (!found_sequence)
573    animation_queue_.push_front(make_linked_ptr(animation));
574}
575
576void 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;
586
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]);
595    }
596  }
597
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());
604
605  for (size_t i = 0; i < sequences.size(); ++i) {
606    if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
607      continue;
608
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());
616    }
617  }
618}
619
620void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence* sequence) {
621  // Need to detect if our sequence gets destroyed.
622  base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
623      sequence->AsWeakPtr();
624
625  const bool abort = false;
626  RemoveAllAnimationsWithACommonProperty(sequence, abort);
627  if (!weak_sequence_ptr.get())
628    return;
629
630  LayerAnimationSequence* removed = RemoveAnimation(sequence);
631  DCHECK(removed == NULL || removed == sequence);
632  if (!weak_sequence_ptr.get())
633    return;
634
635  ProgressAnimationToEnd(sequence);
636  if (!weak_sequence_ptr.get())
637    return;
638
639  delete sequence;
640}
641
642void LayerAnimator::ImmediatelyAnimateToNewTarget(
643    LayerAnimationSequence* sequence) {
644  // Need to detect if our sequence gets destroyed.
645  base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
646      sequence->AsWeakPtr();
647
648  const bool abort = true;
649  RemoveAllAnimationsWithACommonProperty(sequence, abort);
650  if (!weak_sequence_ptr.get())
651    return;
652
653  AddToQueueIfNotPresent(sequence);
654  if (!weak_sequence_ptr.get())
655    return;
656
657  StartSequenceImmediately(sequence);
658}
659
660void 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();
666}
667
668void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence* sequence) {
669  // Need to detect if our sequence gets destroyed.
670  base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
671      sequence->AsWeakPtr();
672
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;
680
681    PurgeDeletedAnimations();
682
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;
689      }
690    }
691
692    if (!is_running)
693      delete RemoveAnimation(animation_queue_[i].get());
694    else
695      ++i;
696  }
697  animation_queue_.push_back(make_linked_ptr(sequence));
698  ProcessQueue();
699}
700
701void 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;
712
713      animated |= (*iter).sequence()->properties();
714    }
715
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());
724
725    for (size_t i = 0; i < sequences.size(); ++i) {
726      if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
727        continue;
728
729      if (!sequences[i]->HasConflictingProperty(animated)) {
730        StartSequenceImmediately(sequences[i].get());
731        started_sequence = true;
732        break;
733      }
734
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();
744    }
745
746    // If we started a sequence, try again. We may be able to start several.
747  } while (started_sequence);
748}
749
750bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) {
751  PurgeDeletedAnimations();
752
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;
758  }
759
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();
775
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());
782  }
783  running_animations_.push_back(
784      RunningAnimation(sequence->AsWeakPtr()));
785
786  // Need to keep a reference to the animation.
787  AddToQueueIfNotPresent(sequence);
788
789  // Ensure that animations get stepped at their start time.
790  Step(start_time);
791
792  return true;
793}
794
795void 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);
800  }
801}
802
803void 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);
809    }
810  }
811  sequence->OnScheduled();
812}
813
814void LayerAnimator::SetTransitionDuration(base::TimeDelta duration) {
815  if (is_transition_duration_locked_)
816    return;
817  transition_duration_ = duration;
818}
819
820void LayerAnimator::ClearAnimationsInternal() {
821  PurgeDeletedAnimations();
822
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;
829
830    scoped_ptr<LayerAnimationSequence> removed(
831        RemoveAnimation(running_animations_copy[i].sequence()));
832    if (removed.get())
833      removed->Abort(delegate());
834  }
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();
840}
841
842void 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++;
848  }
849}
850
851LayerAnimatorCollection* LayerAnimator::GetLayerAnimatorCollection() {
852  return delegate_ ? delegate_->GetLayerAnimatorCollection() : NULL;
853}
854
855LayerAnimator::RunningAnimation::RunningAnimation(
856    const base::WeakPtr<LayerAnimationSequence>& sequence)
857    : sequence_(sequence) {
858}
859
860LayerAnimator::RunningAnimation::~RunningAnimation() { }
861
862}  // namespace ui
863