Merge "Animator refactoring & fixes"
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index d86b699..ddc185c 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -21,9 +21,6 @@
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 @@
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 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 @@
///////////////////////////////////////////////////////////////////////////
private static native void nAddAnimator(long renderNode, long animatorPtr);
- private static native void nRemoveAnimator(long renderNode, long animatorPtr);
///////////////////////////////////////////////////////////////////////////
// Finalization
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 4979059..1363a5c 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -172,12 +172,14 @@
@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 @@
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 @@
@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 @@
@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 @@
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 @@
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);
}
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 3ffde2d..6ba22bf 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -456,16 +456,9 @@
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 @@
{ "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
};
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index d689864..de3dd16 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -149,6 +149,11 @@
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 @@
{ "nSetStartDelay", "(JJ)V", (void*) setStartDelay },
{ "nGetStartDelay", "(J)J", (void*) getStartDelay },
{ "nSetInterpolator", "(JJ)V", (void*) setInterpolator },
+ { "nCancel", "(J)V", (void*) cancel },
#endif
};
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index a704e19..1a96b2f 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -13,6 +13,7 @@
font/Font.cpp \
AmbientShadow.cpp \
Animator.cpp \
+ AnimatorManager.cpp \
AssetAtlas.cpp \
DamageAccumulator.cpp \
FontRenderer.cpp \
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index dc6d852..4a8c122 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -18,6 +18,7 @@
#include "Animator.h"
+#include <inttypes.h>
#include <set>
#include "RenderNode.h"
@@ -35,72 +36,105 @@
, 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 @@
callOnFinishedListener(info);
return true;
}
+
+ info.out.hasAnimations |= true;
return false;
}
@@ -153,7 +189,7 @@
}
void RenderPropertyAnimator::onAttached(RenderNode* target) {
- if (mPlayState == NEEDS_START
+ if (!mHasStartValue
&& target->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
setStartValue((target->stagingProperties().*mPropertyAccess->getter)());
}
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 6cb72c4c..a981b5a 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -50,12 +50,11 @@
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 @@
void callOnFinishedListener(TreeInfo& info);
enum PlayState {
- NEEDS_START,
- PENDING,
+ NOT_STARTED,
RUNNING,
FINISHED,
};
@@ -84,13 +82,19 @@
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 @@
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();
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
new file mode 100644
index 0000000..6a10cf8
--- /dev/null
+++ b/libs/hwui/AnimatorManager.cpp
@@ -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 */
diff --git a/libs/hwui/AnimatorManager.h b/libs/hwui/AnimatorManager.h
new file mode 100644
index 0000000..2568121
--- /dev/null
+++ b/libs/hwui/AnimatorManager.h
@@ -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 */
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 8e99b9a..02b0372 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -58,7 +58,7 @@
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);
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index c76bd5e..5905b95 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -75,7 +75,7 @@
ANDROID_API void setPaint(const SkPaint* paint);
- ANDROID_API bool apply(TreeInfo& info);
+ ANDROID_API bool apply();
ANDROID_API Layer* backingLayer() {
return mLayer;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 131384a..e803ec3 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -62,7 +62,7 @@
, mNeedsDisplayListDataSync(false)
, mDisplayListData(0)
, mStagingDisplayListData(0)
- , mNeedsAnimatorsSync(false)
+ , mAnimatorManager(*this)
, mLayer(0) {
}
@@ -117,6 +117,10 @@
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 @@
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 @@
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 @@
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 @@
}
}
-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;
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 3980dad..7d42b59 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -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 @@
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 @@
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 @@
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.
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 249e525..083100e 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -79,6 +79,17 @@
, 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;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 281a8e1..9c3cf44 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -123,8 +123,8 @@
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 @@
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);
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index d2ce1a6..dbfb3d2 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -56,7 +56,7 @@
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();
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index fddffd5..dd34e09 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -127,7 +127,7 @@
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);