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