blob: 6f256f0ae4dc1fa5c8aa8273c8bf4d3ed16788db [file] [log] [blame]
John Reckcec24ae2013-11-05 13:27:50 -08001/*
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
John Reck23b797a2014-01-03 18:08:34 -080017#define LOG_TAG "ThreadedRenderer"
John Reckcec24ae2013-11-05 13:27:50 -080018
John Recke45b1fd2014-04-15 09:50:16 -070019#include <algorithm>
20
John Reckcec24ae2013-11-05 13:27:50 -080021#include "jni.h"
22#include <nativehelper/JNIHelp.h>
23#include <android_runtime/AndroidRuntime.h>
24
John Reck4f02bf42014-01-03 18:09:17 -080025#include <utils/StrongPointer.h>
26#include <android_runtime/android_view_Surface.h>
27#include <system/window.h>
28
John Reck66f0be62014-05-13 13:39:31 -070029#include "android_view_GraphicBuffer.h"
30
John Reck52244ff2014-05-01 21:27:37 -070031#include <Animator.h>
John Recke45b1fd2014-04-15 09:50:16 -070032#include <RenderNode.h>
John Reck66f0be62014-05-13 13:39:31 -070033#include <renderthread/CanvasContext.h>
John Reck4f02bf42014-01-03 18:09:17 -080034#include <renderthread/RenderProxy.h>
John Reckcec24ae2013-11-05 13:27:50 -080035#include <renderthread/RenderTask.h>
36#include <renderthread/RenderThread.h>
Chris Craik797b95b2014-05-20 18:10:25 -070037#include <Vector.h>
John Reckcec24ae2013-11-05 13:27:50 -080038
39namespace android {
40
41#ifdef USE_OPENGL_RENDERER
42
John Reck4f02bf42014-01-03 18:09:17 -080043using namespace android::uirenderer;
44using namespace android::uirenderer::renderthread;
John Reckcec24ae2013-11-05 13:27:50 -080045
46static jmethodID gRunnableMethod;
47
John Reck4f02bf42014-01-03 18:09:17 -080048class JavaTask : public RenderTask {
John Reckcec24ae2013-11-05 13:27:50 -080049public:
50 JavaTask(JNIEnv* env, jobject jrunnable) {
51 env->GetJavaVM(&mVm);
52 mRunnable = env->NewGlobalRef(jrunnable);
53 }
54
John Reckcec24ae2013-11-05 13:27:50 -080055 virtual void run() {
56 env()->CallVoidMethod(mRunnable, gRunnableMethod);
John Reck4f02bf42014-01-03 18:09:17 -080057 env()->DeleteGlobalRef(mRunnable);
58 delete this;
John Reckcec24ae2013-11-05 13:27:50 -080059 };
60
61private:
62 JNIEnv* env() {
63 JNIEnv* env;
64 if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
65 return 0;
66 }
67 return env;
68 }
69
70 JavaVM* mVm;
71 jobject mRunnable;
72};
73
John Reck66f0be62014-05-13 13:39:31 -070074class SetAtlasTask : public RenderTask {
75public:
76 SetAtlasTask(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size)
77 : mBuffer(buffer)
78 , mMap(map)
79 , mMapSize(size) {
80 }
81
82 virtual void run() {
83 CanvasContext::setTextureAtlas(mBuffer, mMap, mMapSize);
84 mMap = 0;
85 delete this;
86 }
87
88private:
89 sp<GraphicBuffer> mBuffer;
90 int64_t* mMap;
91 size_t mMapSize;
92};
93
John Reck52244ff2014-05-01 21:27:37 -070094class OnFinishedEvent {
95public:
John Reckff941dc2014-05-14 16:34:14 -070096 OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
John Reck52244ff2014-05-01 21:27:37 -070097 : animator(animator), listener(listener) {}
John Reckff941dc2014-05-14 16:34:14 -070098 sp<BaseRenderNodeAnimator> animator;
John Reck52244ff2014-05-01 21:27:37 -070099 sp<AnimationListener> listener;
100};
101
John Recke45b1fd2014-04-15 09:50:16 -0700102class InvokeAnimationListeners : public MessageHandler {
103public:
John Reck52244ff2014-05-01 21:27:37 -0700104 InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
105 mOnFinishedEvents.swap(events);
John Recke45b1fd2014-04-15 09:50:16 -0700106 }
107
John Reck52244ff2014-05-01 21:27:37 -0700108 static void callOnFinished(OnFinishedEvent& event) {
109 event.listener->onAnimationFinished(event.animator.get());
John Recke45b1fd2014-04-15 09:50:16 -0700110 }
111
112 virtual void handleMessage(const Message& message) {
John Reck52244ff2014-05-01 21:27:37 -0700113 std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
114 mOnFinishedEvents.clear();
John Recke45b1fd2014-04-15 09:50:16 -0700115 }
116
117private:
John Reck52244ff2014-05-01 21:27:37 -0700118 std::vector<OnFinishedEvent> mOnFinishedEvents;
John Recke45b1fd2014-04-15 09:50:16 -0700119};
120
John Reck52244ff2014-05-01 21:27:37 -0700121class RootRenderNode : public RenderNode, public AnimationHook {
John Recke45b1fd2014-04-15 09:50:16 -0700122public:
123 RootRenderNode() : RenderNode() {
124 mLooper = Looper::getForThread();
125 LOG_ALWAYS_FATAL_IF(!mLooper.get(),
126 "Must create RootRenderNode on a thread with a looper!");
127 }
128
129 virtual ~RootRenderNode() {}
130
John Reckff941dc2014-05-14 16:34:14 -0700131 virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
John Reck52244ff2014-05-01 21:27:37 -0700132 OnFinishedEvent event(animator, listener);
133 mOnFinishedEvents.push_back(event);
John Recke45b1fd2014-04-15 09:50:16 -0700134 }
135
136 virtual void prepareTree(TreeInfo& info) {
John Reck52244ff2014-05-01 21:27:37 -0700137 info.animationHook = this;
John Recke45b1fd2014-04-15 09:50:16 -0700138 RenderNode::prepareTree(info);
John Reck52244ff2014-05-01 21:27:37 -0700139 info.animationHook = NULL;
John Recke45b1fd2014-04-15 09:50:16 -0700140
141 // post all the finished stuff
John Reck52244ff2014-05-01 21:27:37 -0700142 if (mOnFinishedEvents.size()) {
John Recke45b1fd2014-04-15 09:50:16 -0700143 sp<InvokeAnimationListeners> message
John Reck52244ff2014-05-01 21:27:37 -0700144 = new InvokeAnimationListeners(mOnFinishedEvents);
John Recke45b1fd2014-04-15 09:50:16 -0700145 mLooper->sendMessage(message, 0);
146 }
147 }
148
149private:
150 sp<Looper> mLooper;
John Reck52244ff2014-05-01 21:27:37 -0700151 std::vector<OnFinishedEvent> mOnFinishedEvents;
John Recke45b1fd2014-04-15 09:50:16 -0700152};
153
John Reck66f0be62014-05-13 13:39:31 -0700154static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
155 jobject graphicBuffer, jlongArray atlasMapArray) {
156 sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
157 jsize len = env->GetArrayLength(atlasMapArray);
158 if (len <= 0) {
159 ALOGW("Failed to initialize atlas, invalid map length: %d", len);
160 return;
161 }
162 int64_t* map = new int64_t[len];
163 env->GetLongArrayRegion(atlasMapArray, 0, len, map);
164
165 SetAtlasTask* task = new SetAtlasTask(buffer, map, len);
John Reck4f02bf42014-01-03 18:09:17 -0800166 RenderThread::getInstance().queue(task);
167}
168
John Recke45b1fd2014-04-15 09:50:16 -0700169static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
170 RootRenderNode* node = new RootRenderNode();
171 node->incStrong(0);
172 node->setName("RootRenderNode");
173 return reinterpret_cast<jlong>(node);
174}
175
John Reck4f02bf42014-01-03 18:09:17 -0800176static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
John Recke45b1fd2014-04-15 09:50:16 -0700177 jboolean translucent, jlong rootRenderNodePtr) {
178 RenderNode* rootRenderNode = reinterpret_cast<RenderNode*>(rootRenderNodePtr);
179 return (jlong) new RenderProxy(translucent, rootRenderNode);
John Reck4f02bf42014-01-03 18:09:17 -0800180}
181
182static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
183 jlong proxyPtr) {
John Reck19b6bcf2014-02-14 20:03:38 -0800184 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
John Reck4f02bf42014-01-03 18:09:17 -0800185 delete proxy;
186}
187
John Reck18f16e62014-05-02 16:46:41 -0700188static void android_view_ThreadedRenderer_setFrameInterval(JNIEnv* env, jobject clazz,
189 jlong proxyPtr, jlong frameIntervalNanos) {
190 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
191 proxy->setFrameInterval(frameIntervalNanos);
192}
193
John Recke4280ba2014-05-05 16:39:37 -0700194static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
195 jlong proxyPtr) {
196 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
197 return proxy->loadSystemProperties();
198}
199
John Reck4f02bf42014-01-03 18:09:17 -0800200static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
201 jlong proxyPtr, jobject jsurface) {
John Reck19b6bcf2014-02-14 20:03:38 -0800202 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
John Reck4f02bf42014-01-03 18:09:17 -0800203 sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
John Reckf7d9c1d2014-04-09 10:01:03 -0700204 return proxy->initialize(window);
John Reck4f02bf42014-01-03 18:09:17 -0800205}
206
207static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
208 jlong proxyPtr, jobject jsurface) {
John Reck19b6bcf2014-02-14 20:03:38 -0800209 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
John Reck4f02bf42014-01-03 18:09:17 -0800210 sp<ANativeWindow> window;
211 if (jsurface) {
212 window = android_view_Surface_getNativeWindow(env, jsurface);
213 }
John Reckf7d9c1d2014-04-09 10:01:03 -0700214 proxy->updateSurface(window);
215}
216
217static void android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
218 jlong proxyPtr, jobject jsurface) {
219 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
220 sp<ANativeWindow> window;
221 if (jsurface) {
222 window = android_view_Surface_getNativeWindow(env, jsurface);
223 }
224 proxy->pauseSurface(window);
John Reck4f02bf42014-01-03 18:09:17 -0800225}
226
Chris Craik797b95b2014-05-20 18:10:25 -0700227static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
228 jint width, jint height,
229 jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius) {
John Reck19b6bcf2014-02-14 20:03:38 -0800230 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
Chris Craik797b95b2014-05-20 18:10:25 -0700231 proxy->setup(width, height, Vector3(lightX, lightY, lightZ), lightRadius);
John Reck4f02bf42014-01-03 18:09:17 -0800232}
233
John Reck63a06672014-05-07 13:45:54 -0700234static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
235 jlong proxyPtr, jboolean opaque) {
236 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
237 proxy->setOpaque(opaque);
238}
239
John Reckf9be7792014-05-02 18:21:16 -0700240static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
John Reck18f16e62014-05-02 16:46:41 -0700241 jlong proxyPtr, jlong frameTimeNanos, jint dirtyLeft, jint dirtyTop,
John Reck4f02bf42014-01-03 18:09:17 -0800242 jint dirtyRight, jint dirtyBottom) {
John Reck19b6bcf2014-02-14 20:03:38 -0800243 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
John Reckf9be7792014-05-02 18:21:16 -0700244 return proxy->syncAndDrawFrame(frameTimeNanos, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
John Reck4f02bf42014-01-03 18:09:17 -0800245}
246
John Reckfae904d2014-04-14 11:01:57 -0700247static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
John Reck4f02bf42014-01-03 18:09:17 -0800248 jlong proxyPtr) {
John Reck19b6bcf2014-02-14 20:03:38 -0800249 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
John Reckfae904d2014-04-14 11:01:57 -0700250 proxy->destroyCanvasAndSurface();
John Reck4f02bf42014-01-03 18:09:17 -0800251}
252
John Reck0d1f6342014-03-28 20:30:27 -0700253static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
254 jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) {
255 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
256 Functor* functor = reinterpret_cast<Functor*>(functorPtr);
257 proxy->invokeFunctor(functor, waitForCompletion);
258}
259
John Reckfc53ef272014-02-11 10:40:25 -0800260static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz,
261 jlong proxyPtr, jobject jrunnable) {
John Reck19b6bcf2014-02-14 20:03:38 -0800262 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
John Reckfc53ef272014-02-11 10:40:25 -0800263 RenderTask* task = new JavaTask(env, jrunnable);
264 proxy->runWithGlContext(task);
265}
266
John Reck19b6bcf2014-02-14 20:03:38 -0800267static jlong android_view_ThreadedRenderer_createDisplayListLayer(JNIEnv* env, jobject clazz,
268 jlong proxyPtr, jint width, jint height) {
269 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
270 DeferredLayerUpdater* layer = proxy->createDisplayListLayer(width, height);
271 return reinterpret_cast<jlong>(layer);
272}
273
274static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
275 jlong proxyPtr) {
276 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
277 DeferredLayerUpdater* layer = proxy->createTextureLayer();
278 return reinterpret_cast<jlong>(layer);
279}
280
281static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
282 jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
283 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
284 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
285 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
286 return proxy->copyLayerInto(layer, bitmap);
287}
288
289static void android_view_ThreadedRenderer_destroyLayer(JNIEnv* env, jobject clazz,
290 jlong proxyPtr, jlong layerPtr) {
291 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
292 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
293 proxy->destroyLayer(layer);
294}
295
John Recke1628b72014-05-23 15:11:19 -0700296static void android_view_ThreadedRenderer_flushCaches(JNIEnv* env, jobject clazz,
297 jlong proxyPtr, jint flushMode) {
298 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
299 proxy->flushCaches(static_cast<Caches::FlushMode>(flushMode));
300}
301
John Reck28ad7b52014-04-07 16:59:25 -0700302static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
303 jlong proxyPtr) {
304 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
305 proxy->fence();
306}
307
John Recka5dda642014-05-22 15:43:54 -0700308static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
309 jlong proxyPtr) {
310 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
311 proxy->notifyFramePending();
312}
313
John Reckcec24ae2013-11-05 13:27:50 -0800314#endif
315
316// ----------------------------------------------------------------------------
317// JNI Glue
318// ----------------------------------------------------------------------------
319
320const char* const kClassPathName = "android/view/ThreadedRenderer";
321
322static JNINativeMethod gMethods[] = {
323#ifdef USE_OPENGL_RENDERER
John Reck66f0be62014-05-13 13:39:31 -0700324 { "nSetAtlas", "(Landroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas },
John Recke45b1fd2014-04-15 09:50:16 -0700325 { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
326 { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
John Reck4f02bf42014-01-03 18:09:17 -0800327 { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
John Reck18f16e62014-05-02 16:46:41 -0700328 { "nSetFrameInterval", "(JJ)V", (void*) android_view_ThreadedRenderer_setFrameInterval },
John Recke4280ba2014-05-05 16:39:37 -0700329 { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
John Reck4f02bf42014-01-03 18:09:17 -0800330 { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
331 { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
John Reckf7d9c1d2014-04-09 10:01:03 -0700332 { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
Chris Craik797b95b2014-05-20 18:10:25 -0700333 { "nSetup", "(JIIFFFF)V", (void*) android_view_ThreadedRenderer_setup },
John Reck63a06672014-05-07 13:45:54 -0700334 { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
John Reckf9be7792014-05-02 18:21:16 -0700335 { "nSyncAndDrawFrame", "(JJIIII)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
John Reckfae904d2014-04-14 11:01:57 -0700336 { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
John Reck0d1f6342014-03-28 20:30:27 -0700337 { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
John Reckfc53ef272014-02-11 10:40:25 -0800338 { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
John Reck19b6bcf2014-02-14 20:03:38 -0800339 { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
340 { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
341 { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
342 { "nDestroyLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_destroyLayer },
John Recke1628b72014-05-23 15:11:19 -0700343 { "nFlushCaches", "(JI)V", (void*) android_view_ThreadedRenderer_flushCaches },
John Reck28ad7b52014-04-07 16:59:25 -0700344 { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
John Recka5dda642014-05-22 15:43:54 -0700345 { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
John Reckcec24ae2013-11-05 13:27:50 -0800346#endif
347};
348
349int register_android_view_ThreadedRenderer(JNIEnv* env) {
350#ifdef USE_OPENGL_RENDERER
351 jclass cls = env->FindClass("java/lang/Runnable");
352 gRunnableMethod = env->GetMethodID(cls, "run", "()V");
353 env->DeleteLocalRef(cls);
354#endif
355 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
356}
357
358}; // namespace android