android_view_ThreadedRenderer.cpp revision e2478d45ccbe5b6abb360ac9d44771b5f4a50bde
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 <android_runtime/AndroidRuntime.h>
24
25#include <EGL/egl.h>
26#include <EGL/eglext.h>
27#include <EGL/egl_cache.h>
28
29#include <utils/StrongPointer.h>
30#include <android_runtime/android_view_Surface.h>
31#include <system/window.h>
32
33#include "android_view_GraphicBuffer.h"
34
35#include <Animator.h>
36#include <AnimationContext.h>
37#include <IContextFactory.h>
38#include <RenderNode.h>
39#include <renderthread/CanvasContext.h>
40#include <renderthread/RenderProxy.h>
41#include <renderthread/RenderTask.h>
42#include <renderthread/RenderThread.h>
43#include <Vector.h>
44
45namespace android {
46
47#ifdef USE_OPENGL_RENDERER
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() {
162        mRootNode->doAttachAnimatingNodes(this);
163        AnimationContext::startFrame();
164    }
165
166    // Runs any animations still left in mCurrentFrameAnimations
167    virtual void runRemainingAnimations(TreeInfo& info) {
168        AnimationContext::runRemainingAnimations(info);
169        postOnFinishedEvents();
170    }
171
172    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
173        OnFinishedEvent event(animator, listener);
174        mOnFinishedEvents.push_back(event);
175    }
176
177    virtual void destroy() {
178        AnimationContext::destroy();
179        postOnFinishedEvents();
180    }
181
182private:
183    sp<RootRenderNode> mRootNode;
184    std::vector<OnFinishedEvent> mOnFinishedEvents;
185
186    void postOnFinishedEvents() {
187        if (mOnFinishedEvents.size()) {
188            sp<InvokeAnimationListeners> message
189                    = new InvokeAnimationListeners(mOnFinishedEvents);
190            mRootNode->sendMessage(message);
191        }
192    }
193};
194
195class ContextFactoryImpl : public IContextFactory {
196public:
197    ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
198
199    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
200        return new AnimationContextBridge(clock, mRootNode);
201    }
202
203private:
204    RootRenderNode* mRootNode;
205};
206
207static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
208        jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
209    sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
210    jsize len = env->GetArrayLength(atlasMapArray);
211    if (len <= 0) {
212        ALOGW("Failed to initialize atlas, invalid map length: %d", len);
213        return;
214    }
215    int64_t* map = new int64_t[len];
216    env->GetLongArrayRegion(atlasMapArray, 0, len, map);
217
218    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
219    proxy->setTextureAtlas(buffer, map, len);
220}
221
222static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
223    RootRenderNode* node = new RootRenderNode(env);
224    node->incStrong(0);
225    node->setName("RootRenderNode");
226    return reinterpret_cast<jlong>(node);
227}
228
229static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
230        jboolean translucent, jlong rootRenderNodePtr) {
231    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
232    ContextFactoryImpl factory(rootRenderNode);
233    return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
234}
235
236static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
237        jlong proxyPtr) {
238    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
239    delete proxy;
240}
241
242static void android_view_ThreadedRenderer_setFrameInterval(JNIEnv* env, jobject clazz,
243        jlong proxyPtr, jlong frameIntervalNanos) {
244    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
245    proxy->setFrameInterval(frameIntervalNanos);
246}
247
248static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
249        jlong proxyPtr) {
250    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
251    return proxy->loadSystemProperties();
252}
253
254static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
255        jlong proxyPtr, jobject jsurface) {
256    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
257    sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
258    return proxy->initialize(window);
259}
260
261static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
262        jlong proxyPtr, jobject jsurface) {
263    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
264    sp<ANativeWindow> window;
265    if (jsurface) {
266        window = android_view_Surface_getNativeWindow(env, jsurface);
267    }
268    proxy->updateSurface(window);
269}
270
271static void android_view_ThreadedRenderer_pauseSurface(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->pauseSurface(window);
279}
280
281static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
282        jint width, jint height,
283        jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius,
284        jint ambientShadowAlpha, jint spotShadowAlpha) {
285    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
286    proxy->setup(width, height, (Vector3){lightX, lightY, lightZ}, lightRadius,
287            ambientShadowAlpha, spotShadowAlpha);
288}
289
290static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
291        jlong proxyPtr, jboolean opaque) {
292    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
293    proxy->setOpaque(opaque);
294}
295
296static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
297        jlong proxyPtr, jlong frameTimeNanos, jlong recordDuration, jfloat density) {
298    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
299    return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density);
300}
301
302static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
303        jlong proxyPtr) {
304    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
305    proxy->destroy();
306}
307
308static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
309        jlong rootNodePtr, jlong animatingNodePtr) {
310    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
311    RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
312    rootRenderNode->attachAnimatingNode(animatingNode);
313}
314
315static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
316        jlong functorPtr, jboolean waitForCompletion) {
317    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
318    RenderProxy::invokeFunctor(functor, waitForCompletion);
319}
320
321static jlong android_view_ThreadedRenderer_createDisplayListLayer(JNIEnv* env, jobject clazz,
322        jlong proxyPtr, jint width, jint height) {
323    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
324    DeferredLayerUpdater* layer = proxy->createDisplayListLayer(width, height);
325    return reinterpret_cast<jlong>(layer);
326}
327
328static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
329        jlong proxyPtr) {
330    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
331    DeferredLayerUpdater* layer = proxy->createTextureLayer();
332    return reinterpret_cast<jlong>(layer);
333}
334
335static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
336        jlong proxyPtr, jlong nodePtr) {
337    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
338    RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
339    proxy->buildLayer(node);
340}
341
342static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
343        jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
344    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
345    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
346    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
347    return proxy->copyLayerInto(layer, bitmap);
348}
349
350static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
351        jlong proxyPtr, jlong layerPtr) {
352    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
353    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
354    proxy->pushLayerUpdate(layer);
355}
356
357static void android_view_ThreadedRenderer_cancelLayerUpdate(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->cancelLayerUpdate(layer);
362}
363
364static void android_view_ThreadedRenderer_detachSurfaceTexture(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->detachSurfaceTexture(layer);
369}
370
371static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
372        jlong proxyPtr) {
373    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
374    proxy->destroyHardwareResources();
375}
376
377static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
378        jint level) {
379    RenderProxy::trimMemory(level);
380}
381
382static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
383        jlong proxyPtr) {
384    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
385    proxy->fence();
386}
387
388static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
389        jlong proxyPtr) {
390    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
391    proxy->stopDrawing();
392}
393
394static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
395        jlong proxyPtr) {
396    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
397    proxy->notifyFramePending();
398}
399
400static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
401        jlong proxyPtr, jobject javaFileDescriptor) {
402    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
403    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
404    proxy->dumpProfileInfo(fd);
405}
406
407#endif
408
409// ----------------------------------------------------------------------------
410// Shaders
411// ----------------------------------------------------------------------------
412
413static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
414        jstring diskCachePath) {
415
416    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
417    egl_cache_t::get()->setCacheFilename(cacheArray);
418    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
419}
420
421// ----------------------------------------------------------------------------
422// JNI Glue
423// ----------------------------------------------------------------------------
424
425const char* const kClassPathName = "android/view/ThreadedRenderer";
426
427static JNINativeMethod gMethods[] = {
428#ifdef USE_OPENGL_RENDERER
429    { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
430    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
431    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
432    { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
433    { "nSetFrameInterval", "(JJ)V", (void*) android_view_ThreadedRenderer_setFrameInterval },
434    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
435    { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
436    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
437    { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
438    { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
439    { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
440    { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
441    { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
442    { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
443    { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
444    { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
445    { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
446    { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
447    { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
448    { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
449    { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
450    { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
451    { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
452    { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
453    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
454    { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
455    { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
456    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
457#endif
458    { "setupShadersDiskCache", "(Ljava/lang/String;)V",
459                (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
460};
461
462int register_android_view_ThreadedRenderer(JNIEnv* env) {
463    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
464}
465
466}; // namespace android
467