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 <renderthread/RenderProxy.h> 37 38#include "core_jni_helpers.h" 39 40namespace android { 41 42using namespace uirenderer; 43 44jmethodID gRunnableMethodId; 45 46static JNIEnv* jnienv(JavaVM* vm) { 47 JNIEnv* env; 48 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { 49 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm); 50 } 51 return env; 52} 53 54class InvokeRunnableMessage : public MessageHandler { 55public: 56 InvokeRunnableMessage(JNIEnv* env, jobject runnable) { 57 mRunnable = env->NewGlobalRef(runnable); 58 env->GetJavaVM(&mVm); 59 } 60 61 virtual ~InvokeRunnableMessage() { 62 jnienv(mVm)->DeleteGlobalRef(mRunnable); 63 } 64 65 virtual void handleMessage(const Message&) { 66 jnienv(mVm)->CallVoidMethod(mRunnable, gRunnableMethodId); 67 } 68 69private: 70 JavaVM* mVm; 71 jobject mRunnable; 72}; 73 74class GlFunctorReleasedCallbackBridge : public GlFunctorLifecycleListener { 75public: 76 GlFunctorReleasedCallbackBridge(JNIEnv* env, jobject javaCallback) { 77 mLooper = Looper::getForThread(); 78 mMessage = new InvokeRunnableMessage(env, javaCallback); 79 } 80 81 virtual void onGlFunctorReleased(Functor* functor) override { 82 mLooper->sendMessage(mMessage, 0); 83 } 84 85private: 86 sp<Looper> mLooper; 87 sp<InvokeRunnableMessage> mMessage; 88}; 89 90// ---------------------------------------------------------------------------- 91// Setup 92// ---------------------------------------------------------------------------- 93 94static void android_view_DisplayListCanvas_insertReorderBarrier(JNIEnv* env, jobject clazz, 95 jlong canvasPtr, jboolean reorderEnable) { 96 Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr); 97 canvas->insertReorderBarrier(reorderEnable); 98} 99 100// ---------------------------------------------------------------------------- 101// Functor 102// ---------------------------------------------------------------------------- 103 104static 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// Misc 117// ---------------------------------------------------------------------------- 118 119static jint android_view_DisplayListCanvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) { 120 if (!Caches::hasInstance()) { 121 android::uirenderer::renderthread::RenderProxy::staticFence(); 122 } 123 return Caches::getInstance().maxTextureSize; 124} 125 126static jint android_view_DisplayListCanvas_getMaxTextureHeight(JNIEnv* env, jobject clazz) { 127 if (!Caches::hasInstance()) { 128 android::uirenderer::renderthread::RenderProxy::staticFence(); 129 } 130 return Caches::getInstance().maxTextureSize; 131} 132 133// ---------------------------------------------------------------------------- 134// Drawing 135// ---------------------------------------------------------------------------- 136 137static void android_view_DisplayListCanvas_drawRoundRectProps(JNIEnv* env, jobject clazz, 138 jlong canvasPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr, 139 jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) { 140 Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr); 141 CanvasPropertyPrimitive* leftProp = reinterpret_cast<CanvasPropertyPrimitive*>(leftPropPtr); 142 CanvasPropertyPrimitive* topProp = reinterpret_cast<CanvasPropertyPrimitive*>(topPropPtr); 143 CanvasPropertyPrimitive* rightProp = reinterpret_cast<CanvasPropertyPrimitive*>(rightPropPtr); 144 CanvasPropertyPrimitive* bottomProp = reinterpret_cast<CanvasPropertyPrimitive*>(bottomPropPtr); 145 CanvasPropertyPrimitive* rxProp = reinterpret_cast<CanvasPropertyPrimitive*>(rxPropPtr); 146 CanvasPropertyPrimitive* ryProp = reinterpret_cast<CanvasPropertyPrimitive*>(ryPropPtr); 147 CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr); 148 canvas->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp); 149} 150 151static void android_view_DisplayListCanvas_drawCircleProps(JNIEnv* env, jobject clazz, 152 jlong canvasPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) { 153 Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr); 154 CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr); 155 CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr); 156 CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr); 157 CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr); 158 canvas->drawCircle(xProp, yProp, radiusProp, paintProp); 159} 160 161// ---------------------------------------------------------------------------- 162// Display lists 163// ---------------------------------------------------------------------------- 164 165static jlong android_view_DisplayListCanvas_finishRecording(JNIEnv* env, 166 jobject clazz, jlong canvasPtr) { 167 Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr); 168 return reinterpret_cast<jlong>(canvas->finishRecording()); 169} 170 171static jlong android_view_DisplayListCanvas_createDisplayListCanvas(JNIEnv* env, jobject clazz, 172 jint width, jint height) { 173 return reinterpret_cast<jlong>(Canvas::create_recording_canvas(width, height)); 174} 175 176static void android_view_DisplayListCanvas_resetDisplayListCanvas(JNIEnv* env, jobject clazz, 177 jlong canvasPtr, jint width, jint height) { 178 Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr); 179 canvas->resetRecording(width, height); 180} 181 182 183static void android_view_DisplayListCanvas_drawRenderNode(JNIEnv* env, 184 jobject clazz, jlong canvasPtr, jlong renderNodePtr) { 185 Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr); 186 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 187 canvas->drawRenderNode(renderNode); 188} 189 190// ---------------------------------------------------------------------------- 191// Layers 192// ---------------------------------------------------------------------------- 193 194static void android_view_DisplayListCanvas_drawLayer(JNIEnv* env, jobject clazz, 195 jlong canvasPtr, jlong layerPtr) { 196 Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr); 197 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 198 canvas->drawLayer(layer); 199} 200 201// ---------------------------------------------------------------------------- 202// Common 203// ---------------------------------------------------------------------------- 204 205static jboolean android_view_DisplayListCanvas_isAvailable(JNIEnv* env, jobject clazz) { 206 char prop[PROPERTY_VALUE_MAX]; 207 if (property_get("ro.kernel.qemu", prop, NULL) == 0) { 208 // not in the emulator 209 return JNI_TRUE; 210 } 211 // In the emulator this property will be set > 0 when OpenGL ES 2.0 is 212 // enabled, 0 otherwise. On old emulator versions it will be undefined. 213 property_get("qemu.gles", prop, "0"); 214 return atoi(prop) > 0 ? JNI_TRUE : JNI_FALSE; 215} 216 217// ---------------------------------------------------------------------------- 218// Logging 219// ---------------------------------------------------------------------------- 220 221static void 222android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) { 223 int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor); 224 android::uirenderer::renderthread::RenderProxy::dumpGraphicsMemory(fd); 225} 226 227// ---------------------------------------------------------------------------- 228// JNI Glue 229// ---------------------------------------------------------------------------- 230 231const char* const kClassPathName = "android/view/DisplayListCanvas"; 232 233static JNINativeMethod gMethods[] = { 234 { "nIsAvailable", "!()Z", (void*) android_view_DisplayListCanvas_isAvailable }, 235 { "nInsertReorderBarrier","!(JZ)V", (void*) android_view_DisplayListCanvas_insertReorderBarrier }, 236 237 { "nCallDrawGLFunction", "!(JJLjava/lang/Runnable;)V", 238 (void*) android_view_DisplayListCanvas_callDrawGLFunction }, 239 240 { "nDrawRoundRect", "!(JJJJJJJJ)V", (void*) android_view_DisplayListCanvas_drawRoundRectProps }, 241 { "nDrawCircle", "!(JJJJJ)V", (void*) android_view_DisplayListCanvas_drawCircleProps }, 242 243 { "nFinishRecording", "!(J)J", (void*) android_view_DisplayListCanvas_finishRecording }, 244 { "nDrawRenderNode", "!(JJ)V", (void*) android_view_DisplayListCanvas_drawRenderNode }, 245 246 { "nCreateDisplayListCanvas", "!(II)J", (void*) android_view_DisplayListCanvas_createDisplayListCanvas }, 247 { "nResetDisplayListCanvas", "!(JII)V", (void*) android_view_DisplayListCanvas_resetDisplayListCanvas }, 248 249 { "nDrawLayer", "!(JJ)V", (void*) android_view_DisplayListCanvas_drawLayer }, 250 251 { "nGetMaximumTextureWidth", "!()I", (void*) android_view_DisplayListCanvas_getMaxTextureWidth }, 252 { "nGetMaximumTextureHeight", "!()I", (void*) android_view_DisplayListCanvas_getMaxTextureHeight }, 253}; 254 255static JNINativeMethod gActivityThreadMethods[] = { 256 { "dumpGraphicsInfo", "(Ljava/io/FileDescriptor;)V", 257 (void*) android_app_ActivityThread_dumpGraphics } 258}; 259 260int register_android_view_DisplayListCanvas(JNIEnv* env) { 261 jclass runnableClass = FindClassOrDie(env, "java/lang/Runnable"); 262 gRunnableMethodId = GetMethodIDOrDie(env, runnableClass, "run", "()V"); 263 264 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); 265} 266 267int register_android_app_ActivityThread(JNIEnv* env) { 268 return RegisterMethodsOrDie(env, "android/app/ActivityThread", 269 gActivityThreadMethods, NELEM(gActivityThreadMethods)); 270} 271 272}; 273