android_view_ThreadedRenderer.cpp revision 0a1abd3247d856fe875d5ef45f75bc2c8167ea96
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 "core_jni_helpers.h"
24#include <GraphicsJNI.h>
25#include <ScopedPrimitiveArray.h>
26
27#include <EGL/egl.h>
28#include <EGL/eglext.h>
29#include <EGL/egl_cache.h>
30#include <vulkan/vulkan_loader_data.h>
31
32#include <utils/Looper.h>
33#include <utils/RefBase.h>
34#include <utils/StrongPointer.h>
35#include <android_runtime/android_view_Surface.h>
36#include <system/window.h>
37
38#include "android_view_GraphicBuffer.h"
39#include "android_os_MessageQueue.h"
40
41#include <Animator.h>
42#include <AnimationContext.h>
43#include <FrameInfo.h>
44#include <IContextFactory.h>
45#include <JankTracker.h>
46#include <RenderNode.h>
47#include <renderthread/CanvasContext.h>
48#include <renderthread/RenderProxy.h>
49#include <renderthread/RenderTask.h>
50#include <renderthread/RenderThread.h>
51#include <Vector.h>
52
53namespace android {
54
55using namespace android::uirenderer;
56using namespace android::uirenderer::renderthread;
57
58struct {
59    jfieldID buffer;
60    jfieldID messageQueue;
61    jmethodID notifyData;
62} gFrameStatsObserverClassInfo;
63
64static JNIEnv* getenv(JavaVM* vm) {
65    JNIEnv* env;
66    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
67        LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
68    }
69    return env;
70}
71
72class OnFinishedEvent {
73public:
74    OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
75            : animator(animator), listener(listener) {}
76    sp<BaseRenderNodeAnimator> animator;
77    sp<AnimationListener> listener;
78};
79
80class InvokeAnimationListeners : public MessageHandler {
81public:
82    InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
83        mOnFinishedEvents.swap(events);
84    }
85
86    static void callOnFinished(OnFinishedEvent& event) {
87        event.listener->onAnimationFinished(event.animator.get());
88    }
89
90    virtual void handleMessage(const Message& message) {
91        std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
92        mOnFinishedEvents.clear();
93    }
94
95private:
96    std::vector<OnFinishedEvent> mOnFinishedEvents;
97};
98
99class RenderingException : public MessageHandler {
100public:
101    RenderingException(JavaVM* vm, const std::string& message)
102            : mVm(vm)
103            , mMessage(message) {
104    }
105
106    virtual void handleMessage(const Message&) {
107        throwException(mVm, mMessage);
108    }
109
110    static void throwException(JavaVM* vm, const std::string& message) {
111        JNIEnv* env = getenv(vm);
112        jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
113    }
114
115private:
116    JavaVM* mVm;
117    std::string mMessage;
118};
119
120class RootRenderNode : public RenderNode, ErrorHandler {
121public:
122    RootRenderNode(JNIEnv* env) : RenderNode() {
123        mLooper = Looper::getForThread();
124        LOG_ALWAYS_FATAL_IF(!mLooper.get(),
125                "Must create RootRenderNode on a thread with a looper!");
126        env->GetJavaVM(&mVm);
127    }
128
129    virtual ~RootRenderNode() {}
130
131    virtual void onError(const std::string& message) {
132        mLooper->sendMessage(new RenderingException(mVm, message), 0);
133    }
134
135    virtual void prepareTree(TreeInfo& info) {
136        info.errorHandler = this;
137        // TODO: This is hacky
138        info.windowInsetLeft = -stagingProperties().getLeft();
139        info.windowInsetTop = -stagingProperties().getTop();
140        info.updateWindowPositions = true;
141        RenderNode::prepareTree(info);
142        info.updateWindowPositions = false;
143        info.windowInsetLeft = 0;
144        info.windowInsetTop = 0;
145        info.errorHandler = NULL;
146    }
147
148    void sendMessage(const sp<MessageHandler>& handler) {
149        mLooper->sendMessage(handler, 0);
150    }
151
152    void attachAnimatingNode(RenderNode* animatingNode) {
153        mPendingAnimatingRenderNodes.push_back(animatingNode);
154    }
155
156    void doAttachAnimatingNodes(AnimationContext* context) {
157        for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
158            RenderNode* node = mPendingAnimatingRenderNodes[i].get();
159            context->addAnimatingRenderNode(*node);
160        }
161        mPendingAnimatingRenderNodes.clear();
162    }
163
164private:
165    sp<Looper> mLooper;
166    JavaVM* mVm;
167    std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
168};
169
170class AnimationContextBridge : public AnimationContext {
171public:
172    AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
173            : AnimationContext(clock), mRootNode(rootNode) {
174    }
175
176    virtual ~AnimationContextBridge() {}
177
178    // Marks the start of a frame, which will update the frame time and move all
179    // next frame animations into the current frame
180    virtual void startFrame(TreeInfo::TraversalMode mode) {
181        if (mode == TreeInfo::MODE_FULL) {
182            mRootNode->doAttachAnimatingNodes(this);
183        }
184        AnimationContext::startFrame(mode);
185    }
186
187    // Runs any animations still left in mCurrentFrameAnimations
188    virtual void runRemainingAnimations(TreeInfo& info) {
189        AnimationContext::runRemainingAnimations(info);
190        postOnFinishedEvents();
191    }
192
193    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
194        OnFinishedEvent event(animator, listener);
195        mOnFinishedEvents.push_back(event);
196    }
197
198    virtual void destroy() {
199        AnimationContext::destroy();
200        postOnFinishedEvents();
201    }
202
203private:
204    sp<RootRenderNode> mRootNode;
205    std::vector<OnFinishedEvent> mOnFinishedEvents;
206
207    void postOnFinishedEvents() {
208        if (mOnFinishedEvents.size()) {
209            sp<InvokeAnimationListeners> message
210                    = new InvokeAnimationListeners(mOnFinishedEvents);
211            mRootNode->sendMessage(message);
212        }
213    }
214};
215
216class ContextFactoryImpl : public IContextFactory {
217public:
218    ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
219
220    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
221        return new AnimationContextBridge(clock, mRootNode);
222    }
223
224private:
225    RootRenderNode* mRootNode;
226};
227
228class ObserverProxy;
229
230class NotifyHandler : public MessageHandler {
231public:
232    NotifyHandler(JavaVM* vm) : mVm(vm) {}
233
234    void setObserver(ObserverProxy* observer) {
235        mObserver = observer;
236    }
237
238    void setBuffer(BufferPool::Buffer* buffer) {
239        mBuffer = buffer;
240    }
241
242    virtual void handleMessage(const Message& message);
243
244private:
245    JavaVM* mVm;
246
247    sp<ObserverProxy> mObserver;
248    BufferPool::Buffer* mBuffer;
249};
250
251class ObserverProxy : public FrameStatsObserver {
252public:
253    ObserverProxy(JavaVM *vm, jobject fso) : mVm(vm) {
254        JNIEnv* env = getenv(mVm);
255
256        jlongArray longArrayLocal = env->NewLongArray(kBufferSize);
257        LOG_ALWAYS_FATAL_IF(longArrayLocal == nullptr,
258                "OOM: can't allocate frame stats buffer");
259        env->SetObjectField(fso, gFrameStatsObserverClassInfo.buffer, longArrayLocal);
260
261        mFsoWeak = env->NewWeakGlobalRef(fso);
262        LOG_ALWAYS_FATAL_IF(mFsoWeak == nullptr,
263                "unable to create frame stats observer reference");
264
265        jobject messageQueueLocal =
266                env->GetObjectField(fso, gFrameStatsObserverClassInfo.messageQueue);
267        mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal);
268        LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available");
269
270        mMessageHandler = new NotifyHandler(mVm);
271        LOG_ALWAYS_FATAL_IF(mMessageHandler == nullptr,
272                "OOM: unable to allocate NotifyHandler");
273    }
274
275    ~ObserverProxy() {
276        JNIEnv* env = getenv(mVm);
277        env->DeleteWeakGlobalRef(mFsoWeak);
278    }
279
280    jweak getJavaObjectRef() {
281        return mFsoWeak;
282    }
283
284    virtual void notify(BufferPool::Buffer* buffer) {
285        buffer->incRef();
286        mMessageHandler->setBuffer(buffer);
287        mMessageHandler->setObserver(this);
288        mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage);
289    }
290
291private:
292    static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes);
293
294    JavaVM* mVm;
295    jweak mFsoWeak;
296
297    sp<MessageQueue> mMessageQueue;
298    sp<NotifyHandler> mMessageHandler;
299    Message mMessage;
300};
301
302void NotifyHandler::handleMessage(const Message& message) {
303    JNIEnv* env = getenv(mVm);
304
305    jobject target = env->NewLocalRef(mObserver->getJavaObjectRef());
306
307    if (target != nullptr) {
308        jobject javaBuffer = env->GetObjectField(target, gFrameStatsObserverClassInfo.buffer);
309        if (javaBuffer != nullptr) {
310            env->SetLongArrayRegion(reinterpret_cast<jlongArray>(javaBuffer),
311                    0, mBuffer->getSize(), mBuffer->getBuffer());
312            env->CallVoidMethod(target, gFrameStatsObserverClassInfo.notifyData);
313            env->DeleteLocalRef(target);
314        }
315    }
316
317    mBuffer->release();
318    mObserver.clear();
319}
320
321static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
322        jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
323    sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
324    jsize len = env->GetArrayLength(atlasMapArray);
325    if (len <= 0) {
326        ALOGW("Failed to initialize atlas, invalid map length: %d", len);
327        return;
328    }
329    int64_t* map = new int64_t[len];
330    env->GetLongArrayRegion(atlasMapArray, 0, len, map);
331
332    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
333    proxy->setTextureAtlas(buffer, map, len);
334}
335
336static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
337        jlong proxyPtr, jint fd) {
338    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
339    proxy->setProcessStatsBuffer(fd);
340}
341
342static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
343    RootRenderNode* node = new RootRenderNode(env);
344    node->incStrong(0);
345    node->setName("RootRenderNode");
346    return reinterpret_cast<jlong>(node);
347}
348
349static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
350        jboolean translucent, jlong rootRenderNodePtr) {
351    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
352    ContextFactoryImpl factory(rootRenderNode);
353    return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
354}
355
356static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
357        jlong proxyPtr) {
358    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
359    delete proxy;
360}
361
362static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
363        jlong proxyPtr) {
364    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
365    return proxy->loadSystemProperties();
366}
367
368static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
369        jlong proxyPtr, jstring jname) {
370    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
371    const char* name = env->GetStringUTFChars(jname, NULL);
372    proxy->setName(name);
373    env->ReleaseStringUTFChars(jname, name);
374}
375
376static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
377        jlong proxyPtr, jobject jsurface) {
378    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
379    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
380    proxy->initialize(surface);
381}
382
383static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
384        jlong proxyPtr, jobject jsurface) {
385    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
386    sp<Surface> surface;
387    if (jsurface) {
388        surface = android_view_Surface_getSurface(env, jsurface);
389    }
390    proxy->updateSurface(surface);
391}
392
393static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
394        jlong proxyPtr, jobject jsurface) {
395    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
396    sp<Surface> surface;
397    if (jsurface) {
398        surface = android_view_Surface_getSurface(env, jsurface);
399    }
400    return proxy->pauseSurface(surface);
401}
402
403static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
404        jint width, jint height, jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
405    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
406    proxy->setup(width, height, lightRadius, ambientShadowAlpha, spotShadowAlpha);
407}
408
409static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
410        jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
411    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
412    proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
413}
414
415static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
416        jlong proxyPtr, jboolean opaque) {
417    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
418    proxy->setOpaque(opaque);
419}
420
421static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
422        jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
423    LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
424            "Mismatched size expectations, given %d expected %d",
425            frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
426    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
427    env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
428    return proxy->syncAndDrawFrame();
429}
430
431static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
432        jlong proxyPtr) {
433    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
434    proxy->destroy();
435}
436
437static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
438        jlong rootNodePtr, jlong animatingNodePtr) {
439    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
440    RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
441    rootRenderNode->attachAnimatingNode(animatingNode);
442}
443
444static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
445        jlong functorPtr, jboolean waitForCompletion) {
446    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
447    RenderProxy::invokeFunctor(functor, waitForCompletion);
448}
449
450static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
451        jlong proxyPtr) {
452    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
453    DeferredLayerUpdater* layer = proxy->createTextureLayer();
454    return reinterpret_cast<jlong>(layer);
455}
456
457static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
458        jlong proxyPtr, jlong nodePtr) {
459    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
460    RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
461    proxy->buildLayer(node);
462}
463
464static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
465        jlong proxyPtr, jlong layerPtr, jobject jbitmap) {
466    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
467    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
468    SkBitmap bitmap;
469    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
470    return proxy->copyLayerInto(layer, bitmap);
471}
472
473static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
474        jlong proxyPtr, jlong layerPtr) {
475    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
476    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
477    proxy->pushLayerUpdate(layer);
478}
479
480static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
481        jlong proxyPtr, jlong layerPtr) {
482    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
483    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
484    proxy->cancelLayerUpdate(layer);
485}
486
487static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
488        jlong proxyPtr, jlong layerPtr) {
489    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
490    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
491    proxy->detachSurfaceTexture(layer);
492}
493
494static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
495        jlong proxyPtr) {
496    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
497    proxy->destroyHardwareResources();
498}
499
500static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
501        jint level) {
502    RenderProxy::trimMemory(level);
503}
504
505static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
506        jstring name, jstring value) {
507    const char* nameCharArray = env->GetStringUTFChars(name, NULL);
508    const char* valueCharArray = env->GetStringUTFChars(value, NULL);
509    RenderProxy::overrideProperty(nameCharArray, valueCharArray);
510    env->ReleaseStringUTFChars(name, nameCharArray);
511    env->ReleaseStringUTFChars(name, valueCharArray);
512}
513
514static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
515        jlong proxyPtr) {
516    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
517    proxy->fence();
518}
519
520static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
521        jlong proxyPtr) {
522    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
523    proxy->stopDrawing();
524}
525
526static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
527        jlong proxyPtr) {
528    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
529    proxy->notifyFramePending();
530}
531
532static void android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv* env, jobject clazz,
533        jlong proxyPtr) {
534    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
535    proxy->serializeDisplayListTree();
536}
537
538static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
539        jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
540    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
541    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
542    proxy->dumpProfileInfo(fd, dumpFlags);
543}
544
545static void android_view_ThreadedRenderer_dumpProfileData(JNIEnv* env, jobject clazz,
546        jbyteArray jdata, jobject javaFileDescriptor) {
547    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
548    ScopedByteArrayRO buffer(env, jdata);
549    if (buffer.get()) {
550        JankTracker::dumpBuffer(buffer.get(), buffer.size(), fd);
551    }
552}
553
554static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
555        jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
556    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
557    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
558    proxy->addRenderNode(renderNode, placeFront);
559}
560
561static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz,
562        jlong proxyPtr, jlong renderNodePtr) {
563    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
564    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
565    proxy->removeRenderNode(renderNode);
566}
567
568static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz,
569        jlong proxyPtr, jlong renderNodePtr) {
570    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
571    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
572    proxy->drawRenderNode(renderNode);
573}
574
575static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
576        jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
577    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
578    proxy->setContentDrawBounds(left, top, right, bottom);
579}
580
581// ----------------------------------------------------------------------------
582// FrameStatsObserver
583// ----------------------------------------------------------------------------
584
585static jlong android_view_ThreadedRenderer_addFrameStatsObserver(JNIEnv* env,
586        jclass clazz, jlong proxyPtr, jobject fso) {
587    JavaVM* vm = nullptr;
588    if (env->GetJavaVM(&vm) != JNI_OK) {
589        LOG_ALWAYS_FATAL("Unable to get Java VM");
590        return 0;
591    }
592
593    renderthread::RenderProxy* renderProxy =
594            reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
595
596    FrameStatsObserver* observer = new ObserverProxy(vm, fso);
597    renderProxy->addFrameStatsObserver(observer);
598    return reinterpret_cast<jlong>(observer);
599}
600
601static void android_view_ThreadedRenderer_removeFrameStatsObserver(JNIEnv* env, jclass clazz,
602        jlong proxyPtr, jlong observerPtr) {
603    FrameStatsObserver* observer = reinterpret_cast<FrameStatsObserver*>(observerPtr);
604    renderthread::RenderProxy* renderProxy =
605            reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
606
607    renderProxy->removeFrameStatsObserver(observer);
608}
609
610static jint android_view_ThreadedRenderer_getDroppedFrameReportCount(JNIEnv* env, jclass clazz,
611        jlong proxyPtr) {
612    renderthread::RenderProxy* renderProxy =
613            reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
614    return renderProxy->getDroppedFrameReportCount();
615}
616
617// ----------------------------------------------------------------------------
618// Shaders
619// ----------------------------------------------------------------------------
620
621static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
622        jstring diskCachePath) {
623    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
624    egl_cache_t::get()->setCacheFilename(cacheArray);
625    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
626}
627
628// ----------------------------------------------------------------------------
629// Layers
630// ----------------------------------------------------------------------------
631
632static void android_view_ThreadedRenderer_setupVulkanLayerPath(JNIEnv* env, jobject clazz,
633        jstring layerPath) {
634
635    const char* layerArray = env->GetStringUTFChars(layerPath, NULL);
636    vulkan::LoaderData::GetInstance().layer_path = layerArray;
637    env->ReleaseStringUTFChars(layerPath, layerArray);
638}
639
640// ----------------------------------------------------------------------------
641// JNI Glue
642// ----------------------------------------------------------------------------
643
644const char* const kClassPathName = "android/view/ThreadedRenderer";
645
646static const JNINativeMethod gMethods[] = {
647    { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
648    { "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
649    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
650    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
651    { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
652    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
653    { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
654    { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
655    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
656    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
657    { "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup },
658    { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
659    { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
660    { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
661    { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
662    { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
663    { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
664    { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
665    { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
666    { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
667    { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
668    { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
669    { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
670    { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
671    { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
672    { "nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V",  (void*) android_view_ThreadedRenderer_overrideProperty },
673    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
674    { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
675    { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
676    { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree },
677    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
678    { "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
679    { "setupShadersDiskCache", "(Ljava/lang/String;)V",
680                (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
681    { "setupVulkanLayerPath", "(Ljava/lang/String;)V",
682                (void*) android_view_ThreadedRenderer_setupVulkanLayerPath },
683    { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
684    { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
685    { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
686    { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
687    { "nAddFrameStatsObserver",
688            "(JLandroid/view/FrameStatsObserver;)J",
689            (void*)android_view_ThreadedRenderer_addFrameStatsObserver },
690    { "nRemoveFrameStatsObserver",
691            "(JJ)V",
692            (void*)android_view_ThreadedRenderer_removeFrameStatsObserver },
693    { "nGetDroppedFrameReportCount",
694            "(J)J",
695            (void*)android_view_ThreadedRenderer_getDroppedFrameReportCount },
696};
697
698int register_android_view_ThreadedRenderer(JNIEnv* env) {
699    jclass clazz = FindClassOrDie(env, "android/view/FrameStatsObserver");
700    gFrameStatsObserverClassInfo.messageQueue  =
701            GetFieldIDOrDie(env, clazz, "mMessageQueue", "Landroid/os/MessageQueue;");
702    gFrameStatsObserverClassInfo.buffer =
703            GetFieldIDOrDie(env, clazz, "mBuffer", "[J");
704    gFrameStatsObserverClassInfo.notifyData =
705            GetMethodIDOrDie(env, clazz, "notifyDataAvailable", "()V");
706
707    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
708}
709
710}; // namespace android
711