android_view_ThreadedRenderer.cpp revision 66f0be65a1046f54ddce0498b242c1fa0776b1ea
10c1bc742181ded4930842b46e9507372f0b1b963James Dong/*
278e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * Copyright (C) 2010 The Android Open Source Project
378e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar *
478e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
578e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * you may not use this file except in compliance with the License.
678e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * You may obtain a copy of the License at
778e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar *
878e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
978e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar *
1078e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * Unless required by applicable law or agreed to in writing, software
1178e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
1278e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1378e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * See the License for the specific language governing permissions and
1478e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * limitations under the License.
1578e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar */
1678e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar
170c1bc742181ded4930842b46e9507372f0b1b963James Dong#define LOG_TAG "ThreadedRenderer"
180c1bc742181ded4930842b46e9507372f0b1b963James Dong
190c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <algorithm>
200c1bc742181ded4930842b46e9507372f0b1b963James Dong
210c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "jni.h"
220c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <nativehelper/JNIHelp.h>
230c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <android_runtime/AndroidRuntime.h>
240c1bc742181ded4930842b46e9507372f0b1b963James Dong
250c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <utils/StrongPointer.h>
260c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <android_runtime/android_view_Surface.h>
270c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <system/window.h>
280c1bc742181ded4930842b46e9507372f0b1b963James Dong
290c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "android_view_GraphicBuffer.h"
300c1bc742181ded4930842b46e9507372f0b1b963James Dong
310c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <Animator.h>
320c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <RenderNode.h>
330c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <renderthread/CanvasContext.h>
340c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <renderthread/RenderProxy.h>
350c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <renderthread/RenderTask.h>
360c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <renderthread/RenderThread.h>
370c1bc742181ded4930842b46e9507372f0b1b963James Dong
380c1bc742181ded4930842b46e9507372f0b1b963James Dongnamespace android {
390c1bc742181ded4930842b46e9507372f0b1b963James Dong
400c1bc742181ded4930842b46e9507372f0b1b963James Dong#ifdef USE_OPENGL_RENDERER
410c1bc742181ded4930842b46e9507372f0b1b963James Dong
420c1bc742181ded4930842b46e9507372f0b1b963James Dongusing namespace android::uirenderer;
430c1bc742181ded4930842b46e9507372f0b1b963James Dongusing namespace android::uirenderer::renderthread;
440c1bc742181ded4930842b46e9507372f0b1b963James Dong
450c1bc742181ded4930842b46e9507372f0b1b963James Dongstatic jmethodID gRunnableMethod;
460c1bc742181ded4930842b46e9507372f0b1b963James Dong
470c1bc742181ded4930842b46e9507372f0b1b963James Dongclass JavaTask : public RenderTask {
480c1bc742181ded4930842b46e9507372f0b1b963James Dongpublic:
490c1bc742181ded4930842b46e9507372f0b1b963James Dong    JavaTask(JNIEnv* env, jobject jrunnable) {
500c1bc742181ded4930842b46e9507372f0b1b963James Dong        env->GetJavaVM(&mVm);
510c1bc742181ded4930842b46e9507372f0b1b963James Dong        mRunnable = env->NewGlobalRef(jrunnable);
520c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
530c1bc742181ded4930842b46e9507372f0b1b963James Dong
540c1bc742181ded4930842b46e9507372f0b1b963James Dong    virtual void run() {
550c1bc742181ded4930842b46e9507372f0b1b963James Dong        env()->CallVoidMethod(mRunnable, gRunnableMethod);
560c1bc742181ded4930842b46e9507372f0b1b963James Dong        env()->DeleteGlobalRef(mRunnable);
570c1bc742181ded4930842b46e9507372f0b1b963James Dong        delete this;
580c1bc742181ded4930842b46e9507372f0b1b963James Dong    };
590c1bc742181ded4930842b46e9507372f0b1b963James Dong
600c1bc742181ded4930842b46e9507372f0b1b963James Dongprivate:
610c1bc742181ded4930842b46e9507372f0b1b963James Dong    JNIEnv* env() {
620c1bc742181ded4930842b46e9507372f0b1b963James Dong        JNIEnv* env;
630c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
640c1bc742181ded4930842b46e9507372f0b1b963James Dong            return 0;
650c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
660c1bc742181ded4930842b46e9507372f0b1b963James Dong        return env;
670c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
680c1bc742181ded4930842b46e9507372f0b1b963James Dong
690c1bc742181ded4930842b46e9507372f0b1b963James Dong    JavaVM* mVm;
700c1bc742181ded4930842b46e9507372f0b1b963James Dong    jobject mRunnable;
710c1bc742181ded4930842b46e9507372f0b1b963James Dong};
720c1bc742181ded4930842b46e9507372f0b1b963James Dong
730c1bc742181ded4930842b46e9507372f0b1b963James Dongclass SetAtlasTask : public RenderTask {
740c1bc742181ded4930842b46e9507372f0b1b963James Dongpublic:
750c1bc742181ded4930842b46e9507372f0b1b963James Dong    SetAtlasTask(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size)
760c1bc742181ded4930842b46e9507372f0b1b963James Dong            : mBuffer(buffer)
770c1bc742181ded4930842b46e9507372f0b1b963James Dong            , mMap(map)
780c1bc742181ded4930842b46e9507372f0b1b963James Dong            , mMapSize(size) {
790c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
800c1bc742181ded4930842b46e9507372f0b1b963James Dong
810c1bc742181ded4930842b46e9507372f0b1b963James Dong    virtual void run() {
820c1bc742181ded4930842b46e9507372f0b1b963James Dong        CanvasContext::setTextureAtlas(mBuffer, mMap, mMapSize);
830c1bc742181ded4930842b46e9507372f0b1b963James Dong        mMap = 0;
840c1bc742181ded4930842b46e9507372f0b1b963James Dong        delete this;
850c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
860c1bc742181ded4930842b46e9507372f0b1b963James Dong
870c1bc742181ded4930842b46e9507372f0b1b963James Dongprivate:
880c1bc742181ded4930842b46e9507372f0b1b963James Dong    sp<GraphicBuffer> mBuffer;
890c1bc742181ded4930842b46e9507372f0b1b963James Dong    int64_t* mMap;
900c1bc742181ded4930842b46e9507372f0b1b963James Dong    size_t mMapSize;
910c1bc742181ded4930842b46e9507372f0b1b963James Dong};
920c1bc742181ded4930842b46e9507372f0b1b963James Dong
930c1bc742181ded4930842b46e9507372f0b1b963James Dongclass OnFinishedEvent {
940c1bc742181ded4930842b46e9507372f0b1b963James Dongpublic:
950c1bc742181ded4930842b46e9507372f0b1b963James Dong    OnFinishedEvent(BaseAnimator* animator, AnimationListener* listener)
960c1bc742181ded4930842b46e9507372f0b1b963James Dong            : animator(animator), listener(listener) {}
970c1bc742181ded4930842b46e9507372f0b1b963James Dong    sp<BaseAnimator> animator;
980c1bc742181ded4930842b46e9507372f0b1b963James Dong    sp<AnimationListener> listener;
990c1bc742181ded4930842b46e9507372f0b1b963James Dong};
1000c1bc742181ded4930842b46e9507372f0b1b963James Dong
1010c1bc742181ded4930842b46e9507372f0b1b963James Dongclass InvokeAnimationListeners : public MessageHandler {
1020c1bc742181ded4930842b46e9507372f0b1b963James Dongpublic:
1030c1bc742181ded4930842b46e9507372f0b1b963James Dong    InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
1040c1bc742181ded4930842b46e9507372f0b1b963James Dong        mOnFinishedEvents.swap(events);
1050c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1060c1bc742181ded4930842b46e9507372f0b1b963James Dong
1070c1bc742181ded4930842b46e9507372f0b1b963James Dong    static void callOnFinished(OnFinishedEvent& event) {
1080c1bc742181ded4930842b46e9507372f0b1b963James Dong        event.listener->onAnimationFinished(event.animator.get());
1090c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1100c1bc742181ded4930842b46e9507372f0b1b963James Dong
1110c1bc742181ded4930842b46e9507372f0b1b963James Dong    virtual void handleMessage(const Message& message) {
1120c1bc742181ded4930842b46e9507372f0b1b963James Dong        std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
1130c1bc742181ded4930842b46e9507372f0b1b963James Dong        mOnFinishedEvents.clear();
1140c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1150c1bc742181ded4930842b46e9507372f0b1b963James Dong
1160c1bc742181ded4930842b46e9507372f0b1b963James Dongprivate:
1170c1bc742181ded4930842b46e9507372f0b1b963James Dong    std::vector<OnFinishedEvent> mOnFinishedEvents;
1180c1bc742181ded4930842b46e9507372f0b1b963James Dong};
1190c1bc742181ded4930842b46e9507372f0b1b963James Dong
1200c1bc742181ded4930842b46e9507372f0b1b963James Dongclass RootRenderNode : public RenderNode, public AnimationHook {
1210c1bc742181ded4930842b46e9507372f0b1b963James Dongpublic:
1220c1bc742181ded4930842b46e9507372f0b1b963James Dong    RootRenderNode() : RenderNode() {
1230c1bc742181ded4930842b46e9507372f0b1b963James Dong        mLooper = Looper::getForThread();
1240c1bc742181ded4930842b46e9507372f0b1b963James Dong        LOG_ALWAYS_FATAL_IF(!mLooper.get(),
1250c1bc742181ded4930842b46e9507372f0b1b963James Dong                "Must create RootRenderNode on a thread with a looper!");
1260c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1270c1bc742181ded4930842b46e9507372f0b1b963James Dong
1280c1bc742181ded4930842b46e9507372f0b1b963James Dong    virtual ~RootRenderNode() {}
1290c1bc742181ded4930842b46e9507372f0b1b963James Dong
1300c1bc742181ded4930842b46e9507372f0b1b963James Dong    virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) {
1310c1bc742181ded4930842b46e9507372f0b1b963James Dong        OnFinishedEvent event(animator, listener);
1320c1bc742181ded4930842b46e9507372f0b1b963James Dong        mOnFinishedEvents.push_back(event);
1330c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1340c1bc742181ded4930842b46e9507372f0b1b963James Dong
1350c1bc742181ded4930842b46e9507372f0b1b963James Dong    virtual void prepareTree(TreeInfo& info) {
1360c1bc742181ded4930842b46e9507372f0b1b963James Dong        info.animationHook = this;
1370c1bc742181ded4930842b46e9507372f0b1b963James Dong        RenderNode::prepareTree(info);
1380c1bc742181ded4930842b46e9507372f0b1b963James Dong        info.animationHook = NULL;
1390c1bc742181ded4930842b46e9507372f0b1b963James Dong
1400c1bc742181ded4930842b46e9507372f0b1b963James Dong        // post all the finished stuff
1410c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (mOnFinishedEvents.size()) {
1420c1bc742181ded4930842b46e9507372f0b1b963James Dong            sp<InvokeAnimationListeners> message
1430c1bc742181ded4930842b46e9507372f0b1b963James Dong                    = new InvokeAnimationListeners(mOnFinishedEvents);
1440c1bc742181ded4930842b46e9507372f0b1b963James Dong            mLooper->sendMessage(message, 0);
1450c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1460c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1470c1bc742181ded4930842b46e9507372f0b1b963James Dong
1480c1bc742181ded4930842b46e9507372f0b1b963James Dongprivate:
1490c1bc742181ded4930842b46e9507372f0b1b963James Dong    sp<Looper> mLooper;
1500c1bc742181ded4930842b46e9507372f0b1b963James Dong    std::vector<OnFinishedEvent> mOnFinishedEvents;
1510c1bc742181ded4930842b46e9507372f0b1b963James Dong};
1520c1bc742181ded4930842b46e9507372f0b1b963James Dong
1530c1bc742181ded4930842b46e9507372f0b1b963James Dongstatic void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
1540c1bc742181ded4930842b46e9507372f0b1b963James Dong        jobject graphicBuffer, jlongArray atlasMapArray) {
1550c1bc742181ded4930842b46e9507372f0b1b963James Dong    sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
1560c1bc742181ded4930842b46e9507372f0b1b963James Dong    jsize len = env->GetArrayLength(atlasMapArray);
1570c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (len <= 0) {
1580c1bc742181ded4930842b46e9507372f0b1b963James Dong        ALOGW("Failed to initialize atlas, invalid map length: %d", len);
1590c1bc742181ded4930842b46e9507372f0b1b963James Dong        return;
1600c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1610c1bc742181ded4930842b46e9507372f0b1b963James Dong    int64_t* map = new int64_t[len];
1620c1bc742181ded4930842b46e9507372f0b1b963James Dong    env->GetLongArrayRegion(atlasMapArray, 0, len, map);
16378e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar
164    SetAtlasTask* task = new SetAtlasTask(buffer, map, len);
165    RenderThread::getInstance().queue(task);
166}
167
168static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
169    RootRenderNode* node = new RootRenderNode();
170    node->incStrong(0);
171    node->setName("RootRenderNode");
172    return reinterpret_cast<jlong>(node);
173}
174
175static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
176        jboolean translucent, jlong rootRenderNodePtr) {
177    RenderNode* rootRenderNode = reinterpret_cast<RenderNode*>(rootRenderNodePtr);
178    return (jlong) new RenderProxy(translucent, rootRenderNode);
179}
180
181static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
182        jlong proxyPtr) {
183    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
184    delete proxy;
185}
186
187static void android_view_ThreadedRenderer_setFrameInterval(JNIEnv* env, jobject clazz,
188        jlong proxyPtr, jlong frameIntervalNanos) {
189    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
190    proxy->setFrameInterval(frameIntervalNanos);
191}
192
193static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
194        jlong proxyPtr) {
195    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
196    return proxy->loadSystemProperties();
197}
198
199static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
200        jlong proxyPtr, jobject jsurface) {
201    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
202    sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
203    return proxy->initialize(window);
204}
205
206static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
207        jlong proxyPtr, jobject jsurface) {
208    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
209    sp<ANativeWindow> window;
210    if (jsurface) {
211        window = android_view_Surface_getNativeWindow(env, jsurface);
212    }
213    proxy->updateSurface(window);
214}
215
216static void android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
217        jlong proxyPtr, jobject jsurface) {
218    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
219    sp<ANativeWindow> window;
220    if (jsurface) {
221        window = android_view_Surface_getNativeWindow(env, jsurface);
222    }
223    proxy->pauseSurface(window);
224}
225
226static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz,
227        jlong proxyPtr, jint width, jint height) {
228    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
229    proxy->setup(width, height);
230}
231
232static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
233        jlong proxyPtr, jboolean opaque) {
234    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
235    proxy->setOpaque(opaque);
236}
237
238static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
239        jlong proxyPtr, jlong frameTimeNanos, jint dirtyLeft, jint dirtyTop,
240        jint dirtyRight, jint dirtyBottom) {
241    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
242    return proxy->syncAndDrawFrame(frameTimeNanos, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
243}
244
245static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
246        jlong proxyPtr) {
247    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
248    proxy->destroyCanvasAndSurface();
249}
250
251static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
252        jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) {
253    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
254    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
255    proxy->invokeFunctor(functor, waitForCompletion);
256}
257
258static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz,
259        jlong proxyPtr, jobject jrunnable) {
260    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
261    RenderTask* task = new JavaTask(env, jrunnable);
262    proxy->runWithGlContext(task);
263}
264
265static jlong android_view_ThreadedRenderer_createDisplayListLayer(JNIEnv* env, jobject clazz,
266        jlong proxyPtr, jint width, jint height) {
267    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
268    DeferredLayerUpdater* layer = proxy->createDisplayListLayer(width, height);
269    return reinterpret_cast<jlong>(layer);
270}
271
272static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
273        jlong proxyPtr) {
274    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
275    DeferredLayerUpdater* layer = proxy->createTextureLayer();
276    return reinterpret_cast<jlong>(layer);
277}
278
279static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
280        jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
281    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
282    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
283    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
284    return proxy->copyLayerInto(layer, bitmap);
285}
286
287static void android_view_ThreadedRenderer_destroyLayer(JNIEnv* env, jobject clazz,
288        jlong proxyPtr, jlong layerPtr) {
289    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
290    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
291    proxy->destroyLayer(layer);
292}
293
294static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
295        jlong proxyPtr) {
296    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
297    proxy->fence();
298}
299
300#endif
301
302// ----------------------------------------------------------------------------
303// JNI Glue
304// ----------------------------------------------------------------------------
305
306const char* const kClassPathName = "android/view/ThreadedRenderer";
307
308static JNINativeMethod gMethods[] = {
309#ifdef USE_OPENGL_RENDERER
310    { "nSetAtlas", "(Landroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
311    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
312    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
313    { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
314    { "nSetFrameInterval", "(JJ)V", (void*) android_view_ThreadedRenderer_setFrameInterval },
315    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
316    { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
317    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
318    { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
319    { "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup },
320    { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
321    { "nSyncAndDrawFrame", "(JJIIII)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
322    { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
323    { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
324    { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
325    { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
326    { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
327    { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
328    { "nDestroyLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_destroyLayer },
329    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
330#endif
331};
332
333int register_android_view_ThreadedRenderer(JNIEnv* env) {
334#ifdef USE_OPENGL_RENDERER
335    jclass cls = env->FindClass("java/lang/Runnable");
336    gRunnableMethod = env->GetMethodID(cls, "run", "()V");
337    env->DeleteLocalRef(cls);
338#endif
339    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
340}
341
342}; // namespace android
343