android_view_ThreadedRenderer.cpp revision 9d4efdf2802f06ccf7031610891f75af70ea5538
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 <ScopedPrimitiveArray.h>
25
26#include <EGL/egl.h>
27#include <EGL/eglext.h>
28#include <EGL/egl_cache.h>
29
30#include <utils/StrongPointer.h>
31#include <android_runtime/android_view_Surface.h>
32#include <system/window.h>
33
34#include "android_view_GraphicBuffer.h"
35
36#include <Animator.h>
37#include <AnimationContext.h>
38#include <IContextFactory.h>
39#include <JankTracker.h>
40#include <RenderNode.h>
41#include <renderthread/CanvasContext.h>
42#include <renderthread/RenderProxy.h>
43#include <renderthread/RenderTask.h>
44#include <renderthread/RenderThread.h>
45#include <Vector.h>
46
47namespace android {
48
49using namespace android::uirenderer;
50using namespace android::uirenderer::renderthread;
51
52static JNIEnv* getenv(JavaVM* vm) {
53    JNIEnv* env;
54    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
55        LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
56    }
57    return env;
58}
59
60class OnFinishedEvent {
61public:
62    OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
63            : animator(animator), listener(listener) {}
64    sp<BaseRenderNodeAnimator> animator;
65    sp<AnimationListener> listener;
66};
67
68class InvokeAnimationListeners : public MessageHandler {
69public:
70    InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
71        mOnFinishedEvents.swap(events);
72    }
73
74    static void callOnFinished(OnFinishedEvent& event) {
75        event.listener->onAnimationFinished(event.animator.get());
76    }
77
78    virtual void handleMessage(const Message& message) {
79        std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
80        mOnFinishedEvents.clear();
81    }
82
83private:
84    std::vector<OnFinishedEvent> mOnFinishedEvents;
85};
86
87class RenderingException : public MessageHandler {
88public:
89    RenderingException(JavaVM* vm, const std::string& message)
90            : mVm(vm)
91            , mMessage(message) {
92    }
93
94    virtual void handleMessage(const Message&) {
95        throwException(mVm, mMessage);
96    }
97
98    static void throwException(JavaVM* vm, const std::string& message) {
99        JNIEnv* env = getenv(vm);
100        jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
101    }
102
103private:
104    JavaVM* mVm;
105    std::string mMessage;
106};
107
108class RootRenderNode : public RenderNode, ErrorHandler {
109public:
110    RootRenderNode(JNIEnv* env) : RenderNode() {
111        mLooper = Looper::getForThread();
112        LOG_ALWAYS_FATAL_IF(!mLooper.get(),
113                "Must create RootRenderNode on a thread with a looper!");
114        env->GetJavaVM(&mVm);
115    }
116
117    virtual ~RootRenderNode() {}
118
119    virtual void onError(const std::string& message) {
120        mLooper->sendMessage(new RenderingException(mVm, message), 0);
121    }
122
123    virtual void prepareTree(TreeInfo& info) {
124        info.errorHandler = this;
125        RenderNode::prepareTree(info);
126        info.errorHandler = NULL;
127    }
128
129    void sendMessage(const sp<MessageHandler>& handler) {
130        mLooper->sendMessage(handler, 0);
131    }
132
133    void attachAnimatingNode(RenderNode* animatingNode) {
134        mPendingAnimatingRenderNodes.push_back(animatingNode);
135    }
136
137    void doAttachAnimatingNodes(AnimationContext* context) {
138        for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
139            RenderNode* node = mPendingAnimatingRenderNodes[i].get();
140            context->addAnimatingRenderNode(*node);
141        }
142        mPendingAnimatingRenderNodes.clear();
143    }
144
145private:
146    sp<Looper> mLooper;
147    JavaVM* mVm;
148    std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
149};
150
151class AnimationContextBridge : public AnimationContext {
152public:
153    AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
154            : AnimationContext(clock), mRootNode(rootNode) {
155    }
156
157    virtual ~AnimationContextBridge() {}
158
159    // Marks the start of a frame, which will update the frame time and move all
160    // next frame animations into the current frame
161    virtual void startFrame(TreeInfo::TraversalMode mode) {
162        if (mode == TreeInfo::MODE_FULL) {
163            mRootNode->doAttachAnimatingNodes(this);
164        }
165        AnimationContext::startFrame(mode);
166    }
167
168    // Runs any animations still left in mCurrentFrameAnimations
169    virtual void runRemainingAnimations(TreeInfo& info) {
170        AnimationContext::runRemainingAnimations(info);
171        postOnFinishedEvents();
172    }
173
174    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
175        OnFinishedEvent event(animator, listener);
176        mOnFinishedEvents.push_back(event);
177    }
178
179    virtual void destroy() {
180        AnimationContext::destroy();
181        postOnFinishedEvents();
182    }
183
184private:
185    sp<RootRenderNode> mRootNode;
186    std::vector<OnFinishedEvent> mOnFinishedEvents;
187
188    void postOnFinishedEvents() {
189        if (mOnFinishedEvents.size()) {
190            sp<InvokeAnimationListeners> message
191                    = new InvokeAnimationListeners(mOnFinishedEvents);
192            mRootNode->sendMessage(message);
193        }
194    }
195};
196
197class ContextFactoryImpl : public IContextFactory {
198public:
199    ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
200
201    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
202        return new AnimationContextBridge(clock, mRootNode);
203    }
204
205private:
206    RootRenderNode* mRootNode;
207};
208
209static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
210        jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
211    sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
212    jsize len = env->GetArrayLength(atlasMapArray);
213    if (len <= 0) {
214        ALOGW("Failed to initialize atlas, invalid map length: %d", len);
215        return;
216    }
217    int64_t* map = new int64_t[len];
218    env->GetLongArrayRegion(atlasMapArray, 0, len, map);
219
220    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
221    proxy->setTextureAtlas(buffer, map, len);
222}
223
224static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
225        jlong proxyPtr, jint fd) {
226    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
227    proxy->setProcessStatsBuffer(fd);
228}
229
230static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
231    RootRenderNode* node = new RootRenderNode(env);
232    node->incStrong(0);
233    node->setName("RootRenderNode");
234    return reinterpret_cast<jlong>(node);
235}
236
237static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
238        jboolean translucent, jlong rootRenderNodePtr) {
239    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
240    ContextFactoryImpl factory(rootRenderNode);
241    return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
242}
243
244static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
245        jlong proxyPtr) {
246    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
247    delete proxy;
248}
249
250static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
251        jlong proxyPtr) {
252    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
253    return proxy->loadSystemProperties();
254}
255
256static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
257        jlong proxyPtr, jstring jname) {
258    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
259    const char* name = env->GetStringUTFChars(jname, NULL);
260    proxy->setName(name);
261    env->ReleaseStringUTFChars(jname, name);
262}
263
264static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
265        jlong proxyPtr, jobject jsurface) {
266    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
267    sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
268    return proxy->initialize(window);
269}
270
271static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
272        jlong proxyPtr, jobject jsurface) {
273    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
274    sp<ANativeWindow> window;
275    if (jsurface) {
276        window = android_view_Surface_getNativeWindow(env, jsurface);
277    }
278    proxy->updateSurface(window);
279}
280
281static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
282        jlong proxyPtr, jobject jsurface) {
283    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
284    sp<ANativeWindow> window;
285    if (jsurface) {
286        window = android_view_Surface_getNativeWindow(env, jsurface);
287    }
288    return proxy->pauseSurface(window);
289}
290
291static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
292        jint width, jint height,
293        jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius,
294        jint ambientShadowAlpha, jint spotShadowAlpha, jfloat density) {
295    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
296    proxy->setup(width, height, (Vector3){lightX, lightY, lightZ}, lightRadius,
297            ambientShadowAlpha, spotShadowAlpha);
298}
299
300static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
301        jlong proxyPtr, jboolean opaque) {
302    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
303    proxy->setOpaque(opaque);
304}
305
306static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
307        jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
308    LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
309            "Mismatched size expectations, given %d expected %d",
310            frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
311    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
312    env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
313    return proxy->syncAndDrawFrame();
314}
315
316static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
317        jlong proxyPtr) {
318    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
319    proxy->destroy();
320}
321
322static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
323        jlong rootNodePtr, jlong animatingNodePtr) {
324    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
325    RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
326    rootRenderNode->attachAnimatingNode(animatingNode);
327}
328
329static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
330        jlong functorPtr, jboolean waitForCompletion) {
331    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
332    RenderProxy::invokeFunctor(functor, waitForCompletion);
333}
334
335static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
336        jlong proxyPtr) {
337    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
338    DeferredLayerUpdater* layer = proxy->createTextureLayer();
339    return reinterpret_cast<jlong>(layer);
340}
341
342static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
343        jlong proxyPtr, jlong nodePtr) {
344    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
345    RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
346    proxy->buildLayer(node);
347}
348
349static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
350        jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
351    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
352    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
353    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
354    return proxy->copyLayerInto(layer, bitmap);
355}
356
357static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
358        jlong proxyPtr, jlong layerPtr) {
359    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
360    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
361    proxy->pushLayerUpdate(layer);
362}
363
364static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
365        jlong proxyPtr, jlong layerPtr) {
366    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
367    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
368    proxy->cancelLayerUpdate(layer);
369}
370
371static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
372        jlong proxyPtr, jlong layerPtr) {
373    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
374    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
375    proxy->detachSurfaceTexture(layer);
376}
377
378static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
379        jlong proxyPtr) {
380    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
381    proxy->destroyHardwareResources();
382}
383
384static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
385        jint level) {
386    RenderProxy::trimMemory(level);
387}
388
389static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
390        jlong proxyPtr) {
391    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
392    proxy->fence();
393}
394
395static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
396        jlong proxyPtr) {
397    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
398    proxy->stopDrawing();
399}
400
401static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
402        jlong proxyPtr) {
403    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
404    proxy->notifyFramePending();
405}
406
407static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
408        jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
409    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
410    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
411    proxy->dumpProfileInfo(fd, dumpFlags);
412}
413
414static void android_view_ThreadedRenderer_dumpProfileData(JNIEnv* env, jobject clazz,
415        jbyteArray jdata, jobject javaFileDescriptor) {
416    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
417    ScopedByteArrayRO buffer(env, jdata);
418    if (buffer.get()) {
419        JankTracker::dumpBuffer(buffer.get(), buffer.size(), fd);
420    }
421}
422
423
424// ----------------------------------------------------------------------------
425// Shaders
426// ----------------------------------------------------------------------------
427
428static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
429        jstring diskCachePath) {
430
431    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
432    egl_cache_t::get()->setCacheFilename(cacheArray);
433    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
434}
435
436// ----------------------------------------------------------------------------
437// JNI Glue
438// ----------------------------------------------------------------------------
439
440const char* const kClassPathName = "android/view/ThreadedRenderer";
441
442static JNINativeMethod gMethods[] = {
443    { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
444    { "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
445    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
446    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
447    { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
448    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
449    { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
450    { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
451    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
452    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
453    { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
454    { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
455    { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
456    { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
457    { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
458    { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
459    { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
460    { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
461    { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
462    { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
463    { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
464    { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
465    { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
466    { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
467    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
468    { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
469    { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
470    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
471    { "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
472    { "setupShadersDiskCache", "(Ljava/lang/String;)V",
473                (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
474};
475
476int register_android_view_ThreadedRenderer(JNIEnv* env) {
477    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
478}
479
480}; // namespace android
481