layer_animator.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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 32namespace ui { 33 34class LayerAnimator; 35 36namespace { 37 38const int kDefaultTransitionDurationMs = 120; 39const int kTimerIntervalMs = 10; 40 41// Returns the AnimationContainer we're added to. 42gfx::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 55LayerAnimator::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 66LayerAnimator::~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 76LayerAnimator* LayerAnimator::CreateDefaultAnimator() { 77 return new LayerAnimator(base::TimeDelta::FromMilliseconds(0)); 78} 79 80// static 81LayerAnimator* 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) \ 93void 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 \ 107member_type LayerAnimator::GetTarget##name() const { \ 108 LayerAnimationElement::TargetValue target(delegate()); \ 109 GetTargetValue(&target); \ 110 return target.member; \ 111} 112 113ANIMATED_PROPERTY( 114 const gfx::Transform&, TRANSFORM, Transform, gfx::Transform, transform); 115ANIMATED_PROPERTY(const gfx::Rect&, BOUNDS, Bounds, gfx::Rect, bounds); 116ANIMATED_PROPERTY(float, OPACITY, Opacity, float, opacity); 117ANIMATED_PROPERTY(bool, VISIBILITY, Visibility, bool, visibility); 118ANIMATED_PROPERTY(float, BRIGHTNESS, Brightness, float, brightness); 119ANIMATED_PROPERTY(float, GRAYSCALE, Grayscale, float, grayscale); 120ANIMATED_PROPERTY(SkColor, COLOR, Color, SkColor, color); 121 122base::TimeDelta LayerAnimator::GetTransitionDuration() const { 123 return transition_duration_; 124} 125 126void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) { 127 delegate_ = delegate; 128} 129 130void 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 159void 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 171void 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 LayerAnimationElement::UNKNOWN; 193 194 std::vector<LayerAnimationSequence*>::const_iterator iter; 195 for (iter = animations.begin(); iter != animations.end(); ++iter) 196 animated_properties |= (*iter)->properties(); 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 225void 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 LayerAnimationElement::UNKNOWN; 232 233 std::vector<LayerAnimationSequence*>::const_iterator iter; 234 for (iter = animations.begin(); iter != animations.end(); ++iter) 235 animated_properties |= (*iter)->properties(); 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 261void LayerAnimator::SchedulePauseForProperties( 262 base::TimeDelta duration, 263 LayerAnimationElement::AnimatableProperties properties_to_pause) { 264 ScheduleAnimation(new ui::LayerAnimationSequence( 265 ui::LayerAnimationElement::CreatePauseElement( 266 properties_to_pause, duration))); 267} 268 269bool LayerAnimator::IsAnimatingProperty( 270 LayerAnimationElement::AnimatableProperty property) const { 271 for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin(); 272 queue_iter != animation_queue_.end(); ++queue_iter) { 273 if ((*queue_iter)->properties() & property) 274 return true; 275 } 276 return false; 277} 278 279void LayerAnimator::StopAnimatingProperty( 280 LayerAnimationElement::AnimatableProperty property) { 281 scoped_refptr<LayerAnimator> retain(this); 282 while (true) { 283 // GetRunningAnimation purges deleted animations before searching, so we are 284 // guaranteed to find a live animation if any is returned at all. 285 RunningAnimation* running = GetRunningAnimation(property); 286 if (!running) 287 break; 288 // As was mentioned above, this sequence must be alive. 289 DCHECK(running->is_sequence_alive()); 290 FinishAnimation(running->sequence(), false); 291 } 292} 293 294void LayerAnimator::AddObserver(LayerAnimationObserver* observer) { 295 if (!observers_.HasObserver(observer)) 296 observers_.AddObserver(observer); 297} 298 299void LayerAnimator::RemoveObserver(LayerAnimationObserver* observer) { 300 observers_.RemoveObserver(observer); 301 // Remove the observer from all sequences as well. 302 for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); 303 queue_iter != animation_queue_.end(); ++queue_iter) { 304 (*queue_iter)->RemoveObserver(observer); 305 } 306} 307 308void LayerAnimator::OnThreadedAnimationStarted( 309 const cc::AnimationEvent& event) { 310 LayerAnimationElement::AnimatableProperty property = 311 LayerAnimationElement::ToAnimatableProperty(event.target_property); 312 313 RunningAnimation* running = GetRunningAnimation(property); 314 if (!running) 315 return; 316 DCHECK(running->is_sequence_alive()); 317 318 if (running->sequence()->animation_group_id() != event.group_id) 319 return; 320 321 running->sequence()->OnThreadedAnimationStarted(event); 322 if (!running->sequence()->waiting_for_group_start()) 323 return; 324 325 base::TimeTicks start_time = event.monotonic_time; 326 327 running->sequence()->set_waiting_for_group_start(false); 328 329 // The call to GetRunningAnimation made above already purged deleted 330 // animations, so we are guaranteed that all the animations we iterate 331 // over now are alive. 332 for (RunningAnimations::iterator iter = running_animations_.begin(); 333 iter != running_animations_.end(); ++iter) { 334 // Ensure that each sequence is only Started once, regardless of the 335 // number of sequences in the group that have threaded first elements. 336 if (((*iter).sequence()->animation_group_id() == event.group_id) && 337 !(*iter).sequence()->IsFirstElementThreaded() && 338 (*iter).sequence()->waiting_for_group_start()) { 339 (*iter).sequence()->set_start_time(start_time); 340 (*iter).sequence()->set_waiting_for_group_start(false); 341 (*iter).sequence()->Start(delegate()); 342 } 343 } 344} 345 346// LayerAnimator protected ----------------------------------------------------- 347 348void LayerAnimator::ProgressAnimation(LayerAnimationSequence* sequence, 349 base::TimeTicks now) { 350 if (!delegate() || sequence->waiting_for_group_start()) 351 return; 352 353 sequence->Progress(now, delegate()); 354} 355 356void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence* sequence) { 357 if (!delegate()) 358 return; 359 360 sequence->ProgressToEnd(delegate()); 361} 362 363bool LayerAnimator::HasAnimation(LayerAnimationSequence* sequence) const { 364 for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin(); 365 queue_iter != animation_queue_.end(); ++queue_iter) { 366 if ((*queue_iter).get() == sequence) 367 return true; 368 } 369 return false; 370} 371 372// LayerAnimator private ------------------------------------------------------- 373 374void LayerAnimator::Step(base::TimeTicks now) { 375 TRACE_EVENT0("ui", "LayerAnimator::Step"); 376 scoped_refptr<LayerAnimator> retain(this); 377 378 last_step_time_ = now; 379 380 PurgeDeletedAnimations(); 381 382 // We need to make a copy of the running animations because progressing them 383 // and finishing them may indirectly affect the collection of running 384 // animations. 385 RunningAnimations running_animations_copy = running_animations_; 386 for (size_t i = 0; i < running_animations_copy.size(); ++i) { 387 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i])) 388 continue; 389 390 if (running_animations_copy[i].sequence()->IsFinished(now)) { 391 SAFE_INVOKE_VOID(FinishAnimation, running_animations_copy[i], false); 392 } else { 393 SAFE_INVOKE_VOID(ProgressAnimation, running_animations_copy[i], now); 394 } 395 } 396} 397 398void LayerAnimator::SetStartTime(base::TimeTicks start_time) { 399 // Do nothing. 400} 401 402base::TimeDelta LayerAnimator::GetTimerInterval() const { 403 return base::TimeDelta::FromMilliseconds(kTimerIntervalMs); 404} 405 406void LayerAnimator::StopAnimatingInternal(bool abort) { 407 scoped_refptr<LayerAnimator> retain(this); 408 while (is_animating()) { 409 // We're going to attempt to finish the first running animation. Let's 410 // ensure that it's valid. 411 PurgeDeletedAnimations(); 412 413 // If we've purged all running animations, attempt to start one up. 414 if (running_animations_.empty()) 415 ProcessQueue(); 416 417 DCHECK(!running_animations_.empty()); 418 419 // Still no luck, let's just bail and clear all animations. 420 if (running_animations_.empty()) { 421 ClearAnimationsInternal(); 422 break; 423 } 424 425 SAFE_INVOKE_VOID(FinishAnimation, running_animations_[0], abort); 426 } 427} 428 429void LayerAnimator::UpdateAnimationState() { 430 if (disable_timer_for_test_) 431 return; 432 433 const bool should_start = is_animating(); 434 if (should_start && !is_started_) 435 GetAnimationContainer()->Start(this); 436 else if (!should_start && is_started_) 437 GetAnimationContainer()->Stop(this); 438 439 is_started_ = should_start; 440} 441 442LayerAnimationSequence* LayerAnimator::RemoveAnimation( 443 LayerAnimationSequence* sequence) { 444 linked_ptr<LayerAnimationSequence> to_return; 445 446 bool is_running = false; 447 448 // First remove from running animations 449 for (RunningAnimations::iterator iter = running_animations_.begin(); 450 iter != running_animations_.end(); ++iter) { 451 if ((*iter).sequence() == sequence) { 452 running_animations_.erase(iter); 453 is_running = true; 454 break; 455 } 456 } 457 458 // Then remove from the queue 459 for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); 460 queue_iter != animation_queue_.end(); ++queue_iter) { 461 if ((*queue_iter) == sequence) { 462 to_return = *queue_iter; 463 animation_queue_.erase(queue_iter); 464 break; 465 } 466 } 467 468 if (!to_return.get() || 469 !to_return->waiting_for_group_start() || 470 !to_return->IsFirstElementThreaded()) 471 return to_return.release(); 472 473 // The removed sequence may have been responsible for making other sequences 474 // wait for a group start. If no other sequences in the group have a 475 // threaded first element, the group no longer needs the additional wait. 476 bool is_wait_still_needed = false; 477 int group_id = to_return->animation_group_id(); 478 for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); 479 queue_iter != animation_queue_.end(); ++queue_iter) { 480 if (((*queue_iter)->animation_group_id() == group_id) && 481 (*queue_iter)->IsFirstElementThreaded()) { 482 is_wait_still_needed = true; 483 break; 484 } 485 } 486 487 if (is_wait_still_needed) 488 return to_return.release(); 489 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)->waiting_for_group_start()) { 494 (*queue_iter)->set_waiting_for_group_start(false); 495 if (is_running) { 496 (*queue_iter)->set_start_time(last_step_time_); 497 (*queue_iter)->Start(delegate()); 498 } 499 } 500 } 501 return to_return.release(); 502} 503 504void LayerAnimator::FinishAnimation( 505 LayerAnimationSequence* sequence, bool abort) { 506 scoped_refptr<LayerAnimator> retain(this); 507 scoped_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence)); 508 if (abort) 509 sequence->Abort(delegate()); 510 else 511 ProgressAnimationToEnd(sequence); 512 ProcessQueue(); 513 UpdateAnimationState(); 514} 515 516void LayerAnimator::FinishAnyAnimationWithZeroDuration() { 517 scoped_refptr<LayerAnimator> retain(this); 518 // Special case: if we've started a 0 duration animation, just finish it now 519 // and get rid of it. We need to make a copy because Progress may indirectly 520 // cause new animations to start running. 521 RunningAnimations running_animations_copy = running_animations_; 522 for (size_t i = 0; i < running_animations_copy.size(); ++i) { 523 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i])) 524 continue; 525 526 if (running_animations_copy[i].sequence()->IsFinished( 527 running_animations_copy[i].sequence()->start_time())) { 528 SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]); 529 scoped_ptr<LayerAnimationSequence> removed( 530 SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i])); 531 } 532 } 533 ProcessQueue(); 534 UpdateAnimationState(); 535} 536 537void LayerAnimator::ClearAnimations() { 538 scoped_refptr<LayerAnimator> retain(this); 539 ClearAnimationsInternal(); 540} 541 542LayerAnimator::RunningAnimation* LayerAnimator::GetRunningAnimation( 543 LayerAnimationElement::AnimatableProperty property) { 544 PurgeDeletedAnimations(); 545 for (RunningAnimations::iterator iter = running_animations_.begin(); 546 iter != running_animations_.end(); ++iter) { 547 if ((*iter).sequence()->properties() & property) 548 return &(*iter); 549 } 550 return NULL; 551} 552 553void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence* animation) { 554 // If we don't have the animation in the queue yet, add it. 555 bool found_sequence = false; 556 for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); 557 queue_iter != animation_queue_.end(); ++queue_iter) { 558 if ((*queue_iter) == animation) { 559 found_sequence = true; 560 break; 561 } 562 } 563 564 if (!found_sequence) 565 animation_queue_.push_front(make_linked_ptr(animation)); 566} 567 568void LayerAnimator::RemoveAllAnimationsWithACommonProperty( 569 LayerAnimationSequence* sequence, bool abort) { 570 // For all the running animations, if they animate the same property, 571 // progress them to the end and remove them. Note, Aborting or Progressing 572 // animations may affect the collection of running animations, so we need to 573 // operate on a copy. 574 RunningAnimations running_animations_copy = running_animations_; 575 for (size_t i = 0; i < running_animations_copy.size(); ++i) { 576 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i])) 577 continue; 578 579 if (running_animations_copy[i].sequence()->HasConflictingProperty( 580 sequence->properties())) { 581 scoped_ptr<LayerAnimationSequence> removed( 582 SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i])); 583 if (abort) 584 running_animations_copy[i].sequence()->Abort(delegate()); 585 else 586 SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]); 587 } 588 } 589 590 // Same for the queued animations that haven't been started. Again, we'll 591 // need to operate on a copy. 592 std::vector<base::WeakPtr<LayerAnimationSequence> > sequences; 593 for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); 594 queue_iter != animation_queue_.end(); ++queue_iter) 595 sequences.push_back((*queue_iter)->AsWeakPtr()); 596 597 for (size_t i = 0; i < sequences.size(); ++i) { 598 if (!sequences[i].get() || !HasAnimation(sequences[i].get())) 599 continue; 600 601 if (sequences[i]->HasConflictingProperty(sequence->properties())) { 602 scoped_ptr<LayerAnimationSequence> removed( 603 RemoveAnimation(sequences[i].get())); 604 if (abort) 605 sequences[i]->Abort(delegate()); 606 else 607 ProgressAnimationToEnd(sequences[i].get()); 608 } 609 } 610} 611 612void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence* sequence) { 613 // Need to detect if our sequence gets destroyed. 614 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr = 615 sequence->AsWeakPtr(); 616 617 const bool abort = false; 618 RemoveAllAnimationsWithACommonProperty(sequence, abort); 619 if (!weak_sequence_ptr.get()) 620 return; 621 622 LayerAnimationSequence* removed = RemoveAnimation(sequence); 623 DCHECK(removed == NULL || removed == sequence); 624 if (!weak_sequence_ptr.get()) 625 return; 626 627 ProgressAnimationToEnd(sequence); 628 if (!weak_sequence_ptr.get()) 629 return; 630 631 delete sequence; 632} 633 634void LayerAnimator::ImmediatelyAnimateToNewTarget( 635 LayerAnimationSequence* sequence) { 636 // Need to detect if our sequence gets destroyed. 637 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr = 638 sequence->AsWeakPtr(); 639 640 const bool abort = true; 641 RemoveAllAnimationsWithACommonProperty(sequence, abort); 642 if (!weak_sequence_ptr.get()) 643 return; 644 645 AddToQueueIfNotPresent(sequence); 646 if (!weak_sequence_ptr.get()) 647 return; 648 649 StartSequenceImmediately(sequence); 650} 651 652void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence* sequence) { 653 // It is assumed that if there was no conflicting animation, we would 654 // not have been called. No need to check for a collision; just 655 // add to the queue. 656 animation_queue_.push_back(make_linked_ptr(sequence)); 657 ProcessQueue(); 658} 659 660void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence* sequence) { 661 // Need to detect if our sequence gets destroyed. 662 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr = 663 sequence->AsWeakPtr(); 664 665 // Remove all animations that aren't running. Note: at each iteration i is 666 // incremented or an element is removed from the queue, so 667 // animation_queue_.size() - i is always decreasing and we are always making 668 // progress towards the loop terminating. 669 for (size_t i = 0; i < animation_queue_.size();) { 670 if (!weak_sequence_ptr.get()) 671 break; 672 673 PurgeDeletedAnimations(); 674 675 bool is_running = false; 676 for (RunningAnimations::const_iterator iter = running_animations_.begin(); 677 iter != running_animations_.end(); ++iter) { 678 if ((*iter).sequence() == animation_queue_[i].get()) { 679 is_running = true; 680 break; 681 } 682 } 683 684 if (!is_running) 685 delete RemoveAnimation(animation_queue_[i].get()); 686 else 687 ++i; 688 } 689 animation_queue_.push_back(make_linked_ptr(sequence)); 690 ProcessQueue(); 691} 692 693void LayerAnimator::ProcessQueue() { 694 bool started_sequence = false; 695 do { 696 started_sequence = false; 697 // Build a list of all currently animated properties. 698 LayerAnimationElement::AnimatableProperties animated = 699 LayerAnimationElement::UNKNOWN; 700 for (RunningAnimations::const_iterator iter = running_animations_.begin(); 701 iter != running_animations_.end(); ++iter) { 702 if (!(*iter).is_sequence_alive()) 703 continue; 704 705 animated |= (*iter).sequence()->properties(); 706 } 707 708 // Try to find an animation that doesn't conflict with an animated 709 // property or a property that will be animated before it. Note: starting 710 // the animation may indirectly cause more animations to be started, so we 711 // need to operate on a copy. 712 std::vector<base::WeakPtr<LayerAnimationSequence> > sequences; 713 for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); 714 queue_iter != animation_queue_.end(); ++queue_iter) 715 sequences.push_back((*queue_iter)->AsWeakPtr()); 716 717 for (size_t i = 0; i < sequences.size(); ++i) { 718 if (!sequences[i].get() || !HasAnimation(sequences[i].get())) 719 continue; 720 721 if (!sequences[i]->HasConflictingProperty(animated)) { 722 StartSequenceImmediately(sequences[i].get()); 723 started_sequence = true; 724 break; 725 } 726 727 // Animation couldn't be started. Add its properties to the collection so 728 // that we don't start a conflicting animation. For example, if our queue 729 // has the elements { {T,B}, {B} } (that is, an element that animates both 730 // the transform and the bounds followed by an element that animates the 731 // bounds), and we're currently animating the transform, we can't start 732 // the first element because it animates the transform, too. We cannot 733 // start the second element, either, because the first element animates 734 // bounds too, and needs to go first. 735 animated |= sequences[i]->properties(); 736 } 737 738 // If we started a sequence, try again. We may be able to start several. 739 } while (started_sequence); 740} 741 742bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) { 743 PurgeDeletedAnimations(); 744 745 // Ensure that no one is animating one of the sequence's properties already. 746 for (RunningAnimations::const_iterator iter = running_animations_.begin(); 747 iter != running_animations_.end(); ++iter) { 748 if ((*iter).sequence()->HasConflictingProperty(sequence->properties())) 749 return false; 750 } 751 752 // All clear, actually start the sequence. Note: base::TimeTicks::Now has 753 // a resolution that can be as bad as 15ms. If this causes glitches in the 754 // animations, this can be switched to HighResNow() (animation uses Now() 755 // internally). 756 // All LayerAnimators share the same AnimationContainer. Use the 757 // last_tick_time() from there to ensure animations started during the same 758 // event complete at the same time. 759 base::TimeTicks start_time; 760 if (is_animating() || adding_animations_) 761 start_time = last_step_time_; 762 else if (GetAnimationContainer()->is_running()) 763 start_time = GetAnimationContainer()->last_tick_time(); 764 else 765 start_time = gfx::FrameTime::Now(); 766 767 if (!sequence->animation_group_id()) 768 sequence->set_animation_group_id(cc::AnimationIdProvider::NextGroupId()); 769 if (!sequence->waiting_for_group_start() || 770 sequence->IsFirstElementThreaded()) { 771 sequence->set_start_time(start_time); 772 sequence->Start(delegate()); 773 } 774 running_animations_.push_back( 775 RunningAnimation(sequence->AsWeakPtr())); 776 777 // Need to keep a reference to the animation. 778 AddToQueueIfNotPresent(sequence); 779 780 // Ensure that animations get stepped at their start time. 781 Step(start_time); 782 783 return true; 784} 785 786void LayerAnimator::GetTargetValue( 787 LayerAnimationElement::TargetValue* target) const { 788 for (AnimationQueue::const_iterator iter = animation_queue_.begin(); 789 iter != animation_queue_.end(); ++iter) { 790 (*iter)->GetTargetValue(target); 791 } 792} 793 794void LayerAnimator::OnScheduled(LayerAnimationSequence* sequence) { 795 if (observers_.might_have_observers()) { 796 ObserverListBase<LayerAnimationObserver>::Iterator it(observers_); 797 LayerAnimationObserver* obs; 798 while ((obs = it.GetNext()) != NULL) { 799 sequence->AddObserver(obs); 800 } 801 } 802 sequence->OnScheduled(); 803} 804 805void LayerAnimator::SetTransitionDuration(base::TimeDelta duration) { 806 if (is_transition_duration_locked_) 807 return; 808 transition_duration_ = duration; 809} 810 811void LayerAnimator::ClearAnimationsInternal() { 812 PurgeDeletedAnimations(); 813 814 // Abort should never affect the set of running animations, but just in case 815 // clients are badly behaved, we will use a copy of the running animations. 816 RunningAnimations running_animations_copy = running_animations_; 817 for (size_t i = 0; i < running_animations_copy.size(); ++i) { 818 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i])) 819 continue; 820 821 scoped_ptr<LayerAnimationSequence> removed( 822 RemoveAnimation(running_animations_copy[i].sequence())); 823 if (removed.get()) 824 removed->Abort(delegate()); 825 } 826 // This *should* have cleared the list of running animations. 827 DCHECK(running_animations_.empty()); 828 running_animations_.clear(); 829 animation_queue_.clear(); 830 UpdateAnimationState(); 831} 832 833void LayerAnimator::PurgeDeletedAnimations() { 834 for (size_t i = 0; i < running_animations_.size();) { 835 if (!running_animations_[i].is_sequence_alive()) 836 running_animations_.erase(running_animations_.begin() + i); 837 else 838 i++; 839 } 840} 841 842LayerAnimator::RunningAnimation::RunningAnimation( 843 const base::WeakPtr<LayerAnimationSequence>& sequence) 844 : sequence_(sequence) { 845} 846 847LayerAnimator::RunningAnimation::~RunningAnimation() { } 848 849} // namespace ui 850