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.
5 #include "cc/layer_animation_controller.h"
9 #include "cc/animation.h"
10 #include "cc/animation_registrar.h"
11 #include "cc/keyframed_animation_curve.h"
12 #include "cc/layer_animation_value_observer.h"
13 #include "cc/scoped_ptr_algorithm.h"
14 #include "ui/gfx/transform.h"
17 gfx::Transform
convertWebTransformationMatrixToTransform(const WebKit::WebTransformationMatrix
& matrix
)
19 gfx::Transform transform
;
20 transform
.matrix().setDouble(0, 0, matrix
.m11());
21 transform
.matrix().setDouble(0, 1, matrix
.m21());
22 transform
.matrix().setDouble(0, 2, matrix
.m31());
23 transform
.matrix().setDouble(0, 3, matrix
.m41());
24 transform
.matrix().setDouble(1, 0, matrix
.m12());
25 transform
.matrix().setDouble(1, 1, matrix
.m22());
26 transform
.matrix().setDouble(1, 2, matrix
.m32());
27 transform
.matrix().setDouble(1, 3, matrix
.m42());
28 transform
.matrix().setDouble(2, 0, matrix
.m13());
29 transform
.matrix().setDouble(2, 1, matrix
.m23());
30 transform
.matrix().setDouble(2, 2, matrix
.m33());
31 transform
.matrix().setDouble(2, 3, matrix
.m43());
32 transform
.matrix().setDouble(3, 0, matrix
.m14());
33 transform
.matrix().setDouble(3, 1, matrix
.m24());
34 transform
.matrix().setDouble(3, 2, matrix
.m34());
35 transform
.matrix().setDouble(3, 3, matrix
.m44());
42 LayerAnimationController::LayerAnimationController(int id
)
50 LayerAnimationController::~LayerAnimationController()
53 m_registrar
->UnregisterAnimationController(this);
56 scoped_refptr
<LayerAnimationController
> LayerAnimationController::create(int id
)
58 return make_scoped_refptr(new LayerAnimationController(id
));
61 void LayerAnimationController::pauseAnimation(int animationId
, double timeOffset
)
63 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
64 if (m_activeAnimations
[i
]->id() == animationId
)
65 m_activeAnimations
[i
]->setRunState(Animation::Paused
, timeOffset
+ m_activeAnimations
[i
]->startTime());
69 struct HasAnimationId
{
70 HasAnimationId(int id
) : m_id(id
) { }
71 bool operator()(Animation
* animation
) const { return animation
->id() == m_id
; }
76 void LayerAnimationController::removeAnimation(int animationId
)
78 ScopedPtrVector
<Animation
>& animations
= m_activeAnimations
;
79 animations
.erase(cc::remove_if(animations
, animations
.begin(), animations
.end(), HasAnimationId(animationId
)), animations
.end());
83 struct HasAnimationIdAndProperty
{
84 HasAnimationIdAndProperty(int id
, Animation::TargetProperty targetProperty
) : m_id(id
), m_targetProperty(targetProperty
) { }
85 bool operator()(Animation
* animation
) const { return animation
->id() == m_id
&& animation
->targetProperty() == m_targetProperty
; }
88 Animation::TargetProperty m_targetProperty
;
91 void LayerAnimationController::removeAnimation(int animationId
, Animation::TargetProperty targetProperty
)
93 ScopedPtrVector
<Animation
>& animations
= m_activeAnimations
;
94 animations
.erase(cc::remove_if(animations
, animations
.begin(), animations
.end(), HasAnimationIdAndProperty(animationId
, targetProperty
)), animations
.end());
98 // According to render layer backing, these are for testing only.
99 void LayerAnimationController::suspendAnimations(double monotonicTime
)
101 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
102 if (!m_activeAnimations
[i
]->isFinished())
103 m_activeAnimations
[i
]->setRunState(Animation::Paused
, monotonicTime
);
107 // Looking at GraphicsLayerCA, this appears to be the analog to suspendAnimations, which is for testing.
108 void LayerAnimationController::resumeAnimations(double monotonicTime
)
110 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
111 if (m_activeAnimations
[i
]->runState() == Animation::Paused
)
112 m_activeAnimations
[i
]->setRunState(Animation::Running
, monotonicTime
);
116 // Ensures that the list of active animations on the main thread and the impl thread
118 void LayerAnimationController::pushAnimationUpdatesTo(LayerAnimationController
* controllerImpl
)
121 replaceImplThreadAnimations(controllerImpl
);
124 purgeAnimationsMarkedForDeletion();
125 pushNewAnimationsToImplThread(controllerImpl
);
127 // Remove finished impl side animations only after pushing,
128 // and only after the animations are deleted on the main thread
129 // this insures we will never push an animation twice.
130 removeAnimationsCompletedOnMainThread(controllerImpl
);
132 pushPropertiesToImplThread(controllerImpl
);
134 controllerImpl
->updateActivation();
138 void LayerAnimationController::animate(double monotonicTime
, AnimationEventsVector
* events
)
140 if (!hasActiveObserver())
143 startAnimationsWaitingForNextTick(monotonicTime
, events
);
144 startAnimationsWaitingForStartTime(monotonicTime
, events
);
145 startAnimationsWaitingForTargetAvailability(monotonicTime
, events
);
146 resolveConflicts(monotonicTime
);
147 tickAnimations(monotonicTime
);
148 markAnimationsForDeletion(monotonicTime
, events
);
149 startAnimationsWaitingForTargetAvailability(monotonicTime
, events
);
154 void LayerAnimationController::addAnimation(scoped_ptr
<Animation
> animation
)
156 m_activeAnimations
.push_back(animation
.Pass());
160 Animation
* LayerAnimationController::getAnimation(int groupId
, Animation::TargetProperty targetProperty
) const
162 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
)
163 if (m_activeAnimations
[i
]->group() == groupId
&& m_activeAnimations
[i
]->targetProperty() == targetProperty
)
164 return m_activeAnimations
[i
];
168 Animation
* LayerAnimationController::getAnimation(Animation::TargetProperty targetProperty
) const
170 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
171 size_t index
= m_activeAnimations
.size() - i
- 1;
172 if (m_activeAnimations
[index
]->targetProperty() == targetProperty
)
173 return m_activeAnimations
[index
];
178 bool LayerAnimationController::hasActiveAnimation() const
180 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
181 if (!m_activeAnimations
[i
]->isFinished())
187 bool LayerAnimationController::isAnimatingProperty(Animation::TargetProperty targetProperty
) const
189 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
190 if (m_activeAnimations
[i
]->runState() != Animation::Finished
&& m_activeAnimations
[i
]->runState() != Animation::Aborted
&& m_activeAnimations
[i
]->targetProperty() == targetProperty
)
196 void LayerAnimationController::OnAnimationStarted(const AnimationEvent
& event
)
198 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
199 if (m_activeAnimations
[i
]->group() == event
.groupId
&& m_activeAnimations
[i
]->targetProperty() == event
.targetProperty
&& m_activeAnimations
[i
]->needsSynchronizedStartTime()) {
200 m_activeAnimations
[i
]->setNeedsSynchronizedStartTime(false);
201 m_activeAnimations
[i
]->setStartTime(event
.monotonicTime
);
207 void LayerAnimationController::setAnimationRegistrar(AnimationRegistrar
* registrar
)
209 if (m_registrar
== registrar
)
213 m_registrar
->UnregisterAnimationController(this);
215 m_registrar
= registrar
;
217 m_registrar
->RegisterAnimationController(this);
220 updateActivation(force
);
223 void LayerAnimationController::addObserver(LayerAnimationValueObserver
* observer
)
225 if (!m_observers
.HasObserver(observer
))
226 m_observers
.AddObserver(observer
);
229 void LayerAnimationController::removeObserver(LayerAnimationValueObserver
* observer
)
231 m_observers
.RemoveObserver(observer
);
234 void LayerAnimationController::pushNewAnimationsToImplThread(LayerAnimationController
* controllerImpl
) const
236 // Any new animations owned by the main thread's controller are cloned and adde to the impl thread's controller.
237 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
238 // If the animation is already running on the impl thread, there is no need to copy it over.
239 if (controllerImpl
->getAnimation(m_activeAnimations
[i
]->group(), m_activeAnimations
[i
]->targetProperty()))
242 // If the animation is not running on the impl thread, it does not necessarily mean that it needs
243 // to be copied over and started; it may have already finished. In this case, the impl thread animation
244 // will have already notified that it has started and the main thread animation will no longer need
245 // a synchronized start time.
246 if (!m_activeAnimations
[i
]->needsSynchronizedStartTime())
249 // The new animation should be set to run as soon as possible.
250 Animation::RunState initialRunState
= Animation::WaitingForTargetAvailability
;
251 double startTime
= 0;
252 scoped_ptr
<Animation
> toAdd(m_activeAnimations
[i
]->cloneAndInitialize(Animation::ControllingInstance
, initialRunState
, startTime
));
253 DCHECK(!toAdd
->needsSynchronizedStartTime());
254 controllerImpl
->addAnimation(toAdd
.Pass());
259 IsCompleted(const LayerAnimationController
& mainThreadController
) : m_mainThreadController(mainThreadController
) { }
260 bool operator()(Animation
* animation
) const { return !m_mainThreadController
.getAnimation(animation
->group(), animation
->targetProperty()); }
262 const LayerAnimationController
& m_mainThreadController
;
265 void LayerAnimationController::removeAnimationsCompletedOnMainThread(LayerAnimationController
* controllerImpl
) const
267 // Delete all impl thread animations for which there is no corresponding main thread animation.
268 // Each iteration, controller->m_activeAnimations.size() is decremented or i is incremented
269 // guaranteeing progress towards loop termination.
270 ScopedPtrVector
<Animation
>& animations
= controllerImpl
->m_activeAnimations
;
271 animations
.erase(cc::remove_if(animations
, animations
.begin(), animations
.end(), IsCompleted(*this)), animations
.end());
274 void LayerAnimationController::pushPropertiesToImplThread(LayerAnimationController
* controllerImpl
) const
276 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
277 Animation
* currentImpl
= controllerImpl
->getAnimation(m_activeAnimations
[i
]->group(), m_activeAnimations
[i
]->targetProperty());
279 m_activeAnimations
[i
]->pushPropertiesTo(currentImpl
);
283 void LayerAnimationController::startAnimationsWaitingForNextTick(double monotonicTime
, AnimationEventsVector
* events
)
285 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
286 if (m_activeAnimations
[i
]->runState() == Animation::WaitingForNextTick
) {
287 m_activeAnimations
[i
]->setRunState(Animation::Running
, monotonicTime
);
288 if (!m_activeAnimations
[i
]->hasSetStartTime())
289 m_activeAnimations
[i
]->setStartTime(monotonicTime
);
291 events
->push_back(AnimationEvent(AnimationEvent::Started
, m_id
, m_activeAnimations
[i
]->group(), m_activeAnimations
[i
]->targetProperty(), monotonicTime
));
296 void LayerAnimationController::startAnimationsWaitingForStartTime(double monotonicTime
, AnimationEventsVector
* events
)
298 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
299 if (m_activeAnimations
[i
]->runState() == Animation::WaitingForStartTime
&& m_activeAnimations
[i
]->startTime() <= monotonicTime
) {
300 m_activeAnimations
[i
]->setRunState(Animation::Running
, monotonicTime
);
302 events
->push_back(AnimationEvent(AnimationEvent::Started
, m_id
, m_activeAnimations
[i
]->group(), m_activeAnimations
[i
]->targetProperty(), monotonicTime
));
307 void LayerAnimationController::startAnimationsWaitingForTargetAvailability(double monotonicTime
, AnimationEventsVector
* events
)
309 // First collect running properties.
310 TargetProperties blockedProperties
;
311 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
312 if (m_activeAnimations
[i
]->runState() == Animation::Running
|| m_activeAnimations
[i
]->runState() == Animation::Finished
)
313 blockedProperties
.insert(m_activeAnimations
[i
]->targetProperty());
316 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
317 if (m_activeAnimations
[i
]->runState() == Animation::WaitingForTargetAvailability
) {
318 // Collect all properties for animations with the same group id (they should all also be in the list of animations).
319 TargetProperties enqueuedProperties
;
320 enqueuedProperties
.insert(m_activeAnimations
[i
]->targetProperty());
321 for (size_t j
= i
+ 1; j
< m_activeAnimations
.size(); ++j
) {
322 if (m_activeAnimations
[i
]->group() == m_activeAnimations
[j
]->group())
323 enqueuedProperties
.insert(m_activeAnimations
[j
]->targetProperty());
326 // Check to see if intersection of the list of properties affected by the group and the list of currently
327 // blocked properties is null. In any case, the group's target properties need to be added to the list
328 // of blocked properties.
329 bool nullIntersection
= true;
330 for (TargetProperties::iterator pIter
= enqueuedProperties
.begin(); pIter
!= enqueuedProperties
.end(); ++pIter
) {
331 if (!blockedProperties
.insert(*pIter
).second
)
332 nullIntersection
= false;
335 // If the intersection is null, then we are free to start the animations in the group.
336 if (nullIntersection
) {
337 m_activeAnimations
[i
]->setRunState(Animation::Running
, monotonicTime
);
338 if (!m_activeAnimations
[i
]->hasSetStartTime())
339 m_activeAnimations
[i
]->setStartTime(monotonicTime
);
341 events
->push_back(AnimationEvent(AnimationEvent::Started
, m_id
, m_activeAnimations
[i
]->group(), m_activeAnimations
[i
]->targetProperty(), monotonicTime
));
342 for (size_t j
= i
+ 1; j
< m_activeAnimations
.size(); ++j
) {
343 if (m_activeAnimations
[i
]->group() == m_activeAnimations
[j
]->group()) {
344 m_activeAnimations
[j
]->setRunState(Animation::Running
, monotonicTime
);
345 if (!m_activeAnimations
[j
]->hasSetStartTime())
346 m_activeAnimations
[j
]->setStartTime(monotonicTime
);
354 void LayerAnimationController::resolveConflicts(double monotonicTime
)
356 // Find any animations that are animating the same property and resolve the
357 // confict. We could eventually blend, but for now we'll just abort the
358 // previous animation (where 'previous' means: (1) has a prior start time or
359 // (2) has an equal start time, but was added to the queue earlier, i.e.,
360 // has a lower index in m_activeAnimations).
361 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
362 if (m_activeAnimations
[i
]->runState() == Animation::Running
) {
363 for (size_t j
= i
+ 1; j
< m_activeAnimations
.size(); ++j
) {
364 if (m_activeAnimations
[j
]->runState() == Animation::Running
&& m_activeAnimations
[i
]->targetProperty() == m_activeAnimations
[j
]->targetProperty()) {
365 if (m_activeAnimations
[i
]->startTime() > m_activeAnimations
[j
]->startTime())
366 m_activeAnimations
[j
]->setRunState(Animation::Aborted
, monotonicTime
);
368 m_activeAnimations
[i
]->setRunState(Animation::Aborted
, monotonicTime
);
375 void LayerAnimationController::markAnimationsForDeletion(double monotonicTime
, AnimationEventsVector
* events
)
377 for (size_t i
= 0; i
< m_activeAnimations
.size(); i
++) {
378 int groupId
= m_activeAnimations
[i
]->group();
379 bool allAnimsWithSameIdAreFinished
= false;
380 // If an animation is finished, and not already marked for deletion,
381 // Find out if all other animations in the same group are also finished.
382 if (m_activeAnimations
[i
]->isFinished()) {
383 allAnimsWithSameIdAreFinished
= true;
384 for (size_t j
= 0; j
< m_activeAnimations
.size(); ++j
) {
385 if (groupId
== m_activeAnimations
[j
]->group() && !m_activeAnimations
[j
]->isFinished()) {
386 allAnimsWithSameIdAreFinished
= false;
391 if (allAnimsWithSameIdAreFinished
) {
392 // We now need to remove all animations with the same group id as groupId
393 // (and send along animation finished notifications, if necessary).
394 for (size_t j
= i
; j
< m_activeAnimations
.size(); j
++) {
395 if (groupId
== m_activeAnimations
[j
]->group()) {
397 events
->push_back(AnimationEvent(AnimationEvent::Finished
, m_id
, m_activeAnimations
[j
]->group(), m_activeAnimations
[j
]->targetProperty(), monotonicTime
));
398 m_activeAnimations
[j
]->setRunState(Animation::WaitingForDeletion
, monotonicTime
);
405 static bool isWaitingForDeletion(Animation
* animation
) { return animation
->runState() == Animation::WaitingForDeletion
; }
407 void LayerAnimationController::purgeAnimationsMarkedForDeletion()
409 ScopedPtrVector
<Animation
>& animations
= m_activeAnimations
;
410 animations
.erase(cc::remove_if(animations
, animations
.begin(), animations
.end(), isWaitingForDeletion
), animations
.end());
413 void LayerAnimationController::replaceImplThreadAnimations(LayerAnimationController
* controllerImpl
) const
415 controllerImpl
->m_activeAnimations
.clear();
416 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
417 scoped_ptr
<Animation
> toAdd
;
418 if (m_activeAnimations
[i
]->needsSynchronizedStartTime()) {
419 // We haven't received an animation started notification yet, so it
420 // is important that we add it in a 'waiting' and not 'running' state.
421 Animation::RunState initialRunState
= Animation::WaitingForTargetAvailability
;
422 double startTime
= 0;
423 toAdd
= m_activeAnimations
[i
]->cloneAndInitialize(Animation::ControllingInstance
, initialRunState
, startTime
).Pass();
425 toAdd
= m_activeAnimations
[i
]->clone(Animation::ControllingInstance
).Pass();
427 controllerImpl
->addAnimation(toAdd
.Pass());
431 void LayerAnimationController::tickAnimations(double monotonicTime
)
433 for (size_t i
= 0; i
< m_activeAnimations
.size(); ++i
) {
434 if (m_activeAnimations
[i
]->runState() == Animation::Running
|| m_activeAnimations
[i
]->runState() == Animation::Paused
) {
435 double trimmed
= m_activeAnimations
[i
]->trimTimeToCurrentIteration(monotonicTime
);
437 // Animation assumes its initial value until it gets the synchronized start time
438 // from the impl thread and can start ticking.
439 if (m_activeAnimations
[i
]->needsSynchronizedStartTime())
442 switch (m_activeAnimations
[i
]->targetProperty()) {
444 case Animation::Transform
: {
445 const TransformAnimationCurve
* transformAnimationCurve
= m_activeAnimations
[i
]->curve()->toTransformAnimationCurve();
446 const gfx::Transform transform
= convertWebTransformationMatrixToTransform(transformAnimationCurve
->getValue(trimmed
));
447 if (m_activeAnimations
[i
]->isFinishedAt(monotonicTime
))
448 m_activeAnimations
[i
]->setRunState(Animation::Finished
, monotonicTime
);
450 notifyObserversTransformAnimated(transform
);
454 case Animation::Opacity
: {
455 const FloatAnimationCurve
* floatAnimationCurve
= m_activeAnimations
[i
]->curve()->toFloatAnimationCurve();
456 const float opacity
= floatAnimationCurve
->getValue(trimmed
);
457 if (m_activeAnimations
[i
]->isFinishedAt(monotonicTime
))
458 m_activeAnimations
[i
]->setRunState(Animation::Finished
, monotonicTime
);
460 notifyObserversOpacityAnimated(opacity
);
464 // Do nothing for sentinel value.
465 case Animation::TargetPropertyEnumSize
:
472 void LayerAnimationController::updateActivation(bool force
)
475 if (!m_activeAnimations
.empty() && (!m_isActive
|| force
))
476 m_registrar
->DidActivateAnimationController(this);
477 else if (m_activeAnimations
.empty() && (m_isActive
|| force
))
478 m_registrar
->DidDeactivateAnimationController(this);
479 m_isActive
= !m_activeAnimations
.empty();
483 void LayerAnimationController::notifyObserversOpacityAnimated(float opacity
)
485 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
487 OnOpacityAnimated(opacity
));
490 void LayerAnimationController::notifyObserversTransformAnimated(const gfx::Transform
& transform
)
492 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
494 OnTransformAnimated(transform
));
497 bool LayerAnimationController::hasActiveObserver()
499 if (m_observers
.might_have_observers()) {
500 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(m_observers
);
501 LayerAnimationValueObserver
* obs
;
502 while ((obs
= it
.GetNext()) != NULL
)