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