android_view_ThreadedRenderer.cpp revision 63a06673253914510bbeebd500655008682dade1
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "ThreadedRenderer" 18 19#include <algorithm> 20 21#include "jni.h" 22#include <nativehelper/JNIHelp.h> 23#include <android_runtime/AndroidRuntime.h> 24 25#include <utils/StrongPointer.h> 26#include <android_runtime/android_view_Surface.h> 27#include <system/window.h> 28 29#include <Animator.h> 30#include <RenderNode.h> 31#include <renderthread/RenderProxy.h> 32#include <renderthread/RenderTask.h> 33#include <renderthread/RenderThread.h> 34 35namespace android { 36 37#ifdef USE_OPENGL_RENDERER 38 39using namespace android::uirenderer; 40using namespace android::uirenderer::renderthread; 41 42static jmethodID gRunnableMethod; 43 44class JavaTask : public RenderTask { 45public: 46 JavaTask(JNIEnv* env, jobject jrunnable) { 47 env->GetJavaVM(&mVm); 48 mRunnable = env->NewGlobalRef(jrunnable); 49 } 50 51 virtual void run() { 52 env()->CallVoidMethod(mRunnable, gRunnableMethod); 53 env()->DeleteGlobalRef(mRunnable); 54 delete this; 55 }; 56 57private: 58 JNIEnv* env() { 59 JNIEnv* env; 60 if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { 61 return 0; 62 } 63 return env; 64 } 65 66 JavaVM* mVm; 67 jobject mRunnable; 68}; 69 70class OnFinishedEvent { 71public: 72 OnFinishedEvent(BaseAnimator* animator, AnimationListener* listener) 73 : animator(animator), listener(listener) {} 74 sp<BaseAnimator> animator; 75 sp<AnimationListener> listener; 76}; 77 78class InvokeAnimationListeners : public MessageHandler { 79public: 80 InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) { 81 mOnFinishedEvents.swap(events); 82 } 83 84 static void callOnFinished(OnFinishedEvent& event) { 85 event.listener->onAnimationFinished(event.animator.get()); 86 } 87 88 virtual void handleMessage(const Message& message) { 89 std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished); 90 mOnFinishedEvents.clear(); 91 } 92 93private: 94 std::vector<OnFinishedEvent> mOnFinishedEvents; 95}; 96 97class RootRenderNode : public RenderNode, public AnimationHook { 98public: 99 RootRenderNode() : RenderNode() { 100 mLooper = Looper::getForThread(); 101 LOG_ALWAYS_FATAL_IF(!mLooper.get(), 102 "Must create RootRenderNode on a thread with a looper!"); 103 } 104 105 virtual ~RootRenderNode() {} 106 107 virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) { 108 OnFinishedEvent event(animator, listener); 109 mOnFinishedEvents.push_back(event); 110 } 111 112 virtual void prepareTree(TreeInfo& info) { 113 info.animationHook = this; 114 RenderNode::prepareTree(info); 115 info.animationHook = NULL; 116 117 // post all the finished stuff 118 if (mOnFinishedEvents.size()) { 119 sp<InvokeAnimationListeners> message 120 = new InvokeAnimationListeners(mOnFinishedEvents); 121 mLooper->sendMessage(message, 0); 122 } 123 } 124 125private: 126 sp<Looper> mLooper; 127 std::vector<OnFinishedEvent> mOnFinishedEvents; 128}; 129 130static void android_view_ThreadedRenderer_postToRenderThread(JNIEnv* env, jobject clazz, 131 jobject jrunnable) { 132 RenderTask* task = new JavaTask(env, jrunnable); 133 RenderThread::getInstance().queue(task); 134} 135 136static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) { 137 RootRenderNode* node = new RootRenderNode(); 138 node->incStrong(0); 139 node->setName("RootRenderNode"); 140 return reinterpret_cast<jlong>(node); 141} 142 143static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz, 144 jboolean translucent, jlong rootRenderNodePtr) { 145 RenderNode* rootRenderNode = reinterpret_cast<RenderNode*>(rootRenderNodePtr); 146 return (jlong) new RenderProxy(translucent, rootRenderNode); 147} 148 149static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz, 150 jlong proxyPtr) { 151 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 152 delete proxy; 153} 154 155static void android_view_ThreadedRenderer_setFrameInterval(JNIEnv* env, jobject clazz, 156 jlong proxyPtr, jlong frameIntervalNanos) { 157 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 158 proxy->setFrameInterval(frameIntervalNanos); 159} 160 161static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz, 162 jlong proxyPtr) { 163 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 164 return proxy->loadSystemProperties(); 165} 166 167static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz, 168 jlong proxyPtr, jobject jsurface) { 169 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 170 sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface); 171 return proxy->initialize(window); 172} 173 174static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz, 175 jlong proxyPtr, jobject jsurface) { 176 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 177 sp<ANativeWindow> window; 178 if (jsurface) { 179 window = android_view_Surface_getNativeWindow(env, jsurface); 180 } 181 proxy->updateSurface(window); 182} 183 184static void android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz, 185 jlong proxyPtr, jobject jsurface) { 186 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 187 sp<ANativeWindow> window; 188 if (jsurface) { 189 window = android_view_Surface_getNativeWindow(env, jsurface); 190 } 191 proxy->pauseSurface(window); 192} 193 194static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, 195 jlong proxyPtr, jint width, jint height) { 196 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 197 proxy->setup(width, height); 198} 199 200static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz, 201 jlong proxyPtr, jboolean opaque) { 202 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 203 proxy->setOpaque(opaque); 204} 205 206static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz, 207 jlong proxyPtr, jlong frameTimeNanos, jint dirtyLeft, jint dirtyTop, 208 jint dirtyRight, jint dirtyBottom) { 209 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 210 return proxy->syncAndDrawFrame(frameTimeNanos, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom); 211} 212 213static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz, 214 jlong proxyPtr) { 215 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 216 proxy->destroyCanvasAndSurface(); 217} 218 219static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz, 220 jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) { 221 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 222 Functor* functor = reinterpret_cast<Functor*>(functorPtr); 223 proxy->invokeFunctor(functor, waitForCompletion); 224} 225 226static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz, 227 jlong proxyPtr, jobject jrunnable) { 228 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 229 RenderTask* task = new JavaTask(env, jrunnable); 230 proxy->runWithGlContext(task); 231} 232 233static jlong android_view_ThreadedRenderer_createDisplayListLayer(JNIEnv* env, jobject clazz, 234 jlong proxyPtr, jint width, jint height) { 235 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 236 DeferredLayerUpdater* layer = proxy->createDisplayListLayer(width, height); 237 return reinterpret_cast<jlong>(layer); 238} 239 240static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz, 241 jlong proxyPtr) { 242 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 243 DeferredLayerUpdater* layer = proxy->createTextureLayer(); 244 return reinterpret_cast<jlong>(layer); 245} 246 247static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz, 248 jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) { 249 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 250 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 251 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr); 252 return proxy->copyLayerInto(layer, bitmap); 253} 254 255static void android_view_ThreadedRenderer_destroyLayer(JNIEnv* env, jobject clazz, 256 jlong proxyPtr, jlong layerPtr) { 257 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 258 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 259 proxy->destroyLayer(layer); 260} 261 262static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz, 263 jlong proxyPtr) { 264 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 265 proxy->fence(); 266} 267 268#endif 269 270// ---------------------------------------------------------------------------- 271// JNI Glue 272// ---------------------------------------------------------------------------- 273 274const char* const kClassPathName = "android/view/ThreadedRenderer"; 275 276static JNINativeMethod gMethods[] = { 277#ifdef USE_OPENGL_RENDERER 278 { "postToRenderThread", "(Ljava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_postToRenderThread }, 279 { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode }, 280 { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy }, 281 { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy }, 282 { "nSetFrameInterval", "(JJ)V", (void*) android_view_ThreadedRenderer_setFrameInterval }, 283 { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties }, 284 { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize }, 285 { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface }, 286 { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface }, 287 { "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup }, 288 { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque }, 289 { "nSyncAndDrawFrame", "(JJIIII)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, 290 { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface }, 291 { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, 292 { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext }, 293 { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer }, 294 { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, 295 { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto }, 296 { "nDestroyLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_destroyLayer }, 297 { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence }, 298#endif 299}; 300 301int register_android_view_ThreadedRenderer(JNIEnv* env) { 302#ifdef USE_OPENGL_RENDERER 303 jclass cls = env->FindClass("java/lang/Runnable"); 304 gRunnableMethod = env->GetMethodID(cls, "run", "()V"); 305 env->DeleteLocalRef(cls); 306#endif 307 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 308} 309 310}; // namespace android 311