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