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