• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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