139 lines
4.6 KiB
C++
139 lines
4.6 KiB
C++
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#include "AnimationContext.h"
|
|
|
|
#include "Animator.h"
|
|
#include "RenderNode.h"
|
|
#include "renderthread/TimeLord.h"
|
|
|
|
namespace android {
|
|
namespace uirenderer {
|
|
|
|
AnimationContext::AnimationContext(renderthread::TimeLord& clock)
|
|
: mClock(clock)
|
|
, mCurrentFrameAnimations(*this)
|
|
, mNextFrameAnimations(*this)
|
|
, mFrameTimeMs(0) {}
|
|
|
|
AnimationContext::~AnimationContext() {}
|
|
|
|
void AnimationContext::destroy() {
|
|
startFrame(TreeInfo::MODE_RT_ONLY);
|
|
while (mCurrentFrameAnimations.mNextHandle) {
|
|
AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
|
|
AnimatorManager& animators = current->mRenderNode->animators();
|
|
animators.endAllActiveAnimators();
|
|
LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
|
|
"endAllAnimators failed to remove from current frame list!");
|
|
}
|
|
}
|
|
|
|
void AnimationContext::addAnimatingRenderNode(RenderNode& node) {
|
|
if (!node.animators().hasAnimationHandle()) {
|
|
AnimationHandle* handle = new AnimationHandle(node, *this);
|
|
addAnimationHandle(handle);
|
|
}
|
|
}
|
|
|
|
void AnimationContext::addAnimationHandle(AnimationHandle* handle) {
|
|
handle->insertAfter(&mNextFrameAnimations);
|
|
}
|
|
|
|
void AnimationContext::startFrame(TreeInfo::TraversalMode mode) {
|
|
LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle,
|
|
"Missed running animations last frame!");
|
|
AnimationHandle* head = mNextFrameAnimations.mNextHandle;
|
|
if (head) {
|
|
mNextFrameAnimations.mNextHandle = nullptr;
|
|
mCurrentFrameAnimations.mNextHandle = head;
|
|
head->mPreviousHandle = &mCurrentFrameAnimations;
|
|
}
|
|
mFrameTimeMs = ns2ms(mClock.latestVsync());
|
|
}
|
|
|
|
void AnimationContext::runRemainingAnimations(TreeInfo& info) {
|
|
while (mCurrentFrameAnimations.mNextHandle) {
|
|
AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
|
|
AnimatorManager& animators = current->mRenderNode->animators();
|
|
animators.pushStaging();
|
|
animators.animateNoDamage(info);
|
|
LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
|
|
"Animate failed to remove from current frame list!");
|
|
}
|
|
}
|
|
|
|
void AnimationContext::callOnFinished(BaseRenderNodeAnimator* animator,
|
|
AnimationListener* listener) {
|
|
listener->onAnimationFinished(animator);
|
|
}
|
|
|
|
AnimationHandle::AnimationHandle(AnimationContext& context)
|
|
: mContext(context), mPreviousHandle(nullptr), mNextHandle(nullptr) {}
|
|
|
|
AnimationHandle::AnimationHandle(RenderNode& animatingNode, AnimationContext& context)
|
|
: mRenderNode(&animatingNode)
|
|
, mContext(context)
|
|
, mPreviousHandle(nullptr)
|
|
, mNextHandle(nullptr) {
|
|
mRenderNode->animators().setAnimationHandle(this);
|
|
}
|
|
|
|
AnimationHandle::~AnimationHandle() {
|
|
LOG_ALWAYS_FATAL_IF(mPreviousHandle || mNextHandle,
|
|
"AnimationHandle destroyed while still animating!");
|
|
}
|
|
|
|
void AnimationHandle::notifyAnimationsRan() {
|
|
removeFromList();
|
|
if (mRenderNode->animators().hasAnimators()) {
|
|
mContext.addAnimationHandle(this);
|
|
} else {
|
|
release();
|
|
}
|
|
}
|
|
|
|
void AnimationHandle::release() {
|
|
LOG_ALWAYS_FATAL_IF(mRenderNode->animators().hasAnimators(),
|
|
"Releasing the handle for an RenderNode with outstanding animators!");
|
|
removeFromList();
|
|
mRenderNode->animators().setAnimationHandle(nullptr);
|
|
delete this;
|
|
}
|
|
|
|
void AnimationHandle::insertAfter(AnimationHandle* prev) {
|
|
removeFromList();
|
|
mNextHandle = prev->mNextHandle;
|
|
if (mNextHandle) {
|
|
mNextHandle->mPreviousHandle = this;
|
|
}
|
|
prev->mNextHandle = this;
|
|
mPreviousHandle = prev;
|
|
}
|
|
|
|
void AnimationHandle::removeFromList() {
|
|
if (mPreviousHandle) {
|
|
mPreviousHandle->mNextHandle = mNextHandle;
|
|
}
|
|
if (mNextHandle) {
|
|
mNextHandle->mPreviousHandle = mPreviousHandle;
|
|
}
|
|
mPreviousHandle = nullptr;
|
|
mNextHandle = nullptr;
|
|
}
|
|
|
|
} /* namespace uirenderer */
|
|
} /* namespace android */
|