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