diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/view/RenderNode.java | 51 | ||||
-rw-r--r-- | core/java/android/view/RenderNodeAnimator.java | 122 | ||||
-rw-r--r-- | core/java/android/view/ThreadedRenderer.java | 15 | ||||
-rw-r--r-- | core/java/android/view/ViewPropertyAnimator.java | 26 | ||||
-rw-r--r-- | core/jni/Android.mk | 1 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 2 | ||||
-rw-r--r-- | core/jni/android_view_RenderNode.cpp | 23 | ||||
-rw-r--r-- | core/jni/android_view_RenderNodeAnimator.cpp | 127 | ||||
-rw-r--r-- | core/jni/android_view_RenderNodeAnimator.h | 36 | ||||
-rw-r--r-- | core/jni/android_view_ThreadedRenderer.cpp | 80 |
10 files changed, 455 insertions, 28 deletions
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index 3dc09c4..8b80c3e0 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -20,6 +20,9 @@ import android.annotation.NonNull; import android.graphics.Matrix; import android.graphics.Outline; +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 @@ -176,11 +179,24 @@ public class RenderNode { private boolean mValid; private final long mNativeRenderNode; + // We need to keep a strong reference to all running animators to ensure that + // they can call removeAnimator when they have finished, as the native-side + // object can only hold a WeakReference<> to avoid leaking memory due to + // cyclic references. + private List<RenderNodeAnimator> mActiveAnimators; + private RenderNode(String name) { mNativeRenderNode = nCreate(name); } /** + * @see RenderNode#adopt(long) + */ + private RenderNode(long nativePtr) { + mNativeRenderNode = nativePtr; + } + + /** * Creates a new display list that can be used to record batches of * drawing operations. * @@ -195,6 +211,17 @@ public class RenderNode { } /** + * Adopts an existing native render node. + * + * Note: This will *NOT* incRef() on the native object, however it will + * decRef() when it is destroyed. The caller should have already incRef'd it + */ + public static RenderNode adopt(long nativePtr) { + return new RenderNode(nativePtr); + } + + + /** * Starts recording a display list for the render node. All * operations performed on the returned canvas are recorded and * stored in this display list. @@ -822,6 +849,23 @@ public class RenderNode { } /////////////////////////////////////////////////////////////////////////// + // Animations + /////////////////////////////////////////////////////////////////////////// + + 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 /////////////////////////////////////////////////////////////////////////// @@ -896,6 +940,13 @@ public class RenderNode { private static native void nOutput(long renderNode); /////////////////////////////////////////////////////////////////////////// + // Animations + /////////////////////////////////////////////////////////////////////////// + + 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 new file mode 100644 index 0000000..b70ae3d --- /dev/null +++ b/core/java/android/view/RenderNodeAnimator.java @@ -0,0 +1,122 @@ +/* + * 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. + */ + +package android.view; + +import android.util.SparseIntArray; + +import java.lang.ref.WeakReference; + +/** + * @hide + */ +public final class RenderNodeAnimator { + + // Keep in sync with enum RenderProperty in Animator.h + private static final int TRANSLATION_X = 0; + private static final int TRANSLATION_Y = 1; + private static final int TRANSLATION_Z = 2; + private static final int SCALE_X = 3; + private static final int SCALE_Y = 4; + private static final int ROTATION = 5; + private static final int ROTATION_X = 6; + private static final int ROTATION_Y = 7; + private static final int X = 8; + private static final int Y = 9; + private static final int Z = 10; + private static final int ALPHA = 11; + + // ViewPropertyAnimator uses a mask for its values, we need to remap them + // to the enum values here. RenderPropertyAnimator can't use the mask values + // directly as internally it uses a lookup table so it needs the values to + // be sequential starting from 0 + private static final SparseIntArray sViewPropertyAnimatorMap = new SparseIntArray(15) {{ + put(ViewPropertyAnimator.TRANSLATION_X, TRANSLATION_X); + put(ViewPropertyAnimator.TRANSLATION_Y, TRANSLATION_Y); + put(ViewPropertyAnimator.TRANSLATION_Z, TRANSLATION_Z); + put(ViewPropertyAnimator.SCALE_X, SCALE_X); + put(ViewPropertyAnimator.SCALE_Y, SCALE_Y); + put(ViewPropertyAnimator.ROTATION, ROTATION); + put(ViewPropertyAnimator.ROTATION_X, ROTATION_X); + put(ViewPropertyAnimator.ROTATION_Y, ROTATION_Y); + put(ViewPropertyAnimator.X, X); + put(ViewPropertyAnimator.Y, Y); + put(ViewPropertyAnimator.Z, Z); + put(ViewPropertyAnimator.ALPHA, ALPHA); + }}; + + // Keep in sync DeltaValueType in Animator.h + private static final int DELTA_TYPE_ABSOLUTE = 0; + private static final int DELTA_TYPE_DELTA = 1; + + private RenderNode mTarget; + private long mNativePtr; + + public int mapViewPropertyToRenderProperty(int viewProperty) { + return sViewPropertyAnimatorMap.get(viewProperty); + } + + public RenderNodeAnimator(int property, int deltaType, float deltaValue) { + mNativePtr = nCreateAnimator(new WeakReference<RenderNodeAnimator>(this), + property, deltaType, deltaValue); + } + + public void start(View target) { + mTarget = target.mRenderNode; + mTarget.addAnimator(this); + // Kick off a frame to start the process + target.invalidateViewProperty(true, false); + } + + public void cancel() { + mTarget.removeAnimator(this); + } + + public void setDuration(int duration) { + nSetDuration(mNativePtr, duration); + } + + long getNativeAnimator() { + return mNativePtr; + } + + private void onFinished() { + mTarget.removeAnimator(this); + } + + // Called by native + private static void callOnFinished(WeakReference<RenderNodeAnimator> weakThis) { + RenderNodeAnimator animator = weakThis.get(); + if (animator != null) { + animator.onFinished(); + } + } + + @Override + protected void finalize() throws Throwable { + try { + nUnref(mNativePtr); + mNativePtr = 0; + } finally { + super.finalize(); + } + } + + private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis, + int property, int deltaValueType, float deltaValue); + private static native void nSetDuration(long nativePtr, int duration); + private static native void nUnref(long nativePtr); +} diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index c7a6d41..eaec8ab 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -50,7 +50,7 @@ import java.io.PrintWriter; public class ThreadedRenderer extends HardwareRenderer { private static final String LOGTAG = "ThreadedRenderer"; - private static final Rect NULL_RECT = new Rect(-1, -1, -1, -1); + private static final Rect NULL_RECT = new Rect(); private int mWidth, mHeight; private long mNativeProxy; @@ -58,9 +58,10 @@ public class ThreadedRenderer extends HardwareRenderer { private RenderNode mRootNode; ThreadedRenderer(boolean translucent) { - mNativeProxy = nCreateProxy(translucent); - mRootNode = RenderNode.create("RootNode"); + long rootNodePtr = nCreateRootRenderNode(); + mRootNode = RenderNode.adopt(rootNodePtr); mRootNode.setClipToBounds(false); + mNativeProxy = nCreateProxy(translucent, rootNodePtr); } @Override @@ -202,8 +203,7 @@ public class ThreadedRenderer extends HardwareRenderer { if (dirty == null) { dirty = NULL_RECT; } - nDrawDisplayList(mNativeProxy, mRootNode.getNativeDisplayList(), - dirty.left, dirty.top, dirty.right, dirty.bottom); + nSyncAndDrawFrame(mNativeProxy, dirty.left, dirty.top, dirty.right, dirty.bottom); } @Override @@ -293,7 +293,8 @@ public class ThreadedRenderer extends HardwareRenderer { /** @hide */ public static native void postToRenderThread(Runnable runnable); - private static native long nCreateProxy(boolean translucent); + private static native long nCreateRootRenderNode(); + private static native long nCreateProxy(boolean translucent, long rootRenderNode); private static native void nDeleteProxy(long nativeProxy); private static native boolean nInitialize(long nativeProxy, Surface window); @@ -302,7 +303,7 @@ public class ThreadedRenderer extends HardwareRenderer { private static native void nSetup(long nativeProxy, int width, int height); private static native void nSetDisplayListData(long nativeProxy, long displayList, long newData); - private static native void nDrawDisplayList(long nativeProxy, long displayList, + private static native void nSyncAndDrawFrame(long nativeProxy, int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom); private static native void nRunWithGlContext(long nativeProxy, Runnable runnable); private static native void nDestroyCanvasAndSurface(long nativeProxy); diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java index b1aa7b2..11d2622 100644 --- a/core/java/android/view/ViewPropertyAnimator.java +++ b/core/java/android/view/ViewPropertyAnimator.java @@ -133,19 +133,19 @@ public class ViewPropertyAnimator { * Constants used to associate a property being requested and the mechanism used to set * the property (this class calls directly into View to set the properties in question). */ - private static final int NONE = 0x0000; - private static final int TRANSLATION_X = 0x0001; - private static final int TRANSLATION_Y = 0x0002; - private static final int TRANSLATION_Z = 0x0004; - private static final int SCALE_X = 0x0008; - private static final int SCALE_Y = 0x0010; - private static final int ROTATION = 0x0020; - private static final int ROTATION_X = 0x0040; - private static final int ROTATION_Y = 0x0080; - private static final int X = 0x0100; - private static final int Y = 0x0200; - private static final int Z = 0x0400; - private static final int ALPHA = 0x0800; + static final int NONE = 0x0000; + static final int TRANSLATION_X = 0x0001; + static final int TRANSLATION_Y = 0x0002; + static final int TRANSLATION_Z = 0x0004; + static final int SCALE_X = 0x0008; + static final int SCALE_Y = 0x0010; + static final int ROTATION = 0x0020; + static final int ROTATION_X = 0x0040; + static final int ROTATION_Y = 0x0080; + static final int X = 0x0100; + static final int Y = 0x0200; + static final int Z = 0x0400; + static final int ALPHA = 0x0800; private static final int TRANSFORM_MASK = TRANSLATION_X | TRANSLATION_Y | TRANSLATION_Z | SCALE_X | SCALE_Y | ROTATION | ROTATION_X | ROTATION_Y | X | Y | Z; diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 711f28a..ee59c8a 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -61,6 +61,7 @@ LOCAL_SRC_FILES:= \ android_view_MotionEvent.cpp \ android_view_PointerIcon.cpp \ android_view_RenderNode.cpp \ + android_view_RenderNodeAnimator.cpp \ android_view_VelocityTracker.cpp \ android_text_AndroidCharacter.cpp \ android_text_AndroidBidi.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index aa635c6..f964cd2 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -120,6 +120,7 @@ extern int register_android_graphics_Xfermode(JNIEnv* env); extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env); extern int register_android_view_DisplayEventReceiver(JNIEnv* env); extern int register_android_view_RenderNode(JNIEnv* env); +extern int register_android_view_RenderNodeAnimator(JNIEnv* env); extern int register_android_view_GraphicBuffer(JNIEnv* env); extern int register_android_view_GLES20Canvas(JNIEnv* env); extern int register_android_view_GLRenderer(JNIEnv* env); @@ -1193,6 +1194,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_graphics_Graphics), REG_JNI(register_android_view_DisplayEventReceiver), REG_JNI(register_android_view_RenderNode), + REG_JNI(register_android_view_RenderNodeAnimator), REG_JNI(register_android_view_GraphicBuffer), REG_JNI(register_android_view_GLES20Canvas), REG_JNI(register_android_view_GLRenderer), diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 3ad2ae5..4715c26 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -23,6 +23,7 @@ #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> +#include <Animator.h> #include <DisplayListRenderer.h> #include <RenderNode.h> @@ -438,6 +439,25 @@ static jfloat android_view_RenderNode_getPivotY(JNIEnv* env, return renderNode->stagingProperties().getPivotY(); } +// ---------------------------------------------------------------------------- +// RenderProperties - Animations +// ---------------------------------------------------------------------------- + +static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz, + jlong renderNodePtr, jlong animatorPtr) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr); + renderNode->addAnimator(animator); +} + +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 // ---------------------------------------------------------------------------- @@ -513,6 +533,9 @@ static JNINativeMethod gMethods[] = { { "nGetPivotX", "(J)F", (void*) android_view_RenderNode_getPivotX }, { "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 new file mode 100644 index 0000000..35cdf60 --- /dev/null +++ b/core/jni/android_view_RenderNodeAnimator.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2013 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. + */ + +#define LOG_TAG "OpenGLRenderer" + +#include "android_view_RenderNodeAnimator.h" + +#include "jni.h" +#include "GraphicsJNI.h" +#include <nativehelper/JNIHelp.h> +#include <android_runtime/AndroidRuntime.h> + +#include <Animator.h> +#include <Interpolator.h> +#include <RenderProperties.h> + +namespace android { + +using namespace uirenderer; + +static struct { + jclass clazz; + + jmethodID callOnFinished; +} gRenderNodeAnimatorClassInfo; + +static JNIEnv* getEnv(JavaVM* vm) { + JNIEnv* env; + if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { + return 0; + } + return env; +} + +RenderNodeAnimator::RenderNodeAnimator(JNIEnv* env, jobject weakThis, + RenderProperty property, DeltaValueType deltaType, float delta) + : RenderPropertyAnimator(property, deltaType, delta) { + mWeakThis = env->NewGlobalRef(weakThis); + env->GetJavaVM(&mJvm); +} + +RenderNodeAnimator::~RenderNodeAnimator() { + JNIEnv* env = getEnv(mJvm); + env->DeleteGlobalRef(mWeakThis); + mWeakThis = NULL; +} + +void RenderNodeAnimator::callOnFinished() { + JNIEnv* env = getEnv(mJvm); + env->CallStaticVoidMethod( + gRenderNodeAnimatorClassInfo.clazz, + gRenderNodeAnimatorClassInfo.callOnFinished, + mWeakThis); +} + +static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis, + jint property, jint deltaType, jfloat deltaValue) { + LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderNodeAnimator::ALPHA, + "Invalid property %d", property); + LOG_ALWAYS_FATAL_IF(deltaType != RenderPropertyAnimator::DELTA + && deltaType != RenderPropertyAnimator::ABSOLUTE, + "Invalid delta type %d", deltaType); + + RenderNodeAnimator* animator = new RenderNodeAnimator(env, weakThis, + static_cast<RenderPropertyAnimator::RenderProperty>(property), + static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType), + deltaValue); + animator->incStrong(0); + 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"); + RenderNodeAnimator* animator = reinterpret_cast<RenderNodeAnimator*>(animatorPtr); + animator->setDuration(duration); +} + +static void unref(JNIEnv* env, jobject clazz, jlong objPtr) { + VirtualLightRefBase* obj = reinterpret_cast<VirtualLightRefBase*>(objPtr); + obj->decStrong(0); +} + +// ---------------------------------------------------------------------------- +// JNI Glue +// ---------------------------------------------------------------------------- + +const char* const kClassPathName = "android/view/RenderNodeAnimator"; + +static JNINativeMethod gMethods[] = { + { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IIF)J", (void*) createAnimator }, + { "nSetDuration", "(JI)V", (void*) setDuration }, + { "nUnref", "(J)V", (void*) unref }, +}; + +#define FIND_CLASS(var, className) \ + var = env->FindClass(className); \ + LOG_FATAL_IF(! var, "Unable to find class " className); + +#define GET_STATIC_METHOD_ID(var, clazz, methodName, methodDescriptor) \ + var = env->GetStaticMethodID(clazz, methodName, methodDescriptor); \ + LOG_FATAL_IF(! var, "Unable to find method " methodName); + +int register_android_view_RenderNodeAnimator(JNIEnv* env) { + FIND_CLASS(gRenderNodeAnimatorClassInfo.clazz, kClassPathName); + gRenderNodeAnimatorClassInfo.clazz = jclass(env->NewGlobalRef(gRenderNodeAnimatorClassInfo.clazz)); + + GET_STATIC_METHOD_ID(gRenderNodeAnimatorClassInfo.callOnFinished, gRenderNodeAnimatorClassInfo.clazz, + "callOnFinished", "(Ljava/lang/ref/WeakReference;)V"); + + return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); +} + + +} // namespace android diff --git a/core/jni/android_view_RenderNodeAnimator.h b/core/jni/android_view_RenderNodeAnimator.h new file mode 100644 index 0000000..d84003f --- /dev/null +++ b/core/jni/android_view_RenderNodeAnimator.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 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 "jni.h" + +#include <Animator.h> + +namespace android { + +class RenderNodeAnimator : public uirenderer::RenderPropertyAnimator { +public: + RenderNodeAnimator(JNIEnv* env, jobject callbackObject, + RenderProperty property, DeltaValueType deltaType, float delta); + virtual ~RenderNodeAnimator(); + + void callOnFinished(); + +private: + JavaVM* mJvm; + jobject mWeakThis; +}; + +} diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index b5f489d..58fc1e1 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -16,6 +16,8 @@ #define LOG_TAG "ThreadedRenderer" +#include <algorithm> + #include "jni.h" #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> @@ -24,6 +26,8 @@ #include <android_runtime/android_view_Surface.h> #include <system/window.h> +#include "android_view_RenderNodeAnimator.h" +#include <RenderNode.h> #include <renderthread/RenderProxy.h> #include <renderthread/RenderTask.h> #include <renderthread/RenderThread.h> @@ -63,15 +67,75 @@ private: jobject mRunnable; }; +class InvokeAnimationListeners : public MessageHandler { +public: + InvokeAnimationListeners(std::vector< sp<RenderNodeAnimator> >& animators) { + mAnimators.swap(animators); + } + + static void callOnFinished(const sp<RenderNodeAnimator>& animator) { + animator->callOnFinished(); + } + + virtual void handleMessage(const Message& message) { + std::for_each(mAnimators.begin(), mAnimators.end(), callOnFinished); + mAnimators.clear(); + } + +private: + std::vector< sp<RenderNodeAnimator> > mAnimators; +}; + +class RootRenderNode : public RenderNode, public AnimationListener { +public: + RootRenderNode() : RenderNode() { + mLooper = Looper::getForThread(); + LOG_ALWAYS_FATAL_IF(!mLooper.get(), + "Must create RootRenderNode on a thread with a looper!"); + } + + virtual ~RootRenderNode() {} + + void onAnimationFinished(const sp<RenderPropertyAnimator>& animator) { + mFinishedAnimators.push_back( + reinterpret_cast<RenderNodeAnimator*>(animator.get())); + } + + virtual void prepareTree(TreeInfo& info) { + info.animationListener = this; + RenderNode::prepareTree(info); + info.animationListener = NULL; + + // post all the finished stuff + if (mFinishedAnimators.size()) { + sp<InvokeAnimationListeners> message + = new InvokeAnimationListeners(mFinishedAnimators); + mLooper->sendMessage(message, 0); + } + } + +private: + sp<Looper> mLooper; + std::vector< sp<RenderNodeAnimator> > mFinishedAnimators; +}; + static void android_view_ThreadedRenderer_postToRenderThread(JNIEnv* env, jobject clazz, jobject jrunnable) { RenderTask* task = new JavaTask(env, jrunnable); RenderThread::getInstance().queue(task); } +static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) { + RootRenderNode* node = new RootRenderNode(); + node->incStrong(0); + node->setName("RootRenderNode"); + return reinterpret_cast<jlong>(node); +} + static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz, - jboolean translucent) { - return (jlong) new RenderProxy(translucent); + jboolean translucent, jlong rootRenderNodePtr) { + RenderNode* rootRenderNode = reinterpret_cast<RenderNode*>(rootRenderNodePtr); + return (jlong) new RenderProxy(translucent, rootRenderNode); } static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz, @@ -113,12 +177,11 @@ static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, proxy->setup(width, height); } -static void android_view_ThreadedRenderer_drawDisplayList(JNIEnv* env, jobject clazz, - jlong proxyPtr, jlong displayListPtr, jint dirtyLeft, jint dirtyTop, +static void android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz, + jlong proxyPtr, jint dirtyLeft, jint dirtyTop, jint dirtyRight, jint dirtyBottom) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); - RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr); - proxy->drawDisplayList(displayList, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom); + proxy->syncAndDrawFrame(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom); } static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz, @@ -187,13 +250,14 @@ const char* const kClassPathName = "android/view/ThreadedRenderer"; static JNINativeMethod gMethods[] = { #ifdef USE_OPENGL_RENDERER { "postToRenderThread", "(Ljava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_postToRenderThread }, - { "nCreateProxy", "(Z)J", (void*) android_view_ThreadedRenderer_createProxy }, + { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode }, + { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy }, { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy }, { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize }, { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface }, { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface }, { "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup }, - { "nDrawDisplayList", "(JJIIII)V", (void*) android_view_ThreadedRenderer_drawDisplayList }, + { "nSyncAndDrawFrame", "(JIIII)V", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface }, { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext }, |