Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(413)

Side by Side Diff: cc/layer_animation_controller.cc

Issue 12822004: Part 3 of cc/ directory shuffles: animation (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/layer_animation_controller.h ('k') | cc/layer_animation_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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/layer_animation_controller.h"
6
7 #include <algorithm>
8
9 #include "cc/animation.h"
10 #include "cc/animation_registrar.h"
11 #include "cc/base/scoped_ptr_algorithm.h"
12 #include "cc/keyframed_animation_curve.h"
13 #include "cc/layer_animation_value_observer.h"
14 #include "ui/gfx/transform.h"
15
16 namespace cc {
17
18 LayerAnimationController::LayerAnimationController(int id)
19 : force_sync_(false),
20 registrar_(0),
21 id_(id),
22 is_active_(false),
23 last_tick_time_(0) {}
24
25 LayerAnimationController::~LayerAnimationController() {
26 if (registrar_)
27 registrar_->UnregisterAnimationController(this);
28 }
29
30 scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
31 int id) {
32 return make_scoped_refptr(new LayerAnimationController(id));
33 }
34
35 void LayerAnimationController::PauseAnimation(int animation_id,
36 double time_offset) {
37 for (size_t i = 0; i < active_animations_.size(); ++i) {
38 if (active_animations_[i]->id() == animation_id) {
39 active_animations_[i]->SetRunState(
40 Animation::Paused, time_offset + active_animations_[i]->start_time());
41 }
42 }
43 }
44
45 struct HasAnimationId {
46 HasAnimationId(int id) : id_(id) {}
47 bool operator()(Animation* animation) const {
48 return animation->id() == id_;
49 }
50
51 private:
52 int id_;
53 };
54
55 void LayerAnimationController::RemoveAnimation(int animation_id) {
56 ScopedPtrVector<Animation>& animations = active_animations_;
57 animations.erase(cc::remove_if(animations,
58 animations.begin(),
59 animations.end(),
60 HasAnimationId(animation_id)),
61 animations.end());
62 UpdateActivation(NormalActivation);
63 }
64
65 struct HasAnimationIdAndProperty {
66 HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property)
67 : id_(id), target_property_(target_property) {}
68 bool operator()(Animation* animation) const {
69 return animation->id() == id_ &&
70 animation->target_property() == target_property_;
71 }
72
73 private:
74 int id_;
75 Animation::TargetProperty target_property_;
76 };
77
78 void LayerAnimationController::RemoveAnimation(
79 int animation_id,
80 Animation::TargetProperty target_property) {
81 ScopedPtrVector<Animation>& animations = active_animations_;
82 animations.erase(cc::remove_if(animations,
83 animations.begin(),
84 animations.end(),
85 HasAnimationIdAndProperty(animation_id,
86 target_property)),
87 animations.end());
88 UpdateActivation(NormalActivation);
89 }
90
91 // According to render layer backing, these are for testing only.
92 void LayerAnimationController::SuspendAnimations(double monotonic_time) {
93 for (size_t i = 0; i < active_animations_.size(); ++i) {
94 if (!active_animations_[i]->is_finished())
95 active_animations_[i]->SetRunState(Animation::Paused, monotonic_time);
96 }
97 }
98
99 // Looking at GraphicsLayerCA, this appears to be the analog to
100 // suspendAnimations, which is for testing.
101 void LayerAnimationController::ResumeAnimations(double monotonic_time) {
102 for (size_t i = 0; i < active_animations_.size(); ++i) {
103 if (active_animations_[i]->run_state() == Animation::Paused)
104 active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
105 }
106 }
107
108 // Ensures that the list of active animations on the main thread and the impl
109 // thread are kept in sync.
110 void LayerAnimationController::PushAnimationUpdatesTo(
111 LayerAnimationController* controller_impl) {
112 if (force_sync_) {
113 ReplaceImplThreadAnimations(controller_impl);
114 force_sync_ = false;
115 } else {
116 PurgeAnimationsMarkedForDeletion();
117 PushNewAnimationsToImplThread(controller_impl);
118
119 // Remove finished impl side animations only after pushing,
120 // and only after the animations are deleted on the main thread
121 // this insures we will never push an animation twice.
122 RemoveAnimationsCompletedOnMainThread(controller_impl);
123
124 PushPropertiesToImplThread(controller_impl);
125 }
126 controller_impl->UpdateActivation(NormalActivation);
127 UpdateActivation(NormalActivation);
128 }
129
130 void LayerAnimationController::Animate(double monotonic_time) {
131 if (!HasActiveObserver())
132 return;
133
134 StartAnimationsWaitingForNextTick(monotonic_time);
135 StartAnimationsWaitingForStartTime(monotonic_time);
136 StartAnimationsWaitingForTargetAvailability(monotonic_time);
137 ResolveConflicts(monotonic_time);
138 TickAnimations(monotonic_time);
139 last_tick_time_ = monotonic_time;
140 }
141
142 void LayerAnimationController::AccumulatePropertyUpdates(
143 double monotonic_time,
144 AnimationEventsVector* events) {
145 if (!events)
146 return;
147
148 for (size_t i = 0; i < active_animations_.size(); ++i) {
149 Animation* animation = active_animations_[i];
150 if (!animation->is_impl_only())
151 continue;
152
153 if (animation->target_property() == Animation::Opacity) {
154 AnimationEvent event(AnimationEvent::PropertyUpdate,
155 id_,
156 animation->group(),
157 Animation::Opacity,
158 monotonic_time);
159 event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue(
160 monotonic_time);
161
162 events->push_back(event);
163 }
164 else if (animation->target_property() == Animation::Transform) {
165 AnimationEvent event(AnimationEvent::PropertyUpdate,
166 id_,
167 animation->group(),
168 Animation::Transform,
169 monotonic_time);
170 event.transform =
171 animation->curve()->ToTransformAnimationCurve()->GetValue(
172 monotonic_time);
173 events->push_back(event);
174 }
175 }
176 }
177
178 void LayerAnimationController::UpdateState(AnimationEventsVector* events) {
179 if (!HasActiveObserver())
180 return;
181
182 PromoteStartedAnimations(last_tick_time_, events);
183 MarkFinishedAnimations(last_tick_time_);
184 MarkAnimationsForDeletion(last_tick_time_, events);
185 StartAnimationsWaitingForTargetAvailability(last_tick_time_);
186 PromoteStartedAnimations(last_tick_time_, events);
187
188 AccumulatePropertyUpdates(last_tick_time_, events);
189
190 UpdateActivation(NormalActivation);
191 }
192
193 void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
194 active_animations_.push_back(animation.Pass());
195 UpdateActivation(NormalActivation);
196 }
197
198 Animation* LayerAnimationController::GetAnimation(
199 int group_id,
200 Animation::TargetProperty target_property) const {
201 for (size_t i = 0; i < active_animations_.size(); ++i)
202 if (active_animations_[i]->group() == group_id &&
203 active_animations_[i]->target_property() == target_property)
204 return active_animations_[i];
205 return 0;
206 }
207
208 Animation* LayerAnimationController::GetAnimation(
209 Animation::TargetProperty target_property) const {
210 for (size_t i = 0; i < active_animations_.size(); ++i) {
211 size_t index = active_animations_.size() - i - 1;
212 if (active_animations_[index]->target_property() == target_property)
213 return active_animations_[index];
214 }
215 return 0;
216 }
217
218 bool LayerAnimationController::HasActiveAnimation() const {
219 for (size_t i = 0; i < active_animations_.size(); ++i) {
220 if (!active_animations_[i]->is_finished())
221 return true;
222 }
223 return false;
224 }
225
226 bool LayerAnimationController::IsAnimatingProperty(
227 Animation::TargetProperty target_property) const {
228 for (size_t i = 0; i < active_animations_.size(); ++i) {
229 if (active_animations_[i]->run_state() != Animation::Finished &&
230 active_animations_[i]->run_state() != Animation::Aborted &&
231 active_animations_[i]->target_property() == target_property)
232 return true;
233 }
234 return false;
235 }
236
237 void LayerAnimationController::OnAnimationStarted(
238 const AnimationEvent& event) {
239 for (size_t i = 0; i < active_animations_.size(); ++i) {
240 if (active_animations_[i]->group() == event.group_id &&
241 active_animations_[i]->target_property() == event.target_property &&
242 active_animations_[i]->needs_synchronized_start_time()) {
243 active_animations_[i]->set_needs_synchronized_start_time(false);
244 active_animations_[i]->set_start_time(event.monotonic_time);
245 return;
246 }
247 }
248 }
249
250 void LayerAnimationController::SetAnimationRegistrar(
251 AnimationRegistrar* registrar) {
252 if (registrar_ == registrar)
253 return;
254
255 if (registrar_)
256 registrar_->UnregisterAnimationController(this);
257
258 registrar_ = registrar;
259 if (registrar_)
260 registrar_->RegisterAnimationController(this);
261
262 UpdateActivation(ForceActivation);
263 }
264
265 void LayerAnimationController::AddObserver(
266 LayerAnimationValueObserver* observer) {
267 if (!observers_.HasObserver(observer))
268 observers_.AddObserver(observer);
269 }
270
271 void LayerAnimationController::RemoveObserver(
272 LayerAnimationValueObserver* observer) {
273 observers_.RemoveObserver(observer);
274 }
275
276 void LayerAnimationController::PushNewAnimationsToImplThread(
277 LayerAnimationController* controller_impl) const {
278 // Any new animations owned by the main thread's controller are cloned and
279 // add to the impl thread's controller.
280 for (size_t i = 0; i < active_animations_.size(); ++i) {
281 // If the animation is already running on the impl thread, there is no
282 // need to copy it over.
283 if (controller_impl->GetAnimation(active_animations_[i]->group(),
284 active_animations_[i]->target_property()))
285 continue;
286
287 // If the animation is not running on the impl thread, it does not
288 // necessarily mean that it needs to be copied over and started; it may
289 // have already finished. In this case, the impl thread animation will
290 // have already notified that it has started and the main thread animation
291 // will no longer need
292 // a synchronized start time.
293 if (!active_animations_[i]->needs_synchronized_start_time())
294 continue;
295
296 // The new animation should be set to run as soon as possible.
297 Animation::RunState initial_run_state =
298 Animation::WaitingForTargetAvailability;
299 double start_time = 0;
300 scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize(
301 Animation::ControllingInstance, initial_run_state, start_time));
302 DCHECK(!to_add->needs_synchronized_start_time());
303 controller_impl->AddAnimation(to_add.Pass());
304 }
305 }
306
307 struct IsCompleted {
308 IsCompleted(const LayerAnimationController& main_thread_controller)
309 : main_thread_controller_(main_thread_controller) {}
310 bool operator()(Animation* animation) const {
311 if (animation->is_impl_only())
312 return false;
313 return !main_thread_controller_.GetAnimation(animation->group(),
314 animation->target_property());
315 }
316
317 private:
318 const LayerAnimationController& main_thread_controller_;
319 };
320
321 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
322 LayerAnimationController* controller_impl) const {
323 // Delete all impl thread animations for which there is no corresponding
324 // main thread animation. Each iteration,
325 // controller->active_animations_.size() is decremented or i is incremented
326 // guaranteeing progress towards loop termination.
327 ScopedPtrVector<Animation>& animations =
328 controller_impl->active_animations_;
329 animations.erase(cc::remove_if(animations,
330 animations.begin(),
331 animations.end(),
332 IsCompleted(*this)),
333 animations.end());
334 }
335
336 void LayerAnimationController::PushPropertiesToImplThread(
337 LayerAnimationController* controller_impl) const {
338 for (size_t i = 0; i < active_animations_.size(); ++i) {
339 Animation* current_impl =
340 controller_impl->GetAnimation(
341 active_animations_[i]->group(),
342 active_animations_[i]->target_property());
343 if (current_impl)
344 active_animations_[i]->PushPropertiesTo(current_impl);
345 }
346 }
347
348 void LayerAnimationController::StartAnimationsWaitingForNextTick(
349 double monotonic_time) {
350 for (size_t i = 0; i < active_animations_.size(); ++i) {
351 if (active_animations_[i]->run_state() == Animation::WaitingForNextTick)
352 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
353 }
354 }
355
356 void LayerAnimationController::StartAnimationsWaitingForStartTime(
357 double monotonic_time) {
358 for (size_t i = 0; i < active_animations_.size(); ++i) {
359 if (active_animations_[i]->run_state() == Animation::WaitingForStartTime &&
360 active_animations_[i]->start_time() <= monotonic_time)
361 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
362 }
363 }
364
365 void LayerAnimationController::StartAnimationsWaitingForTargetAvailability(
366 double monotonic_time) {
367 // First collect running properties.
368 TargetProperties blocked_properties;
369 for (size_t i = 0; i < active_animations_.size(); ++i) {
370 if (active_animations_[i]->run_state() == Animation::Starting ||
371 active_animations_[i]->run_state() == Animation::Running ||
372 active_animations_[i]->run_state() == Animation::Finished)
373 blocked_properties.insert(active_animations_[i]->target_property());
374 }
375
376 for (size_t i = 0; i < active_animations_.size(); ++i) {
377 if (active_animations_[i]->run_state() ==
378 Animation::WaitingForTargetAvailability) {
379 // Collect all properties for animations with the same group id (they
380 // should all also be in the list of animations).
381 TargetProperties enqueued_properties;
382 enqueued_properties.insert(active_animations_[i]->target_property());
383 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
384 if (active_animations_[i]->group() == active_animations_[j]->group())
385 enqueued_properties.insert(active_animations_[j]->target_property());
386 }
387
388 // Check to see if intersection of the list of properties affected by
389 // the group and the list of currently blocked properties is null. In
390 // any case, the group's target properties need to be added to the list
391 // of blocked properties.
392 bool null_intersection = true;
393 for (TargetProperties::iterator p_iter = enqueued_properties.begin();
394 p_iter != enqueued_properties.end();
395 ++p_iter) {
396 if (!blocked_properties.insert(*p_iter).second)
397 null_intersection = false;
398 }
399
400 // If the intersection is null, then we are free to start the animations
401 // in the group.
402 if (null_intersection) {
403 active_animations_[i]->SetRunState(
404 Animation::Starting, monotonic_time);
405 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
406 if (active_animations_[i]->group() ==
407 active_animations_[j]->group()) {
408 active_animations_[j]->SetRunState(
409 Animation::Starting, monotonic_time);
410 }
411 }
412 }
413 }
414 }
415 }
416
417 void LayerAnimationController::PromoteStartedAnimations(
418 double monotonic_time,
419 AnimationEventsVector* events) {
420 for (size_t i = 0; i < active_animations_.size(); ++i) {
421 if (active_animations_[i]->run_state() == Animation::Starting) {
422 active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
423 if (!active_animations_[i]->has_set_start_time())
424 active_animations_[i]->set_start_time(monotonic_time);
425 if (events) {
426 events->push_back(AnimationEvent(
427 AnimationEvent::Started,
428 id_,
429 active_animations_[i]->group(),
430 active_animations_[i]->target_property(),
431 monotonic_time));
432 }
433 }
434 }
435 }
436
437 void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) {
438 for (size_t i = 0; i < active_animations_.size(); ++i) {
439 if (active_animations_[i]->IsFinishedAt(monotonic_time))
440 active_animations_[i]->SetRunState(Animation::Finished, monotonic_time);
441 }
442 }
443
444 void LayerAnimationController::ResolveConflicts(double monotonic_time) {
445 // Find any animations that are animating the same property and resolve the
446 // confict. We could eventually blend, but for now we'll just abort the
447 // previous animation (where 'previous' means: (1) has a prior start time or
448 // (2) has an equal start time, but was added to the queue earlier, i.e.,
449 // has a lower index in active_animations_).
450 for (size_t i = 0; i < active_animations_.size(); ++i) {
451 if (active_animations_[i]->run_state() == Animation::Starting ||
452 active_animations_[i]->run_state() == Animation::Running) {
453 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
454 if ((active_animations_[j]->run_state() == Animation::Starting ||
455 active_animations_[j]->run_state() == Animation::Running) &&
456 active_animations_[i]->target_property() ==
457 active_animations_[j]->target_property()) {
458 if (active_animations_[i]->start_time() >
459 active_animations_[j]->start_time()) {
460 active_animations_[j]->SetRunState(Animation::Aborted,
461 monotonic_time);
462 } else {
463 active_animations_[i]->SetRunState(Animation::Aborted,
464 monotonic_time);
465 }
466 }
467 }
468 }
469 }
470 }
471
472 void LayerAnimationController::MarkAnimationsForDeletion(
473 double monotonic_time, AnimationEventsVector* events) {
474 for (size_t i = 0; i < active_animations_.size(); i++) {
475 int group_id = active_animations_[i]->group();
476 bool all_anims_with_same_id_are_finished = false;
477 // If an animation is finished, and not already marked for deletion,
478 // Find out if all other animations in the same group are also finished.
479 if (active_animations_[i]->is_finished() &&
480 active_animations_[i]->run_state() != Animation::WaitingForDeletion) {
481 all_anims_with_same_id_are_finished = true;
482 for (size_t j = 0; j < active_animations_.size(); ++j) {
483 if (group_id == active_animations_[j]->group() &&
484 !active_animations_[j]->is_finished()) {
485 all_anims_with_same_id_are_finished = false;
486 break;
487 }
488 }
489 }
490 if (all_anims_with_same_id_are_finished) {
491 // We now need to remove all animations with the same group id as
492 // group_id (and send along animation finished notifications, if
493 // necessary).
494 for (size_t j = i; j < active_animations_.size(); j++) {
495 if (group_id == active_animations_[j]->group()) {
496 if (events) {
497 events->push_back(AnimationEvent(
498 AnimationEvent::Finished,
499 id_,
500 active_animations_[j]->group(),
501 active_animations_[j]->target_property(),
502 monotonic_time));
503 }
504 active_animations_[j]->SetRunState(Animation::WaitingForDeletion,
505 monotonic_time);
506 }
507 }
508 }
509 }
510 }
511
512 static bool IsWaitingForDeletion(Animation* animation) {
513 return animation->run_state() == Animation::WaitingForDeletion;
514 }
515
516 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
517 ScopedPtrVector<Animation>& animations = active_animations_;
518 animations.erase(cc::remove_if(animations,
519 animations.begin(),
520 animations.end(),
521 IsWaitingForDeletion),
522 animations.end());
523 }
524
525 void LayerAnimationController::ReplaceImplThreadAnimations(
526 LayerAnimationController* controller_impl) const {
527 controller_impl->active_animations_.clear();
528 for (size_t i = 0; i < active_animations_.size(); ++i) {
529 scoped_ptr<Animation> to_add;
530 if (active_animations_[i]->needs_synchronized_start_time()) {
531 // We haven't received an animation started notification yet, so it
532 // is important that we add it in a 'waiting' and not 'running' state.
533 Animation::RunState initial_run_state =
534 Animation::WaitingForTargetAvailability;
535 double start_time = 0;
536 to_add = active_animations_[i]->CloneAndInitialize(
537 Animation::ControllingInstance,
538 initial_run_state, start_time).Pass();
539 } else {
540 to_add = active_animations_[i]->Clone(
541 Animation::ControllingInstance).Pass();
542 }
543
544 controller_impl->AddAnimation(to_add.Pass());
545 }
546 }
547
548 void LayerAnimationController::TickAnimations(double monotonic_time) {
549 for (size_t i = 0; i < active_animations_.size(); ++i) {
550 if (active_animations_[i]->run_state() == Animation::Starting ||
551 active_animations_[i]->run_state() == Animation::Running ||
552 active_animations_[i]->run_state() == Animation::Paused) {
553 double trimmed =
554 active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
555
556 // Animation assumes its initial value until it gets the synchronized
557 // start time from the impl thread and can start ticking.
558 if (active_animations_[i]->needs_synchronized_start_time())
559 trimmed = 0;
560
561 // A just-started animation assumes its initial value.
562 if (active_animations_[i]->run_state() == Animation::Starting &&
563 !active_animations_[i]->has_set_start_time())
564 trimmed = 0;
565
566 switch (active_animations_[i]->target_property()) {
567
568 case Animation::Transform: {
569 const TransformAnimationCurve* transform_animation_curve =
570 active_animations_[i]->curve()->ToTransformAnimationCurve();
571 const gfx::Transform transform =
572 transform_animation_curve->GetValue(trimmed);
573 NotifyObserversTransformAnimated(transform);
574 break;
575 }
576
577 case Animation::Opacity: {
578 const FloatAnimationCurve* float_animation_curve =
579 active_animations_[i]->curve()->ToFloatAnimationCurve();
580 const float opacity = float_animation_curve->GetValue(trimmed);
581 NotifyObserversOpacityAnimated(opacity);
582 break;
583 }
584
585 // Do nothing for sentinel value.
586 case Animation::TargetPropertyEnumSize:
587 NOTREACHED();
588 }
589 }
590 }
591 }
592
593 void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
594 bool force = type == ForceActivation;
595 if (registrar_) {
596 if (!active_animations_.empty() && (!is_active_ || force))
597 registrar_->DidActivateAnimationController(this);
598 else if (active_animations_.empty() && (is_active_ || force))
599 registrar_->DidDeactivateAnimationController(this);
600 is_active_ = !active_animations_.empty();
601 }
602 }
603
604 void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) {
605 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
606 observers_,
607 OnOpacityAnimated(opacity));
608 }
609
610 void LayerAnimationController::NotifyObserversTransformAnimated(
611 const gfx::Transform& transform) {
612 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
613 observers_,
614 OnTransformAnimated(transform));
615 }
616
617 bool LayerAnimationController::HasActiveObserver() {
618 if (observers_.might_have_observers()) {
619 ObserverListBase<LayerAnimationValueObserver>::Iterator it(observers_);
620 LayerAnimationValueObserver* obs;
621 while ((obs = it.GetNext()) != NULL)
622 if (obs->IsActive())
623 return true;
624 }
625 return false;
626 }
627
628 } // namespace cc
OLDNEW
« no previous file with comments | « cc/layer_animation_controller.h ('k') | cc/layer_animation_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698