blob: 2b49b4743d8969e351511feaf27c2a9cf4cebcf7 [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 Liuc4bb1852016-02-19 21:39:21 +000045 mNewAnimators.emplace_back(animator.get());
John Reck68bfe0a2014-06-24 15:34:58 -070046}
47
John Reck119907c2014-08-14 09:02:01 -070048void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
49 LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
50 mAnimationHandle = handle;
John Recke2478d42014-09-03 16:46:05 -070051 LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
52 "Lost animation handle on %p (%s) with outstanding animators!",
53 &mParent, mParent.getName());
John Reck119907c2014-08-14 09:02:01 -070054}
55
John Reck119907c2014-08-14 09:02:01 -070056void AnimatorManager::pushStaging() {
John Reck68bfe0a2014-06-24 15:34:58 -070057 if (mNewAnimators.size()) {
John Recke2478d42014-09-03 16:46:05 -070058 LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
59 "Trying to start new animators on %p (%s) without an animation handle!",
60 &mParent, mParent.getName());
Doris Liuc4bb1852016-02-19 21:39:21 +000061 // Only add animators that are not already in the on-going animator list.
62 for (auto& animator : mNewAnimators) {
63 RenderNode* targetRenderNode = animator->target();
64 if (targetRenderNode == &mParent) {
65 // Animator already in the animator list: skip adding again
66 continue;
67 }
68
69 if (targetRenderNode){
70 // If the animator is already in another RenderNode's animator list, remove animator from
71 // that list and add animator to current RenderNode's list.
72 targetRenderNode->animators().removeActiveAnimator(animator);
73 }
74 animator->attach(&mParent);
75 mAnimators.push_back(std::move(animator));
76 }
77 mNewAnimators.clear();
John Reck68bfe0a2014-06-24 15:34:58 -070078 }
Doris Liuc4bb1852016-02-19 21:39:21 +000079 for (auto& animator : mAnimators) {
80 animator->pushStaging(mAnimationHandle->context());
John Reck68bfe0a2014-06-24 15:34:58 -070081 }
82}
83
84class AnimateFunctor {
85public:
John Reck119907c2014-08-14 09:02:01 -070086 AnimateFunctor(TreeInfo& info, AnimationContext& context)
87 : dirtyMask(0), mInfo(info), mContext(context) {}
John Reck68bfe0a2014-06-24 15:34:58 -070088
Doris Liuc4bb1852016-02-19 21:39:21 +000089 bool operator() (sp<BaseRenderNodeAnimator>& animator) {
John Recka7c2ea22014-08-08 13:21:00 -070090 dirtyMask |= animator->dirtyMask();
John Reck119907c2014-08-14 09:02:01 -070091 bool remove = animator->animate(mContext);
John Reck68bfe0a2014-06-24 15:34:58 -070092 if (remove) {
Doris Liuc4bb1852016-02-19 21:39:21 +000093 animator->detach();
John Reck119907c2014-08-14 09:02:01 -070094 } else {
95 if (animator->isRunning()) {
96 mInfo.out.hasAnimations = true;
97 }
John Reckf5945a02014-09-05 15:57:47 -070098 if (CC_UNLIKELY(!animator->mayRunAsync())) {
99 mInfo.out.requiresUiRedraw = true;
100 }
John Reck68bfe0a2014-06-24 15:34:58 -0700101 }
102 return remove;
103 }
John Recka7c2ea22014-08-08 13:21:00 -0700104
105 uint32_t dirtyMask;
106
John Reck68bfe0a2014-06-24 15:34:58 -0700107private:
John Reck68bfe0a2014-06-24 15:34:58 -0700108 TreeInfo& mInfo;
John Reck119907c2014-08-14 09:02:01 -0700109 AnimationContext& mContext;
John Reck68bfe0a2014-06-24 15:34:58 -0700110};
111
John Recka7c2ea22014-08-08 13:21:00 -0700112uint32_t AnimatorManager::animate(TreeInfo& info) {
113 if (!mAnimators.size()) return 0;
John Reck68bfe0a2014-06-24 15:34:58 -0700114
115 // TODO: Can we target this better? For now treat it like any other staging
116 // property push and just damage self before and after animators are run
117
118 mParent.damageSelf(info);
119 info.damageAccumulator->popTransform();
120
John Reck119907c2014-08-14 09:02:01 -0700121 uint32_t dirty = animateCommon(info);
John Reck68bfe0a2014-06-24 15:34:58 -0700122
John Reck68bfe0a2014-06-24 15:34:58 -0700123 info.damageAccumulator->pushTransform(&mParent);
124 mParent.damageSelf(info);
John Recka7c2ea22014-08-08 13:21:00 -0700125
John Reck119907c2014-08-14 09:02:01 -0700126 return dirty;
127}
128
129void AnimatorManager::animateNoDamage(TreeInfo& info) {
John Reck119907c2014-08-14 09:02:01 -0700130 animateCommon(info);
131}
132
133uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
134 AnimateFunctor functor(info, mAnimationHandle->context());
Doris Liuc4bb1852016-02-19 21:39:21 +0000135 auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
John Reck119907c2014-08-14 09:02:01 -0700136 mAnimators.erase(newEnd, mAnimators.end());
137 mAnimationHandle->notifyAnimationsRan();
John Reck49dec432015-07-23 15:33:12 -0700138 mParent.mProperties.updateMatrix();
John Recka7c2ea22014-08-08 13:21:00 -0700139 return functor.dirtyMask;
John Reck68bfe0a2014-06-24 15:34:58 -0700140}
141
Doris Liuc4bb1852016-02-19 21:39:21 +0000142static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
143 animator->cancel();
John Reck119907c2014-08-14 09:02:01 -0700144 if (animator->listener()) {
Doris Liuc4bb1852016-02-19 21:39:21 +0000145 animator->listener()->onAnimationFinished(animator.get());
John Reck119907c2014-08-14 09:02:01 -0700146 }
John Reck119907c2014-08-14 09:02:01 -0700147}
148
John Recke2478d42014-09-03 16:46:05 -0700149void AnimatorManager::endAllStagingAnimators() {
150 ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
151 // This works because this state can only happen on the UI thread,
152 // which means we're already on the right thread to invoke listeners
153 for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
154 mNewAnimators.clear();
155}
156
Doris Liuc4bb1852016-02-19 21:39:21 +0000157void AnimatorManager::removeActiveAnimator(const sp<BaseRenderNodeAnimator>& animator) {
158 std::remove(mAnimators.begin(), mAnimators.end(), animator);
159}
160
John Recke2478d42014-09-03 16:46:05 -0700161class EndActiveAnimatorsFunctor {
162public:
163 EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
164
Doris Liuc4bb1852016-02-19 21:39:21 +0000165 void operator() (sp<BaseRenderNodeAnimator>& animator) {
John Recke2478d42014-09-03 16:46:05 -0700166 animator->forceEndNow(mContext);
John Reck119907c2014-08-14 09:02:01 -0700167 }
John Recke2478d42014-09-03 16:46:05 -0700168
169private:
170 AnimationContext& mContext;
171};
172
173void AnimatorManager::endAllActiveAnimators() {
Fred Fettinger2ccb5032015-07-01 16:43:48 -0500174 ALOGD("endAllActiveAnimators on %p (%s) with handle %p",
John Recke2478d42014-09-03 16:46:05 -0700175 &mParent, mParent.getName(), mAnimationHandle);
176 EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
177 for_each(mAnimators.begin(), mAnimators.end(), functor);
178 mAnimators.clear();
179 mAnimationHandle->release();
John Reck119907c2014-08-14 09:02:01 -0700180}
181
John Reck68bfe0a2014-06-24 15:34:58 -0700182} /* namespace uirenderer */
183} /* namespace android */