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