WebKit Roll 139512:139548
[chromium-blink-merge.git] / cc / layer_animation_controller.cc
blobd5ed278bc57932638f4de36a9a67dc26f2399e3f
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"
7 #include <algorithm>
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"
16 namespace {
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());
36 return transform;
38 } // namespace
40 namespace cc {
42 LayerAnimationController::LayerAnimationController(int id)
43 : m_forceSync(false)
44 , m_id(id)
45 , m_registrar(0)
46 , m_isActive(false)
50 LayerAnimationController::~LayerAnimationController()
52 if (m_registrar)
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; }
72 private:
73 int 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());
80 updateActivation();
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; }
86 private:
87 int m_id;
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());
95 updateActivation();
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
117 // are kept in sync.
118 void LayerAnimationController::pushAnimationUpdatesTo(LayerAnimationController* controllerImpl)
120 if (m_forceSync) {
121 replaceImplThreadAnimations(controllerImpl);
122 m_forceSync = false;
123 } else {
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();
135 updateActivation();
138 void LayerAnimationController::animate(double monotonicTime, AnimationEventsVector* events)
140 if (!hasActiveObserver())
141 return;
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);
151 updateActivation();
154 void LayerAnimationController::addAnimation(scoped_ptr<Animation> animation)
156 m_activeAnimations.push_back(animation.Pass());
157 updateActivation();
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];
165 return 0;
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];
175 return 0;
178 bool LayerAnimationController::hasActiveAnimation() const
180 for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
181 if (!m_activeAnimations[i]->isFinished())
182 return true;
184 return false;
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)
191 return true;
193 return false;
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);
202 return;
207 void LayerAnimationController::setAnimationRegistrar(AnimationRegistrar* registrar)
209 if (m_registrar == registrar)
210 return;
212 if (m_registrar)
213 m_registrar->UnregisterAnimationController(this);
215 m_registrar = registrar;
216 if (m_registrar)
217 m_registrar->RegisterAnimationController(this);
219 bool force = true;
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()))
240 continue;
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())
247 continue;
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());
258 struct IsCompleted {
259 IsCompleted(const LayerAnimationController& mainThreadController) : m_mainThreadController(mainThreadController) { }
260 bool operator()(Animation* animation) const { return !m_mainThreadController.getAnimation(animation->group(), animation->targetProperty()); }
261 private:
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());
278 if (currentImpl)
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);
290 if (events)
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);
301 if (events)
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);
340 if (events)
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);
367 else
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;
387 break;
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()) {
396 if (events)
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();
424 } else
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())
440 trimmed = 0;
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);
451 break;
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);
461 break;
464 // Do nothing for sentinel value.
465 case Animation::TargetPropertyEnumSize:
466 NOTREACHED();
472 void LayerAnimationController::updateActivation(bool force)
474 if (m_registrar) {
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,
486 m_observers,
487 OnOpacityAnimated(opacity));
490 void LayerAnimationController::notifyObserversTransformAnimated(const gfx::Transform& transform)
492 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
493 m_observers,
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)
503 if (obs->IsActive())
504 return true;
506 return false;
509 } // namespace cc