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: 989e066cbf59c3e7724eb6c6610ede5697835f65e6John Reck AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask) 999e066cbf59c3e7724eb6c6610ede5697835f65e6John Reck : mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {} 10068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck 101c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu bool operator() (sp<BaseRenderNodeAnimator>& animator) { 1029e066cbf59c3e7724eb6c6610ede5697835f65e6John Reck *mDirtyMask |= 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 11768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckprivate: 11868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck TreeInfo& mInfo; 119119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck AnimationContext& mContext; 1209e066cbf59c3e7724eb6c6610ede5697835f65e6John Reck uint32_t* mDirtyMask; 12168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck}; 12268bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck 123a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reckuint32_t AnimatorManager::animate(TreeInfo& info) { 124a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck if (!mAnimators.size()) return 0; 12568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck 12668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck // TODO: Can we target this better? For now treat it like any other staging 12768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck // property push and just damage self before and after animators are run 12868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck 12968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck mParent.damageSelf(info); 13068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck info.damageAccumulator->popTransform(); 13168bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck 132119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck uint32_t dirty = animateCommon(info); 13368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck 13468bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck info.damageAccumulator->pushTransform(&mParent); 13568bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck mParent.damageSelf(info); 136a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck 137119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck return dirty; 138119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck} 139119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck 140119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckvoid AnimatorManager::animateNoDamage(TreeInfo& info) { 141119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck animateCommon(info); 142119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck} 143119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck 144119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckuint32_t AnimatorManager::animateCommon(TreeInfo& info) { 145a483173c78fb453b73308a9b44ce54fb3878ed0eGeorge Burgess IV uint32_t dirtyMask = 0; 1469e066cbf59c3e7724eb6c6610ede5697835f65e6John Reck AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask); 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(); 1519e066cbf59c3e7724eb6c6610ede5697835f65e6John Reck return 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: 171c6baf563ba6aa207a48317c177b29f1d2b70cf3dChih-Hung Hsieh explicit 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