OLD | NEW |
| (Empty) |
1 // Copyright 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 "cc/animation/layer_animation_controller.h" | |
6 | |
7 #include <algorithm> | |
8 #include <vector> | |
9 | |
10 #include "cc/animation/animation.h" | |
11 #include "cc/animation/animation_delegate.h" | |
12 #include "cc/animation/animation_registrar.h" | |
13 #include "cc/animation/keyframed_animation_curve.h" | |
14 #include "cc/animation/layer_animation_value_observer.h" | |
15 #include "cc/animation/layer_animation_value_provider.h" | |
16 #include "cc/animation/scroll_offset_animation_curve.h" | |
17 #include "cc/base/scoped_ptr_algorithm.h" | |
18 #include "cc/output/filter_operations.h" | |
19 #include "ui/gfx/geometry/box_f.h" | |
20 #include "ui/gfx/transform.h" | |
21 | |
22 namespace cc { | |
23 | |
24 LayerAnimationController::LayerAnimationController(int id) | |
25 : registrar_(0), | |
26 id_(id), | |
27 is_active_(false), | |
28 value_provider_(nullptr), | |
29 layer_animation_delegate_(nullptr), | |
30 needs_to_start_animations_(false), | |
31 scroll_offset_animation_was_interrupted_(false) { | |
32 } | |
33 | |
34 LayerAnimationController::~LayerAnimationController() { | |
35 if (registrar_) | |
36 registrar_->UnregisterAnimationController(this); | |
37 } | |
38 | |
39 scoped_refptr<LayerAnimationController> LayerAnimationController::Create( | |
40 int id) { | |
41 return make_scoped_refptr(new LayerAnimationController(id)); | |
42 } | |
43 | |
44 void LayerAnimationController::PauseAnimation(int animation_id, | |
45 base::TimeDelta time_offset) { | |
46 for (size_t i = 0; i < animations_.size(); ++i) { | |
47 if (animations_[i]->id() == animation_id) { | |
48 animations_[i]->SetRunState(Animation::PAUSED, | |
49 time_offset + animations_[i]->start_time()); | |
50 } | |
51 } | |
52 } | |
53 | |
54 struct HasAnimationId { | |
55 explicit HasAnimationId(int id) : id_(id) {} | |
56 bool operator()(Animation* animation) const { | |
57 return animation->id() == id_; | |
58 } | |
59 | |
60 private: | |
61 int id_; | |
62 }; | |
63 | |
64 void LayerAnimationController::RemoveAnimation(int animation_id) { | |
65 auto animations_to_remove = | |
66 animations_.remove_if(HasAnimationId(animation_id)); | |
67 for (auto it = animations_to_remove; it != animations_.end(); ++it) { | |
68 if ((*it)->target_property() == Animation::SCROLL_OFFSET) { | |
69 scroll_offset_animation_was_interrupted_ = true; | |
70 break; | |
71 } | |
72 } | |
73 animations_.erase(animations_to_remove, animations_.end()); | |
74 UpdateActivation(NORMAL_ACTIVATION); | |
75 } | |
76 | |
77 struct HasAnimationIdAndProperty { | |
78 HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property) | |
79 : id_(id), target_property_(target_property) {} | |
80 bool operator()(Animation* animation) const { | |
81 return animation->id() == id_ && | |
82 animation->target_property() == target_property_; | |
83 } | |
84 | |
85 private: | |
86 int id_; | |
87 Animation::TargetProperty target_property_; | |
88 }; | |
89 | |
90 void LayerAnimationController::RemoveAnimation( | |
91 int animation_id, | |
92 Animation::TargetProperty target_property) { | |
93 auto animations_to_remove = animations_.remove_if( | |
94 HasAnimationIdAndProperty(animation_id, target_property)); | |
95 if (target_property == Animation::SCROLL_OFFSET && | |
96 animations_to_remove != animations_.end()) | |
97 scroll_offset_animation_was_interrupted_ = true; | |
98 | |
99 animations_.erase(animations_to_remove, animations_.end()); | |
100 UpdateActivation(NORMAL_ACTIVATION); | |
101 } | |
102 | |
103 void LayerAnimationController::AbortAnimations( | |
104 Animation::TargetProperty target_property) { | |
105 for (size_t i = 0; i < animations_.size(); ++i) { | |
106 if (animations_[i]->target_property() == target_property && | |
107 !animations_[i]->is_finished()) | |
108 animations_[i]->SetRunState(Animation::ABORTED, last_tick_time_); | |
109 } | |
110 } | |
111 | |
112 // Ensures that the list of active animations on the main thread and the impl | |
113 // thread are kept in sync. | |
114 void LayerAnimationController::PushAnimationUpdatesTo( | |
115 LayerAnimationController* controller_impl) { | |
116 DCHECK(this != controller_impl); | |
117 if (!has_any_animation() && !controller_impl->has_any_animation()) | |
118 return; | |
119 PurgeAnimationsMarkedForDeletion(); | |
120 PushNewAnimationsToImplThread(controller_impl); | |
121 | |
122 // Remove finished impl side animations only after pushing, | |
123 // and only after the animations are deleted on the main thread | |
124 // this insures we will never push an animation twice. | |
125 RemoveAnimationsCompletedOnMainThread(controller_impl); | |
126 | |
127 PushPropertiesToImplThread(controller_impl); | |
128 controller_impl->UpdateActivation(NORMAL_ACTIVATION); | |
129 UpdateActivation(NORMAL_ACTIVATION); | |
130 } | |
131 | |
132 void LayerAnimationController::Animate(base::TimeTicks monotonic_time) { | |
133 DCHECK(!monotonic_time.is_null()); | |
134 if (!HasValueObserver()) | |
135 return; | |
136 | |
137 if (needs_to_start_animations_) | |
138 StartAnimations(monotonic_time); | |
139 TickAnimations(monotonic_time); | |
140 last_tick_time_ = monotonic_time; | |
141 } | |
142 | |
143 void LayerAnimationController::AccumulatePropertyUpdates( | |
144 base::TimeTicks monotonic_time, | |
145 AnimationEventsVector* events) { | |
146 if (!events) | |
147 return; | |
148 | |
149 for (size_t i = 0; i < animations_.size(); ++i) { | |
150 Animation* animation = animations_[i]; | |
151 if (!animation->is_impl_only()) | |
152 continue; | |
153 | |
154 if (!animation->InEffect(monotonic_time)) | |
155 continue; | |
156 | |
157 base::TimeDelta trimmed = | |
158 animation->TrimTimeToCurrentIteration(monotonic_time); | |
159 switch (animation->target_property()) { | |
160 case Animation::OPACITY: { | |
161 AnimationEvent event(AnimationEvent::PROPERTY_UPDATE, id_, | |
162 animation->group(), Animation::OPACITY, | |
163 monotonic_time); | |
164 const FloatAnimationCurve* float_animation_curve = | |
165 animation->curve()->ToFloatAnimationCurve(); | |
166 event.opacity = float_animation_curve->GetValue(trimmed); | |
167 event.is_impl_only = true; | |
168 events->push_back(event); | |
169 break; | |
170 } | |
171 | |
172 case Animation::TRANSFORM: { | |
173 AnimationEvent event(AnimationEvent::PROPERTY_UPDATE, id_, | |
174 animation->group(), Animation::TRANSFORM, | |
175 monotonic_time); | |
176 const TransformAnimationCurve* transform_animation_curve = | |
177 animation->curve()->ToTransformAnimationCurve(); | |
178 event.transform = transform_animation_curve->GetValue(trimmed); | |
179 event.is_impl_only = true; | |
180 events->push_back(event); | |
181 break; | |
182 } | |
183 | |
184 case Animation::FILTER: { | |
185 AnimationEvent event(AnimationEvent::PROPERTY_UPDATE, id_, | |
186 animation->group(), Animation::FILTER, | |
187 monotonic_time); | |
188 const FilterAnimationCurve* filter_animation_curve = | |
189 animation->curve()->ToFilterAnimationCurve(); | |
190 event.filters = filter_animation_curve->GetValue(trimmed); | |
191 event.is_impl_only = true; | |
192 events->push_back(event); | |
193 break; | |
194 } | |
195 | |
196 case Animation::BACKGROUND_COLOR: { | |
197 break; | |
198 } | |
199 | |
200 case Animation::SCROLL_OFFSET: { | |
201 // Impl-side changes to scroll offset are already sent back to the | |
202 // main thread (e.g. for user-driven scrolling), so a PROPERTY_UPDATE | |
203 // isn't needed. | |
204 break; | |
205 } | |
206 } | |
207 } | |
208 } | |
209 | |
210 void LayerAnimationController::UpdateState(bool start_ready_animations, | |
211 AnimationEventsVector* events) { | |
212 if (!HasActiveValueObserver()) | |
213 return; | |
214 | |
215 // Animate hasn't been called, this happens if an observer has been added | |
216 // between the Commit and Draw phases. | |
217 if (last_tick_time_ == base::TimeTicks()) | |
218 return; | |
219 | |
220 if (start_ready_animations) | |
221 PromoteStartedAnimations(last_tick_time_, events); | |
222 | |
223 MarkFinishedAnimations(last_tick_time_); | |
224 MarkAnimationsForDeletion(last_tick_time_, events); | |
225 | |
226 if (needs_to_start_animations_ && start_ready_animations) { | |
227 StartAnimations(last_tick_time_); | |
228 PromoteStartedAnimations(last_tick_time_, events); | |
229 } | |
230 | |
231 AccumulatePropertyUpdates(last_tick_time_, events); | |
232 | |
233 UpdateActivation(NORMAL_ACTIVATION); | |
234 } | |
235 | |
236 struct AffectsNoObservers { | |
237 bool operator()(Animation* animation) const { | |
238 return !animation->affects_active_observers() && | |
239 !animation->affects_pending_observers(); | |
240 } | |
241 }; | |
242 | |
243 void LayerAnimationController::ActivateAnimations() { | |
244 for (size_t i = 0; i < animations_.size(); ++i) { | |
245 animations_[i]->set_affects_active_observers( | |
246 animations_[i]->affects_pending_observers()); | |
247 } | |
248 animations_.erase(cc::remove_if(&animations_, | |
249 animations_.begin(), | |
250 animations_.end(), | |
251 AffectsNoObservers()), | |
252 animations_.end()); | |
253 scroll_offset_animation_was_interrupted_ = false; | |
254 UpdateActivation(NORMAL_ACTIVATION); | |
255 } | |
256 | |
257 void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) { | |
258 animations_.push_back(animation.Pass()); | |
259 needs_to_start_animations_ = true; | |
260 UpdateActivation(NORMAL_ACTIVATION); | |
261 } | |
262 | |
263 Animation* LayerAnimationController::GetAnimation( | |
264 Animation::TargetProperty target_property) const { | |
265 for (size_t i = 0; i < animations_.size(); ++i) { | |
266 size_t index = animations_.size() - i - 1; | |
267 if (animations_[index]->target_property() == target_property) | |
268 return animations_[index]; | |
269 } | |
270 return 0; | |
271 } | |
272 | |
273 Animation* LayerAnimationController::GetAnimationById(int animation_id) const { | |
274 for (size_t i = 0; i < animations_.size(); ++i) | |
275 if (animations_[i]->id() == animation_id) | |
276 return animations_[i]; | |
277 return nullptr; | |
278 } | |
279 | |
280 bool LayerAnimationController::HasActiveAnimation() const { | |
281 for (size_t i = 0; i < animations_.size(); ++i) { | |
282 if (!animations_[i]->is_finished()) | |
283 return true; | |
284 } | |
285 return false; | |
286 } | |
287 | |
288 bool LayerAnimationController::IsAnimatingProperty( | |
289 Animation::TargetProperty target_property) const { | |
290 for (size_t i = 0; i < animations_.size(); ++i) { | |
291 if (!animations_[i]->is_finished() && | |
292 animations_[i]->InEffect(last_tick_time_) && | |
293 animations_[i]->target_property() == target_property) | |
294 return true; | |
295 } | |
296 return false; | |
297 } | |
298 | |
299 void LayerAnimationController::SetAnimationRegistrar( | |
300 AnimationRegistrar* registrar) { | |
301 if (registrar_ == registrar) | |
302 return; | |
303 | |
304 if (registrar_) | |
305 registrar_->UnregisterAnimationController(this); | |
306 | |
307 registrar_ = registrar; | |
308 if (registrar_) | |
309 registrar_->RegisterAnimationController(this); | |
310 | |
311 UpdateActivation(FORCE_ACTIVATION); | |
312 } | |
313 | |
314 void LayerAnimationController::NotifyAnimationStarted( | |
315 const AnimationEvent& event) { | |
316 if (event.is_impl_only) { | |
317 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_, | |
318 OnAnimationStarted(event)); | |
319 if (layer_animation_delegate_) | |
320 layer_animation_delegate_->NotifyAnimationStarted( | |
321 event.monotonic_time, event.target_property, event.group_id); | |
322 return; | |
323 } | |
324 | |
325 for (size_t i = 0; i < animations_.size(); ++i) { | |
326 if (animations_[i]->group() == event.group_id && | |
327 animations_[i]->target_property() == event.target_property && | |
328 animations_[i]->needs_synchronized_start_time()) { | |
329 animations_[i]->set_needs_synchronized_start_time(false); | |
330 if (!animations_[i]->has_set_start_time()) | |
331 animations_[i]->set_start_time(event.monotonic_time); | |
332 | |
333 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_, | |
334 OnAnimationStarted(event)); | |
335 if (layer_animation_delegate_) | |
336 layer_animation_delegate_->NotifyAnimationStarted( | |
337 event.monotonic_time, event.target_property, event.group_id); | |
338 | |
339 return; | |
340 } | |
341 } | |
342 } | |
343 | |
344 void LayerAnimationController::NotifyAnimationFinished( | |
345 const AnimationEvent& event) { | |
346 if (event.is_impl_only) { | |
347 if (layer_animation_delegate_) | |
348 layer_animation_delegate_->NotifyAnimationFinished( | |
349 event.monotonic_time, event.target_property, event.group_id); | |
350 return; | |
351 } | |
352 | |
353 for (size_t i = 0; i < animations_.size(); ++i) { | |
354 if (animations_[i]->group() == event.group_id && | |
355 animations_[i]->target_property() == event.target_property) { | |
356 animations_[i]->set_received_finished_event(true); | |
357 if (layer_animation_delegate_) | |
358 layer_animation_delegate_->NotifyAnimationFinished( | |
359 event.monotonic_time, event.target_property, event.group_id); | |
360 | |
361 return; | |
362 } | |
363 } | |
364 } | |
365 | |
366 void LayerAnimationController::NotifyAnimationAborted( | |
367 const AnimationEvent& event) { | |
368 for (size_t i = 0; i < animations_.size(); ++i) { | |
369 if (animations_[i]->group() == event.group_id && | |
370 animations_[i]->target_property() == event.target_property) { | |
371 animations_[i]->SetRunState(Animation::ABORTED, event.monotonic_time); | |
372 } | |
373 } | |
374 } | |
375 | |
376 void LayerAnimationController::NotifyAnimationPropertyUpdate( | |
377 const AnimationEvent& event) { | |
378 bool notify_active_observers = true; | |
379 bool notify_pending_observers = true; | |
380 switch (event.target_property) { | |
381 case Animation::OPACITY: | |
382 NotifyObserversOpacityAnimated( | |
383 event.opacity, notify_active_observers, notify_pending_observers); | |
384 break; | |
385 case Animation::TRANSFORM: | |
386 NotifyObserversTransformAnimated( | |
387 event.transform, notify_active_observers, notify_pending_observers); | |
388 break; | |
389 default: | |
390 NOTREACHED(); | |
391 } | |
392 } | |
393 | |
394 void LayerAnimationController::AddValueObserver( | |
395 LayerAnimationValueObserver* observer) { | |
396 if (!value_observers_.HasObserver(observer)) | |
397 value_observers_.AddObserver(observer); | |
398 } | |
399 | |
400 void LayerAnimationController::RemoveValueObserver( | |
401 LayerAnimationValueObserver* observer) { | |
402 value_observers_.RemoveObserver(observer); | |
403 } | |
404 | |
405 void LayerAnimationController::AddEventObserver( | |
406 LayerAnimationEventObserver* observer) { | |
407 if (!event_observers_.HasObserver(observer)) | |
408 event_observers_.AddObserver(observer); | |
409 } | |
410 | |
411 void LayerAnimationController::RemoveEventObserver( | |
412 LayerAnimationEventObserver* observer) { | |
413 event_observers_.RemoveObserver(observer); | |
414 } | |
415 | |
416 bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const { | |
417 for (size_t i = 0; i < animations_.size(); ++i) { | |
418 if (!animations_[i]->is_finished() && | |
419 animations_[i]->target_property() == Animation::FILTER && | |
420 animations_[i] | |
421 ->curve() | |
422 ->ToFilterAnimationCurve() | |
423 ->HasFilterThatMovesPixels()) | |
424 return true; | |
425 } | |
426 | |
427 return false; | |
428 } | |
429 | |
430 bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const { | |
431 return IsAnimatingProperty(Animation::TRANSFORM); | |
432 } | |
433 | |
434 bool LayerAnimationController::FilterAnimationBoundsForBox( | |
435 const gfx::BoxF& box, gfx::BoxF* bounds) const { | |
436 // TODO(avallee): Implement. | |
437 return false; | |
438 } | |
439 | |
440 bool LayerAnimationController::TransformAnimationBoundsForBox( | |
441 const gfx::BoxF& box, | |
442 gfx::BoxF* bounds) const { | |
443 DCHECK(HasTransformAnimationThatInflatesBounds()) | |
444 << "TransformAnimationBoundsForBox will give incorrect results if there " | |
445 << "are no transform animations affecting bounds, non-animated transform " | |
446 << "is not known"; | |
447 | |
448 // Compute bounds based on animations for which is_finished() is false. | |
449 // Do nothing if there are no such animations; in this case, it is assumed | |
450 // that callers will take care of computing bounds based on the owning layer's | |
451 // actual transform. | |
452 *bounds = gfx::BoxF(); | |
453 for (size_t i = 0; i < animations_.size(); ++i) { | |
454 if (animations_[i]->is_finished() || | |
455 animations_[i]->target_property() != Animation::TRANSFORM) | |
456 continue; | |
457 | |
458 const TransformAnimationCurve* transform_animation_curve = | |
459 animations_[i]->curve()->ToTransformAnimationCurve(); | |
460 gfx::BoxF animation_bounds; | |
461 bool success = | |
462 transform_animation_curve->AnimatedBoundsForBox(box, &animation_bounds); | |
463 if (!success) | |
464 return false; | |
465 bounds->Union(animation_bounds); | |
466 } | |
467 | |
468 return true; | |
469 } | |
470 | |
471 bool LayerAnimationController::HasAnimationThatAffectsScale() const { | |
472 for (size_t i = 0; i < animations_.size(); ++i) { | |
473 if (animations_[i]->is_finished() || | |
474 animations_[i]->target_property() != Animation::TRANSFORM) | |
475 continue; | |
476 | |
477 const TransformAnimationCurve* transform_animation_curve = | |
478 animations_[i]->curve()->ToTransformAnimationCurve(); | |
479 if (transform_animation_curve->AffectsScale()) | |
480 return true; | |
481 } | |
482 | |
483 return false; | |
484 } | |
485 | |
486 bool LayerAnimationController::HasOnlyTranslationTransforms() const { | |
487 for (size_t i = 0; i < animations_.size(); ++i) { | |
488 if (animations_[i]->is_finished() || | |
489 animations_[i]->target_property() != Animation::TRANSFORM) | |
490 continue; | |
491 | |
492 const TransformAnimationCurve* transform_animation_curve = | |
493 animations_[i]->curve()->ToTransformAnimationCurve(); | |
494 if (!transform_animation_curve->IsTranslation()) | |
495 return false; | |
496 } | |
497 | |
498 return true; | |
499 } | |
500 | |
501 bool LayerAnimationController::AnimationsPreserveAxisAlignment() const { | |
502 for (size_t i = 0; i < animations_.size(); ++i) { | |
503 if (animations_[i]->is_finished() || | |
504 animations_[i]->target_property() != Animation::TRANSFORM) | |
505 continue; | |
506 | |
507 const TransformAnimationCurve* transform_animation_curve = | |
508 animations_[i]->curve()->ToTransformAnimationCurve(); | |
509 if (!transform_animation_curve->PreservesAxisAlignment()) | |
510 return false; | |
511 } | |
512 | |
513 return true; | |
514 } | |
515 | |
516 bool LayerAnimationController::MaximumTargetScale(float* max_scale) const { | |
517 *max_scale = 0.f; | |
518 for (size_t i = 0; i < animations_.size(); ++i) { | |
519 if (animations_[i]->is_finished() || | |
520 animations_[i]->target_property() != Animation::TRANSFORM) | |
521 continue; | |
522 | |
523 bool forward_direction = true; | |
524 switch (animations_[i]->direction()) { | |
525 case Animation::DIRECTION_NORMAL: | |
526 case Animation::DIRECTION_ALTERNATE: | |
527 forward_direction = animations_[i]->playback_rate() >= 0.0; | |
528 break; | |
529 case Animation::DIRECTION_REVERSE: | |
530 case Animation::DIRECTION_ALTERNATE_REVERSE: | |
531 forward_direction = animations_[i]->playback_rate() < 0.0; | |
532 break; | |
533 } | |
534 | |
535 const TransformAnimationCurve* transform_animation_curve = | |
536 animations_[i]->curve()->ToTransformAnimationCurve(); | |
537 float animation_scale = 0.f; | |
538 if (!transform_animation_curve->MaximumTargetScale(forward_direction, | |
539 &animation_scale)) | |
540 return false; | |
541 *max_scale = std::max(*max_scale, animation_scale); | |
542 } | |
543 | |
544 return true; | |
545 } | |
546 | |
547 void LayerAnimationController::PushNewAnimationsToImplThread( | |
548 LayerAnimationController* controller_impl) const { | |
549 // Any new animations owned by the main thread's controller are cloned and | |
550 // add to the impl thread's controller. | |
551 for (size_t i = 0; i < animations_.size(); ++i) { | |
552 // If the animation is already running on the impl thread, there is no | |
553 // need to copy it over. | |
554 if (controller_impl->GetAnimationById(animations_[i]->id())) | |
555 continue; | |
556 | |
557 // If the animation is not running on the impl thread, it does not | |
558 // necessarily mean that it needs to be copied over and started; it may | |
559 // have already finished. In this case, the impl thread animation will | |
560 // have already notified that it has started and the main thread animation | |
561 // will no longer need | |
562 // a synchronized start time. | |
563 if (!animations_[i]->needs_synchronized_start_time()) | |
564 continue; | |
565 | |
566 // Scroll animations always start at the current scroll offset. | |
567 if (animations_[i]->target_property() == Animation::SCROLL_OFFSET) { | |
568 gfx::ScrollOffset current_scroll_offset; | |
569 if (controller_impl->value_provider_) { | |
570 current_scroll_offset = | |
571 controller_impl->value_provider_->ScrollOffsetForAnimation(); | |
572 } else { | |
573 // The owning layer isn't yet in the active tree, so the main thread | |
574 // scroll offset will be up-to-date. | |
575 current_scroll_offset = value_provider_->ScrollOffsetForAnimation(); | |
576 } | |
577 animations_[i]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue( | |
578 current_scroll_offset); | |
579 } | |
580 | |
581 // The new animation should be set to run as soon as possible. | |
582 Animation::RunState initial_run_state = | |
583 Animation::WAITING_FOR_TARGET_AVAILABILITY; | |
584 scoped_ptr<Animation> to_add( | |
585 animations_[i]->CloneAndInitialize(initial_run_state)); | |
586 DCHECK(!to_add->needs_synchronized_start_time()); | |
587 to_add->set_affects_active_observers(false); | |
588 controller_impl->AddAnimation(to_add.Pass()); | |
589 } | |
590 } | |
591 | |
592 static bool IsCompleted( | |
593 Animation* animation, | |
594 const LayerAnimationController* main_thread_controller) { | |
595 if (animation->is_impl_only()) { | |
596 return (animation->run_state() == Animation::WAITING_FOR_DELETION); | |
597 } else { | |
598 return !main_thread_controller->GetAnimationById(animation->id()); | |
599 } | |
600 } | |
601 | |
602 static bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation* animation) { | |
603 return animation->run_state() == Animation::WAITING_FOR_DELETION && | |
604 !animation->affects_pending_observers(); | |
605 } | |
606 | |
607 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread( | |
608 LayerAnimationController* controller_impl) const { | |
609 // Animations removed on the main thread should no longer affect pending | |
610 // observers, and should stop affecting active observers after the next call | |
611 // to ActivateAnimations. If already WAITING_FOR_DELETION, they can be removed | |
612 // immediately. | |
613 ScopedPtrVector<Animation>& animations = controller_impl->animations_; | |
614 for (size_t i = 0; i < animations.size(); ++i) { | |
615 if (IsCompleted(animations[i], this)) | |
616 animations[i]->set_affects_pending_observers(false); | |
617 } | |
618 animations.erase(cc::remove_if(&animations, | |
619 animations.begin(), | |
620 animations.end(), | |
621 AffectsActiveOnlyAndIsWaitingForDeletion), | |
622 animations.end()); | |
623 } | |
624 | |
625 void LayerAnimationController::PushPropertiesToImplThread( | |
626 LayerAnimationController* controller_impl) { | |
627 for (size_t i = 0; i < animations_.size(); ++i) { | |
628 Animation* current_impl = | |
629 controller_impl->GetAnimationById(animations_[i]->id()); | |
630 if (current_impl) | |
631 animations_[i]->PushPropertiesTo(current_impl); | |
632 } | |
633 controller_impl->scroll_offset_animation_was_interrupted_ = | |
634 scroll_offset_animation_was_interrupted_; | |
635 scroll_offset_animation_was_interrupted_ = false; | |
636 } | |
637 | |
638 void LayerAnimationController::StartAnimations(base::TimeTicks monotonic_time) { | |
639 DCHECK(needs_to_start_animations_); | |
640 needs_to_start_animations_ = false; | |
641 // First collect running properties affecting each type of observer. | |
642 TargetProperties blocked_properties_for_active_observers; | |
643 TargetProperties blocked_properties_for_pending_observers; | |
644 std::vector<size_t> animations_waiting_for_target; | |
645 | |
646 animations_waiting_for_target.reserve(animations_.size()); | |
647 for (size_t i = 0; i < animations_.size(); ++i) { | |
648 if (animations_[i]->run_state() == Animation::STARTING || | |
649 animations_[i]->run_state() == Animation::RUNNING) { | |
650 if (animations_[i]->affects_active_observers()) { | |
651 blocked_properties_for_active_observers.insert( | |
652 animations_[i]->target_property()); | |
653 } | |
654 if (animations_[i]->affects_pending_observers()) { | |
655 blocked_properties_for_pending_observers.insert( | |
656 animations_[i]->target_property()); | |
657 } | |
658 } else if (animations_[i]->run_state() == | |
659 Animation::WAITING_FOR_TARGET_AVAILABILITY) { | |
660 animations_waiting_for_target.push_back(i); | |
661 } | |
662 } | |
663 | |
664 for (size_t i = 0; i < animations_waiting_for_target.size(); ++i) { | |
665 // Collect all properties for animations with the same group id (they | |
666 // should all also be in the list of animations). | |
667 size_t animation_index = animations_waiting_for_target[i]; | |
668 Animation* animation_waiting_for_target = animations_[animation_index]; | |
669 // Check for the run state again even though the animation was waiting | |
670 // for target because it might have changed the run state while handling | |
671 // previous animation in this loop (if they belong to same group). | |
672 if (animation_waiting_for_target->run_state() == | |
673 Animation::WAITING_FOR_TARGET_AVAILABILITY) { | |
674 TargetProperties enqueued_properties; | |
675 bool affects_active_observers = | |
676 animation_waiting_for_target->affects_active_observers(); | |
677 bool affects_pending_observers = | |
678 animation_waiting_for_target->affects_pending_observers(); | |
679 enqueued_properties.insert( | |
680 animation_waiting_for_target->target_property()); | |
681 for (size_t j = animation_index + 1; j < animations_.size(); ++j) { | |
682 if (animation_waiting_for_target->group() == animations_[j]->group()) { | |
683 enqueued_properties.insert(animations_[j]->target_property()); | |
684 affects_active_observers |= | |
685 animations_[j]->affects_active_observers(); | |
686 affects_pending_observers |= | |
687 animations_[j]->affects_pending_observers(); | |
688 } | |
689 } | |
690 | |
691 // Check to see if intersection of the list of properties affected by | |
692 // the group and the list of currently blocked properties is null, taking | |
693 // into account the type(s) of observers affected by the group. In any | |
694 // case, the group's target properties need to be added to the lists of | |
695 // blocked properties. | |
696 bool null_intersection = true; | |
697 for (TargetProperties::iterator p_iter = enqueued_properties.begin(); | |
698 p_iter != enqueued_properties.end(); | |
699 ++p_iter) { | |
700 if (affects_active_observers && | |
701 !blocked_properties_for_active_observers.insert(*p_iter).second) | |
702 null_intersection = false; | |
703 if (affects_pending_observers && | |
704 !blocked_properties_for_pending_observers.insert(*p_iter).second) | |
705 null_intersection = false; | |
706 } | |
707 | |
708 // If the intersection is null, then we are free to start the animations | |
709 // in the group. | |
710 if (null_intersection) { | |
711 animation_waiting_for_target->SetRunState(Animation::STARTING, | |
712 monotonic_time); | |
713 for (size_t j = animation_index + 1; j < animations_.size(); ++j) { | |
714 if (animation_waiting_for_target->group() == | |
715 animations_[j]->group()) { | |
716 animations_[j]->SetRunState(Animation::STARTING, monotonic_time); | |
717 } | |
718 } | |
719 } else { | |
720 needs_to_start_animations_ = true; | |
721 } | |
722 } | |
723 } | |
724 } | |
725 | |
726 void LayerAnimationController::PromoteStartedAnimations( | |
727 base::TimeTicks monotonic_time, | |
728 AnimationEventsVector* events) { | |
729 for (size_t i = 0; i < animations_.size(); ++i) { | |
730 if (animations_[i]->run_state() == Animation::STARTING && | |
731 animations_[i]->affects_active_observers()) { | |
732 animations_[i]->SetRunState(Animation::RUNNING, monotonic_time); | |
733 if (!animations_[i]->has_set_start_time() && | |
734 !animations_[i]->needs_synchronized_start_time()) | |
735 animations_[i]->set_start_time(monotonic_time); | |
736 if (events) { | |
737 AnimationEvent started_event( | |
738 AnimationEvent::STARTED, id_, animations_[i]->group(), | |
739 animations_[i]->target_property(), monotonic_time); | |
740 started_event.is_impl_only = animations_[i]->is_impl_only(); | |
741 if (started_event.is_impl_only) | |
742 NotifyAnimationStarted(started_event); | |
743 else | |
744 events->push_back(started_event); | |
745 } | |
746 } | |
747 } | |
748 } | |
749 | |
750 void LayerAnimationController::MarkFinishedAnimations( | |
751 base::TimeTicks monotonic_time) { | |
752 for (size_t i = 0; i < animations_.size(); ++i) { | |
753 if (animations_[i]->IsFinishedAt(monotonic_time) && | |
754 animations_[i]->run_state() != Animation::ABORTED && | |
755 animations_[i]->run_state() != Animation::WAITING_FOR_DELETION) | |
756 animations_[i]->SetRunState(Animation::FINISHED, monotonic_time); | |
757 } | |
758 } | |
759 | |
760 void LayerAnimationController::MarkAnimationsForDeletion( | |
761 base::TimeTicks monotonic_time, | |
762 AnimationEventsVector* events) { | |
763 bool marked_animations_for_deletions = false; | |
764 std::vector<size_t> animations_with_same_group_id; | |
765 | |
766 animations_with_same_group_id.reserve(animations_.size()); | |
767 // Non-aborted animations are marked for deletion after a corresponding | |
768 // AnimationEvent::FINISHED event is sent or received. This means that if | |
769 // we don't have an events vector, we must ensure that non-aborted animations | |
770 // have received a finished event before marking them for deletion. | |
771 for (size_t i = 0; i < animations_.size(); i++) { | |
772 int group_id = animations_[i]->group(); | |
773 if (animations_[i]->run_state() == Animation::ABORTED) { | |
774 if (events && !animations_[i]->is_impl_only()) { | |
775 AnimationEvent aborted_event(AnimationEvent::ABORTED, id_, group_id, | |
776 animations_[i]->target_property(), | |
777 monotonic_time); | |
778 events->push_back(aborted_event); | |
779 } | |
780 animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION, | |
781 monotonic_time); | |
782 marked_animations_for_deletions = true; | |
783 continue; | |
784 } | |
785 | |
786 bool all_anims_with_same_id_are_finished = false; | |
787 | |
788 // Since deleting an animation on the main thread leads to its deletion | |
789 // on the impl thread, we only mark a FINISHED main thread animation for | |
790 // deletion once it has received a FINISHED event from the impl thread. | |
791 bool animation_i_will_send_or_has_received_finish_event = | |
792 events || animations_[i]->received_finished_event(); | |
793 // If an animation is finished, and not already marked for deletion, | |
794 // find out if all other animations in the same group are also finished. | |
795 if (animations_[i]->run_state() == Animation::FINISHED && | |
796 animation_i_will_send_or_has_received_finish_event) { | |
797 // Clear the animations_with_same_group_id if it was added for | |
798 // the previous animation's iteration. | |
799 if (animations_with_same_group_id.size() > 0) | |
800 animations_with_same_group_id.clear(); | |
801 all_anims_with_same_id_are_finished = true; | |
802 for (size_t j = 0; j < animations_.size(); ++j) { | |
803 bool animation_j_will_send_or_has_received_finish_event = | |
804 events || animations_[j]->received_finished_event(); | |
805 if (group_id == animations_[j]->group()) { | |
806 if (!animations_[j]->is_finished() || | |
807 (animations_[j]->run_state() == Animation::FINISHED && | |
808 !animation_j_will_send_or_has_received_finish_event)) { | |
809 all_anims_with_same_id_are_finished = false; | |
810 break; | |
811 } else if (j >= i && | |
812 animations_[j]->run_state() != Animation::ABORTED) { | |
813 // Mark down the animations which belong to the same group | |
814 // and is not yet aborted. If this current iteration finds that all | |
815 // animations with same ID are finished, then the marked | |
816 // animations below will be set to WAITING_FOR_DELETION in next | |
817 // iteration. | |
818 animations_with_same_group_id.push_back(j); | |
819 } | |
820 } | |
821 } | |
822 } | |
823 if (all_anims_with_same_id_are_finished) { | |
824 // We now need to remove all animations with the same group id as | |
825 // group_id (and send along animation finished notifications, if | |
826 // necessary). | |
827 for (size_t j = 0; j < animations_with_same_group_id.size(); j++) { | |
828 size_t animation_index = animations_with_same_group_id[j]; | |
829 if (events) { | |
830 AnimationEvent finished_event( | |
831 AnimationEvent::FINISHED, id_, | |
832 animations_[animation_index]->group(), | |
833 animations_[animation_index]->target_property(), | |
834 monotonic_time); | |
835 finished_event.is_impl_only = | |
836 animations_[animation_index]->is_impl_only(); | |
837 if (finished_event.is_impl_only) | |
838 NotifyAnimationFinished(finished_event); | |
839 else | |
840 events->push_back(finished_event); | |
841 } | |
842 animations_[animation_index]->SetRunState( | |
843 Animation::WAITING_FOR_DELETION, monotonic_time); | |
844 } | |
845 marked_animations_for_deletions = true; | |
846 } | |
847 } | |
848 if (marked_animations_for_deletions) | |
849 NotifyObserversAnimationWaitingForDeletion(); | |
850 } | |
851 | |
852 static bool IsWaitingForDeletion(Animation* animation) { | |
853 return animation->run_state() == Animation::WAITING_FOR_DELETION; | |
854 } | |
855 | |
856 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() { | |
857 animations_.erase(cc::remove_if(&animations_, | |
858 animations_.begin(), | |
859 animations_.end(), | |
860 IsWaitingForDeletion), | |
861 animations_.end()); | |
862 } | |
863 | |
864 void LayerAnimationController::TickAnimations(base::TimeTicks monotonic_time) { | |
865 for (size_t i = 0; i < animations_.size(); ++i) { | |
866 if (animations_[i]->run_state() == Animation::STARTING || | |
867 animations_[i]->run_state() == Animation::RUNNING || | |
868 animations_[i]->run_state() == Animation::PAUSED) { | |
869 if (!animations_[i]->InEffect(monotonic_time)) | |
870 continue; | |
871 | |
872 base::TimeDelta trimmed = | |
873 animations_[i]->TrimTimeToCurrentIteration(monotonic_time); | |
874 | |
875 switch (animations_[i]->target_property()) { | |
876 case Animation::TRANSFORM: { | |
877 const TransformAnimationCurve* transform_animation_curve = | |
878 animations_[i]->curve()->ToTransformAnimationCurve(); | |
879 const gfx::Transform transform = | |
880 transform_animation_curve->GetValue(trimmed); | |
881 NotifyObserversTransformAnimated( | |
882 transform, | |
883 animations_[i]->affects_active_observers(), | |
884 animations_[i]->affects_pending_observers()); | |
885 break; | |
886 } | |
887 | |
888 case Animation::OPACITY: { | |
889 const FloatAnimationCurve* float_animation_curve = | |
890 animations_[i]->curve()->ToFloatAnimationCurve(); | |
891 const float opacity = std::max( | |
892 std::min(float_animation_curve->GetValue(trimmed), 1.0f), 0.f); | |
893 NotifyObserversOpacityAnimated( | |
894 opacity, | |
895 animations_[i]->affects_active_observers(), | |
896 animations_[i]->affects_pending_observers()); | |
897 break; | |
898 } | |
899 | |
900 case Animation::FILTER: { | |
901 const FilterAnimationCurve* filter_animation_curve = | |
902 animations_[i]->curve()->ToFilterAnimationCurve(); | |
903 const FilterOperations filter = | |
904 filter_animation_curve->GetValue(trimmed); | |
905 NotifyObserversFilterAnimated( | |
906 filter, | |
907 animations_[i]->affects_active_observers(), | |
908 animations_[i]->affects_pending_observers()); | |
909 break; | |
910 } | |
911 | |
912 case Animation::BACKGROUND_COLOR: { | |
913 // Not yet implemented. | |
914 break; | |
915 } | |
916 | |
917 case Animation::SCROLL_OFFSET: { | |
918 const ScrollOffsetAnimationCurve* scroll_offset_animation_curve = | |
919 animations_[i]->curve()->ToScrollOffsetAnimationCurve(); | |
920 const gfx::ScrollOffset scroll_offset = | |
921 scroll_offset_animation_curve->GetValue(trimmed); | |
922 NotifyObserversScrollOffsetAnimated( | |
923 scroll_offset, | |
924 animations_[i]->affects_active_observers(), | |
925 animations_[i]->affects_pending_observers()); | |
926 break; | |
927 } | |
928 } | |
929 } | |
930 } | |
931 } | |
932 | |
933 void LayerAnimationController::UpdateActivation(UpdateActivationType type) { | |
934 bool force = type == FORCE_ACTIVATION; | |
935 if (registrar_) { | |
936 bool was_active = is_active_; | |
937 is_active_ = false; | |
938 for (size_t i = 0; i < animations_.size(); ++i) { | |
939 if (animations_[i]->run_state() != Animation::WAITING_FOR_DELETION) { | |
940 is_active_ = true; | |
941 break; | |
942 } | |
943 } | |
944 | |
945 if (is_active_ && (!was_active || force)) | |
946 registrar_->DidActivateAnimationController(this); | |
947 else if (!is_active_ && (was_active || force)) | |
948 registrar_->DidDeactivateAnimationController(this); | |
949 } | |
950 } | |
951 | |
952 void LayerAnimationController::NotifyObserversOpacityAnimated( | |
953 float opacity, | |
954 bool notify_active_observers, | |
955 bool notify_pending_observers) { | |
956 if (value_observers_.might_have_observers()) { | |
957 ObserverListBase<LayerAnimationValueObserver>::Iterator it( | |
958 &value_observers_); | |
959 LayerAnimationValueObserver* obs; | |
960 while ((obs = it.GetNext()) != nullptr) { | |
961 if ((notify_active_observers && notify_pending_observers) || | |
962 (notify_active_observers && obs->IsActive()) || | |
963 (notify_pending_observers && !obs->IsActive())) | |
964 obs->OnOpacityAnimated(opacity); | |
965 } | |
966 } | |
967 } | |
968 | |
969 void LayerAnimationController::NotifyObserversTransformAnimated( | |
970 const gfx::Transform& transform, | |
971 bool notify_active_observers, | |
972 bool notify_pending_observers) { | |
973 if (value_observers_.might_have_observers()) { | |
974 ObserverListBase<LayerAnimationValueObserver>::Iterator it( | |
975 &value_observers_); | |
976 LayerAnimationValueObserver* obs; | |
977 while ((obs = it.GetNext()) != nullptr) { | |
978 if ((notify_active_observers && notify_pending_observers) || | |
979 (notify_active_observers && obs->IsActive()) || | |
980 (notify_pending_observers && !obs->IsActive())) | |
981 obs->OnTransformAnimated(transform); | |
982 } | |
983 } | |
984 } | |
985 | |
986 void LayerAnimationController::NotifyObserversFilterAnimated( | |
987 const FilterOperations& filters, | |
988 bool notify_active_observers, | |
989 bool notify_pending_observers) { | |
990 if (value_observers_.might_have_observers()) { | |
991 ObserverListBase<LayerAnimationValueObserver>::Iterator it( | |
992 &value_observers_); | |
993 LayerAnimationValueObserver* obs; | |
994 while ((obs = it.GetNext()) != nullptr) { | |
995 if ((notify_active_observers && notify_pending_observers) || | |
996 (notify_active_observers && obs->IsActive()) || | |
997 (notify_pending_observers && !obs->IsActive())) | |
998 obs->OnFilterAnimated(filters); | |
999 } | |
1000 } | |
1001 } | |
1002 | |
1003 void LayerAnimationController::NotifyObserversScrollOffsetAnimated( | |
1004 const gfx::ScrollOffset& scroll_offset, | |
1005 bool notify_active_observers, | |
1006 bool notify_pending_observers) { | |
1007 if (value_observers_.might_have_observers()) { | |
1008 ObserverListBase<LayerAnimationValueObserver>::Iterator it( | |
1009 &value_observers_); | |
1010 LayerAnimationValueObserver* obs; | |
1011 while ((obs = it.GetNext()) != nullptr) { | |
1012 if ((notify_active_observers && notify_pending_observers) || | |
1013 (notify_active_observers && obs->IsActive()) || | |
1014 (notify_pending_observers && !obs->IsActive())) | |
1015 obs->OnScrollOffsetAnimated(scroll_offset); | |
1016 } | |
1017 } | |
1018 } | |
1019 | |
1020 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() { | |
1021 FOR_EACH_OBSERVER(LayerAnimationValueObserver, | |
1022 value_observers_, | |
1023 OnAnimationWaitingForDeletion()); | |
1024 } | |
1025 | |
1026 bool LayerAnimationController::HasValueObserver() { | |
1027 if (value_observers_.might_have_observers()) { | |
1028 ObserverListBase<LayerAnimationValueObserver>::Iterator it( | |
1029 &value_observers_); | |
1030 return it.GetNext() != nullptr; | |
1031 } | |
1032 return false; | |
1033 } | |
1034 | |
1035 bool LayerAnimationController::HasActiveValueObserver() { | |
1036 if (value_observers_.might_have_observers()) { | |
1037 ObserverListBase<LayerAnimationValueObserver>::Iterator it( | |
1038 &value_observers_); | |
1039 LayerAnimationValueObserver* obs; | |
1040 while ((obs = it.GetNext()) != nullptr) | |
1041 if (obs->IsActive()) | |
1042 return true; | |
1043 } | |
1044 return false; | |
1045 } | |
1046 | |
1047 } // namespace cc | |
OLD | NEW |