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