android_view_ThreadedRenderer.cpp revision b36016c65f1d1b5846dba0349aab491dbd3a746a
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
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
47using namespace android::uirenderer;
48using namespace android::uirenderer::renderthread;
49
50static JNIEnv* getenv(JavaVM* vm) {
51    JNIEnv* env;
52    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
53        LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
54    }
55    return env;
56}
57
58class OnFinishedEvent {
59public:
60    OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
61            : animator(animator), listener(listener) {}
62    sp<BaseRenderNodeAnimator> animator;
63    sp<AnimationListener> listener;
64};
65
66class InvokeAnimationListeners : public MessageHandler {
67public:
68    InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
69        mOnFinishedEvents.swap(events);
70    }
71
72    static void callOnFinished(OnFinishedEvent& event) {
73        event.listener->onAnimationFinished(event.animator.get());
74    }
75
76    virtual void handleMessage(const Message& message) {
77        std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
78        mOnFinishedEvents.clear();
79    }
80
81private:
82    std::vector<OnFinishedEvent> mOnFinishedEvents;
83};
84
85class RenderingException : public MessageHandler {
86public:
87    RenderingException(JavaVM* vm, const std::string& message)
88            : mVm(vm)
89            , mMessage(message) {
90    }
91
92    virtual void handleMessage(const Message&) {
93        throwException(mVm, mMessage);
94    }
95
96    static void throwException(JavaVM* vm, const std::string& message) {
97        JNIEnv* env = getenv(vm);
98        jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
99    }
100
101private:
102    JavaVM* mVm;
103    std::string mMessage;
104};
105
106class RootRenderNode : public RenderNode, ErrorHandler {
107public:
108    RootRenderNode(JNIEnv* env) : RenderNode() {
109        mLooper = Looper::getForThread();
110        LOG_ALWAYS_FATAL_IF(!mLooper.get(),
111                "Must create RootRenderNode on a thread with a looper!");
112        env->GetJavaVM(&mVm);
113    }
114
115    virtual ~RootRenderNode() {}
116
117    virtual void onError(const std::string& message) {
118        mLooper->sendMessage(new RenderingException(mVm, message), 0);
119    }
120
121    virtual void prepareTree(TreeInfo& info) {
122        info.errorHandler = this;
123        RenderNode::prepareTree(info);
124        info.errorHandler = NULL;
125    }
126
127    void sendMessage(const sp<MessageHandler>& handler) {
128        mLooper->sendMessage(handler, 0);
129    }
130
131    void attachAnimatingNode(RenderNode* animatingNode) {
132        mPendingAnimatingRenderNodes.push_back(animatingNode);
133    }
134
135    void doAttachAnimatingNodes(AnimationContext* context) {
136        for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
137            RenderNode* node = mPendingAnimatingRenderNodes[i].get();
138            context->addAnimatingRenderNode(*node);
139        }
140        mPendingAnimatingRenderNodes.clear();
141    }
142
143private:
144    sp<Looper> mLooper;
145    JavaVM* mVm;
146    std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
147};
148
149class AnimationContextBridge : public AnimationContext {
150public:
151    AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
152            : AnimationContext(clock), mRootNode(rootNode) {
153    }
154
155    virtual ~AnimationContextBridge() {}
156
157    // Marks the start of a frame, which will update the frame time and move all
158    // next frame animations into the current frame
159    virtual void startFrame(TreeInfo::TraversalMode mode) {
160        if (mode == TreeInfo::MODE_FULL) {
161            mRootNode->doAttachAnimatingNodes(this);
162        }
163        AnimationContext::startFrame(mode);
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 jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
243        jlong proxyPtr) {
244    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
245    return proxy->loadSystemProperties();
246}
247
248static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
249        jlong proxyPtr, jstring jname) {
250    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
251    const char* name = env->GetStringUTFChars(jname, NULL);
252    proxy->setName(name);
253    env->ReleaseStringUTFChars(jname, name);
254}
255
256static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
257        jlong proxyPtr, jobject jsurface) {
258    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
259    sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
260    return proxy->initialize(window);
261}
262
263static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
264        jlong proxyPtr, jobject jsurface) {
265    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
266    sp<ANativeWindow> window;
267    if (jsurface) {
268        window = android_view_Surface_getNativeWindow(env, jsurface);
269    }
270    proxy->updateSurface(window);
271}
272
273static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
274        jlong proxyPtr, jobject jsurface) {
275    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
276    sp<ANativeWindow> window;
277    if (jsurface) {
278        window = android_view_Surface_getNativeWindow(env, jsurface);
279    }
280    return proxy->pauseSurface(window);
281}
282
283static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
284        jint width, jint height,
285        jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius,
286        jint ambientShadowAlpha, jint spotShadowAlpha, jfloat density) {
287    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
288    proxy->setup(width, height, (Vector3){lightX, lightY, lightZ}, lightRadius,
289            ambientShadowAlpha, spotShadowAlpha);
290}
291
292static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
293        jlong proxyPtr, jboolean opaque) {
294    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
295    proxy->setOpaque(opaque);
296}
297
298static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
299        jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
300    LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
301            "Mismatched size expectations, given %d expected %d",
302            frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
303    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
304    env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
305    return proxy->syncAndDrawFrame();
306}
307
308static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
309        jlong proxyPtr) {
310    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
311    proxy->destroy();
312}
313
314static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
315        jlong rootNodePtr, jlong animatingNodePtr) {
316    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
317    RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
318    rootRenderNode->attachAnimatingNode(animatingNode);
319}
320
321static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
322        jlong functorPtr, jboolean waitForCompletion) {
323    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
324    RenderProxy::invokeFunctor(functor, waitForCompletion);
325}
326
327static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
328        jlong proxyPtr) {
329    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
330    DeferredLayerUpdater* layer = proxy->createTextureLayer();
331    return reinterpret_cast<jlong>(layer);
332}
333
334static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
335        jlong proxyPtr, jlong nodePtr) {
336    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
337    RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
338    proxy->buildLayer(node);
339}
340
341static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
342        jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
343    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
344    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
345    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
346    return proxy->copyLayerInto(layer, bitmap);
347}
348
349static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
350        jlong proxyPtr, jlong layerPtr) {
351    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
352    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
353    proxy->pushLayerUpdate(layer);
354}
355
356static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
357        jlong proxyPtr, jlong layerPtr) {
358    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
359    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
360    proxy->cancelLayerUpdate(layer);
361}
362
363static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
364        jlong proxyPtr, jlong layerPtr) {
365    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
366    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
367    proxy->detachSurfaceTexture(layer);
368}
369
370static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
371        jlong proxyPtr) {
372    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
373    proxy->destroyHardwareResources();
374}
375
376static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
377        jint level) {
378    RenderProxy::trimMemory(level);
379}
380
381static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
382        jlong proxyPtr) {
383    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
384    proxy->fence();
385}
386
387static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
388        jlong proxyPtr) {
389    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
390    proxy->stopDrawing();
391}
392
393static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
394        jlong proxyPtr) {
395    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
396    proxy->notifyFramePending();
397}
398
399static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
400        jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
401    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
402    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
403    proxy->dumpProfileInfo(fd, dumpFlags);
404}
405
406// ----------------------------------------------------------------------------
407// Shaders
408// ----------------------------------------------------------------------------
409
410static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
411        jstring diskCachePath) {
412
413    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
414    egl_cache_t::get()->setCacheFilename(cacheArray);
415    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
416}
417
418// ----------------------------------------------------------------------------
419// JNI Glue
420// ----------------------------------------------------------------------------
421
422const char* const kClassPathName = "android/view/ThreadedRenderer";
423
424static JNINativeMethod gMethods[] = {
425    { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
426    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
427    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
428    { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
429    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
430    { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
431    { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
432    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
433    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
434    { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
435    { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
436    { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
437    { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
438    { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
439    { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
440    { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
441    { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
442    { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
443    { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
444    { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
445    { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
446    { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
447    { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
448    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
449    { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
450    { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
451    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
452    { "setupShadersDiskCache", "(Ljava/lang/String;)V",
453                (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
454};
455
456int register_android_view_ThreadedRenderer(JNIEnv* env) {
457    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
458}
459
460}; // namespace android
461