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
20119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck#include "AnimationContext.h"
2168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck#include "RenderNode.h"
2268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
2368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Recknamespace android {
2468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Recknamespace uirenderer {
2568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
2668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckusing namespace std;
2768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
2868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckstatic void unref(BaseRenderNodeAnimator* animator) {
298d8af3c1b768d590754d657a7d1242dcb462454bJohn Reck    animator->detach();
3068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    animator->decStrong(0);
3168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
3268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
3368bfe0a37a0dcef52abd81688d8520c5d16e1a85John ReckAnimatorManager::AnimatorManager(RenderNode& parent)
34119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        : mParent(parent)
35119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        , mAnimationHandle(NULL) {
3668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
3768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
3868bfe0a37a0dcef52abd81688d8520c5d16e1a85John ReckAnimatorManager::~AnimatorManager() {
3968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    for_each(mNewAnimators.begin(), mNewAnimators.end(), unref);
4068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    for_each(mAnimators.begin(), mAnimators.end(), unref);
4168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
4268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
4368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckvoid AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
4468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    animator->incStrong(0);
458d8af3c1b768d590754d657a7d1242dcb462454bJohn Reck    animator->attach(&mParent);
4668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    mNewAnimators.push_back(animator.get());
4768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
4868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
49119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckvoid AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
50119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
51119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    mAnimationHandle = handle;
52e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
53e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck            "Lost animation handle on %p (%s) with outstanding animators!",
54e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck            &mParent, mParent.getName());
55119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck}
56119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
5768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Recktemplate<typename T>
5868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckstatic void move_all(T& source, T& dest) {
5968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    dest.reserve(source.size() + dest.size());
6068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    for (typename T::iterator it = source.begin(); it != source.end(); it++) {
6168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck        dest.push_back(*it);
6268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    }
6368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    source.clear();
6468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
6568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
66119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckvoid AnimatorManager::pushStaging() {
6768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    if (mNewAnimators.size()) {
68e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
69e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck                "Trying to start new animators on %p (%s) without an animation handle!",
70e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck                &mParent, mParent.getName());
7168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck        // Since this is a straight move, we don't need to inc/dec the ref count
7268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck        move_all(mNewAnimators, mAnimators);
7368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    }
7468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
75119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        (*it)->pushStaging(mAnimationHandle->context());
7668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    }
7768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
7868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
7968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckclass AnimateFunctor {
8068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckpublic:
81119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    AnimateFunctor(TreeInfo& info, AnimationContext& context)
82119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck            : dirtyMask(0), mInfo(info), mContext(context) {}
8368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
8468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    bool operator() (BaseRenderNodeAnimator* animator) {
85a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck        dirtyMask |= animator->dirtyMask();
86119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        bool remove = animator->animate(mContext);
8768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck        if (remove) {
8868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck            animator->decStrong(0);
89119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        } else {
90119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck            if (animator->isRunning()) {
91119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck                mInfo.out.hasAnimations = true;
92119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck            }
93f5945a0c8bb868f978d9d0d22043a8b44464a86eJohn Reck            if (CC_UNLIKELY(!animator->mayRunAsync())) {
94f5945a0c8bb868f978d9d0d22043a8b44464a86eJohn Reck                mInfo.out.requiresUiRedraw = true;
95f5945a0c8bb868f978d9d0d22043a8b44464a86eJohn Reck            }
9668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck        }
9768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck        return remove;
9868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    }
99a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck
100a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck    uint32_t dirtyMask;
101a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck
10268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckprivate:
10368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    TreeInfo& mInfo;
104119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    AnimationContext& mContext;
10568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck};
10668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
107a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reckuint32_t AnimatorManager::animate(TreeInfo& info) {
108a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck    if (!mAnimators.size()) return 0;
10968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
11068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    // TODO: Can we target this better? For now treat it like any other staging
11168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    // property push and just damage self before and after animators are run
11268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
11368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    mParent.damageSelf(info);
11468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    info.damageAccumulator->popTransform();
11568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
116119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    uint32_t dirty = animateCommon(info);
11768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
11868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    mParent.mProperties.updateMatrix();
11968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    info.damageAccumulator->pushTransform(&mParent);
12068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    mParent.damageSelf(info);
121a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck
122119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    return dirty;
123119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck}
124119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
125119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckvoid AnimatorManager::animateNoDamage(TreeInfo& info) {
126119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    if (!mAnimators.size()) return;
127119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
128119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    animateCommon(info);
129119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck}
130119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
131119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckuint32_t AnimatorManager::animateCommon(TreeInfo& info) {
132119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    AnimateFunctor functor(info, mAnimationHandle->context());
133119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
134119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
135119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    mAnimators.erase(newEnd, mAnimators.end());
136119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    mAnimationHandle->notifyAnimationsRan();
137a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck    return functor.dirtyMask;
13868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}
13968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
140e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reckstatic void endStagingAnimator(BaseRenderNodeAnimator* animator) {
141e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    animator->end();
142e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    if (animator->listener()) {
143e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        animator->listener()->onAnimationFinished(animator);
144e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    }
145e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    animator->decStrong(0);
146e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck}
147e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck
148e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reckvoid AnimatorManager::endAllStagingAnimators() {
149e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
150e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    // This works because this state can only happen on the UI thread,
151e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    // which means we're already on the right thread to invoke listeners
152e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
153e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    mNewAnimators.clear();
154e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck}
155e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck
156e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reckclass EndActiveAnimatorsFunctor {
157119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckpublic:
158e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
159119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
160119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    void operator() (BaseRenderNodeAnimator* animator) {
161e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        animator->forceEndNow(mContext);
162119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        animator->decStrong(0);
163119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    }
164119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
165119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckprivate:
166119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    AnimationContext& mContext;
167119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck};
168119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
169e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reckvoid AnimatorManager::endAllActiveAnimators() {
170e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    ALOGD("endAllStagingAnimators on %p (%s) with handle %p",
171e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck            &mParent, mParent.getName(), mAnimationHandle);
172e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
173e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    for_each(mAnimators.begin(), mAnimators.end(), functor);
174e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    mAnimators.clear();
175e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck    mAnimationHandle->release();
176119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck}
177119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
17868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck} /* namespace uirenderer */
17968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck} /* namespace android */
180