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