diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index d86b699ef01c0..ddc185cfcef4e 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -21,9 +21,6 @@ import android.graphics.Matrix; import android.graphics.Outline; import android.graphics.Paint; -import java.util.ArrayList; -import java.util.List; - /** *

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 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(); - } - 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 diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index 4979059abf169..1363a5c129c02 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -172,12 +172,14 @@ public final class RenderNodeAnimator extends Animator { @Override public void cancel() { - mTarget.removeAnimator(this); + if (!mFinished) { + nCancel(mNativePtr.get()); - final ArrayList listeners = getListeners(); - final int numListeners = listeners == null ? 0 : listeners.size(); - for (int i = 0; i < numListeners; i++) { - listeners.get(i).onAnimationCancel(this); + final ArrayList 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 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 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 3ffde2d3b8e36..6ba22bf7c5292 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -456,16 +456,9 @@ static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz, RenderNode* renderNode = reinterpret_cast(renderNodePtr); RenderPropertyAnimator* animator = reinterpret_cast(animatorPtr); renderNode->addAnimator(animator); + animator->start(); } -static void android_view_RenderNode_removeAnimator(JNIEnv* env, jobject clazz, - jlong renderNodePtr, jlong animatorPtr) { - RenderNode* renderNode = reinterpret_cast(renderNodePtr); - RenderPropertyAnimator* animator = reinterpret_cast(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 }; diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp index d689864eec8b4..de3dd161e4900 100644 --- a/core/jni/android_view_RenderNodeAnimator.cpp +++ b/core/jni/android_view_RenderNodeAnimator.cpp @@ -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(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 }; diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index a704e19dea7ea..1a96b2f913bf0 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -13,6 +13,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) 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 dc6d8520597c6..4a8c12230eeba 100644 --- a/libs/hwui/Animator.cpp +++ b/libs/hwui/Animator.cpp @@ -18,6 +18,7 @@ #include "Animator.h" +#include #include #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)()); } diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index 6cb72c4ccb020..a981b5a7d4af3 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -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 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(); diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp new file mode 100644 index 0000000000000..6a10cf8f48fc3 --- /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 + +#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& animator) { + animator->incStrong(0); + animator->onAttached(&mParent); + mNewAnimators.push_back(animator.get()); +} + +template +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::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 0000000000000..25681213711a5 --- /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 + +#include +#include + +#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& 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 mNewAnimators; + std::vector mAnimators; +}; + +} /* namespace uirenderer */ +} /* namespace android */ + +#endif /* ANIMATORMANAGER_H */ diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index 8e99b9a8cba7b..02b0372f55263 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -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); diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index c76bd5edd1646..5905b955a2c14 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -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; diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 131384a5a583a..e803ec3dc5101 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -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& 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& 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 >::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& 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 >::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 3980dad29044f..7d42b59054adb 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -20,18 +20,11 @@ #define LOG_TAG "OpenGLRenderer" #endif -#include -#include - #include #include -#include - -#include #include #include -#include #include #include @@ -39,6 +32,7 @@ #include +#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& animator) { - animator->onAttached(this); - mStagingAnimators.insert(animator); - mNeedsAnimatorsSync = true; - } - - // UI thread only! - ANDROID_API void removeAnimator(const sp& animator) { - mStagingAnimators.erase(animator); - // Force a sync of the staging property value - mDirtyPropertyFields |= animator->dirtyMask(); - mNeedsAnimatorsSync = true; - } + ANDROID_API void addAnimator(const sp& 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 > mStagingAnimators; - std::vector< sp > 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 249e52562dd0a..083100e8b183e 100644 --- a/libs/hwui/TreeInfo.h +++ b/libs/hwui/TreeInfo.h @@ -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; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 281a8e151a758..9c3cf44bb1ec0 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -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); } diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index d2ce1a6dfbd10..dbfb3d24102fa 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -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(); diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index fddffd5812765..dd34e095738d4 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -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);