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 <EGL/egl.h>
26 #include <EGL/eglext.h>
27 #include <EGL/egl_cache.h>
28
29 #include <utils/StrongPointer.h>
30 #include <android_runtime/android_view_Surface.h>
31 #include <system/window.h>
32
33 #include "android_view_GraphicBuffer.h"
34
35 #include <Animator.h>
36 #include <AnimationContext.h>
37 #include <IContextFactory.h>
38 #include <RenderNode.h>
39 #include <renderthread/CanvasContext.h>
40 #include <renderthread/RenderProxy.h>
41 #include <renderthread/RenderTask.h>
42 #include <renderthread/RenderThread.h>
43 #include <Vector.h>
44
45 namespace android {
46
47 #ifdef USE_OPENGL_RENDERER
48
49 using namespace android::uirenderer;
50 using namespace android::uirenderer::renderthread;
51
getenv(JavaVM * vm)52 static JNIEnv* getenv(JavaVM* vm) {
53 JNIEnv* env;
54 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
55 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
56 }
57 return env;
58 }
59
60 class OnFinishedEvent {
61 public:
OnFinishedEvent(BaseRenderNodeAnimator * animator,AnimationListener * listener)62 OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
63 : animator(animator), listener(listener) {}
64 sp<BaseRenderNodeAnimator> animator;
65 sp<AnimationListener> listener;
66 };
67
68 class InvokeAnimationListeners : public MessageHandler {
69 public:
InvokeAnimationListeners(std::vector<OnFinishedEvent> & events)70 InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
71 mOnFinishedEvents.swap(events);
72 }
73
callOnFinished(OnFinishedEvent & event)74 static void callOnFinished(OnFinishedEvent& event) {
75 event.listener->onAnimationFinished(event.animator.get());
76 }
77
handleMessage(const Message & message)78 virtual void handleMessage(const Message& message) {
79 std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
80 mOnFinishedEvents.clear();
81 }
82
83 private:
84 std::vector<OnFinishedEvent> mOnFinishedEvents;
85 };
86
87 class RenderingException : public MessageHandler {
88 public:
RenderingException(JavaVM * vm,const std::string & message)89 RenderingException(JavaVM* vm, const std::string& message)
90 : mVm(vm)
91 , mMessage(message) {
92 }
93
handleMessage(const Message &)94 virtual void handleMessage(const Message&) {
95 throwException(mVm, mMessage);
96 }
97
throwException(JavaVM * vm,const std::string & message)98 static void throwException(JavaVM* vm, const std::string& message) {
99 JNIEnv* env = getenv(vm);
100 jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
101 }
102
103 private:
104 JavaVM* mVm;
105 std::string mMessage;
106 };
107
108 class RootRenderNode : public RenderNode, ErrorHandler {
109 public:
RootRenderNode(JNIEnv * env)110 RootRenderNode(JNIEnv* env) : RenderNode() {
111 mLooper = Looper::getForThread();
112 LOG_ALWAYS_FATAL_IF(!mLooper.get(),
113 "Must create RootRenderNode on a thread with a looper!");
114 env->GetJavaVM(&mVm);
115 }
116
~RootRenderNode()117 virtual ~RootRenderNode() {}
118
onError(const std::string & message)119 virtual void onError(const std::string& message) {
120 mLooper->sendMessage(new RenderingException(mVm, message), 0);
121 }
122
prepareTree(TreeInfo & info)123 virtual void prepareTree(TreeInfo& info) {
124 info.errorHandler = this;
125 RenderNode::prepareTree(info);
126 info.errorHandler = NULL;
127 }
128
sendMessage(const sp<MessageHandler> & handler)129 void sendMessage(const sp<MessageHandler>& handler) {
130 mLooper->sendMessage(handler, 0);
131 }
132
attachAnimatingNode(RenderNode * animatingNode)133 void attachAnimatingNode(RenderNode* animatingNode) {
134 mPendingAnimatingRenderNodes.push_back(animatingNode);
135 }
136
doAttachAnimatingNodes(AnimationContext * context)137 void doAttachAnimatingNodes(AnimationContext* context) {
138 for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
139 RenderNode* node = mPendingAnimatingRenderNodes[i].get();
140 context->addAnimatingRenderNode(*node);
141 }
142 mPendingAnimatingRenderNodes.clear();
143 }
144
145 private:
146 sp<Looper> mLooper;
147 JavaVM* mVm;
148 std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
149 };
150
151 class AnimationContextBridge : public AnimationContext {
152 public:
AnimationContextBridge(renderthread::TimeLord & clock,RootRenderNode * rootNode)153 AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
154 : AnimationContext(clock), mRootNode(rootNode) {
155 }
156
~AnimationContextBridge()157 virtual ~AnimationContextBridge() {}
158
159 // Marks the start of a frame, which will update the frame time and move all
160 // next frame animations into the current frame
startFrame(TreeInfo::TraversalMode mode)161 virtual void startFrame(TreeInfo::TraversalMode mode) {
162 if (mode == TreeInfo::MODE_FULL) {
163 mRootNode->doAttachAnimatingNodes(this);
164 }
165 AnimationContext::startFrame(mode);
166 }
167
168 // Runs any animations still left in mCurrentFrameAnimations
runRemainingAnimations(TreeInfo & info)169 virtual void runRemainingAnimations(TreeInfo& info) {
170 AnimationContext::runRemainingAnimations(info);
171 postOnFinishedEvents();
172 }
173
callOnFinished(BaseRenderNodeAnimator * animator,AnimationListener * listener)174 virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
175 OnFinishedEvent event(animator, listener);
176 mOnFinishedEvents.push_back(event);
177 }
178
destroy()179 virtual void destroy() {
180 AnimationContext::destroy();
181 postOnFinishedEvents();
182 }
183
184 private:
185 sp<RootRenderNode> mRootNode;
186 std::vector<OnFinishedEvent> mOnFinishedEvents;
187
postOnFinishedEvents()188 void postOnFinishedEvents() {
189 if (mOnFinishedEvents.size()) {
190 sp<InvokeAnimationListeners> message
191 = new InvokeAnimationListeners(mOnFinishedEvents);
192 mRootNode->sendMessage(message);
193 }
194 }
195 };
196
197 class ContextFactoryImpl : public IContextFactory {
198 public:
ContextFactoryImpl(RootRenderNode * rootNode)199 ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
200
createAnimationContext(renderthread::TimeLord & clock)201 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
202 return new AnimationContextBridge(clock, mRootNode);
203 }
204
205 private:
206 RootRenderNode* mRootNode;
207 };
208
android_view_ThreadedRenderer_setAtlas(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject graphicBuffer,jlongArray atlasMapArray)209 static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
210 jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
211 sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
212 jsize len = env->GetArrayLength(atlasMapArray);
213 if (len <= 0) {
214 ALOGW("Failed to initialize atlas, invalid map length: %d", len);
215 return;
216 }
217 int64_t* map = new int64_t[len];
218 env->GetLongArrayRegion(atlasMapArray, 0, len, map);
219
220 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
221 proxy->setTextureAtlas(buffer, map, len);
222 }
223
android_view_ThreadedRenderer_createRootRenderNode(JNIEnv * env,jobject clazz)224 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
225 RootRenderNode* node = new RootRenderNode(env);
226 node->incStrong(0);
227 node->setName("RootRenderNode");
228 return reinterpret_cast<jlong>(node);
229 }
230
android_view_ThreadedRenderer_createProxy(JNIEnv * env,jobject clazz,jboolean translucent,jlong rootRenderNodePtr)231 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
232 jboolean translucent, jlong rootRenderNodePtr) {
233 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
234 ContextFactoryImpl factory(rootRenderNode);
235 return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
236 }
237
android_view_ThreadedRenderer_deleteProxy(JNIEnv * env,jobject clazz,jlong proxyPtr)238 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
239 jlong proxyPtr) {
240 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
241 delete proxy;
242 }
243
android_view_ThreadedRenderer_setFrameInterval(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong frameIntervalNanos)244 static void android_view_ThreadedRenderer_setFrameInterval(JNIEnv* env, jobject clazz,
245 jlong proxyPtr, jlong frameIntervalNanos) {
246 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
247 proxy->setFrameInterval(frameIntervalNanos);
248 }
249
android_view_ThreadedRenderer_loadSystemProperties(JNIEnv * env,jobject clazz,jlong proxyPtr)250 static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
251 jlong proxyPtr) {
252 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
253 return proxy->loadSystemProperties();
254 }
255
android_view_ThreadedRenderer_initialize(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface)256 static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
257 jlong proxyPtr, jobject jsurface) {
258 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
259 sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
260 return proxy->initialize(window);
261 }
262
android_view_ThreadedRenderer_updateSurface(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface)263 static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
264 jlong proxyPtr, jobject jsurface) {
265 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
266 sp<ANativeWindow> window;
267 if (jsurface) {
268 window = android_view_Surface_getNativeWindow(env, jsurface);
269 }
270 proxy->updateSurface(window);
271 }
272
android_view_ThreadedRenderer_pauseSurface(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface)273 static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
274 jlong proxyPtr, jobject jsurface) {
275 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
276 sp<ANativeWindow> window;
277 if (jsurface) {
278 window = android_view_Surface_getNativeWindow(env, jsurface);
279 }
280 return proxy->pauseSurface(window);
281 }
282
android_view_ThreadedRenderer_setup(JNIEnv * env,jobject clazz,jlong proxyPtr,jint width,jint height,jfloat lightX,jfloat lightY,jfloat lightZ,jfloat lightRadius,jint ambientShadowAlpha,jint spotShadowAlpha)283 static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
284 jint width, jint height,
285 jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius,
286 jint ambientShadowAlpha, jint spotShadowAlpha) {
287 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
288 proxy->setup(width, height, (Vector3){lightX, lightY, lightZ}, lightRadius,
289 ambientShadowAlpha, spotShadowAlpha);
290 }
291
android_view_ThreadedRenderer_setOpaque(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean opaque)292 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
293 jlong proxyPtr, jboolean opaque) {
294 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
295 proxy->setOpaque(opaque);
296 }
297
android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong frameTimeNanos,jlong recordDuration,jfloat density)298 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
299 jlong proxyPtr, jlong frameTimeNanos, jlong recordDuration, jfloat density) {
300 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
301 return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density);
302 }
303
android_view_ThreadedRenderer_destroy(JNIEnv * env,jobject clazz,jlong proxyPtr)304 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
305 jlong proxyPtr) {
306 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
307 proxy->destroy();
308 }
309
android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv * env,jobject clazz,jlong rootNodePtr,jlong animatingNodePtr)310 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
311 jlong rootNodePtr, jlong animatingNodePtr) {
312 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
313 RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
314 rootRenderNode->attachAnimatingNode(animatingNode);
315 }
316
android_view_ThreadedRenderer_invokeFunctor(JNIEnv * env,jobject clazz,jlong functorPtr,jboolean waitForCompletion)317 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
318 jlong functorPtr, jboolean waitForCompletion) {
319 Functor* functor = reinterpret_cast<Functor*>(functorPtr);
320 RenderProxy::invokeFunctor(functor, waitForCompletion);
321 }
322
android_view_ThreadedRenderer_createTextureLayer(JNIEnv * env,jobject clazz,jlong proxyPtr)323 static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
324 jlong proxyPtr) {
325 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
326 DeferredLayerUpdater* layer = proxy->createTextureLayer();
327 return reinterpret_cast<jlong>(layer);
328 }
329
android_view_ThreadedRenderer_buildLayer(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong nodePtr)330 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
331 jlong proxyPtr, jlong nodePtr) {
332 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
333 RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
334 proxy->buildLayer(node);
335 }
336
android_view_ThreadedRenderer_copyLayerInto(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr,jlong bitmapPtr)337 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
338 jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
339 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
340 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
341 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
342 return proxy->copyLayerInto(layer, bitmap);
343 }
344
android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)345 static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
346 jlong proxyPtr, jlong layerPtr) {
347 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
348 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
349 proxy->pushLayerUpdate(layer);
350 }
351
android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)352 static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
353 jlong proxyPtr, jlong layerPtr) {
354 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
355 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
356 proxy->cancelLayerUpdate(layer);
357 }
358
android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)359 static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
360 jlong proxyPtr, jlong layerPtr) {
361 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
362 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
363 proxy->detachSurfaceTexture(layer);
364 }
365
android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv * env,jobject clazz,jlong proxyPtr)366 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
367 jlong proxyPtr) {
368 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
369 proxy->destroyHardwareResources();
370 }
371
android_view_ThreadedRenderer_trimMemory(JNIEnv * env,jobject clazz,jint level)372 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
373 jint level) {
374 RenderProxy::trimMemory(level);
375 }
376
android_view_ThreadedRenderer_fence(JNIEnv * env,jobject clazz,jlong proxyPtr)377 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
378 jlong proxyPtr) {
379 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
380 proxy->fence();
381 }
382
android_view_ThreadedRenderer_stopDrawing(JNIEnv * env,jobject clazz,jlong proxyPtr)383 static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
384 jlong proxyPtr) {
385 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
386 proxy->stopDrawing();
387 }
388
android_view_ThreadedRenderer_notifyFramePending(JNIEnv * env,jobject clazz,jlong proxyPtr)389 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
390 jlong proxyPtr) {
391 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
392 proxy->notifyFramePending();
393 }
394
android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject javaFileDescriptor)395 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
396 jlong proxyPtr, jobject javaFileDescriptor) {
397 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
398 int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
399 proxy->dumpProfileInfo(fd);
400 }
401
402 #endif
403
404 // ----------------------------------------------------------------------------
405 // Shaders
406 // ----------------------------------------------------------------------------
407
android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv * env,jobject clazz,jstring diskCachePath)408 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
409 jstring diskCachePath) {
410
411 const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
412 egl_cache_t::get()->setCacheFilename(cacheArray);
413 env->ReleaseStringUTFChars(diskCachePath, cacheArray);
414 }
415
416 // ----------------------------------------------------------------------------
417 // JNI Glue
418 // ----------------------------------------------------------------------------
419
420 const char* const kClassPathName = "android/view/ThreadedRenderer";
421
422 static JNINativeMethod gMethods[] = {
423 #ifdef USE_OPENGL_RENDERER
424 { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas },
425 { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
426 { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
427 { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
428 { "nSetFrameInterval", "(JJ)V", (void*) android_view_ThreadedRenderer_setFrameInterval },
429 { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
430 { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
431 { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
432 { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
433 { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
434 { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
435 { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
436 { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
437 { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
438 { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
439 { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
440 { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
441 { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
442 { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
443 { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
444 { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
445 { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
446 { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
447 { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
448 { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
449 { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
450 { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
451 #endif
452 { "setupShadersDiskCache", "(Ljava/lang/String;)V",
453 (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
454 };
455
register_android_view_ThreadedRenderer(JNIEnv * env)456 int register_android_view_ThreadedRenderer(JNIEnv* env) {
457 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
458 }
459
460 }; // namespace android
461