1/*
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 "AnimationContext.h"
17
18#include "Animator.h"
19#include "RenderNode.h"
20#include "renderthread/TimeLord.h"
21
22namespace android {
23namespace uirenderer {
24
25AnimationContext::AnimationContext(renderthread::TimeLord& clock)
26        : mClock(clock)
27        , mCurrentFrameAnimations(*this)
28        , mNextFrameAnimations(*this)
29        , mFrameTimeMs(0) {
30}
31
32AnimationContext::~AnimationContext() {
33}
34
35void AnimationContext::destroy() {
36    startFrame(TreeInfo::MODE_RT_ONLY);
37    while (mCurrentFrameAnimations.mNextHandle) {
38        AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
39        AnimatorManager& animators = current->mRenderNode->animators();
40        animators.endAllActiveAnimators();
41        LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
42                "endAllAnimators failed to remove from current frame list!");
43    }
44}
45
46void AnimationContext::addAnimatingRenderNode(RenderNode& node) {
47    if (!node.animators().hasAnimationHandle()) {
48        AnimationHandle* handle = new AnimationHandle(node, *this);
49        addAnimationHandle(handle);
50    }
51}
52
53void AnimationContext::addAnimationHandle(AnimationHandle* handle) {
54    handle->insertAfter(&mNextFrameAnimations);
55}
56
57void AnimationContext::startFrame(TreeInfo::TraversalMode mode) {
58    LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle,
59            "Missed running animations last frame!");
60    AnimationHandle* head = mNextFrameAnimations.mNextHandle;
61    if (head) {
62        mNextFrameAnimations.mNextHandle = NULL;
63        mCurrentFrameAnimations.mNextHandle = head;
64        head->mPreviousHandle = &mCurrentFrameAnimations;
65    }
66    mFrameTimeMs = mClock.computeFrameTimeMs();
67}
68
69void AnimationContext::runRemainingAnimations(TreeInfo& info) {
70    while (mCurrentFrameAnimations.mNextHandle) {
71        AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
72        AnimatorManager& animators = current->mRenderNode->animators();
73        animators.pushStaging();
74        animators.animateNoDamage(info);
75        LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
76                "Animate failed to remove from current frame list!");
77    }
78}
79
80void AnimationContext::callOnFinished(BaseRenderNodeAnimator* animator,
81        AnimationListener* listener) {
82    listener->onAnimationFinished(animator);
83}
84
85AnimationHandle::AnimationHandle(AnimationContext& context)
86        : mContext(context)
87        , mPreviousHandle(NULL)
88        , mNextHandle(NULL) {
89}
90
91AnimationHandle::AnimationHandle(RenderNode& animatingNode, AnimationContext& context)
92        : mRenderNode(&animatingNode)
93        , mContext(context)
94        , mPreviousHandle(NULL)
95        , mNextHandle(NULL) {
96    mRenderNode->animators().setAnimationHandle(this);
97}
98
99AnimationHandle::~AnimationHandle() {
100    LOG_ALWAYS_FATAL_IF(mPreviousHandle || mNextHandle,
101            "AnimationHandle destroyed while still animating!");
102}
103
104void AnimationHandle::notifyAnimationsRan() {
105    removeFromList();
106    if (mRenderNode->animators().hasAnimators()) {
107        mContext.addAnimationHandle(this);
108    } else {
109        release();
110    }
111}
112
113void AnimationHandle::release() {
114    LOG_ALWAYS_FATAL_IF(mRenderNode->animators().hasAnimators(),
115            "Releasing the handle for an RenderNode with outstanding animators!");
116    removeFromList();
117    mRenderNode->animators().setAnimationHandle(NULL);
118    delete this;
119}
120
121void AnimationHandle::insertAfter(AnimationHandle* prev) {
122    removeFromList();
123    mNextHandle = prev->mNextHandle;
124    if (mNextHandle) {
125        mNextHandle->mPreviousHandle = this;
126    }
127    prev->mNextHandle = this;
128    mPreviousHandle = prev;
129}
130
131void AnimationHandle::removeFromList() {
132    if (mPreviousHandle) {
133        mPreviousHandle->mNextHandle = mNextHandle;
134    }
135    if (mNextHandle) {
136        mNextHandle->mPreviousHandle = mPreviousHandle;
137    }
138    mPreviousHandle = NULL;
139    mNextHandle = NULL;
140}
141
142} /* namespace uirenderer */
143} /* namespace android */
144