android_view_ThreadedRenderer.cpp revision a2732a2bf98f7dbd063f4e5679f5b8bfcbec2698
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 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 jboolean 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    return 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_createTextureLayer(JNIEnv* env, jobject clazz,
322        jlong proxyPtr) {
323    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
324    DeferredLayerUpdater* layer = proxy->createTextureLayer();
325    return reinterpret_cast<jlong>(layer);
326}
327
328static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
329        jlong proxyPtr, jlong nodePtr) {
330    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
331    RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
332    proxy->buildLayer(node);
333}
334
335static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
336        jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
337    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
338    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
339    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
340    return proxy->copyLayerInto(layer, bitmap);
341}
342
343static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
344        jlong proxyPtr, jlong layerPtr) {
345    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
346    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
347    proxy->pushLayerUpdate(layer);
348}
349
350static void android_view_ThreadedRenderer_cancelLayerUpdate(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->cancelLayerUpdate(layer);
355}
356
357static void android_view_ThreadedRenderer_detachSurfaceTexture(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->detachSurfaceTexture(layer);
362}
363
364static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
365        jlong proxyPtr) {
366    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
367    proxy->destroyHardwareResources();
368}
369
370static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
371        jint level) {
372    RenderProxy::trimMemory(level);
373}
374
375static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
376        jlong proxyPtr) {
377    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
378    proxy->fence();
379}
380
381static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
382        jlong proxyPtr) {
383    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
384    proxy->stopDrawing();
385}
386
387static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
388        jlong proxyPtr) {
389    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
390    proxy->notifyFramePending();
391}
392
393static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
394        jlong proxyPtr, jobject javaFileDescriptor) {
395    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
396    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
397    proxy->dumpProfileInfo(fd);
398}
399
400// ----------------------------------------------------------------------------
401// Shaders
402// ----------------------------------------------------------------------------
403
404static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
405        jstring diskCachePath) {
406
407    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
408    egl_cache_t::get()->setCacheFilename(cacheArray);
409    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
410}
411
412// ----------------------------------------------------------------------------
413// JNI Glue
414// ----------------------------------------------------------------------------
415
416const char* const kClassPathName = "android/view/ThreadedRenderer";
417
418static JNINativeMethod gMethods[] = {
419    { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
420    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
421    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
422    { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
423    { "nSetFrameInterval", "(JJ)V", (void*) android_view_ThreadedRenderer_setFrameInterval },
424    { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
425    { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
426    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
427    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
428    { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
429    { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
430    { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
431    { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
432    { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
433    { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
434    { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
435    { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
436    { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
437    { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
438    { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
439    { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
440    { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
441    { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
442    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
443    { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
444    { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
445    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
446    { "setupShadersDiskCache", "(Ljava/lang/String;)V",
447                (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
448};
449
450int register_android_view_ThreadedRenderer(JNIEnv* env) {
451    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
452}
453
454}; // namespace android
455