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 "OpenGLRenderer"
     18 
     19 #include "jni.h"
     20 #include "GraphicsJNI.h"
     21 #include <nativehelper/JNIHelp.h>
     22 
     23 #include <android_runtime/AndroidRuntime.h>
     24 
     25 #include <utils/Looper.h>
     26 #include <cutils/properties.h>
     27 
     28 #include <SkBitmap.h>
     29 #include <SkRegion.h>
     30 
     31 #include <Rect.h>
     32 #include <RenderNode.h>
     33 #include <CanvasProperty.h>
     34 #include <hwui/Canvas.h>
     35 #include <hwui/Paint.h>
     36 #include <minikin/Layout.h>
     37 #include <renderthread/RenderProxy.h>
     38 
     39 #include "core_jni_helpers.h"
     40 
     41 namespace android {
     42 
     43 using namespace uirenderer;
     44 
     45 jmethodID gRunnableMethodId;
     46 
     47 static JNIEnv* jnienv(JavaVM* vm) {
     48     JNIEnv* env;
     49     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
     50         LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
     51     }
     52     return env;
     53 }
     54 
     55 class InvokeRunnableMessage : public MessageHandler {
     56 public:
     57     InvokeRunnableMessage(JNIEnv* env, jobject runnable) {
     58         mRunnable = env->NewGlobalRef(runnable);
     59         env->GetJavaVM(&mVm);
     60     }
     61 
     62     virtual ~InvokeRunnableMessage() {
     63         jnienv(mVm)->DeleteGlobalRef(mRunnable);
     64     }
     65 
     66     virtual void handleMessage(const Message&) {
     67         jnienv(mVm)->CallVoidMethod(mRunnable, gRunnableMethodId);
     68     }
     69 
     70 private:
     71     JavaVM* mVm;
     72     jobject mRunnable;
     73 };
     74 
     75 class GlFunctorReleasedCallbackBridge : public GlFunctorLifecycleListener {
     76 public:
     77     GlFunctorReleasedCallbackBridge(JNIEnv* env, jobject javaCallback) {
     78         mLooper = Looper::getForThread();
     79         mMessage = new InvokeRunnableMessage(env, javaCallback);
     80     }
     81 
     82     virtual void onGlFunctorReleased(Functor* functor) override {
     83         mLooper->sendMessage(mMessage, 0);
     84     }
     85 
     86 private:
     87     sp<Looper> mLooper;
     88     sp<InvokeRunnableMessage> mMessage;
     89 };
     90 
     91 
     92 // ---------------- Regular JNI -----------------------------
     93 
     94 static void
     95 android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
     96     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
     97     android::uirenderer::renderthread::RenderProxy::dumpGraphicsMemory(fd);
     98     minikin::Layout::dumpMinikinStats(fd);
     99 }
    100 
    101 
    102 // ---------------- @FastNative -----------------------------
    103 
    104 static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
    105         jlong canvasPtr, jlong functorPtr, jobject releasedCallback) {
    106     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
    107     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
    108     sp<GlFunctorReleasedCallbackBridge> bridge;
    109     if (releasedCallback) {
    110         bridge = new GlFunctorReleasedCallbackBridge(env, releasedCallback);
    111     }
    112     canvas->callDrawGLFunction(functor, bridge.get());
    113 }
    114 
    115 
    116 // ---------------- @CriticalNative -------------------------
    117 
    118 static jlong android_view_DisplayListCanvas_createDisplayListCanvas(jlong renderNodePtr,
    119         jint width, jint height) {
    120     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
    121     return reinterpret_cast<jlong>(Canvas::create_recording_canvas(width, height, renderNode));
    122 }
    123 
    124 static void android_view_DisplayListCanvas_resetDisplayListCanvas(jlong canvasPtr,
    125         jlong renderNodePtr, jint width, jint height) {
    126     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
    127     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
    128     canvas->resetRecording(width, height, renderNode);
    129 }
    130 
    131 static jint android_view_DisplayListCanvas_getMaxTextureWidth() {
    132     if (!Caches::hasInstance()) {
    133         android::uirenderer::renderthread::RenderProxy::staticFence();
    134     }
    135     return Caches::getInstance().maxTextureSize;
    136 }
    137 
    138 static jint android_view_DisplayListCanvas_getMaxTextureHeight() {
    139     if (!Caches::hasInstance()) {
    140         android::uirenderer::renderthread::RenderProxy::staticFence();
    141     }
    142     return Caches::getInstance().maxTextureSize;
    143 }
    144 
    145 static void android_view_DisplayListCanvas_insertReorderBarrier(jlong canvasPtr,
    146         jboolean reorderEnable) {
    147     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
    148     canvas->insertReorderBarrier(reorderEnable);
    149 }
    150 
    151 static jlong android_view_DisplayListCanvas_finishRecording(jlong canvasPtr) {
    152     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
    153     return reinterpret_cast<jlong>(canvas->finishRecording());
    154 }
    155 
    156 static void android_view_DisplayListCanvas_drawRenderNode(jlong canvasPtr, jlong renderNodePtr) {
    157     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
    158     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
    159     canvas->drawRenderNode(renderNode);
    160 }
    161 
    162 static void android_view_DisplayListCanvas_drawTextureLayer(jlong canvasPtr, jlong layerPtr) {
    163     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
    164     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
    165     canvas->drawLayer(layer);
    166 }
    167 
    168 static void android_view_DisplayListCanvas_drawRoundRectProps(jlong canvasPtr,
    169         jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr, jlong bottomPropPtr,
    170         jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) {
    171     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
    172     CanvasPropertyPrimitive* leftProp = reinterpret_cast<CanvasPropertyPrimitive*>(leftPropPtr);
    173     CanvasPropertyPrimitive* topProp = reinterpret_cast<CanvasPropertyPrimitive*>(topPropPtr);
    174     CanvasPropertyPrimitive* rightProp = reinterpret_cast<CanvasPropertyPrimitive*>(rightPropPtr);
    175     CanvasPropertyPrimitive* bottomProp = reinterpret_cast<CanvasPropertyPrimitive*>(bottomPropPtr);
    176     CanvasPropertyPrimitive* rxProp = reinterpret_cast<CanvasPropertyPrimitive*>(rxPropPtr);
    177     CanvasPropertyPrimitive* ryProp = reinterpret_cast<CanvasPropertyPrimitive*>(ryPropPtr);
    178     CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
    179     canvas->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp);
    180 }
    181 
    182 static void android_view_DisplayListCanvas_drawCircleProps(jlong canvasPtr,
    183         jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
    184     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
    185     CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
    186     CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
    187     CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
    188     CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
    189     canvas->drawCircle(xProp, yProp, radiusProp, paintProp);
    190 }
    191 
    192 // ----------------------------------------------------------------------------
    193 // JNI Glue
    194 // ----------------------------------------------------------------------------
    195 
    196 const char* const kClassPathName = "android/view/DisplayListCanvas";
    197 
    198 static JNINativeMethod gMethods[] = {
    199 
    200     // ------------ @FastNative ------------------
    201 
    202     { "nCallDrawGLFunction", "(JJLjava/lang/Runnable;)V",
    203             (void*) android_view_DisplayListCanvas_callDrawGLFunction },
    204 
    205     // ------------ @CriticalNative --------------
    206     { "nCreateDisplayListCanvas", "(JII)J",     (void*) android_view_DisplayListCanvas_createDisplayListCanvas },
    207     { "nResetDisplayListCanvas",  "(JJII)V",    (void*) android_view_DisplayListCanvas_resetDisplayListCanvas },
    208     { "nGetMaximumTextureWidth",  "()I",        (void*) android_view_DisplayListCanvas_getMaxTextureWidth },
    209     { "nGetMaximumTextureHeight", "()I",        (void*) android_view_DisplayListCanvas_getMaxTextureHeight },
    210     { "nInsertReorderBarrier",    "(JZ)V",      (void*) android_view_DisplayListCanvas_insertReorderBarrier },
    211     { "nFinishRecording",         "(J)J",       (void*) android_view_DisplayListCanvas_finishRecording },
    212     { "nDrawRenderNode",          "(JJ)V",      (void*) android_view_DisplayListCanvas_drawRenderNode },
    213     { "nDrawTextureLayer",        "(JJ)V",      (void*) android_view_DisplayListCanvas_drawTextureLayer },
    214     { "nDrawCircle",              "(JJJJJ)V",   (void*) android_view_DisplayListCanvas_drawCircleProps },
    215     { "nDrawRoundRect",           "(JJJJJJJJ)V",(void*) android_view_DisplayListCanvas_drawRoundRectProps },
    216 };
    217 
    218 static JNINativeMethod gActivityThreadMethods[] = {
    219         // ------------ Regular JNI ------------------
    220     { "nDumpGraphicsInfo",        "(Ljava/io/FileDescriptor;)V",
    221                                                (void*) android_app_ActivityThread_dumpGraphics }
    222 };
    223 
    224 int register_android_view_DisplayListCanvas(JNIEnv* env) {
    225     jclass runnableClass = FindClassOrDie(env, "java/lang/Runnable");
    226     gRunnableMethodId = GetMethodIDOrDie(env, runnableClass, "run", "()V");
    227 
    228     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
    229 }
    230 
    231 int register_android_app_ActivityThread(JNIEnv* env) {
    232     return RegisterMethodsOrDie(env, "android/app/ActivityThread",
    233             gActivityThreadMethods, NELEM(gActivityThreadMethods));
    234 }
    235 
    236 };
    237