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