blob: 8d5f1a83e2114097d4dba942a5cc61b4cc594404 [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
Tom Hudson2dc236b2014-10-15 15:46:42 -040020#include "Animator.h"
John Reck119907c2014-08-14 09:02:01 -070021#include "AnimationContext.h"
Tom Hudson2dc236b2014-10-15 15:46:42 -040022#include "DamageAccumulator.h"
John Reck68bfe0a2014-06-24 15:34:58 -070023#include "RenderNode.h"
24
25namespace android {
26namespace uirenderer {
27
28using namespace std;
29
Doris Liuc4bb1852016-02-19 21:39:21 +000030static void detach(sp<BaseRenderNodeAnimator>& animator) {
John Reck8d8af3c2014-07-01 15:23:45 -070031 animator->detach();
John Reck68bfe0a2014-06-24 15:34:58 -070032}
33
34AnimatorManager::AnimatorManager(RenderNode& parent)
John Reck119907c2014-08-14 09:02:01 -070035 : mParent(parent)
Chris Craikd41c4d82015-01-05 15:51:13 -080036 , mAnimationHandle(nullptr) {
John Reck68bfe0a2014-06-24 15:34:58 -070037}
38
39AnimatorManager::~AnimatorManager() {
Doris Liuc4bb1852016-02-19 21:39:21 +000040 for_each(mNewAnimators.begin(), mNewAnimators.end(), detach);
41 for_each(mAnimators.begin(), mAnimators.end(), detach);
John Reck68bfe0a2014-06-24 15:34:58 -070042}
43
44void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
Doris Liu8b083202016-02-19 21:46:06 +000045 RenderNode* stagingTarget = animator->stagingTarget();
46 if (stagingTarget == &mParent) {
47 return;
48 }
Doris Liuc4bb1852016-02-19 21:39:21 +000049 mNewAnimators.emplace_back(animator.get());
Doris Liu8b083202016-02-19 21:46:06 +000050 // If the animator is already attached to other RenderNode, remove it from that RenderNode's
51 // new animator list. This ensures one animator only ends up in one newAnimatorList during one
52 // frame, even when it's added multiple times to multiple targets.
53 if (stagingTarget) {
54 stagingTarget->removeAnimator(animator);
55 }
56 animator->attach(&mParent);
57}
58
59void AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
60 mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator),
61 mNewAnimators.end());
John Reck68bfe0a2014-06-24 15:34:58 -070062}
63
John Reck119907c2014-08-14 09:02:01 -070064void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
65 LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
66 mAnimationHandle = handle;
John Recke2478d42014-09-03 16:46:05 -070067 LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
68 "Lost animation handle on %p (%s) with outstanding animators!",
69 &mParent, mParent.getName());
John Reck119907c2014-08-14 09:02:01 -070070}
71
John Reck119907c2014-08-14 09:02:01 -070072void AnimatorManager::pushStaging() {
John Reck68bfe0a2014-06-24 15:34:58 -070073 if (mNewAnimators.size()) {
John Recke2478d42014-09-03 16:46:05 -070074 LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
75 "Trying to start new animators on %p (%s) without an animation handle!",
76 &mParent, mParent.getName());
Doris Liuc4bb1852016-02-19 21:39:21 +000077
Doris Liu8b083202016-02-19 21:46:06 +000078 // Only add new animators that are not already in the mAnimators list
79 for (auto& anim : mNewAnimators) {
80 if (anim->target() != &mParent) {
81 mAnimators.push_back(std::move(anim));
Doris Liuc4bb1852016-02-19 21:39:21 +000082 }
Doris Liuc4bb1852016-02-19 21:39:21 +000083 }
84 mNewAnimators.clear();
John Reck68bfe0a2014-06-24 15:34:58 -070085 }
John Reckd58230c72016-08-03 10:28:10 -070086 if (mAnimators.size()) {
87 for (auto& animator : mAnimators) {
88 animator->pushStaging(mAnimationHandle->context());
89 }
90 mParent.mProperties.updateMatrix();
John Reck68bfe0a2014-06-24 15:34:58 -070091 }
92}
93
Doris Liu8b083202016-02-19 21:46:06 +000094void AnimatorManager::onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
95 LOG_ALWAYS_FATAL_IF(animator->target() == &mParent, "Target has not been changed");
96 mAnimators.erase(std::remove(mAnimators.begin(), mAnimators.end(), animator), mAnimators.end());
97}
98
John Reck68bfe0a2014-06-24 15:34:58 -070099class AnimateFunctor {
100public:
John Reck9e066cb2016-02-29 13:40:52 -0800101 AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask)
102 : mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {}
John Reck68bfe0a2014-06-24 15:34:58 -0700103
Doris Liuc4bb1852016-02-19 21:39:21 +0000104 bool operator() (sp<BaseRenderNodeAnimator>& animator) {
John Reck9e066cb2016-02-29 13:40:52 -0800105 *mDirtyMask |= animator->dirtyMask();
John Reck119907c2014-08-14 09:02:01 -0700106 bool remove = animator->animate(mContext);
John Reck68bfe0a2014-06-24 15:34:58 -0700107 if (remove) {
Doris Liuc4bb1852016-02-19 21:39:21 +0000108 animator->detach();
John Reck119907c2014-08-14 09:02:01 -0700109 } else {
110 if (animator->isRunning()) {
111 mInfo.out.hasAnimations = true;
112 }
John Reckf5945a02014-09-05 15:57:47 -0700113 if (CC_UNLIKELY(!animator->mayRunAsync())) {
114 mInfo.out.requiresUiRedraw = true;
115 }
John Reck68bfe0a2014-06-24 15:34:58 -0700116 }
117 return remove;
118 }
John Recka7c2ea22014-08-08 13:21:00 -0700119
John Reck68bfe0a2014-06-24 15:34:58 -0700120private:
John Reck68bfe0a2014-06-24 15:34:58 -0700121 TreeInfo& mInfo;
John Reck119907c2014-08-14 09:02:01 -0700122 AnimationContext& mContext;
John Reck9e066cb2016-02-29 13:40:52 -0800123 uint32_t* mDirtyMask;
John Reck68bfe0a2014-06-24 15:34:58 -0700124};
125
John Recka7c2ea22014-08-08 13:21:00 -0700126uint32_t AnimatorManager::animate(TreeInfo& info) {
127 if (!mAnimators.size()) return 0;
John Reck68bfe0a2014-06-24 15:34:58 -0700128
129 // TODO: Can we target this better? For now treat it like any other staging
130 // property push and just damage self before and after animators are run
131
132 mParent.damageSelf(info);
133 info.damageAccumulator->popTransform();
134
John Reck119907c2014-08-14 09:02:01 -0700135 uint32_t dirty = animateCommon(info);
John Reck68bfe0a2014-06-24 15:34:58 -0700136
John Reck68bfe0a2014-06-24 15:34:58 -0700137 info.damageAccumulator->pushTransform(&mParent);
138 mParent.damageSelf(info);
John Recka7c2ea22014-08-08 13:21:00 -0700139
John Reck119907c2014-08-14 09:02:01 -0700140 return dirty;
141}
142
143void AnimatorManager::animateNoDamage(TreeInfo& info) {
John Reck119907c2014-08-14 09:02:01 -0700144 animateCommon(info);
145}
146
147uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
John Reck9e066cb2016-02-29 13:40:52 -0800148 uint32_t dirtyMask;
149 AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask);
Doris Liuc4bb1852016-02-19 21:39:21 +0000150 auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
John Reck119907c2014-08-14 09:02:01 -0700151 mAnimators.erase(newEnd, mAnimators.end());
152 mAnimationHandle->notifyAnimationsRan();
John Reck49dec432015-07-23 15:33:12 -0700153 mParent.mProperties.updateMatrix();
John Reck9e066cb2016-02-29 13:40:52 -0800154 return dirtyMask;
John Reck68bfe0a2014-06-24 15:34:58 -0700155}
156
Doris Liuc4bb1852016-02-19 21:39:21 +0000157static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
158 animator->cancel();
John Reck119907c2014-08-14 09:02:01 -0700159 if (animator->listener()) {
Doris Liuc4bb1852016-02-19 21:39:21 +0000160 animator->listener()->onAnimationFinished(animator.get());
John Reck119907c2014-08-14 09:02:01 -0700161 }
John Reck119907c2014-08-14 09:02:01 -0700162}
163
John Recke2478d42014-09-03 16:46:05 -0700164void AnimatorManager::endAllStagingAnimators() {
165 ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
166 // This works because this state can only happen on the UI thread,
167 // which means we're already on the right thread to invoke listeners
168 for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
169 mNewAnimators.clear();
170}
171
172class EndActiveAnimatorsFunctor {
173public:
174 EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
175
Doris Liuc4bb1852016-02-19 21:39:21 +0000176 void operator() (sp<BaseRenderNodeAnimator>& animator) {
John Recke2478d42014-09-03 16:46:05 -0700177 animator->forceEndNow(mContext);
John Reck119907c2014-08-14 09:02:01 -0700178 }
John Recke2478d42014-09-03 16:46:05 -0700179
180private:
181 AnimationContext& mContext;
182};
183
184void AnimatorManager::endAllActiveAnimators() {
Fred Fettinger2ccb5032015-07-01 16:43:48 -0500185 ALOGD("endAllActiveAnimators on %p (%s) with handle %p",
John Recke2478d42014-09-03 16:46:05 -0700186 &mParent, mParent.getName(), mAnimationHandle);
187 EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
188 for_each(mAnimators.begin(), mAnimators.end(), functor);
189 mAnimators.clear();
190 mAnimationHandle->release();
John Reck119907c2014-08-14 09:02:01 -0700191}
192
John Reck68bfe0a2014-06-24 15:34:58 -0700193} /* namespace uirenderer */
194} /* namespace android */