Home | History | Annotate | Download | only in jni
      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 
     45 namespace android {
     46 
     47 #ifdef USE_OPENGL_RENDERER
     48 
     49 using namespace android::uirenderer;
     50 using namespace android::uirenderer::renderthread;
     51 
     52 static 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 
     60 class OnFinishedEvent {
     61 public:
     62     OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
     63             : animator(animator), listener(listener) {}
     64     sp<BaseRenderNodeAnimator> animator;
     65     sp<AnimationListener> listener;
     66 };
     67 
     68 class InvokeAnimationListeners : public MessageHandler {
     69 public:
     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 
     83 private:
     84     std::vector<OnFinishedEvent> mOnFinishedEvents;
     85 };
     86 
     87 class RenderingException : public MessageHandler {
     88 public:
     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 
    103 private:
    104     JavaVM* mVm;
    105     std::string mMessage;
    106 };
    107 
    108 class RootRenderNode : public RenderNode, ErrorHandler {
    109 public:
    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 
    145 private:
    146     sp<Looper> mLooper;
    147     JavaVM* mVm;
    148     std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
    149 };
    150 
    151 class AnimationContextBridge : public AnimationContext {
    152 public:
    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 
    184 private:
    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 
    197 class ContextFactoryImpl : public IContextFactory {
    198 public:
    199     ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
    200 
    201     virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
    202         return new AnimationContextBridge(clock, mRootNode);
    203     }
    204 
    205 private:
    206     RootRenderNode* mRootNode;
    207 };
    208 
    209 static 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 
    224 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
    225     RootRenderNode* node = new RootRenderNode(env);
    226     node->incStrong(0);
    227     node->setName("RootRenderNode");
    228     return reinterpret_cast<jlong>(node);
    229 }
    230 
    231 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
    232         jboolean translucent, jlong rootRenderNodePtr) {
    233     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
    234     ContextFactoryImpl factory(rootRenderNode);
    235     return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
    236 }
    237 
    238 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
    239         jlong proxyPtr) {
    240     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    241     delete proxy;
    242 }
    243 
    244 static void android_view_ThreadedRenderer_setFrameInterval(JNIEnv* env, jobject clazz,
    245         jlong proxyPtr, jlong frameIntervalNanos) {
    246     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    247     proxy->setFrameInterval(frameIntervalNanos);
    248 }
    249 
    250 static 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 
    256 static 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 
    263 static 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 
    273 static 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 
    283 static 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) {
    287     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    288     proxy->setup(width, height, (Vector3){lightX, lightY, lightZ}, lightRadius,
    289             ambientShadowAlpha, spotShadowAlpha);
    290 }
    291 
    292 static 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 
    298 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
    299         jlong proxyPtr, jlong frameTimeNanos, jlong recordDuration, jfloat density) {
    300     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    301     return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density);
    302 }
    303 
    304 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
    305         jlong proxyPtr) {
    306     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    307     proxy->destroy();
    308 }
    309 
    310 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
    311         jlong rootNodePtr, jlong animatingNodePtr) {
    312     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
    313     RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
    314     rootRenderNode->attachAnimatingNode(animatingNode);
    315 }
    316 
    317 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
    318         jlong functorPtr, jboolean waitForCompletion) {
    319     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
    320     RenderProxy::invokeFunctor(functor, waitForCompletion);
    321 }
    322 
    323 static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
    324         jlong proxyPtr) {
    325     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    326     DeferredLayerUpdater* layer = proxy->createTextureLayer();
    327     return reinterpret_cast<jlong>(layer);
    328 }
    329 
    330 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
    331         jlong proxyPtr, jlong nodePtr) {
    332     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    333     RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
    334     proxy->buildLayer(node);
    335 }
    336 
    337 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
    338         jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
    339     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    340     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
    341     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
    342     return proxy->copyLayerInto(layer, bitmap);
    343 }
    344 
    345 static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
    346         jlong proxyPtr, jlong layerPtr) {
    347     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    348     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
    349     proxy->pushLayerUpdate(layer);
    350 }
    351 
    352 static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
    353         jlong proxyPtr, jlong layerPtr) {
    354     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    355     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
    356     proxy->cancelLayerUpdate(layer);
    357 }
    358 
    359 static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
    360         jlong proxyPtr, jlong layerPtr) {
    361     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    362     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
    363     proxy->detachSurfaceTexture(layer);
    364 }
    365 
    366 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
    367         jlong proxyPtr) {
    368     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    369     proxy->destroyHardwareResources();
    370 }
    371 
    372 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
    373         jint level) {
    374     RenderProxy::trimMemory(level);
    375 }
    376 
    377 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
    378         jlong proxyPtr) {
    379     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    380     proxy->fence();
    381 }
    382 
    383 static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
    384         jlong proxyPtr) {
    385     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    386     proxy->stopDrawing();
    387 }
    388 
    389 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
    390         jlong proxyPtr) {
    391     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    392     proxy->notifyFramePending();
    393 }
    394 
    395 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
    396         jlong proxyPtr, jobject javaFileDescriptor) {
    397     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    398     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
    399     proxy->dumpProfileInfo(fd);
    400 }
    401 
    402 #endif
    403 
    404 // ----------------------------------------------------------------------------
    405 // Shaders
    406 // ----------------------------------------------------------------------------
    407 
    408 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
    409         jstring diskCachePath) {
    410 
    411     const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
    412     egl_cache_t::get()->setCacheFilename(cacheArray);
    413     env->ReleaseStringUTFChars(diskCachePath, cacheArray);
    414 }
    415 
    416 // ----------------------------------------------------------------------------
    417 // JNI Glue
    418 // ----------------------------------------------------------------------------
    419 
    420 const char* const kClassPathName = "android/view/ThreadedRenderer";
    421 
    422 static JNINativeMethod gMethods[] = {
    423 #ifdef USE_OPENGL_RENDERER
    424     { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
    425     { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
    426     { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
    427     { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
    428     { "nSetFrameInterval", "(JJ)V", (void*) android_view_ThreadedRenderer_setFrameInterval },
    429     { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
    430     { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
    431     { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
    432     { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
    433     { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
    434     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
    435     { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
    436     { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
    437     { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
    438     { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
    439     { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
    440     { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
    441     { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
    442     { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
    443     { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
    444     { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
    445     { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
    446     { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
    447     { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
    448     { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
    449     { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
    450     { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
    451 #endif
    452     { "setupShadersDiskCache", "(Ljava/lang/String;)V",
    453                 (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
    454 };
    455 
    456 int register_android_view_ThreadedRenderer(JNIEnv* env) {
    457     return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
    458 }
    459 
    460 }; // namespace android
    461