blob: e06d80044f4c1e88ac1b7833d75273de74ff298d [file] [log] [blame]
John Reck68bfe0a2014-06-24 15:34:58 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "AnimatorManager.h"
17
18#include <algorithm>
19
John Reck119907c2014-08-14 09:02:01 -070020#include "AnimationContext.h"
John Reck68bfe0a2014-06-24 15:34:58 -070021#include "RenderNode.h"
22
23namespace android {
24namespace uirenderer {
25
26using namespace std;
27
28static void unref(BaseRenderNodeAnimator* animator) {
John Reck8d8af3c2014-07-01 15:23:45 -070029 animator->detach();
John Reck68bfe0a2014-06-24 15:34:58 -070030 animator->decStrong(0);
31}
32
33AnimatorManager::AnimatorManager(RenderNode& parent)
John Reck119907c2014-08-14 09:02:01 -070034 : mParent(parent)
35 , mAnimationHandle(NULL) {
John Reck68bfe0a2014-06-24 15:34:58 -070036}
37
38AnimatorManager::~AnimatorManager() {
39 for_each(mNewAnimators.begin(), mNewAnimators.end(), unref);
40 for_each(mAnimators.begin(), mAnimators.end(), unref);
41}
42
43void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
44 animator->incStrong(0);
John Reck8d8af3c2014-07-01 15:23:45 -070045 animator->attach(&mParent);
John Reck68bfe0a2014-06-24 15:34:58 -070046 mNewAnimators.push_back(animator.get());
47}
48
John Reck119907c2014-08-14 09:02:01 -070049void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
50 LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
51 mAnimationHandle = handle;
John Recke2478d42014-09-03 16:46:05 -070052 LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
53 "Lost animation handle on %p (%s) with outstanding animators!",
54 &mParent, mParent.getName());
John Reck119907c2014-08-14 09:02:01 -070055}
56
John Reck68bfe0a2014-06-24 15:34:58 -070057template<typename T>
58static void move_all(T& source, T& dest) {
59 dest.reserve(source.size() + dest.size());
60 for (typename T::iterator it = source.begin(); it != source.end(); it++) {
61 dest.push_back(*it);
62 }
63 source.clear();
64}
65
John Reck119907c2014-08-14 09:02:01 -070066void AnimatorManager::pushStaging() {
John Reck68bfe0a2014-06-24 15:34:58 -070067 if (mNewAnimators.size()) {
John Recke2478d42014-09-03 16:46:05 -070068 LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
69 "Trying to start new animators on %p (%s) without an animation handle!",
70 &mParent, mParent.getName());
John Reck68bfe0a2014-06-24 15:34:58 -070071 // Since this is a straight move, we don't need to inc/dec the ref count
72 move_all(mNewAnimators, mAnimators);
73 }
74 for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
John Reck119907c2014-08-14 09:02:01 -070075 (*it)->pushStaging(mAnimationHandle->context());
John Reck68bfe0a2014-06-24 15:34:58 -070076 }
77}
78
79class AnimateFunctor {
80public:
John Reck119907c2014-08-14 09:02:01 -070081 AnimateFunctor(TreeInfo& info, AnimationContext& context)
82 : dirtyMask(0), mInfo(info), mContext(context) {}
John Reck68bfe0a2014-06-24 15:34:58 -070083
84 bool operator() (BaseRenderNodeAnimator* animator) {
John Recka7c2ea22014-08-08 13:21:00 -070085 dirtyMask |= animator->dirtyMask();
John Reck119907c2014-08-14 09:02:01 -070086 bool remove = animator->animate(mContext);
John Reck68bfe0a2014-06-24 15:34:58 -070087 if (remove) {
88 animator->decStrong(0);
John Reck119907c2014-08-14 09:02:01 -070089 } else {
90 if (animator->isRunning()) {
91 mInfo.out.hasAnimations = true;
92 }
John Reck68bfe0a2014-06-24 15:34:58 -070093 }
94 return remove;
95 }
John Recka7c2ea22014-08-08 13:21:00 -070096
97 uint32_t dirtyMask;
98
John Reck68bfe0a2014-06-24 15:34:58 -070099private:
John Reck68bfe0a2014-06-24 15:34:58 -0700100 TreeInfo& mInfo;
John Reck119907c2014-08-14 09:02:01 -0700101 AnimationContext& mContext;
John Reck68bfe0a2014-06-24 15:34:58 -0700102};
103
John Recka7c2ea22014-08-08 13:21:00 -0700104uint32_t AnimatorManager::animate(TreeInfo& info) {
105 if (!mAnimators.size()) return 0;
John Reck68bfe0a2014-06-24 15:34:58 -0700106
107 // TODO: Can we target this better? For now treat it like any other staging
108 // property push and just damage self before and after animators are run
109
110 mParent.damageSelf(info);
111 info.damageAccumulator->popTransform();
112
John Reck119907c2014-08-14 09:02:01 -0700113 uint32_t dirty = animateCommon(info);
John Reck68bfe0a2014-06-24 15:34:58 -0700114
115 mParent.mProperties.updateMatrix();
116 info.damageAccumulator->pushTransform(&mParent);
117 mParent.damageSelf(info);
John Recka7c2ea22014-08-08 13:21:00 -0700118
John Reck119907c2014-08-14 09:02:01 -0700119 return dirty;
120}
121
122void AnimatorManager::animateNoDamage(TreeInfo& info) {
123 if (!mAnimators.size()) return;
124
125 animateCommon(info);
126}
127
128uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
129 AnimateFunctor functor(info, mAnimationHandle->context());
130 std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
131 newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
132 mAnimators.erase(newEnd, mAnimators.end());
133 mAnimationHandle->notifyAnimationsRan();
John Recka7c2ea22014-08-08 13:21:00 -0700134 return functor.dirtyMask;
John Reck68bfe0a2014-06-24 15:34:58 -0700135}
136
John Recke2478d42014-09-03 16:46:05 -0700137static void endStagingAnimator(BaseRenderNodeAnimator* animator) {
John Reck119907c2014-08-14 09:02:01 -0700138 animator->end();
139 if (animator->listener()) {
140 animator->listener()->onAnimationFinished(animator);
141 }
142 animator->decStrong(0);
143}
144
John Recke2478d42014-09-03 16:46:05 -0700145void AnimatorManager::endAllStagingAnimators() {
146 ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
147 // This works because this state can only happen on the UI thread,
148 // which means we're already on the right thread to invoke listeners
149 for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
150 mNewAnimators.clear();
151}
152
153class EndActiveAnimatorsFunctor {
154public:
155 EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
156
157 void operator() (BaseRenderNodeAnimator* animator) {
158 animator->forceEndNow(mContext);
159 animator->decStrong(0);
John Reck119907c2014-08-14 09:02:01 -0700160 }
John Recke2478d42014-09-03 16:46:05 -0700161
162private:
163 AnimationContext& mContext;
164};
165
166void AnimatorManager::endAllActiveAnimators() {
167 ALOGD("endAllStagingAnimators on %p (%s) with handle %p",
168 &mParent, mParent.getName(), mAnimationHandle);
169 EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
170 for_each(mAnimators.begin(), mAnimators.end(), functor);
171 mAnimators.clear();
172 mAnimationHandle->release();
John Reck119907c2014-08-14 09:02:01 -0700173}
174
John Reck68bfe0a2014-06-24 15:34:58 -0700175} /* namespace uirenderer */
176} /* namespace android */