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