android_view_GLES20Canvas.cpp revision 4de3f481bc59ab4b766dc027e41aff7cda9d62f7
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "OpenGLRenderer"
18
19#include "jni.h"
20#include "GraphicsJNI.h"
21#include <nativehelper/JNIHelp.h>
22
23#include "android_view_GraphicBuffer.h"
24
25#include <android_runtime/AndroidRuntime.h>
26#include <android_runtime/android_graphics_SurfaceTexture.h>
27
28#include <androidfw/ResourceTypes.h>
29
30#include <gui/GLConsumer.h>
31
32#include <private/hwui/DrawGlInfo.h>
33
34#include <cutils/properties.h>
35
36#include <SkBitmap.h>
37#include <SkCanvas.h>
38#include <SkMatrix.h>
39#include <SkPaint.h>
40#include <SkRegion.h>
41#include <SkScalerContext.h>
42#include <SkTemplates.h>
43#include <SkXfermode.h>
44
45#include <DisplayList.h>
46#include <DisplayListRenderer.h>
47#include <LayerRenderer.h>
48#include <OpenGLRenderer.h>
49#include <SkiaShader.h>
50#include <SkiaColorFilter.h>
51#include <Stencil.h>
52#include <Rect.h>
53
54#include <TextLayout.h>
55#include <TextLayoutCache.h>
56
57namespace android {
58
59using namespace uirenderer;
60
61/**
62 * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
63 *       devices. This means all the logic must be compiled only when the
64 *       preprocessor variable USE_OPENGL_RENDERER is defined.
65 */
66#ifdef USE_OPENGL_RENDERER
67
68// ----------------------------------------------------------------------------
69// Defines
70// ----------------------------------------------------------------------------
71
72// Debug
73#define DEBUG_RENDERER 0
74
75// Debug
76#if DEBUG_RENDERER
77    #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__)
78#else
79    #define RENDERER_LOGD(...)
80#endif
81
82#define MODIFIER_SHADOW 1
83#define MODIFIER_SHADER 2
84#define MODIFIER_COLOR_FILTER 4
85
86// ----------------------------------------------------------------------------
87
88static struct {
89    jmethodID set;
90} gRectClassInfo;
91
92// ----------------------------------------------------------------------------
93// Caching
94// ----------------------------------------------------------------------------
95
96static void android_view_GLES20Canvas_flushCaches(JNIEnv* env, jobject clazz,
97        jint mode) {
98    if (Caches::hasInstance()) {
99        Caches::getInstance().flush(static_cast<Caches::FlushMode>(mode));
100    }
101}
102
103static jboolean android_view_GLES20Canvas_initCaches(JNIEnv* env, jobject clazz) {
104    if (Caches::hasInstance()) {
105        return Caches::getInstance().init() ? JNI_TRUE : JNI_FALSE;
106    }
107    return JNI_FALSE;
108}
109
110static void android_view_GLES20Canvas_terminateCaches(JNIEnv* env, jobject clazz) {
111    if (Caches::hasInstance()) {
112        Caches::getInstance().terminate();
113    }
114}
115
116// ----------------------------------------------------------------------------
117// Caching
118// ----------------------------------------------------------------------------
119
120static void android_view_GLES20Canvas_initAtlas(JNIEnv* env, jobject clazz,
121        jobject graphicBuffer, jlongArray atlasMapArray, jint count) {
122
123    sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
124    jlong* jAtlasMap = env->GetLongArrayElements(atlasMapArray, NULL);
125    Caches::getInstance().assetAtlas.init(buffer, jAtlasMap, count);
126    env->ReleaseLongArrayElements(atlasMapArray, jAtlasMap, 0);
127}
128
129// ----------------------------------------------------------------------------
130// Constructors
131// ----------------------------------------------------------------------------
132
133static jlong android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
134    RENDERER_LOGD("Create OpenGLRenderer");
135    OpenGLRenderer* renderer = new OpenGLRenderer();
136    renderer->initProperties();
137    return reinterpret_cast<jlong>(renderer);
138}
139
140static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
141        jlong rendererHandle) {
142    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
143    RENDERER_LOGD("Destroy OpenGLRenderer");
144    delete renderer;
145}
146
147// ----------------------------------------------------------------------------
148// Setup
149// ----------------------------------------------------------------------------
150
151static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz,
152        jlong rendererHandle, jint width, jint height) {
153    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
154    renderer->setViewport(width, height);
155}
156
157static jint android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
158        jlong rendererHandle, jboolean opaque) {
159    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
160    return renderer->prepare(opaque);
161}
162
163static jint android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
164        jlong rendererHandle, jint left, jint top, jint right, jint bottom,
165        jboolean opaque) {
166    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
167    return renderer->prepareDirty(left, top, right, bottom, opaque);
168}
169
170static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
171        jlong rendererHandle) {
172    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
173    renderer->finish();
174}
175
176static jint android_view_GLES20Canvas_getStencilSize(JNIEnv* env, jobject clazz) {
177    return Stencil::getStencilSize();
178}
179
180static void android_view_GLES20Canvas_setName(JNIEnv* env,
181        jobject clazz, jlong rendererHandle, jstring name) {
182    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
183    if (name != NULL) {
184        const char* textArray = env->GetStringUTFChars(name, NULL);
185        renderer->setName(textArray);
186        env->ReleaseStringUTFChars(name, textArray);
187    } else {
188        renderer->setName(NULL);
189    }
190}
191
192static void android_view_GLES20Canvas_setCountOverdrawEnabled(JNIEnv* env, jobject clazz,
193        jlong rendererHandle, jboolean enabled) {
194    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
195    renderer->setCountOverdrawEnabled(enabled);
196}
197
198static jfloat android_view_GLES20Canvas_getOverdraw(JNIEnv* env, jobject clazz,
199        jlong rendererHandle) {
200    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
201    return renderer->getOverdraw();
202}
203
204// ----------------------------------------------------------------------------
205// Functor
206// ----------------------------------------------------------------------------
207
208static jint android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
209        jlong rendererHandle, jlong functorHandle) {
210    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
211    Functor* functor = reinterpret_cast<Functor*>(functorHandle);
212    android::uirenderer::Rect dirty;
213    return renderer->callDrawGLFunction(functor, dirty);
214}
215
216static void android_view_GLES20Canvas_detachFunctor(JNIEnv* env,
217        jobject clazz, jlong rendererHandle, jlong functorHandle) {
218    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
219    Functor* functor = reinterpret_cast<Functor*>(functorHandle);
220    renderer->detachFunctor(functor);
221}
222
223static void android_view_GLES20Canvas_attachFunctor(JNIEnv* env,
224        jobject clazz, jlong rendererHandle, jlong functorHandle) {
225    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
226    Functor* functor = reinterpret_cast<Functor*>(functorHandle);
227    renderer->attachFunctor(functor);
228}
229
230static jint android_view_GLES20Canvas_invokeFunctors(JNIEnv* env,
231        jobject clazz, jlong rendererHandle, jobject dirty) {
232    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
233    android::uirenderer::Rect bounds;
234    status_t status = renderer->invokeFunctors(bounds);
235    if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
236        env->CallVoidMethod(dirty, gRectClassInfo.set,
237                int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
238    }
239    return status;
240}
241
242// ----------------------------------------------------------------------------
243// Misc
244// ----------------------------------------------------------------------------
245
246static jint android_view_GLES20Canvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) {
247    return Caches::getInstance().maxTextureSize;
248}
249
250static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject clazz) {
251    return Caches::getInstance().maxTextureSize;
252}
253
254// ----------------------------------------------------------------------------
255// State
256// ----------------------------------------------------------------------------
257
258static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, jlong rendererHandle,
259        jint flags) {
260    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
261    return renderer->save(flags);
262}
263
264static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz,
265        jlong rendererHandle) {
266    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
267    return renderer->getSaveCount();
268}
269
270static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz,
271        jlong rendererHandle) {
272    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
273    renderer->restore();
274}
275
276static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
277        jlong rendererHandle, jint saveCount) {
278    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
279    renderer->restoreToCount(saveCount);
280}
281
282// ----------------------------------------------------------------------------
283// Layers
284// ----------------------------------------------------------------------------
285
286static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
287        jlong rendererHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
288        jlong paintHandle, jint saveFlags) {
289    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
290    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
291    return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
292}
293
294static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
295        jlong rendererHandle, jlong paintHandle, jint saveFlags) {
296    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
297    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
298    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
299    return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
300            paint, saveFlags);
301}
302
303static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
304        jlong rendererHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
305        jint alpha, jint saveFlags) {
306    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
307    return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
308}
309
310static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
311        jlong rendererHandle, jint alpha, jint saveFlags) {
312    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
313    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
314    return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
315            alpha, saveFlags);
316}
317
318// ----------------------------------------------------------------------------
319// Clipping
320// ----------------------------------------------------------------------------
321
322static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
323        jlong rendererHandle, jfloat left, jfloat top, jfloat right, jfloat bottom) {
324    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
325    bool result = renderer->quickRejectNoScissor(left, top, right, bottom);
326    return result ? JNI_TRUE : JNI_FALSE;
327}
328
329static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
330        jlong rendererHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
331        jint opHandle) {
332    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
333    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
334    bool result;
335    result = renderer->clipRect(left, top, right, bottom, op);
336    return result ? JNI_TRUE : JNI_FALSE;
337}
338
339static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
340        jlong rendererHandle, jint left, jint top, jint right, jint bottom,
341        jint opHandle) {
342    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
343    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
344    bool result = renderer->clipRect(float(left), float(top), float(right), float(bottom), op);
345    return result ? JNI_TRUE : JNI_FALSE;
346}
347
348static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
349        jlong rendererHandle, jlong pathHandle, jint opHandle) {
350    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
351    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
352    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
353    return renderer->clipPath(path, op) ? JNI_TRUE : JNI_FALSE;
354}
355
356static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
357        jlong rendererHandle, jlong regionHandle, jint opHandle) {
358    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
359    SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
360    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
361    return renderer->clipRegion(region, op) ? JNI_TRUE : JNI_FALSE;
362}
363
364static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
365        jlong rendererHandle, jobject rect) {
366    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
367    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
368
369    env->CallVoidMethod(rect, gRectClassInfo.set,
370            int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
371
372    return !bounds.isEmpty() ? JNI_TRUE : JNI_FALSE;
373}
374
375// ----------------------------------------------------------------------------
376// Transforms
377// ----------------------------------------------------------------------------
378
379static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz,
380        jlong rendererHandle, jfloat dx, jfloat dy) {
381    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
382    renderer->translate(dx, dy);
383}
384
385static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz,
386        jlong rendererHandle, jfloat degrees) {
387    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
388    renderer->rotate(degrees);
389}
390
391static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz,
392        jlong rendererHandle, jfloat sx, jfloat sy) {
393    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
394    renderer->scale(sx, sy);
395}
396
397static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz,
398        jlong rendererHandle, jfloat sx, jfloat sy) {
399    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
400    renderer->skew(sx, sy);
401}
402
403static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz,
404        jlong rendererHandle, jlong matrixHandle) {
405    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
406    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
407    renderer->setMatrix(matrix);
408}
409
410static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz,
411        jlong rendererHandle, jlong matrixHandle) {
412    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
413    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
414    renderer->getMatrix(matrix);
415}
416
417static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
418        jlong rendererHandle, jlong matrixHandle) {
419    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
420    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
421    renderer->concatMatrix(matrix);
422}
423
424// ----------------------------------------------------------------------------
425// Drawing
426// ----------------------------------------------------------------------------
427
428static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
429        jlong rendererHandle, jlong bitmapHandle, jbyteArray buffer,
430        jfloat left, jfloat top, jlong paintHandle) {
431    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
432    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
433    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
434    // This object allows the renderer to allocate a global JNI ref to the buffer object.
435    JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
436
437    renderer->drawBitmap(bitmap, left, top, paint);
438}
439
440static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz,
441        jlong rendererHandle, jlong bitmapHandle, jbyteArray buffer,
442        jfloat srcLeft, jfloat srcTop, jfloat srcRight, jfloat srcBottom,
443        jfloat dstLeft, jfloat dstTop, jfloat dstRight, jfloat dstBottom, jlong paintHandle) {
444    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
445    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
446    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
447    // This object allows the renderer to allocate a global JNI ref to the buffer object.
448    JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
449
450    renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
451            dstLeft, dstTop, dstRight, dstBottom, paint);
452}
453
454static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject clazz,
455        jlong rendererHandle, jlong bitmapHandle, jbyteArray buffer,
456        jlong matrixHandle, jlong paintHandle) {
457    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
458    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
459    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
460    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
461    // This object allows the renderer to allocate a global JNI ref to the buffer object.
462    JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
463
464    renderer->drawBitmap(bitmap, matrix, paint);
465}
466
467static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
468        jlong rendererHandle, jintArray colors, jint offset, jint stride,
469        jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, jlong paintHandle) {
470    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
471    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
472    SkBitmap* bitmap = new SkBitmap;
473    bitmap->setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config : SkBitmap::kRGB_565_Config,
474            width, height);
475
476    if (!bitmap->allocPixels()) {
477        delete bitmap;
478        return;
479    }
480
481    if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap, true)) {
482        delete bitmap;
483        return;
484    }
485
486    renderer->drawBitmapData(bitmap, left, top, paint);
487
488    // If the renderer is a deferred renderer it will own the bitmap
489    if (!renderer->isDeferred()) {
490        delete bitmap;
491    }
492}
493
494static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
495        jlong rendererHandle, jlong bitmapHandle, jbyteArray buffer,
496        jint meshWidth, jint meshHeight, jfloatArray vertices, jint offset, jintArray colors,
497        jint colorOffset, jlong paintHandle) {
498    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
499    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
500    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
501    // This object allows the renderer to allocate a global JNI ref to the buffer object.
502    JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
503
504    jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL;
505    jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
506
507    renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint);
508
509    if (vertices) env->ReleaseFloatArrayElements(vertices, verticesArray, 0);
510    if (colors) env->ReleaseIntArrayElements(colors, colorsArray, 0);
511}
512
513static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
514        jlong rendererHandle, jlong bitmapHandle, jbyteArray buffer, jlong patchHandle,
515        jfloat left, jfloat top, jfloat right, jfloat bottom, jlong paintHandle) {
516    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
517    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
518    Res_png_9patch* patch  = reinterpret_cast<Res_png_9patch*>(patchHandle);
519    SkPaint* paint  = reinterpret_cast<SkPaint*>(paintHandle);
520
521    // This object allows the renderer to allocate a global JNI ref to the buffer object.
522    JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
523
524    renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
525}
526
527static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
528        jlong rendererHandle, jint color, SkXfermode::Mode mode) {
529    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
530    renderer->drawColor(color, mode);
531}
532
533static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
534        jlong rendererHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
535        jlong paintHandle) {
536    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
537    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
538    renderer->drawRect(left, top, right, bottom, paint);
539}
540
541static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz,
542        jlong rendererHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
543        jfloat rx, jfloat ry, jlong paintHandle) {
544    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
545    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
546    renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
547}
548
549static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
550        jlong rendererHandle, jfloat x, jfloat y, jfloat radius, jlong paintHandle) {
551    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
552    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
553    renderer->drawCircle(x, y, radius, paint);
554}
555
556static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
557        jlong rendererHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
558        jlong paintHandle) {
559    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
560    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
561    renderer->drawOval(left, top, right, bottom, paint);
562}
563
564static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz,
565        jlong rendererHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
566        jfloat startAngle, jfloat sweepAngle, jboolean useCenter, jlong paintHandle) {
567    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
568    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
569    renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
570}
571
572static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
573        jlong rendererHandle, jlong regionHandle, jlong paintHandle) {
574    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
575    SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
576    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
577
578    if (paint->getStyle() != SkPaint::kFill_Style ||
579            (paint->isAntiAlias() && !renderer->isCurrentTransformSimple())) {
580        SkRegion::Iterator it(*region);
581        while (!it.done()) {
582            const SkIRect& r = it.rect();
583            renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
584            it.next();
585        }
586    } else {
587        int count = 0;
588        Vector<float> rects;
589        SkRegion::Iterator it(*region);
590        while (!it.done()) {
591            const SkIRect& r = it.rect();
592            rects.push(r.fLeft);
593            rects.push(r.fTop);
594            rects.push(r.fRight);
595            rects.push(r.fBottom);
596            count += 4;
597            it.next();
598        }
599        renderer->drawRects(rects.array(), count, paint);
600    }
601}
602
603static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject clazz,
604        jlong rendererHandle, jfloatArray rects, jint count, jlong paintHandle) {
605    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
606    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
607    jfloat* storage = env->GetFloatArrayElements(rects, NULL);
608    renderer->drawRects(storage, count, paint);
609    env->ReleaseFloatArrayElements(rects, storage, 0);
610}
611
612static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
613        jlong rendererHandle, jfloatArray points, jint offset, jint count, jlong paintHandle) {
614    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
615    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
616    jfloat* storage = env->GetFloatArrayElements(points, NULL);
617    renderer->drawPoints(storage + offset, count, paint);
618    env->ReleaseFloatArrayElements(points, storage, 0);
619}
620
621static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
622        jlong rendererHandle, jlong pathHandle, jlong paintHandle) {
623    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
624    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
625    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
626    renderer->drawPath(path, paint);
627}
628
629static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
630        jlong rendererHandle, jfloatArray points, jint offset, jint count, jlong paintHandle) {
631    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
632    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
633    jfloat* storage = env->GetFloatArrayElements(points, NULL);
634    renderer->drawLines(storage + offset, count, paint);
635    env->ReleaseFloatArrayElements(points, storage, 0);
636}
637
638// ----------------------------------------------------------------------------
639// Shaders and color filters
640// ----------------------------------------------------------------------------
641
642static void android_view_GLES20Canvas_resetModifiers(JNIEnv* env, jobject clazz,
643        jlong rendererHandle, jint modifiers) {
644    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
645    if (modifiers & MODIFIER_SHADOW) renderer->resetShadow();
646    if (modifiers & MODIFIER_SHADER) renderer->resetShader();
647    if (modifiers & MODIFIER_COLOR_FILTER) renderer->resetColorFilter();
648}
649
650static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject clazz,
651        jlong rendererHandle, jlong shaderHandle) {
652    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
653    SkiaShader* shader = reinterpret_cast<SkiaShader*>(shaderHandle);
654    renderer->setupShader(shader);
655}
656
657static void android_view_GLES20Canvas_setupColorFilter(JNIEnv* env, jobject clazz,
658        jlong rendererHandle, jlong filterHandle) {
659    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
660    SkiaColorFilter* filter = reinterpret_cast<SkiaColorFilter*>(filterHandle);
661    renderer->setupColorFilter(filter);
662}
663
664static void android_view_GLES20Canvas_setupShadow(JNIEnv* env, jobject clazz,
665        jlong rendererHandle, jfloat radius, jfloat dx, jfloat dy, jint color) {
666    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
667    renderer->setupShadow(radius, dx, dy, color);
668}
669
670// ----------------------------------------------------------------------------
671// Draw filters
672// ----------------------------------------------------------------------------
673
674static void android_view_GLES20Canvas_setupPaintFilter(JNIEnv* env, jobject clazz,
675        jlong rendererHandle, jint clearBits, jint setBits) {
676    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
677    renderer->setupPaintFilter(clearBits, setBits);
678}
679
680static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject clazz,
681        jlong rendererHandle) {
682    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
683    renderer->resetPaintFilter();
684}
685
686// ----------------------------------------------------------------------------
687// Text
688// ----------------------------------------------------------------------------
689
690static float xOffsetForTextAlign(SkPaint* paint, float totalAdvance) {
691    switch (paint->getTextAlign()) {
692        case SkPaint::kCenter_Align:
693            return -totalAdvance / 2.0f;
694            break;
695        case SkPaint::kRight_Align:
696            return -totalAdvance;
697            break;
698        default:
699            break;
700    }
701    return 0;
702}
703
704static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
705        jfloat x, jfloat y, int flags, SkPaint* paint) {
706    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
707            text, 0, count, count, flags);
708    if (value == NULL) {
709        return;
710    }
711    const jchar* glyphs = value->getGlyphs();
712    size_t glyphsCount = value->getGlyphsCount();
713    jfloat totalAdvance = value->getTotalAdvance();
714    x += xOffsetForTextAlign(paint, totalAdvance);
715    const float* positions = value->getPos();
716    int bytesCount = glyphsCount * sizeof(jchar);
717    const SkRect& r = value->getBounds();
718    android::uirenderer::Rect bounds(r.fLeft, r.fTop, r.fRight, r.fBottom);
719    bounds.translate(x, y);
720
721    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount,
722            x, y, positions, paint, totalAdvance, bounds);
723}
724
725static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
726        SkPath* path, jfloat hOffset, jfloat vOffset, int flags, SkPaint* paint) {
727    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
728            text, 0, count, count, flags);
729    if (value == NULL) {
730        return;
731    }
732    const jchar* glyphs = value->getGlyphs();
733    size_t glyphsCount = value->getGlyphsCount();
734    int bytesCount = glyphsCount * sizeof(jchar);
735    renderer->drawTextOnPath((const char*) glyphs, bytesCount, glyphsCount, path,
736            hOffset, vOffset, paint);
737}
738
739static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
740        jint start, jint count, jint contextCount, jfloat x, jfloat y,
741        int flags, SkPaint* paint) {
742    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
743            text, start, count, contextCount, flags);
744    if (value == NULL) {
745        return;
746    }
747    const jchar* glyphs = value->getGlyphs();
748    size_t glyphsCount = value->getGlyphsCount();
749    jfloat totalAdvance = value->getTotalAdvance();
750    x += xOffsetForTextAlign(paint, totalAdvance);
751    const float* positions = value->getPos();
752    int bytesCount = glyphsCount * sizeof(jchar);
753    const SkRect& r = value->getBounds();
754    android::uirenderer::Rect bounds(r.fLeft, r.fTop, r.fRight, r.fBottom);
755    bounds.translate(x, y);
756
757    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount,
758            x, y, positions, paint, totalAdvance, bounds);
759}
760
761static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
762        jlong rendererHandle, jcharArray text, jint index, jint count,
763        jfloat x, jfloat y, jint flags, jlong paintHandle) {
764    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
765    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
766    jchar* textArray = env->GetCharArrayElements(text, NULL);
767    renderText(renderer, textArray + index, count, x, y, flags, paint);
768    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
769}
770
771static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
772        jlong rendererHandle, jstring text, jint start, jint end,
773        jfloat x, jfloat y, jint flags, jlong paintHandle) {
774    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
775    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
776    const jchar* textArray = env->GetStringChars(text, NULL);
777    renderText(renderer, textArray + start, end - start, x, y, flags, paint);
778    env->ReleaseStringChars(text, textArray);
779}
780
781static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
782        jlong rendererHandle, jcharArray text, jint index, jint count,
783        jlong pathHandle, jfloat hOffset, jfloat vOffset, jint flags, jlong paintHandle) {
784    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
785    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
786    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
787    jchar* textArray = env->GetCharArrayElements(text, NULL);
788    renderTextOnPath(renderer, textArray + index, count, path,
789            hOffset, vOffset, flags, paint);
790    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
791}
792
793static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
794        jlong rendererHandle, jstring text, jint start, jint end,
795        jlong pathHandle, jfloat hOffset, jfloat vOffset, jint flags, jlong paintHandle) {
796    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
797    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
798    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
799    const jchar* textArray = env->GetStringChars(text, NULL);
800    renderTextOnPath(renderer, textArray + start, end - start, path,
801            hOffset, vOffset, flags, paint);
802    env->ReleaseStringChars(text, textArray);
803}
804
805static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
806        jlong rendererHandle, jcharArray text, jint index, jint count,
807        jint contextIndex, jint contextCount, jfloat x, jfloat y, jint dirFlags,
808        jlong paintHandle) {
809    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
810    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
811    jchar* textArray = env->GetCharArrayElements(text, NULL);
812    renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
813            count, contextCount, x, y, dirFlags, paint);
814    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
815 }
816
817static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
818        jlong rendererHandle, jstring text, jint start, jint end,
819        jint contextStart, jint contextEnd, jfloat x, jfloat y, jint dirFlags,
820        jlong paintHandle) {
821    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
822    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
823    const jchar* textArray = env->GetStringChars(text, NULL);
824    jint count = end - start;
825    jint contextCount = contextEnd - contextStart;
826    renderTextRun(renderer, textArray + contextStart, start - contextStart,
827            count, contextCount, x, y, dirFlags, paint);
828    env->ReleaseStringChars(text, textArray);
829}
830
831static void renderPosText(OpenGLRenderer* renderer, const jchar* text, int count,
832        const jfloat* positions, jint dirFlags, SkPaint* paint) {
833    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
834            text, 0, count, count, dirFlags);
835    if (value == NULL) {
836        return;
837    }
838    const jchar* glyphs = value->getGlyphs();
839    size_t glyphsCount = value->getGlyphsCount();
840    if (count < int(glyphsCount)) glyphsCount = count;
841    int bytesCount = glyphsCount * sizeof(jchar);
842
843    renderer->drawPosText((const char*) glyphs, bytesCount, glyphsCount, positions, paint);
844}
845
846static void android_view_GLES20Canvas_drawPosTextArray(JNIEnv* env, jobject clazz,
847        jlong rendererHandle, jcharArray text, jint index, jint count,
848        jfloatArray pos, jlong paintHandle) {
849    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
850    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
851    jchar* textArray = env->GetCharArrayElements(text, NULL);
852    jfloat* positions = env->GetFloatArrayElements(pos, NULL);
853
854    renderPosText(renderer, textArray + index, count, positions, kBidi_LTR, paint);
855
856    env->ReleaseFloatArrayElements(pos, positions, JNI_ABORT);
857    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
858}
859
860static void android_view_GLES20Canvas_drawPosText(JNIEnv* env, jobject clazz,
861        jlong rendererHandle, jstring text, jint start, jint end,
862        jfloatArray pos, jlong paintHandle) {
863    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
864    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
865    const jchar* textArray = env->GetStringChars(text, NULL);
866    jfloat* positions = env->GetFloatArrayElements(pos, NULL);
867
868    renderPosText(renderer, textArray + start, end - start, positions, kBidi_LTR, paint);
869
870    env->ReleaseFloatArrayElements(pos, positions, JNI_ABORT);
871    env->ReleaseStringChars(text, textArray);
872}
873
874// ----------------------------------------------------------------------------
875// Display lists
876// ----------------------------------------------------------------------------
877
878static jlong android_view_GLES20Canvas_getDisplayList(JNIEnv* env,
879        jobject clazz, jlong rendererHandle, jlong displayListHandle) {
880    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererHandle);
881    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListHandle);
882    DisplayList* list = renderer->getDisplayList(displayList);
883    return reinterpret_cast<jlong>(list);
884}
885
886static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env,
887        jobject clazz) {
888    OpenGLRenderer* renderer = new DisplayListRenderer;
889    return reinterpret_cast<jlong>(renderer);
890}
891
892static void android_view_GLES20Canvas_resetDisplayListRenderer(JNIEnv* env,
893        jobject clazz, jlong rendererHandle) {
894    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererHandle);
895    renderer->reset();
896}
897
898static jint android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
899        jobject clazz, jlong rendererHandle, jlong displayListHandle,
900        jobject dirty, jint flags) {
901    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
902    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListHandle);
903    android::uirenderer::Rect bounds;
904    status_t status = renderer->drawDisplayList(displayList, bounds, flags);
905    if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
906        env->CallVoidMethod(dirty, gRectClassInfo.set,
907                int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
908    }
909    return status;
910}
911
912static void android_view_GLES20Canvas_outputDisplayList(JNIEnv* env,
913        jobject clazz, jlong rendererHandle, jlong displayListHandle) {
914    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
915    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListHandle);
916    renderer->outputDisplayList(displayList);
917}
918
919// ----------------------------------------------------------------------------
920// Layers
921// ----------------------------------------------------------------------------
922
923static void android_view_GLES20Canvas_interrupt(JNIEnv* env, jobject clazz,
924        jlong rendererHandle) {
925    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
926    renderer->interrupt();
927}
928
929static void android_view_GLES20Canvas_resume(JNIEnv* env, jobject clazz,
930        jlong rendererHandle) {
931    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
932    renderer->resume();
933}
934
935static jlong android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env,
936        jobject clazz, jlong layerHandle) {
937    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
938    if (layer) {
939        OpenGLRenderer* renderer = new LayerRenderer(layer);
940        renderer->initProperties();
941        return reinterpret_cast<jlong>(renderer);
942    }
943    return NULL;
944}
945
946static jlong android_view_GLES20Canvas_createTextureLayer(JNIEnv* env, jobject clazz,
947        jboolean isOpaque, jintArray layerInfo) {
948    Layer* layer = LayerRenderer::createTextureLayer(isOpaque);
949
950    if (layer) {
951        jint* storage = env->GetIntArrayElements(layerInfo, NULL);
952        storage[0] = layer->getTexture();
953        env->ReleaseIntArrayElements(layerInfo, storage, 0);
954    }
955
956    return reinterpret_cast<jlong>(layer);
957}
958
959static jlong android_view_GLES20Canvas_createLayer(JNIEnv* env, jobject clazz,
960        jint width, jint height, jboolean isOpaque, jintArray layerInfo) {
961    Layer* layer = LayerRenderer::createLayer(width, height, isOpaque);
962
963    if (layer) {
964        jint* storage = env->GetIntArrayElements(layerInfo, NULL);
965        storage[0] = layer->getWidth();
966        storage[1] = layer->getHeight();
967        env->ReleaseIntArrayElements(layerInfo, storage, 0);
968    }
969
970    return reinterpret_cast<jlong>(layer);
971}
972
973static jboolean android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz,
974        jlong layerHandle, jint width, jint height, jintArray layerInfo) {
975    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
976    if (LayerRenderer::resizeLayer(layer, width, height)) {
977        jint* storage = env->GetIntArrayElements(layerInfo, NULL);
978        storage[0] = layer->getWidth();
979        storage[1] = layer->getHeight();
980        env->ReleaseIntArrayElements(layerInfo, storage, 0);
981        return JNI_TRUE;
982    }
983    return JNI_FALSE;
984}
985
986static void android_view_GLES20Canvas_setLayerPaint(JNIEnv* env, jobject clazz,
987        jlong layerHandle, jlong paintHandle) {
988    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
989    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
990    if (layer) {
991        layer->setPaint(paint);
992    }
993}
994
995static void android_view_GLES20Canvas_setLayerColorFilter(JNIEnv* env, jobject clazz,
996        jlong layerHandle, jlong colorFilterHandle) {
997    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
998    SkiaColorFilter* colorFilter = reinterpret_cast<SkiaColorFilter*>(colorFilterHandle);
999    if (layer) {
1000        layer->setColorFilter(colorFilter);
1001    }
1002}
1003
1004static void android_view_GLES20Canvas_setOpaqueLayer(JNIEnv* env, jobject clazz,
1005        jlong layerHandle, jboolean isOpaque) {
1006    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1007    if (layer) {
1008        layer->setBlend(!isOpaque);
1009    }
1010}
1011
1012static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz,
1013        jlong layerHandle, jint width, jint height, jboolean isOpaque, jobject surface) {
1014    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1015    float transform[16];
1016    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
1017
1018    if (surfaceTexture->updateTexImage() == NO_ERROR) {
1019        int64_t frameNumber = surfaceTexture->getFrameNumber();
1020        // If the GLConsumer queue is in synchronous mode, need to discard all
1021        // but latest frame, using the frame number to tell when we no longer
1022        // have newer frames to target. Since we can't tell which mode it is in,
1023        // do this unconditionally.
1024        int dropCounter = 0;
1025        while (surfaceTexture->updateTexImage() == NO_ERROR) {
1026            int64_t newFrameNumber = surfaceTexture->getFrameNumber();
1027            if (newFrameNumber == frameNumber) break;
1028            frameNumber = newFrameNumber;
1029            dropCounter++;
1030        }
1031        #if DEBUG_RENDERER
1032        if (dropCounter > 0) {
1033            RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
1034        }
1035        #endif
1036        surfaceTexture->getTransformMatrix(transform);
1037        GLenum renderTarget = surfaceTexture->getCurrentTextureTarget();
1038
1039        LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform);
1040    }
1041}
1042
1043static void android_view_GLES20Canvas_updateRenderLayer(JNIEnv* env, jobject clazz,
1044        jlong layerHandle, jlong rendererHandle, jlong displayListHandle,
1045        jint left, jint top, jint right, jint bottom) {
1046    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1047    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
1048    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListHandle);
1049    layer->updateDeferred(renderer, displayList, left, top, right, bottom);
1050}
1051
1052static void android_view_GLES20Canvas_clearLayerTexture(JNIEnv* env, jobject clazz,
1053        jlong layerHandle) {
1054    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1055    layer->clearTexture();
1056}
1057
1058static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz,
1059        jlong layerHandle, jlong matrixHandle) {
1060    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1061    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1062    layer->getTransform().load(*matrix);
1063}
1064
1065static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, jlong layerHandle) {
1066    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1067    LayerRenderer::destroyLayer(layer);
1068}
1069
1070static void android_view_GLES20Canvas_destroyLayerDeferred(JNIEnv* env,
1071        jobject clazz, jlong layerHandle) {
1072    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1073    LayerRenderer::destroyLayerDeferred(layer);
1074}
1075
1076static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
1077        jlong rendererHandle, jlong layerHandle, jfloat x, jfloat y) {
1078    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
1079    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1080    renderer->drawLayer(layer, x, y);
1081}
1082
1083static jboolean android_view_GLES20Canvas_copyLayer(JNIEnv* env, jobject clazz,
1084        jlong layerHandle, jlong bitmapHandle) {
1085    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1086    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
1087    return LayerRenderer::copyLayer(layer, bitmap);
1088}
1089
1090static void android_view_GLES20Canvas_pushLayerUpdate(JNIEnv* env, jobject clazz,
1091        jlong rendererHandle, jlong layerHandle) {
1092    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
1093    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1094    renderer->pushLayerUpdate(layer);
1095}
1096
1097static void android_view_GLES20Canvas_cancelLayerUpdate(JNIEnv* env, jobject clazz,
1098        jlong rendererHandle, jlong layerHandle) {
1099    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
1100    Layer* layer = reinterpret_cast<Layer*>(layerHandle);
1101    renderer->cancelLayerUpdate(layer);
1102}
1103
1104static void android_view_GLES20Canvas_clearLayerUpdates(JNIEnv* env, jobject clazz,
1105        jlong rendererHandle) {
1106    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
1107    renderer->clearLayerUpdates();
1108}
1109
1110static void android_view_GLES20Canvas_flushLayerUpdates(JNIEnv* env, jobject clazz,
1111        jlong rendererHandle) {
1112    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
1113    renderer->flushLayerUpdates();
1114}
1115
1116#endif // USE_OPENGL_RENDERER
1117
1118// ----------------------------------------------------------------------------
1119// Common
1120// ----------------------------------------------------------------------------
1121
1122static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz) {
1123#ifdef USE_OPENGL_RENDERER
1124    char prop[PROPERTY_VALUE_MAX];
1125    if (property_get("ro.kernel.qemu", prop, NULL) == 0) {
1126        // not in the emulator
1127        return JNI_TRUE;
1128    }
1129    // In the emulator this property will be set to 1 when hardware GLES is
1130    // enabled, 0 otherwise. On old emulator versions it will be undefined.
1131    property_get("ro.kernel.qemu.gles", prop, "0");
1132    return atoi(prop) == 1 ? JNI_TRUE : JNI_FALSE;
1133#else
1134    return JNI_FALSE;
1135#endif
1136}
1137
1138// ----------------------------------------------------------------------------
1139// Logging
1140// ----------------------------------------------------------------------------
1141
1142static void
1143android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
1144#ifdef USE_OPENGL_RENDERER
1145    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
1146    android::uirenderer::DisplayList::outputLogBuffer(fd);
1147#endif // USE_OPENGL_RENDERER
1148}
1149
1150// ----------------------------------------------------------------------------
1151// JNI Glue
1152// ----------------------------------------------------------------------------
1153
1154const char* const kClassPathName = "android/view/GLES20Canvas";
1155
1156static JNINativeMethod gMethods[] = {
1157    { "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
1158
1159#ifdef USE_OPENGL_RENDERER
1160    { "nFlushCaches",       "(I)V",            (void*) android_view_GLES20Canvas_flushCaches },
1161    { "nInitCaches",        "()Z",             (void*) android_view_GLES20Canvas_initCaches },
1162    { "nTerminateCaches",   "()V",             (void*) android_view_GLES20Canvas_terminateCaches },
1163
1164    { "nInitAtlas",         "(Landroid/view/GraphicBuffer;[JI)V",
1165            (void*) android_view_GLES20Canvas_initAtlas },
1166
1167    { "nCreateRenderer",    "()J",             (void*) android_view_GLES20Canvas_createRenderer },
1168    { "nDestroyRenderer",   "(J)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
1169    { "nSetViewport",       "(JII)V",          (void*) android_view_GLES20Canvas_setViewport },
1170    { "nPrepare",           "(JZ)I",           (void*) android_view_GLES20Canvas_prepare },
1171    { "nPrepareDirty",      "(JIIIIZ)I",       (void*) android_view_GLES20Canvas_prepareDirty },
1172    { "nFinish",            "(J)V",            (void*) android_view_GLES20Canvas_finish },
1173    { "nSetName",           "(JLjava/lang/String;)V",
1174            (void*) android_view_GLES20Canvas_setName },
1175
1176    { "nSetCountOverdrawEnabled", "(JZ)V",     (void*) android_view_GLES20Canvas_setCountOverdrawEnabled },
1177    { "nGetOverdraw",             "(J)F",      (void*) android_view_GLES20Canvas_getOverdraw },
1178
1179    { "nGetStencilSize",    "()I",             (void*) android_view_GLES20Canvas_getStencilSize },
1180
1181    { "nCallDrawGLFunction", "(JJ)I",          (void*) android_view_GLES20Canvas_callDrawGLFunction },
1182    { "nDetachFunctor",      "(JJ)V",          (void*) android_view_GLES20Canvas_detachFunctor },
1183    { "nAttachFunctor",      "(JJ)V",          (void*) android_view_GLES20Canvas_attachFunctor },
1184    { "nInvokeFunctors",     "(JLandroid/graphics/Rect;)I",
1185            (void*) android_view_GLES20Canvas_invokeFunctors },
1186
1187    { "nSave",              "(JI)I",           (void*) android_view_GLES20Canvas_save },
1188    { "nRestore",           "(J)V",            (void*) android_view_GLES20Canvas_restore },
1189    { "nRestoreToCount",    "(JI)V",           (void*) android_view_GLES20Canvas_restoreToCount },
1190    { "nGetSaveCount",      "(J)I",            (void*) android_view_GLES20Canvas_getSaveCount },
1191
1192    { "nSaveLayer",         "(JFFFFJI)I",      (void*) android_view_GLES20Canvas_saveLayer },
1193    { "nSaveLayer",         "(JJI)I",          (void*) android_view_GLES20Canvas_saveLayerClip },
1194    { "nSaveLayerAlpha",    "(JFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
1195    { "nSaveLayerAlpha",    "(JII)I",          (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
1196
1197    { "nQuickReject",       "(JFFFF)Z",        (void*) android_view_GLES20Canvas_quickReject },
1198    { "nClipRect",          "(JFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
1199    { "nClipRect",          "(JIIIII)Z",       (void*) android_view_GLES20Canvas_clipRect },
1200    { "nClipPath",          "(JJI)Z",          (void*) android_view_GLES20Canvas_clipPath },
1201    { "nClipRegion",        "(JJI)Z",          (void*) android_view_GLES20Canvas_clipRegion },
1202
1203    { "nTranslate",         "(JFF)V",          (void*) android_view_GLES20Canvas_translate },
1204    { "nRotate",            "(JF)V",           (void*) android_view_GLES20Canvas_rotate },
1205    { "nScale",             "(JFF)V",          (void*) android_view_GLES20Canvas_scale },
1206    { "nSkew",              "(JFF)V",          (void*) android_view_GLES20Canvas_skew },
1207
1208    { "nSetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_setMatrix },
1209    { "nGetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_getMatrix },
1210    { "nConcatMatrix",      "(JJ)V",           (void*) android_view_GLES20Canvas_concatMatrix },
1211
1212    { "nDrawBitmap",        "(JJ[BFFJ)V",      (void*) android_view_GLES20Canvas_drawBitmap },
1213    { "nDrawBitmap",        "(JJ[BFFFFFFFFJ)V",(void*) android_view_GLES20Canvas_drawBitmapRect },
1214    { "nDrawBitmap",        "(JJ[BJJ)V",       (void*) android_view_GLES20Canvas_drawBitmapMatrix },
1215    { "nDrawBitmap",        "(J[IIIFFIIZJ)V",  (void*) android_view_GLES20Canvas_drawBitmapData },
1216
1217    { "nDrawBitmapMesh",    "(JJ[BII[FI[IIJ)V",(void*) android_view_GLES20Canvas_drawBitmapMesh },
1218
1219    { "nDrawPatch",         "(JJ[BJFFFFJ)V",   (void*) android_view_GLES20Canvas_drawPatch },
1220
1221    { "nDrawColor",         "(JII)V",          (void*) android_view_GLES20Canvas_drawColor },
1222    { "nDrawRect",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawRect },
1223    { "nDrawRects",         "(JJJ)V",          (void*) android_view_GLES20Canvas_drawRegionAsRects },
1224    { "nDrawRects",         "(J[FIJ)V",        (void*) android_view_GLES20Canvas_drawRects },
1225    { "nDrawRoundRect",     "(JFFFFFFJ)V",     (void*) android_view_GLES20Canvas_drawRoundRect },
1226    { "nDrawCircle",        "(JFFFJ)V",        (void*) android_view_GLES20Canvas_drawCircle },
1227    { "nDrawOval",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawOval },
1228    { "nDrawArc",           "(JFFFFFFZJ)V",    (void*) android_view_GLES20Canvas_drawArc },
1229    { "nDrawPoints",        "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawPoints },
1230
1231    { "nDrawPath",          "(JJJ)V",          (void*) android_view_GLES20Canvas_drawPath },
1232    { "nDrawLines",         "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawLines },
1233
1234    { "nResetModifiers",    "(JI)V",           (void*) android_view_GLES20Canvas_resetModifiers },
1235    { "nSetupShader",       "(JJ)V",           (void*) android_view_GLES20Canvas_setupShader },
1236    { "nSetupColorFilter",  "(JJ)V",           (void*) android_view_GLES20Canvas_setupColorFilter },
1237    { "nSetupShadow",       "(JFFFI)V",        (void*) android_view_GLES20Canvas_setupShadow },
1238
1239    { "nSetupPaintFilter",  "(JII)V",          (void*) android_view_GLES20Canvas_setupPaintFilter },
1240    { "nResetPaintFilter",  "(J)V",            (void*) android_view_GLES20Canvas_resetPaintFilter },
1241
1242    { "nDrawText",          "(J[CIIFFIJ)V",    (void*) android_view_GLES20Canvas_drawTextArray },
1243    { "nDrawText",          "(JLjava/lang/String;IIFFIJ)V",
1244            (void*) android_view_GLES20Canvas_drawText },
1245
1246    { "nDrawTextOnPath",    "(J[CIIJFFIJ)V",   (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
1247    { "nDrawTextOnPath",    "(JLjava/lang/String;IIJFFIJ)V",
1248            (void*) android_view_GLES20Canvas_drawTextOnPath },
1249
1250    { "nDrawTextRun",       "(J[CIIIIFFIJ)V",  (void*) android_view_GLES20Canvas_drawTextRunArray },
1251    { "nDrawTextRun",       "(JLjava/lang/String;IIIIFFIJ)V",
1252            (void*) android_view_GLES20Canvas_drawTextRun },
1253
1254    { "nDrawPosText",       "(J[CII[FJ)V",     (void*) android_view_GLES20Canvas_drawPosTextArray },
1255    { "nDrawPosText",       "(JLjava/lang/String;II[FJ)V",
1256            (void*) android_view_GLES20Canvas_drawPosText },
1257
1258    { "nGetClipBounds",     "(JLandroid/graphics/Rect;)Z",
1259            (void*) android_view_GLES20Canvas_getClipBounds },
1260
1261    { "nGetDisplayList",         "(JJ)J",      (void*) android_view_GLES20Canvas_getDisplayList },
1262    { "nOutputDisplayList",      "(JJ)V",      (void*) android_view_GLES20Canvas_outputDisplayList },
1263    { "nDrawDisplayList",        "(JJLandroid/graphics/Rect;I)I",
1264            (void*) android_view_GLES20Canvas_drawDisplayList },
1265
1266    { "nCreateDisplayListRenderer", "()J",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
1267    { "nResetDisplayListRenderer",  "(J)V",    (void*) android_view_GLES20Canvas_resetDisplayListRenderer },
1268
1269    { "nInterrupt",              "(J)V",       (void*) android_view_GLES20Canvas_interrupt },
1270    { "nResume",                 "(J)V",       (void*) android_view_GLES20Canvas_resume },
1271
1272    { "nCreateLayerRenderer",    "(J)J",       (void*) android_view_GLES20Canvas_createLayerRenderer },
1273    { "nCreateLayer",            "(IIZ[I)J",   (void*) android_view_GLES20Canvas_createLayer },
1274    { "nResizeLayer",            "(JII[I)Z" ,  (void*) android_view_GLES20Canvas_resizeLayer },
1275    { "nSetLayerPaint",          "(JJ)V",      (void*) android_view_GLES20Canvas_setLayerPaint },
1276    { "nSetLayerColorFilter",    "(JJ)V",      (void*) android_view_GLES20Canvas_setLayerColorFilter },
1277    { "nSetOpaqueLayer",         "(JZ)V",      (void*) android_view_GLES20Canvas_setOpaqueLayer },
1278    { "nCreateTextureLayer",     "(Z[I)J",     (void*) android_view_GLES20Canvas_createTextureLayer },
1279    { "nUpdateTextureLayer",     "(JIIZLandroid/graphics/SurfaceTexture;)V",
1280            (void*) android_view_GLES20Canvas_updateTextureLayer },
1281    { "nUpdateRenderLayer",      "(JJJIIII)V", (void*) android_view_GLES20Canvas_updateRenderLayer },
1282    { "nClearLayerTexture",      "(J)V",       (void*) android_view_GLES20Canvas_clearLayerTexture },
1283    { "nDestroyLayer",           "(J)V",       (void*) android_view_GLES20Canvas_destroyLayer },
1284    { "nDestroyLayerDeferred",   "(J)V",       (void*) android_view_GLES20Canvas_destroyLayerDeferred },
1285    { "nDrawLayer",              "(JJFF)V",    (void*) android_view_GLES20Canvas_drawLayer },
1286    { "nCopyLayer",              "(JJ)Z",      (void*) android_view_GLES20Canvas_copyLayer },
1287    { "nClearLayerUpdates",      "(J)V",       (void*) android_view_GLES20Canvas_clearLayerUpdates },
1288    { "nFlushLayerUpdates",      "(J)V",       (void*) android_view_GLES20Canvas_flushLayerUpdates },
1289    { "nPushLayerUpdate",        "(JJ)V",      (void*) android_view_GLES20Canvas_pushLayerUpdate },
1290    { "nCancelLayerUpdate",      "(JJ)V",      (void*) android_view_GLES20Canvas_cancelLayerUpdate },
1291
1292    { "nSetTextureLayerTransform", "(JJ)V",    (void*) android_view_GLES20Canvas_setTextureLayerTransform },
1293
1294    { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_GLES20Canvas_getMaxTextureWidth },
1295    { "nGetMaximumTextureHeight", "()I",       (void*) android_view_GLES20Canvas_getMaxTextureHeight },
1296
1297#endif
1298};
1299
1300static JNINativeMethod gActivityThreadMethods[] = {
1301    { "dumpGraphicsInfo",        "(Ljava/io/FileDescriptor;)V",
1302                                               (void*) android_app_ActivityThread_dumpGraphics }
1303};
1304
1305
1306#ifdef USE_OPENGL_RENDERER
1307    #define FIND_CLASS(var, className) \
1308            var = env->FindClass(className); \
1309            LOG_FATAL_IF(! var, "Unable to find class " className);
1310
1311    #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
1312            var = env->GetMethodID(clazz, methodName, methodDescriptor); \
1313            LOG_FATAL_IF(! var, "Unable to find method " methodName);
1314#else
1315    #define FIND_CLASS(var, className)
1316    #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor)
1317#endif
1318
1319int register_android_view_GLES20Canvas(JNIEnv* env) {
1320    jclass clazz;
1321    FIND_CLASS(clazz, "android/graphics/Rect");
1322    GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V");
1323
1324    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
1325}
1326
1327const char* const kActivityThreadPathName = "android/app/ActivityThread";
1328
1329int register_android_app_ActivityThread(JNIEnv* env) {
1330    return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName,
1331            gActivityThreadMethods, NELEM(gActivityThreadMethods));
1332}
1333
1334};
1335