Merge "Animator refactoring & fixes"

This commit is contained in:
John Reck
2014-06-26 17:57:37 +00:00
committed by Android (Google) Code Review
17 changed files with 298 additions and 175 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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
};

View File

@@ -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
};

View File

@@ -13,6 +13,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
font/Font.cpp \
AmbientShadow.cpp \
Animator.cpp \
AnimatorManager.cpp \
AssetAtlas.cpp \
DamageAccumulator.cpp \
FontRenderer.cpp \

View File

@@ -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)());
}

View File

@@ -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();

View 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 */

View 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 */

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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);