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 <EGL/egl.h>
20
21 #include "jni.h"
22 #include "GraphicsJNI.h"
23 #include <nativehelper/JNIHelp.h>
24
25 #include <android_runtime/AndroidRuntime.h>
26 #include <android_runtime/android_graphics_SurfaceTexture.h>
27 #include <gui/GLConsumer.h>
28
29 #include <androidfw/ResourceTypes.h>
30
31 #include <private/hwui/DrawGlInfo.h>
32
33 #include <cutils/properties.h>
34
35 #include <SkBitmap.h>
36 #include <SkCanvas.h>
37 #include <SkMatrix.h>
38 #include <SkPaint.h>
39 #include <SkRegion.h>
40 #include <SkScalerContext.h>
41 #include <SkTemplates.h>
42 #include <SkXfermode.h>
43
44 #include <DisplayList.h>
45 #include <DisplayListRenderer.h>
46 #include <LayerRenderer.h>
47 #include <OpenGLRenderer.h>
48 #include <SkiaShader.h>
49 #include <SkiaColorFilter.h>
50 #include <Stencil.h>
51 #include <Rect.h>
52
53 #include <TextLayout.h>
54 #include <TextLayoutCache.h>
55
56 namespace android {
57
58 using namespace uirenderer;
59
60 /**
61 * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
62 * devices. This means all the logic must be compiled only when the
63 * preprocessor variable USE_OPENGL_RENDERER is defined.
64 */
65 #ifdef USE_OPENGL_RENDERER
66
67 // ----------------------------------------------------------------------------
68 // Defines
69 // ----------------------------------------------------------------------------
70
71 // Debug
72 #define DEBUG_RENDERER 0
73
74 // Debug
75 #if DEBUG_RENDERER
76 #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__)
77 #else
78 #define RENDERER_LOGD(...)
79 #endif
80
81 #define MODIFIER_SHADOW 1
82 #define MODIFIER_SHADER 2
83 #define MODIFIER_COLOR_FILTER 4
84
85 // ----------------------------------------------------------------------------
86
87 static struct {
88 jmethodID set;
89 } gRectClassInfo;
90
91 // ----------------------------------------------------------------------------
92 // Caching
93 // ----------------------------------------------------------------------------
94
android_view_GLES20Canvas_flushCaches(JNIEnv * env,jobject clazz,Caches::FlushMode mode)95 static void android_view_GLES20Canvas_flushCaches(JNIEnv* env, jobject clazz,
96 Caches::FlushMode mode) {
97 if (Caches::hasInstance()) {
98 Caches::getInstance().flush(mode);
99 }
100 }
101
android_view_GLES20Canvas_initCaches(JNIEnv * env,jobject clazz)102 static void android_view_GLES20Canvas_initCaches(JNIEnv* env, jobject clazz) {
103 if (Caches::hasInstance()) {
104 Caches::getInstance().init();
105 }
106 }
107
android_view_GLES20Canvas_terminateCaches(JNIEnv * env,jobject clazz)108 static void android_view_GLES20Canvas_terminateCaches(JNIEnv* env, jobject clazz) {
109 if (Caches::hasInstance()) {
110 Caches::getInstance().terminate();
111 }
112 }
113
114 // ----------------------------------------------------------------------------
115 // Constructors
116 // ----------------------------------------------------------------------------
117
android_view_GLES20Canvas_createRenderer(JNIEnv * env,jobject clazz)118 static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
119 RENDERER_LOGD("Create OpenGLRenderer");
120 OpenGLRenderer* renderer = new OpenGLRenderer();
121 renderer->initProperties();
122 return renderer;
123 }
124
android_view_GLES20Canvas_destroyRenderer(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer)125 static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
126 OpenGLRenderer* renderer) {
127 RENDERER_LOGD("Destroy OpenGLRenderer");
128 delete renderer;
129 }
130
131 // ----------------------------------------------------------------------------
132 // Setup
133 // ----------------------------------------------------------------------------
134
android_view_GLES20Canvas_setViewport(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jint width,jint height)135 static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz,
136 OpenGLRenderer* renderer, jint width, jint height) {
137 renderer->setViewport(width, height);
138 }
139
android_view_GLES20Canvas_prepare(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jboolean opaque)140 static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
141 OpenGLRenderer* renderer, jboolean opaque) {
142 return renderer->prepare(opaque);
143 }
144
android_view_GLES20Canvas_prepareDirty(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jint left,jint top,jint right,jint bottom,jboolean opaque)145 static int android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
146 OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom,
147 jboolean opaque) {
148 return renderer->prepareDirty(left, top, right, bottom, opaque);
149 }
150
android_view_GLES20Canvas_finish(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer)151 static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
152 OpenGLRenderer* renderer) {
153 renderer->finish();
154 }
155
android_view_GLES20Canvas_getStencilSize(JNIEnv * env,jobject clazz)156 static jint android_view_GLES20Canvas_getStencilSize(JNIEnv* env, jobject clazz) {
157 return Stencil::getStencilSize();
158 }
159
android_view_GLES20Canvas_setName(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jstring name)160 static void android_view_GLES20Canvas_setName(JNIEnv* env,
161 jobject clazz, OpenGLRenderer* renderer, jstring name) {
162 if (name != NULL) {
163 const char* textArray = env->GetStringUTFChars(name, NULL);
164 renderer->setName(textArray);
165 env->ReleaseStringUTFChars(name, textArray);
166 } else {
167 renderer->setName(NULL);
168 }
169 }
170
171 // ----------------------------------------------------------------------------
172 // Functor
173 // ----------------------------------------------------------------------------
174
android_view_GLES20Canvas_callDrawGLFunction(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,Functor * functor)175 static jint android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
176 OpenGLRenderer* renderer, Functor* functor) {
177 android::uirenderer::Rect dirty;
178 return renderer->callDrawGLFunction(functor, dirty);
179 }
180
android_view_GLES20Canvas_detachFunctor(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,Functor * functor)181 static void android_view_GLES20Canvas_detachFunctor(JNIEnv* env,
182 jobject clazz, OpenGLRenderer* renderer, Functor* functor) {
183 renderer->detachFunctor(functor);
184 }
185
android_view_GLES20Canvas_attachFunctor(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,Functor * functor)186 static void android_view_GLES20Canvas_attachFunctor(JNIEnv* env,
187 jobject clazz, OpenGLRenderer* renderer, Functor* functor) {
188 renderer->attachFunctor(functor);
189 }
190
android_view_GLES20Canvas_invokeFunctors(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jobject dirty)191 static jint android_view_GLES20Canvas_invokeFunctors(JNIEnv* env,
192 jobject clazz, OpenGLRenderer* renderer, jobject dirty) {
193 android::uirenderer::Rect bounds;
194 status_t status = renderer->invokeFunctors(bounds);
195 if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
196 env->CallVoidMethod(dirty, gRectClassInfo.set,
197 int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
198 }
199 return status;
200 }
201
202 // ----------------------------------------------------------------------------
203 // Misc
204 // ----------------------------------------------------------------------------
205
android_view_GLES20Canvas_getMaxTextureWidth(JNIEnv * env,jobject clazz)206 static jint android_view_GLES20Canvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) {
207 return Caches::getInstance().maxTextureSize;
208 }
209
android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv * env,jobject clazz)210 static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject clazz) {
211 return Caches::getInstance().maxTextureSize;
212 }
213
214 // ----------------------------------------------------------------------------
215 // State
216 // ----------------------------------------------------------------------------
217
android_view_GLES20Canvas_save(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jint flags)218 static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer,
219 jint flags) {
220 return renderer->save(flags);
221 }
222
android_view_GLES20Canvas_getSaveCount(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer)223 static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz,
224 OpenGLRenderer* renderer) {
225 return renderer->getSaveCount();
226 }
227
android_view_GLES20Canvas_restore(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer)228 static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz,
229 OpenGLRenderer* renderer) {
230 renderer->restore();
231 }
232
android_view_GLES20Canvas_restoreToCount(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jint saveCount)233 static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
234 OpenGLRenderer* renderer, jint saveCount) {
235 renderer->restoreToCount(saveCount);
236 }
237
238 // ----------------------------------------------------------------------------
239 // Layers
240 // ----------------------------------------------------------------------------
241
android_view_GLES20Canvas_saveLayer(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat left,jfloat top,jfloat right,jfloat bottom,SkPaint * paint,jint saveFlags)242 static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
243 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
244 SkPaint* paint, jint saveFlags) {
245 return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
246 }
247
android_view_GLES20Canvas_saveLayerClip(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkPaint * paint,jint saveFlags)248 static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
249 OpenGLRenderer* renderer, SkPaint* paint, jint saveFlags) {
250 const android::uirenderer::Rect& bounds(renderer->getClipBounds());
251 return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
252 paint, saveFlags);
253 }
254
android_view_GLES20Canvas_saveLayerAlpha(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat left,jfloat top,jfloat right,jfloat bottom,jint alpha,jint saveFlags)255 static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
256 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
257 jint alpha, jint saveFlags) {
258 return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
259 }
260
android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jint alpha,jint saveFlags)261 static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
262 OpenGLRenderer* renderer, jint alpha, jint saveFlags) {
263 const android::uirenderer::Rect& bounds(renderer->getClipBounds());
264 return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
265 alpha, saveFlags);
266 }
267
268 // ----------------------------------------------------------------------------
269 // Clipping
270 // ----------------------------------------------------------------------------
271
android_view_GLES20Canvas_quickReject(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat left,jfloat top,jfloat right,jfloat bottom)272 static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
273 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) {
274 return renderer->quickReject(left, top, right, bottom);
275 }
276
android_view_GLES20Canvas_clipRectF(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat left,jfloat top,jfloat right,jfloat bottom,SkRegion::Op op)277 static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
278 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
279 SkRegion::Op op) {
280 return renderer->clipRect(left, top, right, bottom, op);
281 }
282
android_view_GLES20Canvas_clipRect(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jint left,jint top,jint right,jint bottom,SkRegion::Op op)283 static bool android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
284 OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom,
285 SkRegion::Op op) {
286 return renderer->clipRect(float(left), float(top), float(right), float(bottom), op);
287 }
288
android_view_GLES20Canvas_clipPath(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkPath * path,SkRegion::Op op)289 static bool android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
290 OpenGLRenderer* renderer, SkPath* path, SkRegion::Op op) {
291 return renderer->clipPath(path, op);
292 }
293
android_view_GLES20Canvas_clipRegion(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkRegion * region,SkRegion::Op op)294 static bool android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
295 OpenGLRenderer* renderer, SkRegion* region, SkRegion::Op op) {
296 return renderer->clipRegion(region, op);
297 }
298
android_view_GLES20Canvas_getClipBounds(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jobject rect)299 static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
300 OpenGLRenderer* renderer, jobject rect) {
301 const android::uirenderer::Rect& bounds(renderer->getClipBounds());
302
303 env->CallVoidMethod(rect, gRectClassInfo.set,
304 int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
305
306 return !bounds.isEmpty();
307 }
308
309 // ----------------------------------------------------------------------------
310 // Transforms
311 // ----------------------------------------------------------------------------
312
android_view_GLES20Canvas_translate(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat dx,jfloat dy)313 static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz,
314 OpenGLRenderer* renderer, jfloat dx, jfloat dy) {
315 renderer->translate(dx, dy);
316 }
317
android_view_GLES20Canvas_rotate(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat degrees)318 static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz,
319 OpenGLRenderer* renderer, jfloat degrees) {
320 renderer->rotate(degrees);
321 }
322
android_view_GLES20Canvas_scale(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat sx,jfloat sy)323 static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz,
324 OpenGLRenderer* renderer, jfloat sx, jfloat sy) {
325 renderer->scale(sx, sy);
326 }
327
android_view_GLES20Canvas_skew(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat sx,jfloat sy)328 static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz,
329 OpenGLRenderer* renderer, jfloat sx, jfloat sy) {
330 renderer->skew(sx, sy);
331 }
332
android_view_GLES20Canvas_setMatrix(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkMatrix * matrix)333 static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz,
334 OpenGLRenderer* renderer, SkMatrix* matrix) {
335 renderer->setMatrix(matrix);
336 }
337
android_view_GLES20Canvas_getMatrix(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkMatrix * matrix)338 static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz,
339 OpenGLRenderer* renderer, SkMatrix* matrix) {
340 renderer->getMatrix(matrix);
341 }
342
android_view_GLES20Canvas_concatMatrix(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkMatrix * matrix)343 static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
344 OpenGLRenderer* renderer, SkMatrix* matrix) {
345 renderer->concatMatrix(matrix);
346 }
347
348 // ----------------------------------------------------------------------------
349 // Drawing
350 // ----------------------------------------------------------------------------
351
android_view_GLES20Canvas_drawBitmap(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkBitmap * bitmap,jbyteArray buffer,jfloat left,jfloat top,SkPaint * paint)352 static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
353 OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
354 jfloat left, jfloat top, SkPaint* paint) {
355 // This object allows the renderer to allocate a global JNI ref to the buffer object.
356 JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
357
358 renderer->drawBitmap(bitmap, left, top, paint);
359 }
360
android_view_GLES20Canvas_drawBitmapRect(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkBitmap * bitmap,jbyteArray buffer,float srcLeft,float srcTop,float srcRight,float srcBottom,float dstLeft,float dstTop,float dstRight,float dstBottom,SkPaint * paint)361 static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz,
362 OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
363 float srcLeft, float srcTop, float srcRight, float srcBottom,
364 float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint) {
365 // This object allows the renderer to allocate a global JNI ref to the buffer object.
366 JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
367
368 renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
369 dstLeft, dstTop, dstRight, dstBottom, paint);
370 }
371
android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkBitmap * bitmap,jbyteArray buffer,SkMatrix * matrix,SkPaint * paint)372 static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject clazz,
373 OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer, SkMatrix* matrix,
374 SkPaint* paint) {
375 // This object allows the renderer to allocate a global JNI ref to the buffer object.
376 JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
377
378 renderer->drawBitmap(bitmap, matrix, paint);
379 }
380
android_view_GLES20Canvas_drawBitmapData(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jintArray colors,jint offset,jint stride,jfloat left,jfloat top,jint width,jint height,jboolean hasAlpha,SkPaint * paint)381 static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
382 OpenGLRenderer* renderer, jintArray colors, jint offset, jint stride,
383 jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, SkPaint* paint) {
384 SkBitmap* bitmap = new SkBitmap;
385 bitmap->setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config : SkBitmap::kRGB_565_Config,
386 width, height);
387
388 if (!bitmap->allocPixels()) {
389 delete bitmap;
390 return;
391 }
392
393 if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap)) {
394 delete bitmap;
395 return;
396 }
397
398 renderer->drawBitmapData(bitmap, left, top, paint);
399
400 // If the renderer is a deferred renderer it will own the bitmap
401 if (!renderer->isDeferred()) {
402 delete bitmap;
403 }
404 }
405
android_view_GLES20Canvas_drawBitmapMesh(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkBitmap * bitmap,jbyteArray buffer,jint meshWidth,jint meshHeight,jfloatArray vertices,jint offset,jintArray colors,jint colorOffset,SkPaint * paint)406 static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
407 OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
408 jint meshWidth, jint meshHeight, jfloatArray vertices, jint offset,
409 jintArray colors, jint colorOffset, SkPaint* paint) {
410 // This object allows the renderer to allocate a global JNI ref to the buffer object.
411 JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
412
413 jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL;
414 jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
415
416 renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint);
417
418 if (vertices) env->ReleaseFloatArrayElements(vertices, verticesArray, 0);
419 if (colors) env->ReleaseIntArrayElements(colors, colorsArray, 0);
420 }
421
android_view_GLES20Canvas_drawPatch(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkBitmap * bitmap,jbyteArray buffer,jbyteArray chunks,float left,float top,float right,float bottom,SkPaint * paint)422 static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
423 OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer, jbyteArray chunks,
424 float left, float top, float right, float bottom, SkPaint* paint) {
425 // This object allows the renderer to allocate a global JNI ref to the buffer object.
426 JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
427
428 jbyte* storage = env->GetByteArrayElements(chunks, NULL);
429 Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(storage);
430 Res_png_9patch::deserialize(patch);
431
432 renderer->drawPatch(bitmap, &patch->xDivs[0], &patch->yDivs[0],
433 &patch->colors[0], patch->numXDivs, patch->numYDivs, patch->numColors,
434 left, top, right, bottom, paint);
435
436 env->ReleaseByteArrayElements(chunks, storage, 0);
437 }
438
android_view_GLES20Canvas_drawColor(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jint color,SkXfermode::Mode mode)439 static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
440 OpenGLRenderer* renderer, jint color, SkXfermode::Mode mode) {
441 renderer->drawColor(color, mode);
442 }
443
android_view_GLES20Canvas_drawRect(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat left,jfloat top,jfloat right,jfloat bottom,SkPaint * paint)444 static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
445 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
446 SkPaint* paint) {
447 renderer->drawRect(left, top, right, bottom, paint);
448 }
449
android_view_GLES20Canvas_drawRoundRect(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat left,jfloat top,jfloat right,jfloat bottom,jfloat rx,jfloat ry,SkPaint * paint)450 static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz,
451 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
452 jfloat rx, jfloat ry, SkPaint* paint) {
453 renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
454 }
455
android_view_GLES20Canvas_drawCircle(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat x,jfloat y,jfloat radius,SkPaint * paint)456 static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
457 OpenGLRenderer* renderer, jfloat x, jfloat y, jfloat radius, SkPaint* paint) {
458 renderer->drawCircle(x, y, radius, paint);
459 }
460
android_view_GLES20Canvas_drawOval(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat left,jfloat top,jfloat right,jfloat bottom,SkPaint * paint)461 static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
462 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
463 SkPaint* paint) {
464 renderer->drawOval(left, top, right, bottom, paint);
465 }
466
android_view_GLES20Canvas_drawArc(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat left,jfloat top,jfloat right,jfloat bottom,jfloat startAngle,jfloat sweepAngle,jboolean useCenter,SkPaint * paint)467 static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz,
468 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
469 jfloat startAngle, jfloat sweepAngle, jboolean useCenter, SkPaint* paint) {
470 renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
471 }
472
android_view_GLES20Canvas_drawRegionAsRects(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkRegion * region,SkPaint * paint)473 static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
474 OpenGLRenderer* renderer, SkRegion* region, SkPaint* paint) {
475 if (paint->getStyle() != SkPaint::kFill_Style ||
476 (paint->isAntiAlias() && !renderer->isCurrentTransformSimple())) {
477 SkRegion::Iterator it(*region);
478 while (!it.done()) {
479 const SkIRect& r = it.rect();
480 renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
481 it.next();
482 }
483 } else {
484 int count = 0;
485 Vector<float> rects;
486 SkRegion::Iterator it(*region);
487 while (!it.done()) {
488 const SkIRect& r = it.rect();
489 rects.push(r.fLeft);
490 rects.push(r.fTop);
491 rects.push(r.fRight);
492 rects.push(r.fBottom);
493 count += 4;
494 it.next();
495 }
496 renderer->drawRects(rects.array(), count, paint);
497 }
498 }
499
android_view_GLES20Canvas_drawRects(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloatArray rects,jint count,SkPaint * paint)500 static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject clazz,
501 OpenGLRenderer* renderer, jfloatArray rects, jint count, SkPaint* paint) {
502 jfloat* storage = env->GetFloatArrayElements(rects, NULL);
503 renderer->drawRects(storage, count, paint);
504 env->ReleaseFloatArrayElements(rects, storage, 0);
505 }
506
android_view_GLES20Canvas_drawPoints(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloatArray points,jint offset,jint count,SkPaint * paint)507 static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
508 OpenGLRenderer* renderer, jfloatArray points, jint offset, jint count, SkPaint* paint) {
509 jfloat* storage = env->GetFloatArrayElements(points, NULL);
510 renderer->drawPoints(storage + offset, count, paint);
511 env->ReleaseFloatArrayElements(points, storage, 0);
512 }
513
android_view_GLES20Canvas_drawPath(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkPath * path,SkPaint * paint)514 static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
515 OpenGLRenderer* renderer, SkPath* path, SkPaint* paint) {
516 renderer->drawPath(path, paint);
517 }
518
android_view_GLES20Canvas_drawLines(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloatArray points,jint offset,jint count,SkPaint * paint)519 static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
520 OpenGLRenderer* renderer, jfloatArray points, jint offset, jint count, SkPaint* paint) {
521 jfloat* storage = env->GetFloatArrayElements(points, NULL);
522 renderer->drawLines(storage + offset, count, paint);
523 env->ReleaseFloatArrayElements(points, storage, 0);
524 }
525
526 // ----------------------------------------------------------------------------
527 // Shaders and color filters
528 // ----------------------------------------------------------------------------
529
android_view_GLES20Canvas_resetModifiers(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jint modifiers)530 static void android_view_GLES20Canvas_resetModifiers(JNIEnv* env, jobject clazz,
531 OpenGLRenderer* renderer, jint modifiers) {
532 if (modifiers & MODIFIER_SHADOW) renderer->resetShadow();
533 if (modifiers & MODIFIER_SHADER) renderer->resetShader();
534 if (modifiers & MODIFIER_COLOR_FILTER) renderer->resetColorFilter();
535 }
536
android_view_GLES20Canvas_setupShader(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkiaShader * shader)537 static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject clazz,
538 OpenGLRenderer* renderer, SkiaShader* shader) {
539 renderer->setupShader(shader);
540 }
541
android_view_GLES20Canvas_setupColorFilter(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,SkiaColorFilter * filter)542 static void android_view_GLES20Canvas_setupColorFilter(JNIEnv* env, jobject clazz,
543 OpenGLRenderer* renderer, SkiaColorFilter* filter) {
544 renderer->setupColorFilter(filter);
545 }
546
android_view_GLES20Canvas_setupShadow(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jfloat radius,jfloat dx,jfloat dy,jint color)547 static void android_view_GLES20Canvas_setupShadow(JNIEnv* env, jobject clazz,
548 OpenGLRenderer* renderer, jfloat radius, jfloat dx, jfloat dy, jint color) {
549 renderer->setupShadow(radius, dx, dy, color);
550 }
551
552 // ----------------------------------------------------------------------------
553 // Draw filters
554 // ----------------------------------------------------------------------------
555
android_view_GLES20Canvas_setupPaintFilter(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jint clearBits,jint setBits)556 static void android_view_GLES20Canvas_setupPaintFilter(JNIEnv* env, jobject clazz,
557 OpenGLRenderer* renderer, jint clearBits, jint setBits) {
558 renderer->setupPaintFilter(clearBits, setBits);
559 }
560
android_view_GLES20Canvas_resetPaintFilter(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer)561 static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject clazz,
562 OpenGLRenderer* renderer) {
563 renderer->resetPaintFilter();
564 }
565
566 // ----------------------------------------------------------------------------
567 // Text
568 // ----------------------------------------------------------------------------
569
renderText(OpenGLRenderer * renderer,const jchar * text,int count,jfloat x,jfloat y,int flags,SkPaint * paint)570 static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
571 jfloat x, jfloat y, int flags, SkPaint* paint) {
572 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
573 text, 0, count, count, flags);
574 if (value == NULL) {
575 return;
576 }
577 const jchar* glyphs = value->getGlyphs();
578 size_t glyphsCount = value->getGlyphsCount();
579 jfloat totalAdvance = value->getTotalAdvance();
580 const float* positions = value->getPos();
581 int bytesCount = glyphsCount * sizeof(jchar);
582 renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y,
583 positions, paint, totalAdvance);
584 }
585
renderTextOnPath(OpenGLRenderer * renderer,const jchar * text,int count,SkPath * path,jfloat hOffset,jfloat vOffset,int flags,SkPaint * paint)586 static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
587 SkPath* path, jfloat hOffset, jfloat vOffset, int flags, SkPaint* paint) {
588 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
589 text, 0, count, count, flags);
590 if (value == NULL) {
591 return;
592 }
593 const jchar* glyphs = value->getGlyphs();
594 size_t glyphsCount = value->getGlyphsCount();
595 int bytesCount = glyphsCount * sizeof(jchar);
596 renderer->drawTextOnPath((const char*) glyphs, bytesCount, glyphsCount, path,
597 hOffset, vOffset, paint);
598 }
599
renderTextRun(OpenGLRenderer * renderer,const jchar * text,jint start,jint count,jint contextCount,jfloat x,jfloat y,int flags,SkPaint * paint)600 static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
601 jint start, jint count, jint contextCount, jfloat x, jfloat y,
602 int flags, SkPaint* paint) {
603 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
604 text, start, count, contextCount, flags);
605 if (value == NULL) {
606 return;
607 }
608 const jchar* glyphs = value->getGlyphs();
609 size_t glyphsCount = value->getGlyphsCount();
610 jfloat totalAdvance = value->getTotalAdvance();
611 const float* positions = value->getPos();
612 int bytesCount = glyphsCount * sizeof(jchar);
613 renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y,
614 positions, paint, totalAdvance);
615 }
616
android_view_GLES20Canvas_drawTextArray(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jcharArray text,jint index,jint count,jfloat x,jfloat y,jint flags,SkPaint * paint)617 static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
618 OpenGLRenderer* renderer, jcharArray text, jint index, jint count,
619 jfloat x, jfloat y, jint flags, SkPaint* paint) {
620 jchar* textArray = env->GetCharArrayElements(text, NULL);
621 renderText(renderer, textArray + index, count, x, y, flags, paint);
622 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
623 }
624
android_view_GLES20Canvas_drawText(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jstring text,jint start,jint end,jfloat x,jfloat y,jint flags,SkPaint * paint)625 static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
626 OpenGLRenderer* renderer, jstring text, jint start, jint end,
627 jfloat x, jfloat y, jint flags, SkPaint* paint) {
628 const jchar* textArray = env->GetStringChars(text, NULL);
629 renderText(renderer, textArray + start, end - start, x, y, flags, paint);
630 env->ReleaseStringChars(text, textArray);
631 }
632
android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jcharArray text,jint index,jint count,SkPath * path,jfloat hOffset,jfloat vOffset,jint flags,SkPaint * paint)633 static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
634 OpenGLRenderer* renderer, jcharArray text, jint index, jint count,
635 SkPath* path, jfloat hOffset, jfloat vOffset, jint flags, SkPaint* paint) {
636 jchar* textArray = env->GetCharArrayElements(text, NULL);
637 renderTextOnPath(renderer, textArray + index, count, path,
638 hOffset, vOffset, flags, paint);
639 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
640 }
641
android_view_GLES20Canvas_drawTextOnPath(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jstring text,jint start,jint end,SkPath * path,jfloat hOffset,jfloat vOffset,jint flags,SkPaint * paint)642 static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
643 OpenGLRenderer* renderer, jstring text, jint start, jint end,
644 SkPath* path, jfloat hOffset, jfloat vOffset, jint flags, SkPaint* paint) {
645 const jchar* textArray = env->GetStringChars(text, NULL);
646 renderTextOnPath(renderer, textArray + start, end - start, path,
647 hOffset, vOffset, flags, paint);
648 env->ReleaseStringChars(text, textArray);
649 }
650
android_view_GLES20Canvas_drawTextRunArray(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jcharArray text,jint index,jint count,jint contextIndex,jint contextCount,jfloat x,jfloat y,jint dirFlags,SkPaint * paint)651 static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
652 OpenGLRenderer* renderer, jcharArray text, jint index, jint count,
653 jint contextIndex, jint contextCount, jfloat x, jfloat y, jint dirFlags,
654 SkPaint* paint) {
655 jchar* textArray = env->GetCharArrayElements(text, NULL);
656 renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
657 count, contextCount, x, y, dirFlags, paint);
658 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
659 }
660
android_view_GLES20Canvas_drawTextRun(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jstring text,jint start,jint end,jint contextStart,int contextEnd,jfloat x,jfloat y,jint dirFlags,SkPaint * paint)661 static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
662 OpenGLRenderer* renderer, jstring text, jint start, jint end,
663 jint contextStart, int contextEnd, jfloat x, jfloat y, jint dirFlags,
664 SkPaint* paint) {
665 const jchar* textArray = env->GetStringChars(text, NULL);
666 jint count = end - start;
667 jint contextCount = contextEnd - contextStart;
668 renderTextRun(renderer, textArray + contextStart, start - contextStart,
669 count, contextCount, x, y, dirFlags, paint);
670 env->ReleaseStringChars(text, textArray);
671 }
672
renderPosText(OpenGLRenderer * renderer,const jchar * text,int count,const jfloat * positions,jint dirFlags,SkPaint * paint)673 static void renderPosText(OpenGLRenderer* renderer, const jchar* text, int count,
674 const jfloat* positions, jint dirFlags, SkPaint* paint) {
675 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
676 text, 0, count, count, dirFlags);
677 if (value == NULL) {
678 return;
679 }
680 const jchar* glyphs = value->getGlyphs();
681 size_t glyphsCount = value->getGlyphsCount();
682 if (count < int(glyphsCount)) glyphsCount = count;
683 int bytesCount = glyphsCount * sizeof(jchar);
684
685 renderer->drawPosText((const char*) glyphs, bytesCount, glyphsCount, positions, paint);
686 }
687
android_view_GLES20Canvas_drawPosTextArray(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jcharArray text,jint index,jint count,jfloatArray pos,SkPaint * paint)688 static void android_view_GLES20Canvas_drawPosTextArray(JNIEnv* env, jobject clazz,
689 OpenGLRenderer* renderer, jcharArray text, jint index, jint count,
690 jfloatArray pos, SkPaint* paint) {
691 jchar* textArray = env->GetCharArrayElements(text, NULL);
692 jfloat* positions = env->GetFloatArrayElements(pos, NULL);
693
694 renderPosText(renderer, textArray + index, count, positions, kBidi_LTR, paint);
695
696 env->ReleaseFloatArrayElements(pos, positions, JNI_ABORT);
697 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
698 }
699
android_view_GLES20Canvas_drawPosText(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,jstring text,jint start,jint end,jfloatArray pos,SkPaint * paint)700 static void android_view_GLES20Canvas_drawPosText(JNIEnv* env, jobject clazz,
701 OpenGLRenderer* renderer, jstring text, jint start, jint end,
702 jfloatArray pos, SkPaint* paint) {
703 const jchar* textArray = env->GetStringChars(text, NULL);
704 jfloat* positions = env->GetFloatArrayElements(pos, NULL);
705
706 renderPosText(renderer, textArray + start, end - start, positions, kBidi_LTR, paint);
707
708 env->ReleaseFloatArrayElements(pos, positions, JNI_ABORT);
709 env->ReleaseStringChars(text, textArray);
710 }
711
712 // ----------------------------------------------------------------------------
713 // Display lists
714 // ----------------------------------------------------------------------------
715
android_view_GLES20Canvas_getDisplayList(JNIEnv * env,jobject clazz,DisplayListRenderer * renderer,DisplayList * displayList)716 static DisplayList* android_view_GLES20Canvas_getDisplayList(JNIEnv* env,
717 jobject clazz, DisplayListRenderer* renderer, DisplayList* displayList) {
718 return renderer->getDisplayList(displayList);
719 }
720
android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv * env,jobject clazz)721 static OpenGLRenderer* android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env,
722 jobject clazz) {
723 return new DisplayListRenderer;
724 }
725
android_view_GLES20Canvas_resetDisplayListRenderer(JNIEnv * env,jobject clazz,DisplayListRenderer * renderer)726 static void android_view_GLES20Canvas_resetDisplayListRenderer(JNIEnv* env,
727 jobject clazz, DisplayListRenderer* renderer) {
728 renderer->reset();
729 }
730
android_view_GLES20Canvas_drawDisplayList(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,DisplayList * displayList,jobject dirty,jint flags)731 static jint android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
732 jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList,
733 jobject dirty, jint flags) {
734 android::uirenderer::Rect bounds;
735 status_t status = renderer->drawDisplayList(displayList, bounds, flags);
736 if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
737 env->CallVoidMethod(dirty, gRectClassInfo.set,
738 int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
739 }
740 return status;
741 }
742
android_view_GLES20Canvas_outputDisplayList(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,DisplayList * displayList)743 static void android_view_GLES20Canvas_outputDisplayList(JNIEnv* env,
744 jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList) {
745 renderer->outputDisplayList(displayList);
746 }
747
748 // ----------------------------------------------------------------------------
749 // Layers
750 // ----------------------------------------------------------------------------
751
android_view_GLES20Canvas_interrupt(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer)752 static void android_view_GLES20Canvas_interrupt(JNIEnv* env, jobject clazz,
753 OpenGLRenderer* renderer) {
754 renderer->interrupt();
755 }
756
android_view_GLES20Canvas_resume(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer)757 static void android_view_GLES20Canvas_resume(JNIEnv* env, jobject clazz,
758 OpenGLRenderer* renderer) {
759 renderer->resume();
760 }
761
android_view_GLES20Canvas_createLayerRenderer(JNIEnv * env,jobject clazz,Layer * layer)762 static OpenGLRenderer* android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env,
763 jobject clazz, Layer* layer) {
764 if (layer) {
765 OpenGLRenderer* renderer = new LayerRenderer(layer);
766 renderer->initProperties();
767 return renderer;
768 }
769 return NULL;
770 }
771
android_view_GLES20Canvas_createTextureLayer(JNIEnv * env,jobject clazz,jboolean isOpaque,jintArray layerInfo)772 static Layer* android_view_GLES20Canvas_createTextureLayer(JNIEnv* env, jobject clazz,
773 jboolean isOpaque, jintArray layerInfo) {
774 Layer* layer = LayerRenderer::createTextureLayer(isOpaque);
775
776 if (layer) {
777 jint* storage = env->GetIntArrayElements(layerInfo, NULL);
778 storage[0] = layer->getTexture();
779 env->ReleaseIntArrayElements(layerInfo, storage, 0);
780 }
781
782 return layer;
783 }
784
android_view_GLES20Canvas_createLayer(JNIEnv * env,jobject clazz,jint width,jint height,jboolean isOpaque,jintArray layerInfo)785 static Layer* android_view_GLES20Canvas_createLayer(JNIEnv* env, jobject clazz,
786 jint width, jint height, jboolean isOpaque, jintArray layerInfo) {
787 Layer* layer = LayerRenderer::createLayer(width, height, isOpaque);
788
789 if (layer) {
790 jint* storage = env->GetIntArrayElements(layerInfo, NULL);
791 storage[0] = layer->getWidth();
792 storage[1] = layer->getHeight();
793 env->ReleaseIntArrayElements(layerInfo, storage, 0);
794 }
795
796 return layer;
797 }
798
android_view_GLES20Canvas_resizeLayer(JNIEnv * env,jobject clazz,Layer * layer,jint width,jint height,jintArray layerInfo)799 static bool android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz,
800 Layer* layer, jint width, jint height, jintArray layerInfo) {
801 if (LayerRenderer::resizeLayer(layer, width, height)) {
802 jint* storage = env->GetIntArrayElements(layerInfo, NULL);
803 storage[0] = layer->getWidth();
804 storage[1] = layer->getHeight();
805 env->ReleaseIntArrayElements(layerInfo, storage, 0);
806 return true;
807 }
808 return false;
809 }
810
android_view_GLES20Canvas_setLayerPaint(JNIEnv * env,jobject clazz,Layer * layer,SkPaint * paint)811 static void android_view_GLES20Canvas_setLayerPaint(JNIEnv* env, jobject clazz,
812 Layer* layer, SkPaint* paint) {
813 if (layer) {
814 layer->setPaint(paint);
815 }
816 }
817
android_view_GLES20Canvas_setLayerColorFilter(JNIEnv * env,jobject clazz,Layer * layer,SkiaColorFilter * colorFilter)818 static void android_view_GLES20Canvas_setLayerColorFilter(JNIEnv* env, jobject clazz,
819 Layer* layer, SkiaColorFilter* colorFilter) {
820 if (layer) {
821 layer->setColorFilter(colorFilter);
822 }
823 }
824
android_view_GLES20Canvas_setOpaqueLayer(JNIEnv * env,jobject clazz,Layer * layer,jboolean isOpaque)825 static void android_view_GLES20Canvas_setOpaqueLayer(JNIEnv* env, jobject clazz,
826 Layer* layer, jboolean isOpaque) {
827 if (layer) {
828 layer->setBlend(!isOpaque);
829 }
830 }
831
android_view_GLES20Canvas_updateTextureLayer(JNIEnv * env,jobject clazz,Layer * layer,jint width,jint height,jboolean isOpaque,jobject surface)832 static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz,
833 Layer* layer, jint width, jint height, jboolean isOpaque, jobject surface) {
834 float transform[16];
835 sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
836
837 if (surfaceTexture->updateTexImage() == NO_ERROR) {
838 surfaceTexture->getTransformMatrix(transform);
839 GLenum renderTarget = surfaceTexture->getCurrentTextureTarget();
840
841 LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform);
842 }
843 }
844
android_view_GLES20Canvas_updateRenderLayer(JNIEnv * env,jobject clazz,Layer * layer,OpenGLRenderer * renderer,DisplayList * displayList,jint left,jint top,jint right,jint bottom)845 static void android_view_GLES20Canvas_updateRenderLayer(JNIEnv* env, jobject clazz,
846 Layer* layer, OpenGLRenderer* renderer, DisplayList* displayList,
847 jint left, jint top, jint right, jint bottom) {
848 layer->updateDeferred(renderer, displayList, left, top, right, bottom);
849 }
850
android_view_GLES20Canvas_clearLayerTexture(JNIEnv * env,jobject clazz,Layer * layer)851 static void android_view_GLES20Canvas_clearLayerTexture(JNIEnv* env, jobject clazz,
852 Layer* layer) {
853 layer->clearTexture();
854 }
855
android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv * env,jobject clazz,Layer * layer,SkMatrix * matrix)856 static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz,
857 Layer* layer, SkMatrix* matrix) {
858 layer->getTransform().load(*matrix);
859 }
860
android_view_GLES20Canvas_destroyLayer(JNIEnv * env,jobject clazz,Layer * layer)861 static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, Layer* layer) {
862 LayerRenderer::destroyLayer(layer);
863 }
864
android_view_GLES20Canvas_destroyLayerDeferred(JNIEnv * env,jobject clazz,Layer * layer)865 static void android_view_GLES20Canvas_destroyLayerDeferred(JNIEnv* env,
866 jobject clazz, Layer* layer) {
867 LayerRenderer::destroyLayerDeferred(layer);
868 }
869
android_view_GLES20Canvas_drawLayer(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,Layer * layer,jfloat x,jfloat y)870 static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
871 OpenGLRenderer* renderer, Layer* layer, jfloat x, jfloat y) {
872 renderer->drawLayer(layer, x, y);
873 }
874
android_view_GLES20Canvas_copyLayer(JNIEnv * env,jobject clazz,Layer * layer,SkBitmap * bitmap)875 static jboolean android_view_GLES20Canvas_copyLayer(JNIEnv* env, jobject clazz,
876 Layer* layer, SkBitmap* bitmap) {
877 return LayerRenderer::copyLayer(layer, bitmap);
878 }
879
android_view_GLES20Canvas_pushLayerUpdate(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer,Layer * layer)880 static void android_view_GLES20Canvas_pushLayerUpdate(JNIEnv* env, jobject clazz,
881 OpenGLRenderer* renderer, Layer* layer) {
882 renderer->pushLayerUpdate(layer);
883 }
884
android_view_GLES20Canvas_clearLayerUpdates(JNIEnv * env,jobject clazz,OpenGLRenderer * renderer)885 static void android_view_GLES20Canvas_clearLayerUpdates(JNIEnv* env, jobject clazz,
886 OpenGLRenderer* renderer) {
887 renderer->clearLayerUpdates();
888 }
889
890 #endif // USE_OPENGL_RENDERER
891
892 // ----------------------------------------------------------------------------
893 // Common
894 // ----------------------------------------------------------------------------
895
android_view_GLES20Canvas_isAvailable(JNIEnv * env,jobject clazz)896 static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz) {
897 #ifdef USE_OPENGL_RENDERER
898 char prop[PROPERTY_VALUE_MAX];
899 if (property_get("ro.kernel.qemu", prop, NULL) == 0) {
900 // not in the emulator
901 return JNI_TRUE;
902 }
903 // In the emulator this property will be set to 1 when hardware GLES is
904 // enabled, 0 otherwise. On old emulator versions it will be undefined.
905 property_get("ro.kernel.qemu.gles", prop, "0");
906 return atoi(prop) == 1 ? JNI_TRUE : JNI_FALSE;
907 #else
908 return JNI_FALSE;
909 #endif
910 }
911
912 // ----------------------------------------------------------------------------
913 // Logging
914 // ----------------------------------------------------------------------------
915
916 static void
android_app_ActivityThread_dumpGraphics(JNIEnv * env,jobject clazz,jobject javaFileDescriptor)917 android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
918 #ifdef USE_OPENGL_RENDERER
919 int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
920 android::uirenderer::DisplayList::outputLogBuffer(fd);
921 #endif // USE_OPENGL_RENDERER
922 }
923
924 // ----------------------------------------------------------------------------
925 // JNI Glue
926 // ----------------------------------------------------------------------------
927
928 const char* const kClassPathName = "android/view/GLES20Canvas";
929
930 static JNINativeMethod gMethods[] = {
931 { "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable },
932
933 #ifdef USE_OPENGL_RENDERER
934 { "nFlushCaches", "(I)V", (void*) android_view_GLES20Canvas_flushCaches },
935 { "nInitCaches", "()V", (void*) android_view_GLES20Canvas_initCaches },
936 { "nTerminateCaches", "()V", (void*) android_view_GLES20Canvas_terminateCaches },
937
938 { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer },
939 { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer },
940 { "nSetViewport", "(III)V", (void*) android_view_GLES20Canvas_setViewport },
941 { "nPrepare", "(IZ)I", (void*) android_view_GLES20Canvas_prepare },
942 { "nPrepareDirty", "(IIIIIZ)I", (void*) android_view_GLES20Canvas_prepareDirty },
943 { "nFinish", "(I)V", (void*) android_view_GLES20Canvas_finish },
944 { "nSetName", "(ILjava/lang/String;)V",
945 (void*) android_view_GLES20Canvas_setName },
946
947 { "nGetStencilSize", "()I", (void*) android_view_GLES20Canvas_getStencilSize },
948
949 { "nCallDrawGLFunction", "(II)I", (void*) android_view_GLES20Canvas_callDrawGLFunction },
950 { "nDetachFunctor", "(II)V", (void*) android_view_GLES20Canvas_detachFunctor },
951 { "nAttachFunctor", "(II)V", (void*) android_view_GLES20Canvas_attachFunctor },
952 { "nInvokeFunctors", "(ILandroid/graphics/Rect;)I",
953 (void*) android_view_GLES20Canvas_invokeFunctors },
954
955 { "nSave", "(II)I", (void*) android_view_GLES20Canvas_save },
956 { "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore },
957 { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Canvas_restoreToCount },
958 { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Canvas_getSaveCount },
959
960 { "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayer },
961 { "nSaveLayer", "(III)I", (void*) android_view_GLES20Canvas_saveLayerClip },
962 { "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayerAlpha },
963 { "nSaveLayerAlpha", "(III)I", (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
964
965 { "nQuickReject", "(IFFFF)Z", (void*) android_view_GLES20Canvas_quickReject },
966 { "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF },
967 { "nClipRect", "(IIIIII)Z", (void*) android_view_GLES20Canvas_clipRect },
968 { "nClipPath", "(III)Z", (void*) android_view_GLES20Canvas_clipPath },
969 { "nClipRegion", "(III)Z", (void*) android_view_GLES20Canvas_clipRegion },
970
971 { "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate },
972 { "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate },
973 { "nScale", "(IFF)V", (void*) android_view_GLES20Canvas_scale },
974 { "nSkew", "(IFF)V", (void*) android_view_GLES20Canvas_skew },
975
976 { "nSetMatrix", "(II)V", (void*) android_view_GLES20Canvas_setMatrix },
977 { "nGetMatrix", "(II)V", (void*) android_view_GLES20Canvas_getMatrix },
978 { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Canvas_concatMatrix },
979
980 { "nDrawBitmap", "(II[BFFI)V", (void*) android_view_GLES20Canvas_drawBitmap },
981 { "nDrawBitmap", "(II[BFFFFFFFFI)V",(void*) android_view_GLES20Canvas_drawBitmapRect },
982 { "nDrawBitmap", "(II[BII)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix },
983 { "nDrawBitmap", "(I[IIIFFIIZI)V", (void*) android_view_GLES20Canvas_drawBitmapData },
984
985 { "nDrawBitmapMesh", "(II[BII[FI[III)V",(void*) android_view_GLES20Canvas_drawBitmapMesh },
986
987 { "nDrawPatch", "(II[B[BFFFFI)V", (void*) android_view_GLES20Canvas_drawPatch },
988
989 { "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor },
990 { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect },
991 { "nDrawRects", "(III)V", (void*) android_view_GLES20Canvas_drawRegionAsRects },
992 { "nDrawRects", "(I[FII)V", (void*) android_view_GLES20Canvas_drawRects },
993 { "nDrawRoundRect", "(IFFFFFFI)V", (void*) android_view_GLES20Canvas_drawRoundRect },
994 { "nDrawCircle", "(IFFFI)V", (void*) android_view_GLES20Canvas_drawCircle },
995 { "nDrawOval", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawOval },
996 { "nDrawArc", "(IFFFFFFZI)V", (void*) android_view_GLES20Canvas_drawArc },
997 { "nDrawPoints", "(I[FIII)V", (void*) android_view_GLES20Canvas_drawPoints },
998
999 { "nDrawPath", "(III)V", (void*) android_view_GLES20Canvas_drawPath },
1000 { "nDrawLines", "(I[FIII)V", (void*) android_view_GLES20Canvas_drawLines },
1001
1002 { "nResetModifiers", "(II)V", (void*) android_view_GLES20Canvas_resetModifiers },
1003 { "nSetupShader", "(II)V", (void*) android_view_GLES20Canvas_setupShader },
1004 { "nSetupColorFilter", "(II)V", (void*) android_view_GLES20Canvas_setupColorFilter },
1005 { "nSetupShadow", "(IFFFI)V", (void*) android_view_GLES20Canvas_setupShadow },
1006
1007 { "nSetupPaintFilter", "(III)V", (void*) android_view_GLES20Canvas_setupPaintFilter },
1008 { "nResetPaintFilter", "(I)V", (void*) android_view_GLES20Canvas_resetPaintFilter },
1009
1010 { "nDrawText", "(I[CIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArray },
1011 { "nDrawText", "(ILjava/lang/String;IIFFII)V",
1012 (void*) android_view_GLES20Canvas_drawText },
1013
1014 { "nDrawTextOnPath", "(I[CIIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
1015 { "nDrawTextOnPath", "(ILjava/lang/String;IIIFFII)V",
1016 (void*) android_view_GLES20Canvas_drawTextOnPath },
1017
1018 { "nDrawTextRun", "(I[CIIIIFFII)V", (void*) android_view_GLES20Canvas_drawTextRunArray },
1019 { "nDrawTextRun", "(ILjava/lang/String;IIIIFFII)V",
1020 (void*) android_view_GLES20Canvas_drawTextRun },
1021
1022 { "nDrawPosText", "(I[CII[FI)V", (void*) android_view_GLES20Canvas_drawPosTextArray },
1023 { "nDrawPosText", "(ILjava/lang/String;II[FI)V",
1024 (void*) android_view_GLES20Canvas_drawPosText },
1025
1026 { "nGetClipBounds", "(ILandroid/graphics/Rect;)Z",
1027 (void*) android_view_GLES20Canvas_getClipBounds },
1028
1029 { "nGetDisplayList", "(II)I", (void*) android_view_GLES20Canvas_getDisplayList },
1030 { "nOutputDisplayList", "(II)V", (void*) android_view_GLES20Canvas_outputDisplayList },
1031 { "nDrawDisplayList", "(IILandroid/graphics/Rect;I)I",
1032 (void*) android_view_GLES20Canvas_drawDisplayList },
1033
1034 { "nCreateDisplayListRenderer", "()I", (void*) android_view_GLES20Canvas_createDisplayListRenderer },
1035 { "nResetDisplayListRenderer", "(I)V", (void*) android_view_GLES20Canvas_resetDisplayListRenderer },
1036
1037 { "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt },
1038 { "nResume", "(I)V", (void*) android_view_GLES20Canvas_resume },
1039
1040 { "nCreateLayerRenderer", "(I)I", (void*) android_view_GLES20Canvas_createLayerRenderer },
1041 { "nCreateLayer", "(IIZ[I)I", (void*) android_view_GLES20Canvas_createLayer },
1042 { "nResizeLayer", "(III[I)Z" , (void*) android_view_GLES20Canvas_resizeLayer },
1043 { "nSetLayerPaint", "(II)V", (void*) android_view_GLES20Canvas_setLayerPaint },
1044 { "nSetLayerColorFilter", "(II)V", (void*) android_view_GLES20Canvas_setLayerColorFilter },
1045 { "nSetOpaqueLayer", "(IZ)V", (void*) android_view_GLES20Canvas_setOpaqueLayer },
1046 { "nCreateTextureLayer", "(Z[I)I", (void*) android_view_GLES20Canvas_createTextureLayer },
1047 { "nUpdateTextureLayer", "(IIIZLandroid/graphics/SurfaceTexture;)V",
1048 (void*) android_view_GLES20Canvas_updateTextureLayer },
1049 { "nUpdateRenderLayer", "(IIIIIII)V", (void*) android_view_GLES20Canvas_updateRenderLayer },
1050 { "nClearLayerTexture", "(I)V", (void*) android_view_GLES20Canvas_clearLayerTexture },
1051 { "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer },
1052 { "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred },
1053 { "nDrawLayer", "(IIFF)V", (void*) android_view_GLES20Canvas_drawLayer },
1054 { "nCopyLayer", "(II)Z", (void*) android_view_GLES20Canvas_copyLayer },
1055 { "nClearLayerUpdates", "(I)V", (void*) android_view_GLES20Canvas_clearLayerUpdates },
1056 { "nPushLayerUpdate", "(II)V", (void*) android_view_GLES20Canvas_pushLayerUpdate },
1057
1058 { "nSetTextureLayerTransform", "(II)V", (void*) android_view_GLES20Canvas_setTextureLayerTransform },
1059
1060 { "nGetMaximumTextureWidth", "()I", (void*) android_view_GLES20Canvas_getMaxTextureWidth },
1061 { "nGetMaximumTextureHeight", "()I", (void*) android_view_GLES20Canvas_getMaxTextureHeight },
1062
1063 #endif
1064 };
1065
1066 static JNINativeMethod gActivityThreadMethods[] = {
1067 { "dumpGraphicsInfo", "(Ljava/io/FileDescriptor;)V",
1068 (void*) android_app_ActivityThread_dumpGraphics }
1069 };
1070
1071
1072 #ifdef USE_OPENGL_RENDERER
1073 #define FIND_CLASS(var, className) \
1074 var = env->FindClass(className); \
1075 LOG_FATAL_IF(! var, "Unable to find class " className);
1076
1077 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
1078 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
1079 LOG_FATAL_IF(! var, "Unable to find method " methodName);
1080 #else
1081 #define FIND_CLASS(var, className)
1082 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor)
1083 #endif
1084
register_android_view_GLES20Canvas(JNIEnv * env)1085 int register_android_view_GLES20Canvas(JNIEnv* env) {
1086 jclass clazz;
1087 FIND_CLASS(clazz, "android/graphics/Rect");
1088 GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V");
1089
1090 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
1091 }
1092
1093 const char* const kActivityThreadPathName = "android/app/ActivityThread";
1094
register_android_app_ActivityThread(JNIEnv * env)1095 int register_android_app_ActivityThread(JNIEnv* env) {
1096 return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName,
1097 gActivityThreadMethods, NELEM(gActivityThreadMethods));
1098 }
1099
1100 };
1101