diff options
-rw-r--r-- | core/java/android/view/RenderNodeAnimator.java | 24 | ||||
-rw-r--r-- | core/jni/android_view_RenderNode.cpp | 32 | ||||
-rw-r--r-- | core/jni/android_view_RenderNodeAnimator.cpp | 38 | ||||
-rw-r--r-- | core/jni/android_view_ThreadedRenderer.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/Animator.cpp | 145 | ||||
-rw-r--r-- | libs/hwui/Animator.h | 102 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 34 | ||||
-rw-r--r-- | libs/hwui/RenderNode.h | 28 | ||||
-rw-r--r-- | libs/hwui/TreeInfo.h | 4 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java | 11 | ||||
-rw-r--r-- | tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java | 9 |
11 files changed, 227 insertions, 206 deletions
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index ec4d560..f14e73f 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -21,7 +21,6 @@ import android.graphics.Canvas; import android.graphics.CanvasProperty; import android.graphics.Paint; import android.util.SparseIntArray; -import android.util.TimeUtils; import com.android.internal.util.VirtualRefBasePtr; import com.android.internal.view.animation.FallbackLUTInterpolator; @@ -72,10 +71,6 @@ public final class RenderNodeAnimator { put(ViewPropertyAnimator.ALPHA, ALPHA); }}; - // Keep in sync DeltaValueType in Animator.h - public static final int DELTA_TYPE_ABSOLUTE = 0; - public static final int DELTA_TYPE_DELTA = 1; - private VirtualRefBasePtr mNativePtr; private RenderNode mTarget; @@ -86,22 +81,21 @@ public final class RenderNodeAnimator { return sViewPropertyAnimatorMap.get(viewProperty); } - public RenderNodeAnimator(int property, int deltaType, float deltaValue) { + public RenderNodeAnimator(int property, float finalValue) { init(nCreateAnimator(new WeakReference<RenderNodeAnimator>(this), - property, deltaType, deltaValue)); + property, finalValue)); } - public RenderNodeAnimator(CanvasProperty<Float> property, int deltaType, float deltaValue) { + public RenderNodeAnimator(CanvasProperty<Float> property, float finalValue) { init(nCreateCanvasPropertyFloatAnimator( new WeakReference<RenderNodeAnimator>(this), - property.getNativeContainer(), deltaType, deltaValue)); + property.getNativeContainer(), finalValue)); } - public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField, - int deltaType, float deltaValue) { + public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField, float finalValue) { init(nCreateCanvasPropertyPaintAnimator( new WeakReference<RenderNodeAnimator>(this), - property.getNativeContainer(), paintField, deltaType, deltaValue)); + property.getNativeContainer(), paintField, finalValue)); } private void init(long ptr) { @@ -182,11 +176,11 @@ public final class RenderNodeAnimator { } private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis, - int property, int deltaValueType, float deltaValue); + int property, float deltaValue); private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis, - long canvasProperty, int deltaValueType, float deltaValue); + long canvasProperty, float deltaValue); private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis, - long canvasProperty, int paintField, int deltaValueType, float deltaValue); + long canvasProperty, int paintField, float deltaValue); private static native void nSetDuration(long nativePtr, int duration); private static native int nGetDuration(long nativePtr); private static native void nSetInterpolator(long animPtr, long interpolatorPtr); diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index e45a901..b0defdb 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -80,6 +80,7 @@ static void android_view_RenderNode_setCaching(JNIEnv* env, jobject clazz, jlong renderNodePtr, jboolean caching) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setCaching(caching); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setStaticMatrix(JNIEnv* env, @@ -87,6 +88,7 @@ static void android_view_RenderNode_setStaticMatrix(JNIEnv* env, RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr); renderNode->mutateStagingProperties().setStaticMatrix(matrix); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setAnimationMatrix(JNIEnv* env, @@ -94,24 +96,28 @@ static void android_view_RenderNode_setAnimationMatrix(JNIEnv* env, RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr); renderNode->mutateStagingProperties().setAnimationMatrix(matrix); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setClipToBounds(JNIEnv* env, jobject clazz, jlong renderNodePtr, jboolean clipToBounds) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setClipToBounds(clipToBounds); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setProjectBackwards(JNIEnv* env, jobject clazz, jlong renderNodePtr, jboolean shouldProject) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setProjectBackwards(shouldProject); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setProjectionReceiver(JNIEnv* env, jobject clazz, jlong renderNodePtr, jboolean shouldRecieve) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setProjectionReceiver(shouldRecieve); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setOutlineRoundRect(JNIEnv* env, @@ -119,6 +125,7 @@ static void android_view_RenderNode_setOutlineRoundRect(JNIEnv* env, jint right, jint bottom, jfloat radius) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, radius); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setOutlineConvexPath(JNIEnv* env, @@ -126,18 +133,21 @@ static void android_view_RenderNode_setOutlineConvexPath(JNIEnv* env, RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr); renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setOutlineEmpty(JNIEnv* env, jobject clazz, jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().mutableOutline().setEmpty(); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setClipToOutline(JNIEnv* env, jobject clazz, jlong renderNodePtr, jboolean clipToOutline) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setRevealClip(JNIEnv* env, @@ -146,114 +156,133 @@ static void android_view_RenderNode_setRevealClip(JNIEnv* env, RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().mutableRevealClip().set( shouldClip, inverseClip, x, y, radius); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setAlpha(JNIEnv* env, jobject clazz, jlong renderNodePtr, float alpha) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setAlpha(alpha); + renderNode->setPropertyFieldsDirty(RenderNode::ALPHA); } static void android_view_RenderNode_setHasOverlappingRendering(JNIEnv* env, jobject clazz, jlong renderNodePtr, bool hasOverlappingRendering) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setHasOverlappingRendering(hasOverlappingRendering); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setElevation(JNIEnv* env, jobject clazz, jlong renderNodePtr, float elevation) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setElevation(elevation); + renderNode->setPropertyFieldsDirty(RenderNode::Z); } static void android_view_RenderNode_setTranslationX(JNIEnv* env, jobject clazz, jlong renderNodePtr, float tx) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setTranslationX(tx); + renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_X | RenderNode::X); } static void android_view_RenderNode_setTranslationY(JNIEnv* env, jobject clazz, jlong renderNodePtr, float ty) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setTranslationY(ty); + renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_Y | RenderNode::Y); } static void android_view_RenderNode_setTranslationZ(JNIEnv* env, jobject clazz, jlong renderNodePtr, float tz) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setTranslationZ(tz); + renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z | RenderNode::Z); } static void android_view_RenderNode_setRotation(JNIEnv* env, jobject clazz, jlong renderNodePtr, float rotation) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setRotation(rotation); + renderNode->setPropertyFieldsDirty(RenderNode::ROTATION); } static void android_view_RenderNode_setRotationX(JNIEnv* env, jobject clazz, jlong renderNodePtr, float rx) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setRotationX(rx); + renderNode->setPropertyFieldsDirty(RenderNode::ROTATION_X); } static void android_view_RenderNode_setRotationY(JNIEnv* env, jobject clazz, jlong renderNodePtr, float ry) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setRotationY(ry); + renderNode->setPropertyFieldsDirty(RenderNode::ROTATION_Y); } static void android_view_RenderNode_setScaleX(JNIEnv* env, jobject clazz, jlong renderNodePtr, float sx) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setScaleX(sx); + renderNode->setPropertyFieldsDirty(RenderNode::SCALE_X); } static void android_view_RenderNode_setScaleY(JNIEnv* env, jobject clazz, jlong renderNodePtr, float sy) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setScaleY(sy); + renderNode->setPropertyFieldsDirty(RenderNode::SCALE_Y); } static void android_view_RenderNode_setPivotX(JNIEnv* env, jobject clazz, jlong renderNodePtr, float px) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setPivotX(px); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setPivotY(JNIEnv* env, jobject clazz, jlong renderNodePtr, float py) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setPivotY(py); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setCameraDistance(JNIEnv* env, jobject clazz, jlong renderNodePtr, float distance) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setCameraDistance(distance); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); } static void android_view_RenderNode_setLeft(JNIEnv* env, jobject clazz, jlong renderNodePtr, int left) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setLeft(left); + renderNode->setPropertyFieldsDirty(RenderNode::X); } static void android_view_RenderNode_setTop(JNIEnv* env, jobject clazz, jlong renderNodePtr, int top) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setTop(top); + renderNode->setPropertyFieldsDirty(RenderNode::Y); } static void android_view_RenderNode_setRight(JNIEnv* env, jobject clazz, jlong renderNodePtr, int right) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setRight(right); + renderNode->setPropertyFieldsDirty(RenderNode::X); } static void android_view_RenderNode_setBottom(JNIEnv* env, jobject clazz, jlong renderNodePtr, int bottom) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setBottom(bottom); + renderNode->setPropertyFieldsDirty(RenderNode::Y); } static void android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env, @@ -261,18 +290,21 @@ static void android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env, int right, int bottom) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom); + renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y); } static void android_view_RenderNode_offsetLeftAndRight(JNIEnv* env, jobject clazz, jlong renderNodePtr, float offset) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().offsetLeftRight(offset); + renderNode->setPropertyFieldsDirty(RenderNode::X); } static void android_view_RenderNode_offsetTopAndBottom(JNIEnv* env, jobject clazz, jlong renderNodePtr, float offset) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().offsetTopBottom(offset); + renderNode->setPropertyFieldsDirty(RenderNode::Y); } // ---------------------------------------------------------------------------- diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp index 5733f60..ea2f96e 100644 --- a/core/jni/android_view_RenderNodeAnimator.cpp +++ b/core/jni/android_view_RenderNodeAnimator.cpp @@ -62,7 +62,7 @@ public: mWeakThis = NULL; } - virtual void onAnimationFinished(BaseAnimator*) { + virtual void onAnimationFinished(BaseRenderNodeAnimator*) { JNIEnv* env = getEnv(mJvm); env->CallStaticVoidMethod( gRenderNodeAnimatorClassInfo.clazz, @@ -81,13 +81,6 @@ static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint prope return static_cast<RenderPropertyAnimator::RenderProperty>(property); } -static inline RenderPropertyAnimator::DeltaValueType toDeltaType(jint deltaType) { - LOG_ALWAYS_FATAL_IF(deltaType != RenderPropertyAnimator::DELTA - && deltaType != RenderPropertyAnimator::ABSOLUTE, - "Invalid delta type %d", deltaType); - return static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType); -} - static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) { LOG_ALWAYS_FATAL_IF(field < 0 || field > CanvasPropertyPaintAnimator::ALPHA, @@ -96,49 +89,46 @@ static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) { } static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis, - jint propertyRaw, jint deltaTypeRaw, jfloat deltaValue) { + jint propertyRaw, jfloat finalValue) { RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw); - RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw); - BaseAnimator* animator = new RenderPropertyAnimator(property, deltaType, deltaValue); + BaseRenderNodeAnimator* animator = new RenderPropertyAnimator(property, finalValue); animator->setListener(new AnimationListenerBridge(env, weakThis)); return reinterpret_cast<jlong>( animator ); } static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz, - jobject weakThis, jlong canvasPropertyPtr, jint deltaTypeRaw, jfloat deltaValue) { - RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw); + jobject weakThis, jlong canvasPropertyPtr, jfloat finalValue) { CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr); - BaseAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, deltaType, deltaValue); + BaseRenderNodeAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, finalValue); animator->setListener(new AnimationListenerBridge(env, weakThis)); return reinterpret_cast<jlong>( animator ); } static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz, jobject weakThis, jlong canvasPropertyPtr, jint paintFieldRaw, - jint deltaTypeRaw, jfloat deltaValue) { - RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw); + jfloat finalValue) { CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr); CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw); - BaseAnimator* animator = new CanvasPropertyPaintAnimator( - canvasProperty, paintField, deltaType, deltaValue); + BaseRenderNodeAnimator* animator = new CanvasPropertyPaintAnimator( + canvasProperty, paintField, finalValue); animator->setListener(new AnimationListenerBridge(env, weakThis)); return reinterpret_cast<jlong>( animator ); } static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint duration) { LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative"); - BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr); + BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); animator->setDuration(duration); } static jint getDuration(JNIEnv* env, jobject clazz, jlong animatorPtr) { - BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr); + BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); return static_cast<jint>(animator->duration()); } static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong interpolatorPtr) { - BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr); + BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr); animator->setInterpolator(interpolator); } @@ -153,9 +143,9 @@ const char* const kClassPathName = "android/view/RenderNodeAnimator"; static JNINativeMethod gMethods[] = { #ifdef USE_OPENGL_RENDERER - { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IIF)J", (void*) createAnimator }, - { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyFloatAnimator }, - { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIIF)J", (void*) createCanvasPropertyPaintAnimator }, + { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IF)J", (void*) createAnimator }, + { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JF)J", (void*) createCanvasPropertyFloatAnimator }, + { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyPaintAnimator }, { "nSetDuration", "(JI)V", (void*) setDuration }, { "nGetDuration", "(J)I", (void*) getDuration }, { "nSetInterpolator", "(JJ)V", (void*) setInterpolator }, diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index d130a6d..2c10212 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -92,9 +92,9 @@ private: class OnFinishedEvent { public: - OnFinishedEvent(BaseAnimator* animator, AnimationListener* listener) + OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener) : animator(animator), listener(listener) {} - sp<BaseAnimator> animator; + sp<BaseRenderNodeAnimator> animator; sp<AnimationListener> listener; }; @@ -127,7 +127,7 @@ public: virtual ~RootRenderNode() {} - virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) { + virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) { OnFinishedEvent event(animator, listener); mOnFinishedEvents.push_back(event); } diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp index a033f86..83eedfb 100644 --- a/libs/hwui/Animator.cpp +++ b/libs/hwui/Animator.cpp @@ -27,31 +27,48 @@ namespace android { namespace uirenderer { /************************************************************ - * Base animator + * BaseRenderNodeAnimator ************************************************************/ -BaseAnimator::BaseAnimator() - : mInterpolator(0) - , mPlayState(PENDING) +BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue) + : mFinalValue(finalValue) + , mDeltaValue(0) + , mFromValue(0) + , mInterpolator(0) + , mPlayState(NEEDS_START) , mStartTime(0) - , mDuration(300) { - + , mDuration(300){ } -BaseAnimator::~BaseAnimator() { +BaseRenderNodeAnimator::~BaseRenderNodeAnimator() { setInterpolator(NULL); } -void BaseAnimator::setInterpolator(Interpolator* interpolator) { +void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) { delete mInterpolator; mInterpolator = interpolator; } -void BaseAnimator::setDuration(nsecs_t duration) { +void BaseRenderNodeAnimator::setDuration(nsecs_t duration) { mDuration = duration; } -bool BaseAnimator::animateFrame(TreeInfo& info) { +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; +} + +void BaseRenderNodeAnimator::setupStartValueIfNecessary(RenderNode* target, TreeInfo& info) { + if (mPlayState == NEEDS_START) { + setStartValue(getValue(target)); + mPlayState = PENDING; + } +} + +bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) { if (mPlayState == PENDING) { mPlayState = RUNNING; mStartTime = info.frameTimeMs; @@ -59,7 +76,6 @@ bool BaseAnimator::animateFrame(TreeInfo& info) { if (!mInterpolator) { setInterpolator(Interpolator::createDefaultInterpolator()); } - onAnimationStarted(); } float fraction = 1.0f; @@ -71,17 +87,16 @@ bool BaseAnimator::animateFrame(TreeInfo& info) { } } fraction = mInterpolator->interpolate(fraction); - onAnimationUpdated(fraction); + setValue(target, mFromValue + (mDeltaValue * fraction)); if (mPlayState == FINISHED) { - onAnimationFinished(); callOnFinishedListener(info); return true; } return false; } -void BaseAnimator::callOnFinishedListener(TreeInfo& info) { +void BaseRenderNodeAnimator::callOnFinishedListener(TreeInfo& info) { if (mListener.get()) { if (!info.animationHook) { mListener->onAnimationFinished(this); @@ -92,70 +107,49 @@ void BaseAnimator::callOnFinishedListener(TreeInfo& info) { } /************************************************************ - * BaseRenderNodeAnimator - ************************************************************/ - -BaseRenderNodeAnimator::BaseRenderNodeAnimator( - BaseRenderNodeAnimator::DeltaValueType deltaType, float delta) - : mTarget(0) - , mDeltaValueType(deltaType) - , mDeltaValue(delta) - , mFromValue(-1) { -} - -bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) { - mTarget = target; - bool finished = animateFrame(info); - mTarget = NULL; - return finished; -} - -void BaseRenderNodeAnimator::onAnimationStarted() { - mFromValue = getValue(); - - if (mDeltaValueType == BaseRenderNodeAnimator::ABSOLUTE) { - mDeltaValue = (mDeltaValue - mFromValue); - mDeltaValueType = BaseRenderNodeAnimator::DELTA; - } -} - -void BaseRenderNodeAnimator::onAnimationUpdated(float fraction) { - float value = mFromValue + (mDeltaValue * fraction); - setValue(value); -} - -/************************************************************ * RenderPropertyAnimator ************************************************************/ +struct RenderPropertyAnimator::PropertyAccessors { + RenderNode::DirtyPropertyMask dirtyMask; + GetFloatProperty getter; + SetFloatProperty setter; +}; + // Maps RenderProperty enum to accessors const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = { - {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX }, - {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY }, - {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ }, - {&RenderProperties::getScaleX, &RenderProperties::setScaleX }, - {&RenderProperties::getScaleY, &RenderProperties::setScaleY }, - {&RenderProperties::getRotation, &RenderProperties::setRotation }, - {&RenderProperties::getRotationX, &RenderProperties::setRotationX }, - {&RenderProperties::getRotationY, &RenderProperties::setRotationY }, - {&RenderProperties::getX, &RenderProperties::setX }, - {&RenderProperties::getY, &RenderProperties::setY }, - {&RenderProperties::getZ, &RenderProperties::setZ }, - {&RenderProperties::getAlpha, &RenderProperties::setAlpha }, + {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX, &RenderProperties::setTranslationX }, + {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY, &RenderProperties::setTranslationY }, + {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ }, + {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX }, + {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY }, + {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation }, + {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX }, + {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY }, + {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX }, + {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY }, + {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ }, + {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha }, }; -RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, - DeltaValueType deltaType, float deltaValue) - : BaseRenderNodeAnimator(deltaType, deltaValue) - , mPropertyAccess(PROPERTY_ACCESSOR_LUT[property]) { +RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue) + : BaseRenderNodeAnimator(finalValue) + , mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) { +} + +void RenderPropertyAnimator::onAttached(RenderNode* target) { + if (target->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) { + setStartValue((target->stagingProperties().*mPropertyAccess->getter)()); + } + (target->mutateStagingProperties().*mPropertyAccess->setter)(finalValue()); } -float RenderPropertyAnimator::getValue() const { - return (target()->animatorProperties().*mPropertyAccess.getter)(); +float RenderPropertyAnimator::getValue(RenderNode* target) const { + return (target->properties().*mPropertyAccess->getter)(); } -void RenderPropertyAnimator::setValue(float value) { - (target()->animatorProperties().*mPropertyAccess.setter)(value); +void RenderPropertyAnimator::setValue(RenderNode* target, float value) { + (target->animatorProperties().*mPropertyAccess->setter)(value); } /************************************************************ @@ -163,16 +157,16 @@ void RenderPropertyAnimator::setValue(float value) { ************************************************************/ CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator( - CanvasPropertyPrimitive* property, DeltaValueType deltaType, float deltaValue) - : BaseRenderNodeAnimator(deltaType, deltaValue) + CanvasPropertyPrimitive* property, float finalValue) + : BaseRenderNodeAnimator(finalValue) , mProperty(property) { } -float CanvasPropertyPrimitiveAnimator::getValue() const { +float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const { return mProperty->value; } -void CanvasPropertyPrimitiveAnimator::setValue(float value) { +void CanvasPropertyPrimitiveAnimator::setValue(RenderNode* target, float value) { mProperty->value = value; } @@ -181,14 +175,13 @@ void CanvasPropertyPrimitiveAnimator::setValue(float value) { ************************************************************/ CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator( - CanvasPropertyPaint* property, PaintField field, - DeltaValueType deltaType, float deltaValue) - : BaseRenderNodeAnimator(deltaType, deltaValue) + CanvasPropertyPaint* property, PaintField field, float finalValue) + : BaseRenderNodeAnimator(finalValue) , mProperty(property) , mField(field) { } -float CanvasPropertyPaintAnimator::getValue() const { +float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const { switch (mField) { case STROKE_WIDTH: return mProperty->value.getStrokeWidth(); @@ -204,7 +197,7 @@ static uint8_t to_uint8(float value) { return static_cast<uint8_t>( c < 0 ? 0 : c > 255 ? 255 : c ); } -void CanvasPropertyPaintAnimator::setValue(float value) { +void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) { switch (mField) { case STROKE_WIDTH: mProperty->value.setStrokeWidth(value); diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index 52a1807..fe88cbf 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -33,16 +33,14 @@ class RenderProperties; class AnimationListener : public VirtualLightRefBase { public: - ANDROID_API virtual void onAnimationFinished(BaseAnimator*) = 0; + ANDROID_API virtual void onAnimationFinished(BaseRenderNodeAnimator*) = 0; protected: ANDROID_API virtual ~AnimationListener() {} }; -// Helper class to contain generic animator helpers -class BaseAnimator : public VirtualLightRefBase { - PREVENT_COPY_AND_ASSIGN(BaseAnimator); +class BaseRenderNodeAnimator : public VirtualLightRefBase { + PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator); public: - ANDROID_API void setInterpolator(Interpolator* interpolator); ANDROID_API void setDuration(nsecs_t durationInMs); ANDROID_API nsecs_t duration() { return mDuration; } @@ -50,31 +48,38 @@ public: mListener = listener; } + ANDROID_API virtual void onAttached(RenderNode* target) {} + + // Guaranteed to happen before the staging push + void setupStartValueIfNecessary(RenderNode* target, TreeInfo& info); + + bool animate(RenderNode* target, TreeInfo& info); + bool isFinished() { return mPlayState == FINISHED; } + float finalValue() { return mFinalValue; } protected: - BaseAnimator(); - virtual ~BaseAnimator(); - - // This is the main animation entrypoint that subclasses should call - // to generate the onAnimation* lifecycle events - // Returns true if the animation has finished, false otherwise - bool animateFrame(TreeInfo& info); + BaseRenderNodeAnimator(float finalValue); + virtual ~BaseRenderNodeAnimator(); - // Called when PlayState switches from PENDING to RUNNING - virtual void onAnimationStarted() {} - virtual void onAnimationUpdated(float fraction) = 0; - virtual void onAnimationFinished() {} + void setStartValue(float value); + virtual float getValue(RenderNode* target) const = 0; + virtual void setValue(RenderNode* target, float value) = 0; private: void callOnFinishedListener(TreeInfo& info); enum PlayState { + NEEDS_START, PENDING, RUNNING, FINISHED, }; + float mFinalValue; + float mDeltaValue; + float mFromValue; + Interpolator* mInterpolator; PlayState mPlayState; long mStartTime; @@ -83,42 +88,6 @@ private: sp<AnimationListener> mListener; }; -class BaseRenderNodeAnimator : public BaseAnimator { -public: - // Since the UI thread doesn't necessarily know what the current values - // actually are and thus can't do the calculations, this is used to inform - // the animator how to lazy-resolve the input value - enum DeltaValueType { - // The delta value represents an absolute value endpoint - // mDeltaValue needs to be recalculated to be mDelta = (mDelta - fromValue) - // in onAnimationStarted() - ABSOLUTE = 0, - // The final value represents an offset from the current value - // No recalculation is needed - DELTA, - }; - - bool animate(RenderNode* target, TreeInfo& info); - -protected: - BaseRenderNodeAnimator(DeltaValueType deltaType, float deltaValue); - - RenderNode* target() const { return mTarget; } - virtual float getValue() const = 0; - virtual void setValue(float value) = 0; - -private: - virtual void onAnimationStarted(); - virtual void onAnimationUpdated(float fraction); - - // mTarget is only valid inside animate() - RenderNode* mTarget; - - BaseRenderNodeAnimator::DeltaValueType mDeltaValueType; - float mDeltaValue; - float mFromValue; -}; - class RenderPropertyAnimator : public BaseRenderNodeAnimator { public: enum RenderProperty { @@ -136,23 +105,20 @@ public: ALPHA, }; - ANDROID_API RenderPropertyAnimator(RenderProperty property, - DeltaValueType deltaType, float deltaValue); + ANDROID_API RenderPropertyAnimator(RenderProperty property, float finalValue); + + ANDROID_API virtual void onAttached(RenderNode* target); protected: - ANDROID_API virtual float getValue() const; - ANDROID_API virtual void setValue(float value); + virtual float getValue(RenderNode* target) const; + virtual void setValue(RenderNode* target, float value); private: typedef void (RenderProperties::*SetFloatProperty)(float value); typedef float (RenderProperties::*GetFloatProperty)() const; - struct PropertyAccessors { - GetFloatProperty getter; - SetFloatProperty setter; - }; - - PropertyAccessors mPropertyAccess; + struct PropertyAccessors; + const PropertyAccessors* mPropertyAccess; static const PropertyAccessors PROPERTY_ACCESSOR_LUT[]; }; @@ -160,10 +126,10 @@ private: class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator { public: ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property, - DeltaValueType deltaType, float deltaValue); + float finalValue); protected: - ANDROID_API virtual float getValue() const; - ANDROID_API virtual void setValue(float value); + virtual float getValue(RenderNode* target) const; + virtual void setValue(RenderNode* target, float value); private: sp<CanvasPropertyPrimitive> mProperty; }; @@ -176,10 +142,10 @@ public: }; ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property, - PaintField field, DeltaValueType deltaType, float deltaValue); + PaintField field, float finalValue); protected: - ANDROID_API virtual float getValue() const; - ANDROID_API virtual void setValue(float value); + virtual float getValue(RenderNode* target) const; + virtual void setValue(RenderNode* target, float value); private: sp<CanvasPropertyPaint> mProperty; PaintField mField; diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index fba482d..d4ff4a3 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -53,7 +53,7 @@ void RenderNode::outputLogBuffer(int fd) { } RenderNode::RenderNode() - : mNeedsPropertiesSync(false) + : mDirtyPropertyFields(0) , mNeedsDisplayListDataSync(false) , mDisplayListData(0) , mStagingDisplayListData(0) @@ -109,23 +109,37 @@ void RenderNode::prepareTreeImpl(TreeInfo& info) { prepareSubTree(info, mDisplayListData); } -static bool is_finished(const sp<BaseRenderNodeAnimator>& animator) { - return animator->isFinished(); -} +class PushAnimatorsFunctor { +public: + PushAnimatorsFunctor(RenderNode* target, TreeInfo& info) + : mTarget(target), mInfo(info) {} -void RenderNode::pushStagingChanges(TreeInfo& info) { - if (mNeedsPropertiesSync) { - mNeedsPropertiesSync = false; - mProperties = mStagingProperties; + bool operator() (const sp<BaseRenderNodeAnimator>& animator) { + animator->setupStartValueIfNecessary(mTarget, mInfo); + return animator->isFinished(); } +private: + RenderNode* mTarget; + TreeInfo& mInfo; +}; + +void RenderNode::pushStagingChanges(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(), is_finished); + mAnimators.begin(), functor); mAnimators.resize(std::distance(mAnimators.begin(), it)); } + if (mDirtyPropertyFields) { + mDirtyPropertyFields = 0; + mProperties = mStagingProperties; + } if (mNeedsDisplayListDataSync) { mNeedsDisplayListDataSync = false; // Do a push pass on the old tree to handle freeing DisplayListData @@ -144,7 +158,7 @@ public: AnimateFunctor(RenderNode* target, TreeInfo& info) : mTarget(target), mInfo(info) {} - bool operator() (sp<BaseRenderNodeAnimator>& animator) { + bool operator() (const sp<BaseRenderNodeAnimator>& animator) { return animator->animate(mTarget, mInfo); } private: diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index bc62ee1..1811a7b 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -82,6 +82,22 @@ class DrawDisplayListOp; */ class RenderNode : public VirtualLightRefBase { public: + enum DirtyPropertyMask { + GENERIC = 1 << 1, + TRANSLATION_X = 1 << 2, + TRANSLATION_Y = 1 << 3, + TRANSLATION_Z = 1 << 4, + SCALE_X = 1 << 5, + SCALE_Y = 1 << 6, + ROTATION = 1 << 7, + ROTATION_X = 1 << 8, + ROTATION_Y = 1 << 9, + X = 1 << 10, + Y = 1 << 11, + Z = 1 << 12, + ALPHA = 1 << 13, + }; + ANDROID_API RenderNode(); ANDROID_API virtual ~RenderNode(); @@ -123,6 +139,14 @@ public: } } + bool isPropertyFieldDirty(DirtyPropertyMask field) const { + return mDirtyPropertyFields & field; + } + + void setPropertyFieldsDirty(uint32_t fields) { + mDirtyPropertyFields |= fields; + } + const RenderProperties& properties() { return mProperties; } @@ -136,7 +160,6 @@ public: } RenderProperties& mutateStagingProperties() { - mNeedsPropertiesSync = true; return mStagingProperties; } @@ -152,6 +175,7 @@ public: // UI thread only! ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator) { + animator->onAttached(this); mStagingAnimators.insert(animator); mNeedsAnimatorsSync = true; } @@ -227,7 +251,7 @@ private: String8 mName; - bool mNeedsPropertiesSync; + uint32_t mDirtyPropertyFields; RenderProperties mProperties; RenderProperties mStagingProperties; diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h index fc5994c..d4a23b8 100644 --- a/libs/hwui/TreeInfo.h +++ b/libs/hwui/TreeInfo.h @@ -21,12 +21,12 @@ namespace android { namespace uirenderer { -class BaseAnimator; +class BaseRenderNodeAnimator; class AnimationListener; class AnimationHook { public: - virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) = 0; + virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) = 0; protected: ~AnimationHook() {} }; diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java index 1d0a806..e4ea936 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java @@ -109,26 +109,27 @@ public class CirclePropActivity extends Activity { mToggle = !mToggle; mRunningAnimations.add(new RenderNodeAnimator( - mX, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 400.0f : 200.0f)); + mX, mToggle ? 400.0f : 200.0f)); mRunningAnimations.add(new RenderNodeAnimator( - mY, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 600.0f : 200.0f)); + mY, mToggle ? 600.0f : 200.0f)); mRunningAnimations.add(new RenderNodeAnimator( - mRadius, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 250.0f : 150.0f)); + mRadius, mToggle ? 250.0f : 150.0f)); mRunningAnimations.add(new RenderNodeAnimator( mPaint, RenderNodeAnimator.PAINT_ALPHA, - RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 64.0f : 255.0f)); + mToggle ? 64.0f : 255.0f)); mRunningAnimations.add(new RenderNodeAnimator( mPaint, RenderNodeAnimator.PAINT_STROKE_WIDTH, - RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 5.0f : 60.0f)); + mToggle ? 5.0f : 60.0f)); TimeInterpolator interp = new OvershootInterpolator(3.0f); for (int i = 0; i < mRunningAnimations.size(); i++) { RenderNodeAnimator anim = mRunningAnimations.get(i); anim.setInterpolator(interp); + anim.setDuration(1000); anim.start(this); } diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java index 8f9cf58..b5b12d8 100644 --- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java +++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java @@ -5,6 +5,7 @@ import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; +import android.util.Log; import android.view.HardwareRenderer; import android.view.RenderNodeAnimator; import android.view.View; @@ -73,14 +74,20 @@ public class MainActivity extends Activity implements OnItemClickListener { float delta = (pos - clickedPosition) * 1.1f; if (delta == 0) delta = -1; RenderNodeAnimator animator = new RenderNodeAnimator( - RenderNodeAnimator.TRANSLATION_Y, RenderNodeAnimator.DELTA_TYPE_DELTA, dy * delta); + RenderNodeAnimator.TRANSLATION_Y, dy * delta); animator.setDuration(DURATION); + if (child == clickedView) logTranslationY(clickedView); animator.start(child); + if (child == clickedView) logTranslationY(clickedView); } //mHandler.postDelayed(mLaunchActivity, (long) (DURATION * .4)); mLaunchActivity.run(); } + private void logTranslationY(View v) { + Log.d("RTTest", "View has translationY: " + v.getTranslationY()); + } + private Runnable mLaunchActivity = new Runnable() { @Override |