AnimatorManager.cpp revision 8b083206aef627b6445a8c6be8bf5bb1d778a7f8
168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck/*
268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck * Copyright (C) 2014 The Android Open Source Project
368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck *
468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck * Licensed under the Apache License, Version 2.0 (the "License");
568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck * you may not use this file except in compliance with the License.
668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck * You may obtain a copy of the License at
768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck *
868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck *      http://www.apache.org/licenses/LICENSE-2.0
968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck *
1068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck * Unless required by applicable law or agreed to in writing, software
1168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck * distributed under the License is distributed on an "AS IS" BASIS,
1268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck * See the License for the specific language governing permissions and
1468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck * limitations under the License.
1568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck */
1668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck#include "AnimatorManager.h"
1768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
1868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck#include <algorithm>
1968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
202dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "Animator.h"
21119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck#include "AnimationContext.h"
222dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "DamageAccumulator.h"
2368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck#include "RenderNode.h"
2468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
2568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Recknamespace android {
2668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Recknamespace uirenderer {
2768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
2868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckusing namespace std;
2968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
30c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liustatic void detach(sp<BaseRenderNodeAnimator>& animator) {
318d8af3c1b768d590754d657a7d1242dcb462454bJohn Reck    animator->detach();
3268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
3368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
3468bfe0a37a0dcef52abd81688d8520c5d16e1a85John ReckAnimatorManager::AnimatorManager(RenderNode& parent)
35119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        : mParent(parent)
36d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        , mAnimationHandle(nullptr) {
3768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
3868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
3968bfe0a37a0dcef52abd81688d8520c5d16e1a85John ReckAnimatorManager::~AnimatorManager() {
40c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu    for_each(mNewAnimators.begin(), mNewAnimators.end(), detach);
41c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu    for_each(mAnimators.begin(), mAnimators.end(), detach);
4268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
4368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
4468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckvoid AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
458b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    RenderNode* stagingTarget = animator->stagingTarget();
468b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    if (stagingTarget == &mParent) {
478b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu        return;
488b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    }
49c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu    mNewAnimators.emplace_back(animator.get());
508b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    // If the animator is already attached to other RenderNode, remove it from that RenderNode's
518b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    // new animator list. This ensures one animator only ends up in one newAnimatorList during one
528b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    // frame, even when it's added multiple times to multiple targets.
538b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    if (stagingTarget) {
548b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu        stagingTarget->removeAnimator(animator);
558b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    }
568b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    animator->attach(&mParent);
578b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu}
588b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu
598b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liuvoid AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
608b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator),
618b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu            mNewAnimators.end());
6268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
6368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
64119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckvoid AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
65119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
66119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    mAnimationHandle = handle;
67e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
68e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck            "Lost animation handle on %p (%s) with outstanding animators!",
69e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck            &mParent, mParent.getName());
70119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck}
71119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
72119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckvoid AnimatorManager::pushStaging() {
7368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    if (mNewAnimators.size()) {
74e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
75e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck                "Trying to start new animators on %p (%s) without an animation handle!",
76e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck                &mParent, mParent.getName());
77c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu
788b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu        // Only add new animators that are not already in the mAnimators list
798b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu        for (auto& anim : mNewAnimators) {
808b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu            if (anim->target() != &mParent) {
818b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu                mAnimators.push_back(std::move(anim));
82c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            }
83c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu        }
84c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu        mNewAnimators.clear();
8568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    }
86c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu    for (auto& animator : mAnimators) {
87c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu        animator->pushStaging(mAnimationHandle->context());
8868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    }
8968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
9068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
918b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liuvoid AnimatorManager::onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
928b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    LOG_ALWAYS_FATAL_IF(animator->target() == &mParent, "Target has not been changed");
938b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu    mAnimators.erase(std::remove(mAnimators.begin(), mAnimators.end(), animator), mAnimators.end());
948b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu}
958b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu
9668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckclass AnimateFunctor {
9768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckpublic:
98119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    AnimateFunctor(TreeInfo& info, AnimationContext& context)
99119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck            : dirtyMask(0), mInfo(info), mContext(context) {}
10068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
101c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu    bool operator() (sp<BaseRenderNodeAnimator>& animator) {
102a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck        dirtyMask |= animator->dirtyMask();
103119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        bool remove = animator->animate(mContext);
10468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck        if (remove) {
105c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            animator->detach();
106119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        } else {
107119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck            if (animator->isRunning()) {
108119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck                mInfo.out.hasAnimations = true;
109119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck            }
110f5945a0c8bb868f978d9d0d22043a8b44464a86eJohn Reck            if (CC_UNLIKELY(!animator->mayRunAsync())) {
111f5945a0c8bb868f978d9d0d22043a8b44464a86eJohn Reck                mInfo.out.requiresUiRedraw = true;
112f5945a0c8bb868f978d9d0d22043a8b44464a86eJohn Reck            }
11368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck        }
11468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck        return remove;
11568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    }
116a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck
117a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck    uint32_t dirtyMask;
118a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck
11968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckprivate:
12068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    TreeInfo& mInfo;
121119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    AnimationContext& mContext;
12268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck};
12368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
124a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reckuint32_t AnimatorManager::animate(TreeInfo& info) {
125a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck    if (!mAnimators.size()) return 0;
12668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
12768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    // TODO: Can we target this better? For now treat it like any other staging
12868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    // property push and just damage self before and after animators are run
12968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
13068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    mParent.damageSelf(info);
13168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    info.damageAccumulator->popTransform();
13268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
133119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    uint32_t dirty = animateCommon(info);
13468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
13568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    info.damageAccumulator->pushTransform(&mParent);
13668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    mParent.damageSelf(info);
137a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck
138119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    return dirty;
139119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck}
140119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
141119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckvoid AnimatorManager::animateNoDamage(TreeInfo& info) {
142119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    animateCommon(info);
143119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck}
144119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
145119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckuint32_t AnimatorManager::animateCommon(TreeInfo& info) {
146119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    AnimateFunctor functor(info, mAnimationHandle->context());
147c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu    auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
148119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    mAnimators.erase(newEnd, mAnimators.end());
149119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    mAnimationHandle->notifyAnimationsRan();
15049dec430e8a38943c5e934c1e31b724bf53c47c4John Reck    mParent.mProperties.updateMatrix();
151a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck    return functor.dirtyMask;
15268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
15368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
154c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liustatic void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
155c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu    animator->cancel();
156e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    if (animator->listener()) {
157c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu        animator->listener()->onAnimationFinished(animator.get());
158e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    }
159e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck}
160e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck
161e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reckvoid AnimatorManager::endAllStagingAnimators() {
162e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
163e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    // This works because this state can only happen on the UI thread,
164e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    // which means we're already on the right thread to invoke listeners
165e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
166e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    mNewAnimators.clear();
167e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck}
168e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck
169e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reckclass EndActiveAnimatorsFunctor {
170119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckpublic:
171e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
172119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
173c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu    void operator() (sp<BaseRenderNodeAnimator>& animator) {
174e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        animator->forceEndNow(mContext);
175119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    }
176119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
177119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckprivate:
178119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    AnimationContext& mContext;
179119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck};
180119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
181e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reckvoid AnimatorManager::endAllActiveAnimators() {
1822ccb5030c691849c1dfadf9c7136b7fc18acab9cFred Fettinger    ALOGD("endAllActiveAnimators on %p (%s) with handle %p",
183e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck            &mParent, mParent.getName(), mAnimationHandle);
184e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
185e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    for_each(mAnimators.begin(), mAnimators.end(), functor);
186e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    mAnimators.clear();
187e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    mAnimationHandle->release();
188119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck}
189119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
19068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck} /* namespace uirenderer */
19168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck} /* namespace android */
192