Merge "Animator refactoring & fixes"
This commit is contained in:
@@ -21,9 +21,6 @@ import android.graphics.Matrix;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>A display list records a series of graphics related operations and can replay
|
||||
* them later. Display lists are usually built by recording operations on a
|
||||
@@ -180,12 +177,6 @@ public class RenderNode {
|
||||
private boolean mValid;
|
||||
private final long mNativeRenderNode;
|
||||
|
||||
// We need to keep a strong reference to all running animators to ensure that
|
||||
// they can call removeAnimator when they have finished, as the native-side
|
||||
// object can only hold a WeakReference<> to avoid leaking memory due to
|
||||
// cyclic references.
|
||||
private List<RenderNodeAnimator> mActiveAnimators;
|
||||
|
||||
private RenderNode(String name) {
|
||||
mNativeRenderNode = nCreate(name);
|
||||
}
|
||||
@@ -866,18 +857,9 @@ public class RenderNode {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void addAnimator(RenderNodeAnimator animator) {
|
||||
if (mActiveAnimators == null) {
|
||||
mActiveAnimators = new ArrayList<RenderNodeAnimator>();
|
||||
}
|
||||
mActiveAnimators.add(animator);
|
||||
nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
|
||||
}
|
||||
|
||||
public void removeAnimator(RenderNodeAnimator animator) {
|
||||
nRemoveAnimator(mNativeRenderNode, animator.getNativeAnimator());
|
||||
mActiveAnimators.remove(animator);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Native methods
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -960,7 +942,6 @@ public class RenderNode {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private static native void nAddAnimator(long renderNode, long animatorPtr);
|
||||
private static native void nRemoveAnimator(long renderNode, long animatorPtr);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Finalization
|
||||
|
||||
@@ -172,12 +172,14 @@ public final class RenderNodeAnimator extends Animator {
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
mTarget.removeAnimator(this);
|
||||
if (!mFinished) {
|
||||
nCancel(mNativePtr.get());
|
||||
|
||||
final ArrayList<AnimatorListener> listeners = getListeners();
|
||||
final int numListeners = listeners == null ? 0 : listeners.size();
|
||||
for (int i = 0; i < numListeners; i++) {
|
||||
listeners.get(i).onAnimationCancel(this);
|
||||
final ArrayList<AnimatorListener> listeners = getListeners();
|
||||
final int numListeners = listeners == null ? 0 : listeners.size();
|
||||
for (int i = 0; i < numListeners; i++) {
|
||||
listeners.get(i).onAnimationCancel(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,10 +221,6 @@ public final class RenderNodeAnimator extends Animator {
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING: May only be called once!!!
|
||||
* TODO: Fix above -_-
|
||||
*/
|
||||
public void setStartValue(float startValue) {
|
||||
checkMutable();
|
||||
nSetStartValue(mNativePtr.get(), startValue);
|
||||
@@ -231,6 +229,9 @@ public final class RenderNodeAnimator extends Animator {
|
||||
@Override
|
||||
public void setStartDelay(long startDelay) {
|
||||
checkMutable();
|
||||
if (startDelay < 0) {
|
||||
throw new IllegalArgumentException("startDelay must be positive; " + startDelay);
|
||||
}
|
||||
nSetStartDelay(mNativePtr.get(), startDelay);
|
||||
}
|
||||
|
||||
@@ -242,6 +243,9 @@ public final class RenderNodeAnimator extends Animator {
|
||||
@Override
|
||||
public RenderNodeAnimator setDuration(long duration) {
|
||||
checkMutable();
|
||||
if (duration < 0) {
|
||||
throw new IllegalArgumentException("duration must be positive; " + duration);
|
||||
}
|
||||
nSetDuration(mNativePtr.get(), duration);
|
||||
return this;
|
||||
}
|
||||
@@ -269,7 +273,6 @@ public final class RenderNodeAnimator extends Animator {
|
||||
|
||||
private void onFinished() {
|
||||
mFinished = true;
|
||||
mTarget.removeAnimator(this);
|
||||
|
||||
final ArrayList<AnimatorListener> listeners = getListeners();
|
||||
final int numListeners = listeners == null ? 0 : listeners.size();
|
||||
@@ -296,10 +299,13 @@ public final class RenderNodeAnimator extends Animator {
|
||||
long canvasProperty, float finalValue);
|
||||
private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
|
||||
long canvasProperty, int paintField, float finalValue);
|
||||
|
||||
private static native void nSetStartValue(long nativePtr, float startValue);
|
||||
private static native void nSetDuration(long nativePtr, long duration);
|
||||
private static native long nGetDuration(long nativePtr);
|
||||
private static native void nSetStartDelay(long nativePtr, long startDelay);
|
||||
private static native long nGetStartDelay(long nativePtr);
|
||||
private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
|
||||
|
||||
private static native void nCancel(long animPtr);
|
||||
}
|
||||
|
||||
@@ -456,16 +456,9 @@ static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz,
|
||||
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
|
||||
RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
|
||||
renderNode->addAnimator(animator);
|
||||
animator->start();
|
||||
}
|
||||
|
||||
static void android_view_RenderNode_removeAnimator(JNIEnv* env, jobject clazz,
|
||||
jlong renderNodePtr, jlong animatorPtr) {
|
||||
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
|
||||
RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
|
||||
renderNode->removeAnimator(animator);
|
||||
}
|
||||
|
||||
|
||||
#endif // USE_OPENGL_RENDERER
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -546,7 +539,6 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "nGetPivotY", "(J)F", (void*) android_view_RenderNode_getPivotY },
|
||||
|
||||
{ "nAddAnimator", "(JJ)V", (void*) android_view_RenderNode_addAnimator },
|
||||
{ "nRemoveAnimator", "(JJ)V", (void*) android_view_RenderNode_removeAnimator },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -149,6 +149,11 @@ static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong
|
||||
animator->setInterpolator(interpolator);
|
||||
}
|
||||
|
||||
static void cancel(JNIEnv* env, jobject clazz, jlong animatorPtr) {
|
||||
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
|
||||
animator->cancel();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -168,6 +173,7 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "nSetStartDelay", "(JJ)V", (void*) setStartDelay },
|
||||
{ "nGetStartDelay", "(J)J", (void*) getStartDelay },
|
||||
{ "nSetInterpolator", "(JJ)V", (void*) setInterpolator },
|
||||
{ "nCancel", "(J)V", (void*) cancel },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
|
||||
font/Font.cpp \
|
||||
AmbientShadow.cpp \
|
||||
Animator.cpp \
|
||||
AnimatorManager.cpp \
|
||||
AssetAtlas.cpp \
|
||||
DamageAccumulator.cpp \
|
||||
FontRenderer.cpp \
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "Animator.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <set>
|
||||
|
||||
#include "RenderNode.h"
|
||||
@@ -35,72 +36,105 @@ BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
|
||||
, mDeltaValue(0)
|
||||
, mFromValue(0)
|
||||
, mInterpolator(0)
|
||||
, mPlayState(NEEDS_START)
|
||||
, mStagingPlayState(NOT_STARTED)
|
||||
, mPlayState(NOT_STARTED)
|
||||
, mHasStartValue(false)
|
||||
, mStartTime(0)
|
||||
, mDelayUntil(0)
|
||||
, mDuration(300)
|
||||
, mStartDelay(0) {
|
||||
|
||||
}
|
||||
|
||||
BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
|
||||
setInterpolator(NULL);
|
||||
delete mInterpolator;
|
||||
}
|
||||
|
||||
void BaseRenderNodeAnimator::checkMutable() {
|
||||
// Should be impossible to hit as the Java-side also has guards for this
|
||||
LOG_ALWAYS_FATAL_IF(mStagingPlayState != NOT_STARTED,
|
||||
"Animator has already been started!");
|
||||
}
|
||||
|
||||
void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
|
||||
checkMutable();
|
||||
delete mInterpolator;
|
||||
mInterpolator = interpolator;
|
||||
}
|
||||
|
||||
void BaseRenderNodeAnimator::setStartValue(float value) {
|
||||
LOG_ALWAYS_FATAL_IF(mPlayState != NEEDS_START,
|
||||
"Cannot set the start value after the animator has started!");
|
||||
mFromValue = value;
|
||||
mDeltaValue = (mFinalValue - mFromValue);
|
||||
mPlayState = PENDING;
|
||||
checkMutable();
|
||||
doSetStartValue(value);
|
||||
}
|
||||
|
||||
void BaseRenderNodeAnimator::setupStartValueIfNecessary(RenderNode* target, TreeInfo& info) {
|
||||
if (mPlayState == NEEDS_START) {
|
||||
setStartValue(getValue(target));
|
||||
}
|
||||
void BaseRenderNodeAnimator::doSetStartValue(float value) {
|
||||
mFromValue = value;
|
||||
mDeltaValue = (mFinalValue - mFromValue);
|
||||
mHasStartValue = true;
|
||||
}
|
||||
|
||||
void BaseRenderNodeAnimator::setDuration(nsecs_t duration) {
|
||||
checkMutable();
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
void BaseRenderNodeAnimator::setStartDelay(nsecs_t startDelay) {
|
||||
checkMutable();
|
||||
mStartDelay = startDelay;
|
||||
}
|
||||
|
||||
bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
|
||||
if (mPlayState == PENDING && mStartDelay > 0 && mDelayUntil == 0) {
|
||||
mDelayUntil = info.frameTimeMs + mStartDelay;
|
||||
return false;
|
||||
void BaseRenderNodeAnimator::pushStaging(RenderNode* target, TreeInfo& info) {
|
||||
if (!mHasStartValue) {
|
||||
doSetStartValue(getValue(target));
|
||||
}
|
||||
|
||||
if (mDelayUntil > info.frameTimeMs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mPlayState == PENDING) {
|
||||
mPlayState = RUNNING;
|
||||
mStartTime = info.frameTimeMs;
|
||||
// No interpolator was set, use the default
|
||||
if (!mInterpolator) {
|
||||
setInterpolator(Interpolator::createDefaultInterpolator());
|
||||
if (mStagingPlayState > mPlayState) {
|
||||
mPlayState = mStagingPlayState;
|
||||
// Oh boy, we're starting! Man the battle stations!
|
||||
if (mPlayState == RUNNING) {
|
||||
transitionToRunning(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BaseRenderNodeAnimator::transitionToRunning(TreeInfo& info) {
|
||||
LOG_ALWAYS_FATAL_IF(info.frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", info.frameTimeMs);
|
||||
if (mStartDelay < 0 || mStartDelay > 50000) {
|
||||
ALOGW("Your start delay is strange and confusing: %" PRId64, mStartDelay);
|
||||
}
|
||||
mStartTime = info.frameTimeMs + mStartDelay;
|
||||
if (mStartTime < 0) {
|
||||
ALOGW("Ended up with a really weird start time of %" PRId64
|
||||
" with frame time %" PRId64 " and start delay %" PRId64,
|
||||
mStartTime, info.frameTimeMs, mStartDelay);
|
||||
// Set to 0 so that the animate() basically instantly finishes
|
||||
mStartTime = 0;
|
||||
}
|
||||
// No interpolator was set, use the default
|
||||
if (!mInterpolator) {
|
||||
setInterpolator(Interpolator::createDefaultInterpolator());
|
||||
}
|
||||
if (mDuration < 0 || mDuration > 50000) {
|
||||
ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
|
||||
}
|
||||
}
|
||||
|
||||
bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
|
||||
if (mPlayState < RUNNING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mStartTime > info.frameTimeMs) {
|
||||
info.out.hasAnimations |= true;
|
||||
return false;
|
||||
}
|
||||
|
||||
float fraction = 1.0f;
|
||||
if (mPlayState == RUNNING) {
|
||||
fraction = mDuration > 0 ? (float)(info.frameTimeMs - mStartTime) / mDuration : 1.0f;
|
||||
if (fraction >= 1.0f) {
|
||||
fraction = 1.0f;
|
||||
mPlayState = FINISHED;
|
||||
}
|
||||
if (mPlayState == RUNNING && mDuration > 0) {
|
||||
fraction = (float)(info.frameTimeMs - mStartTime) / mDuration;
|
||||
}
|
||||
if (fraction >= 1.0f) {
|
||||
fraction = 1.0f;
|
||||
mPlayState = FINISHED;
|
||||
}
|
||||
|
||||
fraction = mInterpolator->interpolate(fraction);
|
||||
setValue(target, mFromValue + (mDeltaValue * fraction));
|
||||
|
||||
@@ -108,6 +142,8 @@ bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
|
||||
callOnFinishedListener(info);
|
||||
return true;
|
||||
}
|
||||
|
||||
info.out.hasAnimations |= true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -153,7 +189,7 @@ RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float fi
|
||||
}
|
||||
|
||||
void RenderPropertyAnimator::onAttached(RenderNode* target) {
|
||||
if (mPlayState == NEEDS_START
|
||||
if (!mHasStartValue
|
||||
&& target->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
|
||||
setStartValue((target->stagingProperties().*mPropertyAccess->getter)());
|
||||
}
|
||||
|
||||
@@ -50,12 +50,11 @@ public:
|
||||
ANDROID_API void setListener(AnimationListener* listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
ANDROID_API void start() { mStagingPlayState = RUNNING; }
|
||||
ANDROID_API void cancel() { mStagingPlayState = FINISHED; }
|
||||
|
||||
ANDROID_API virtual void onAttached(RenderNode* target) {}
|
||||
|
||||
// Guaranteed to happen before the staging push
|
||||
void setupStartValueIfNecessary(RenderNode* target, TreeInfo& info);
|
||||
|
||||
virtual void onAttached(RenderNode* target) {}
|
||||
virtual void pushStaging(RenderNode* target, TreeInfo& info);
|
||||
bool animate(RenderNode* target, TreeInfo& info);
|
||||
|
||||
bool isFinished() { return mPlayState == FINISHED; }
|
||||
@@ -73,8 +72,7 @@ protected:
|
||||
void callOnFinishedListener(TreeInfo& info);
|
||||
|
||||
enum PlayState {
|
||||
NEEDS_START,
|
||||
PENDING,
|
||||
NOT_STARTED,
|
||||
RUNNING,
|
||||
FINISHED,
|
||||
};
|
||||
@@ -84,13 +82,19 @@ protected:
|
||||
float mFromValue;
|
||||
|
||||
Interpolator* mInterpolator;
|
||||
PlayState mStagingPlayState;
|
||||
PlayState mPlayState;
|
||||
bool mHasStartValue;
|
||||
nsecs_t mStartTime;
|
||||
nsecs_t mDelayUntil;
|
||||
nsecs_t mDuration;
|
||||
nsecs_t mStartDelay;
|
||||
|
||||
sp<AnimationListener> mListener;
|
||||
|
||||
private:
|
||||
void doSetStartValue(float value);
|
||||
inline void checkMutable();
|
||||
void transitionToRunning(TreeInfo& info);
|
||||
};
|
||||
|
||||
class RenderPropertyAnimator : public BaseRenderNodeAnimator {
|
||||
@@ -112,7 +116,7 @@ public:
|
||||
|
||||
ANDROID_API RenderPropertyAnimator(RenderProperty property, float finalValue);
|
||||
|
||||
ANDROID_API virtual void onAttached(RenderNode* target);
|
||||
virtual void onAttached(RenderNode* target);
|
||||
|
||||
ANDROID_API virtual uint32_t dirtyMask();
|
||||
|
||||
|
||||
102
libs/hwui/AnimatorManager.cpp
Normal file
102
libs/hwui/AnimatorManager.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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 "AnimatorManager.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "RenderNode.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
using namespace std;
|
||||
|
||||
static void unref(BaseRenderNodeAnimator* animator) {
|
||||
animator->decStrong(0);
|
||||
}
|
||||
|
||||
AnimatorManager::AnimatorManager(RenderNode& parent)
|
||||
: mParent(parent) {
|
||||
}
|
||||
|
||||
AnimatorManager::~AnimatorManager() {
|
||||
for_each(mNewAnimators.begin(), mNewAnimators.end(), unref);
|
||||
for_each(mAnimators.begin(), mAnimators.end(), unref);
|
||||
}
|
||||
|
||||
void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
|
||||
animator->incStrong(0);
|
||||
animator->onAttached(&mParent);
|
||||
mNewAnimators.push_back(animator.get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void move_all(T& source, T& dest) {
|
||||
dest.reserve(source.size() + dest.size());
|
||||
for (typename T::iterator it = source.begin(); it != source.end(); it++) {
|
||||
dest.push_back(*it);
|
||||
}
|
||||
source.clear();
|
||||
}
|
||||
|
||||
void AnimatorManager::pushStaging(TreeInfo& info) {
|
||||
if (mNewAnimators.size()) {
|
||||
// Since this is a straight move, we don't need to inc/dec the ref count
|
||||
move_all(mNewAnimators, mAnimators);
|
||||
}
|
||||
for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
|
||||
(*it)->pushStaging(&mParent, info);
|
||||
}
|
||||
}
|
||||
|
||||
class AnimateFunctor {
|
||||
public:
|
||||
AnimateFunctor(RenderNode& target, TreeInfo& info)
|
||||
: mTarget(target), mInfo(info) {}
|
||||
|
||||
bool operator() (BaseRenderNodeAnimator* animator) {
|
||||
bool remove = animator->animate(&mTarget, mInfo);
|
||||
if (remove) {
|
||||
animator->decStrong(0);
|
||||
}
|
||||
return remove;
|
||||
}
|
||||
private:
|
||||
RenderNode& mTarget;
|
||||
TreeInfo& mInfo;
|
||||
};
|
||||
|
||||
void AnimatorManager::animate(TreeInfo& info) {
|
||||
if (!mAnimators.size()) return;
|
||||
|
||||
// TODO: Can we target this better? For now treat it like any other staging
|
||||
// property push and just damage self before and after animators are run
|
||||
|
||||
mParent.damageSelf(info);
|
||||
info.damageAccumulator->popTransform();
|
||||
|
||||
AnimateFunctor functor(mParent, info);
|
||||
std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
|
||||
newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
|
||||
mAnimators.erase(newEnd, mAnimators.end());
|
||||
|
||||
mParent.mProperties.updateMatrix();
|
||||
info.damageAccumulator->pushTransform(&mParent);
|
||||
mParent.damageSelf(info);
|
||||
}
|
||||
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
57
libs/hwui/AnimatorManager.h
Normal file
57
libs/hwui/AnimatorManager.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef ANIMATORMANAGER_H
|
||||
#define ANIMATORMANAGER_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <cutils/compiler.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
|
||||
#include "TreeInfo.h"
|
||||
#include "utils/Macros.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
class BaseRenderNodeAnimator;
|
||||
class RenderNode;
|
||||
|
||||
// Responsible for managing the animators for a single RenderNode
|
||||
class AnimatorManager {
|
||||
PREVENT_COPY_AND_ASSIGN(AnimatorManager);
|
||||
public:
|
||||
AnimatorManager(RenderNode& parent);
|
||||
~AnimatorManager();
|
||||
|
||||
void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
|
||||
|
||||
void pushStaging(TreeInfo& info);
|
||||
void animate(TreeInfo& info);
|
||||
|
||||
private:
|
||||
RenderNode& mParent;
|
||||
|
||||
// To improve the efficiency of resizing & removing from the vector
|
||||
// use manual ref counting instead of sp<>.
|
||||
std::vector<BaseRenderNodeAnimator*> mNewAnimators;
|
||||
std::vector<BaseRenderNodeAnimator*> mAnimators;
|
||||
};
|
||||
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
|
||||
#endif /* ANIMATORMANAGER_H */
|
||||
@@ -58,7 +58,7 @@ void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
|
||||
SkRefCnt_SafeAssign(mColorFilter, colorFilter);
|
||||
}
|
||||
|
||||
bool DeferredLayerUpdater::apply(TreeInfo& info) {
|
||||
bool DeferredLayerUpdater::apply() {
|
||||
bool success = true;
|
||||
// These properties are applied the same to both layer types
|
||||
mLayer->setColorFilter(mColorFilter);
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
|
||||
ANDROID_API void setPaint(const SkPaint* paint);
|
||||
|
||||
ANDROID_API bool apply(TreeInfo& info);
|
||||
ANDROID_API bool apply();
|
||||
|
||||
ANDROID_API Layer* backingLayer() {
|
||||
return mLayer;
|
||||
|
||||
@@ -62,7 +62,7 @@ RenderNode::RenderNode()
|
||||
, mNeedsDisplayListDataSync(false)
|
||||
, mDisplayListData(0)
|
||||
, mStagingDisplayListData(0)
|
||||
, mNeedsAnimatorsSync(false)
|
||||
, mAnimatorManager(*this)
|
||||
, mLayer(0) {
|
||||
}
|
||||
|
||||
@@ -117,6 +117,10 @@ void RenderNode::prepareTree(TreeInfo& info) {
|
||||
prepareTreeImpl(info);
|
||||
}
|
||||
|
||||
void RenderNode::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
|
||||
mAnimatorManager.addAnimator(animator);
|
||||
}
|
||||
|
||||
void RenderNode::damageSelf(TreeInfo& info) {
|
||||
if (isRenderable()) {
|
||||
if (properties().getClipDamageToBounds()) {
|
||||
@@ -193,11 +197,11 @@ void RenderNode::prepareTreeImpl(TreeInfo& info) {
|
||||
info.damageAccumulator->pushTransform(this);
|
||||
if (info.mode == TreeInfo::MODE_FULL) {
|
||||
pushStagingPropertiesChanges(info);
|
||||
evaluateAnimations(info);
|
||||
mAnimatorManager.animate(info);
|
||||
} else if (info.mode == TreeInfo::MODE_MAYBE_DETACHING) {
|
||||
pushStagingPropertiesChanges(info);
|
||||
} else if (info.mode == TreeInfo::MODE_RT_ONLY) {
|
||||
evaluateAnimations(info);
|
||||
mAnimatorManager.animate(info);
|
||||
}
|
||||
|
||||
prepareLayer(info);
|
||||
@@ -210,33 +214,11 @@ void RenderNode::prepareTreeImpl(TreeInfo& info) {
|
||||
info.damageAccumulator->popTransform();
|
||||
}
|
||||
|
||||
class PushAnimatorsFunctor {
|
||||
public:
|
||||
PushAnimatorsFunctor(RenderNode* target, TreeInfo& info)
|
||||
: mTarget(target), mInfo(info) {}
|
||||
|
||||
bool operator() (const sp<BaseRenderNodeAnimator>& animator) {
|
||||
animator->setupStartValueIfNecessary(mTarget, mInfo);
|
||||
return animator->isFinished();
|
||||
}
|
||||
private:
|
||||
RenderNode* mTarget;
|
||||
TreeInfo& mInfo;
|
||||
};
|
||||
|
||||
void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) {
|
||||
// Push the animators first so that setupStartValueIfNecessary() is called
|
||||
// before properties() is trampled by stagingProperties(), as they are
|
||||
// required by some animators.
|
||||
if (mNeedsAnimatorsSync) {
|
||||
mAnimators.resize(mStagingAnimators.size());
|
||||
std::vector< sp<BaseRenderNodeAnimator> >::iterator it;
|
||||
PushAnimatorsFunctor functor(this, info);
|
||||
// hint: this means copy_if_not()
|
||||
it = std::remove_copy_if(mStagingAnimators.begin(), mStagingAnimators.end(),
|
||||
mAnimators.begin(), functor);
|
||||
mAnimators.resize(std::distance(mAnimators.begin(), it));
|
||||
}
|
||||
mAnimatorManager.pushStaging(info);
|
||||
if (mDirtyPropertyFields) {
|
||||
mDirtyPropertyFields = 0;
|
||||
damageSelf(info);
|
||||
@@ -267,8 +249,7 @@ void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) {
|
||||
mNeedsDisplayListDataSync = false;
|
||||
// Do a push pass on the old tree to handle freeing DisplayListData
|
||||
// that are no longer used
|
||||
TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING, info.renderState);
|
||||
oldTreeInfo.damageAccumulator = info.damageAccumulator;
|
||||
TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING, info);
|
||||
prepareSubTree(oldTreeInfo, mDisplayListData);
|
||||
delete mDisplayListData;
|
||||
mDisplayListData = mStagingDisplayListData;
|
||||
@@ -277,39 +258,6 @@ void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) {
|
||||
}
|
||||
}
|
||||
|
||||
class AnimateFunctor {
|
||||
public:
|
||||
AnimateFunctor(RenderNode* target, TreeInfo& info)
|
||||
: mTarget(target), mInfo(info) {}
|
||||
|
||||
bool operator() (const sp<BaseRenderNodeAnimator>& animator) {
|
||||
return animator->animate(mTarget, mInfo);
|
||||
}
|
||||
private:
|
||||
RenderNode* mTarget;
|
||||
TreeInfo& mInfo;
|
||||
};
|
||||
|
||||
void RenderNode::evaluateAnimations(TreeInfo& info) {
|
||||
if (!mAnimators.size()) return;
|
||||
|
||||
// TODO: Can we target this better? For now treat it like any other staging
|
||||
// property push and just damage self before and after animators are run
|
||||
|
||||
damageSelf(info);
|
||||
info.damageAccumulator->popTransform();
|
||||
|
||||
AnimateFunctor functor(this, info);
|
||||
std::vector< sp<BaseRenderNodeAnimator> >::iterator newEnd;
|
||||
newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
|
||||
mAnimators.erase(newEnd, mAnimators.end());
|
||||
mProperties.updateMatrix();
|
||||
info.out.hasAnimations |= mAnimators.size();
|
||||
|
||||
info.damageAccumulator->pushTransform(this);
|
||||
damageSelf(info);
|
||||
}
|
||||
|
||||
void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) {
|
||||
if (subtree) {
|
||||
TextureCache& cache = Caches::getInstance().textureCache;
|
||||
|
||||
@@ -20,18 +20,11 @@
|
||||
#define LOG_TAG "OpenGLRenderer"
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <SkCamera.h>
|
||||
#include <SkMatrix.h>
|
||||
|
||||
#include <private/hwui/DrawGlInfo.h>
|
||||
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/LinearAllocator.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/SortedVector.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/Vector.h>
|
||||
|
||||
@@ -39,6 +32,7 @@
|
||||
|
||||
#include <androidfw/ResourceTypes.h>
|
||||
|
||||
#include "AnimatorManager.h"
|
||||
#include "DamageAccumulator.h"
|
||||
#include "Debug.h"
|
||||
#include "Matrix.h"
|
||||
@@ -176,19 +170,7 @@ public:
|
||||
ANDROID_API virtual void prepareTree(TreeInfo& info);
|
||||
|
||||
// UI thread only!
|
||||
ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
|
||||
animator->onAttached(this);
|
||||
mStagingAnimators.insert(animator);
|
||||
mNeedsAnimatorsSync = true;
|
||||
}
|
||||
|
||||
// UI thread only!
|
||||
ANDROID_API void removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
|
||||
mStagingAnimators.erase(animator);
|
||||
// Force a sync of the staging property value
|
||||
mDirtyPropertyFields |= animator->dirtyMask();
|
||||
mNeedsAnimatorsSync = true;
|
||||
}
|
||||
ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
|
||||
|
||||
protected:
|
||||
virtual void damageSelf(TreeInfo& info);
|
||||
@@ -262,7 +244,6 @@ private:
|
||||
void prepareTreeImpl(TreeInfo& info);
|
||||
void pushStagingPropertiesChanges(TreeInfo& info);
|
||||
void pushStagingDisplayListChanges(TreeInfo& info);
|
||||
void evaluateAnimations(TreeInfo& info);
|
||||
void prepareSubTree(TreeInfo& info, DisplayListData* subtree);
|
||||
void applyLayerPropertiesToLayer(TreeInfo& info);
|
||||
void prepareLayer(TreeInfo& info);
|
||||
@@ -278,9 +259,8 @@ private:
|
||||
DisplayListData* mDisplayListData;
|
||||
DisplayListData* mStagingDisplayListData;
|
||||
|
||||
bool mNeedsAnimatorsSync;
|
||||
std::set< sp<BaseRenderNodeAnimator> > mStagingAnimators;
|
||||
std::vector< sp<BaseRenderNodeAnimator> > mAnimators;
|
||||
friend class AnimatorManager;
|
||||
AnimatorManager mAnimatorManager;
|
||||
|
||||
// Owned by RT. Lifecycle is managed by prepareTree(), with the exception
|
||||
// being in ~RenderNode() which may happen on any thread.
|
||||
|
||||
@@ -79,6 +79,17 @@ public:
|
||||
, errorHandler(NULL)
|
||||
{}
|
||||
|
||||
explicit TreeInfo(TraversalMode mode, const TreeInfo& clone)
|
||||
: mode(mode)
|
||||
, frameTimeMs(clone.frameTimeMs)
|
||||
, animationHook(clone.animationHook)
|
||||
, prepareTextures(mode == MODE_FULL)
|
||||
, damageAccumulator(clone.damageAccumulator)
|
||||
, renderState(clone.renderState)
|
||||
, renderer(clone.renderer)
|
||||
, errorHandler(clone.errorHandler)
|
||||
{}
|
||||
|
||||
const TraversalMode mode;
|
||||
nsecs_t frameTimeMs;
|
||||
AnimationHook* animationHook;
|
||||
|
||||
@@ -123,8 +123,8 @@ void CanvasContext::makeCurrent() {
|
||||
mHaveNewSurface |= mEglManager.makeCurrent(mEglSurface);
|
||||
}
|
||||
|
||||
void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info) {
|
||||
bool success = layerUpdater->apply(info);
|
||||
void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) {
|
||||
bool success = layerUpdater->apply();
|
||||
LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
|
||||
if (layerUpdater->backingLayer()->deferredUpdateScheduled) {
|
||||
mCanvas->pushLayerUpdate(layerUpdater->backingLayer());
|
||||
@@ -237,8 +237,7 @@ void CanvasContext::invokeFunctor(RenderThread& thread, Functor* functor) {
|
||||
|
||||
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
|
||||
requireGlContext();
|
||||
TreeInfo info(TreeInfo::MODE_FULL, mRenderThread.renderState());
|
||||
layer->apply(info);
|
||||
layer->apply();
|
||||
return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
void setup(int width, int height, const Vector3& lightCenter, float lightRadius);
|
||||
void setOpaque(bool opaque);
|
||||
void makeCurrent();
|
||||
void processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info);
|
||||
void processLayerUpdate(DeferredLayerUpdater* layerUpdater);
|
||||
void prepareTree(TreeInfo& info);
|
||||
void draw();
|
||||
void destroyCanvasAndSurface();
|
||||
|
||||
@@ -127,7 +127,7 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
|
||||
Caches::getInstance().textureCache.resetMarkInUse();
|
||||
|
||||
for (size_t i = 0; i < mLayers.size(); i++) {
|
||||
mContext->processLayerUpdate(mLayers[i].get(), info);
|
||||
mContext->processLayerUpdate(mLayers[i].get());
|
||||
}
|
||||
mLayers.clear();
|
||||
mContext->prepareTree(info);
|
||||
|
||||
Reference in New Issue
Block a user