android_view_GLES20Canvas.cpp revision e21e2a2d1d85d422230c1115abba824338763a88
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_runtime/AndroidRuntime.h>
24
25#include <androidfw/ResourceTypes.h>
26
27#include <private/hwui/DrawGlInfo.h>
28
29#include <cutils/properties.h>
30
31#include <SkBitmap.h>
32#include <SkCanvas.h>
33#include <SkImageInfo.h>
34#include <SkMatrix.h>
35#include <SkPorterDuff.h>
36#include <SkRegion.h>
37#include <SkScalerContext.h>
38#include <SkTemplates.h>
39#include <SkXfermode.h>
40
41#include <DisplayListRenderer.h>
42#include <Rect.h>
43#include <RenderNode.h>
44#include <CanvasProperty.h>
45#include <Paint.h>
46
47#include "MinikinUtils.h"
48
49namespace android {
50
51using namespace uirenderer;
52
53/**
54 * Note: DisplayListRenderer JNI layer is generated and compiled only on supported
55 *       devices. This means all the logic must be compiled only when the
56 *       preprocessor variable USE_OPENGL_RENDERER is defined.
57 */
58#ifdef USE_OPENGL_RENDERER
59
60// ----------------------------------------------------------------------------
61// Defines
62// ----------------------------------------------------------------------------
63
64// Debug
65#define DEBUG_RENDERER 0
66
67// Debug
68#if DEBUG_RENDERER
69    #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__)
70#else
71    #define RENDERER_LOGD(...)
72#endif
73
74// ----------------------------------------------------------------------------
75
76static struct {
77    jmethodID set;
78} gRectClassInfo;
79
80// ----------------------------------------------------------------------------
81// Constructors
82// ----------------------------------------------------------------------------
83
84static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
85        jlong rendererPtr) {
86    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
87    RENDERER_LOGD("Destroy DisplayListRenderer");
88    delete renderer;
89}
90
91// ----------------------------------------------------------------------------
92// Setup
93// ----------------------------------------------------------------------------
94
95static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz,
96        jlong rendererPtr, jint width, jint height) {
97    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
98    renderer->setViewport(width, height);
99}
100
101static void android_view_GLES20Canvas_setHighContrastText(JNIEnv* env, jobject clazz,
102        jlong rendererPtr, jboolean highContrastText) {
103    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
104    renderer->setHighContrastText(highContrastText);
105}
106
107static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
108        jlong rendererPtr, jboolean opaque) {
109    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
110    return renderer->prepare(opaque);
111}
112
113static int android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
114        jlong rendererPtr, jint left, jint top, jint right, jint bottom,
115        jboolean opaque) {
116    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
117    return renderer->prepareDirty(left, top, right, bottom, opaque);
118}
119
120static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
121        jlong rendererPtr) {
122    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
123    renderer->finish();
124}
125
126static void android_view_GLES20Canvas_setProperty(JNIEnv* env,
127        jobject clazz, jstring name, jstring value) {
128    if (!Caches::hasInstance()) {
129        ALOGW("can't set property, no Caches instance");
130        return;
131    }
132
133    if (name == NULL || value == NULL) {
134        ALOGW("can't set prop, null passed");
135    }
136
137    const char* nameCharArray = env->GetStringUTFChars(name, NULL);
138    const char* valueCharArray = env->GetStringUTFChars(value, NULL);
139    Caches::getInstance().setTempProperty(nameCharArray, valueCharArray);
140    env->ReleaseStringUTFChars(name, nameCharArray);
141    env->ReleaseStringUTFChars(name, valueCharArray);
142}
143
144// ----------------------------------------------------------------------------
145// Functor
146// ----------------------------------------------------------------------------
147
148static jint android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
149        jlong rendererPtr, jlong functorPtr) {
150    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
151    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
152    android::uirenderer::Rect dirty;
153    return renderer->callDrawGLFunction(functor, dirty);
154}
155
156// ----------------------------------------------------------------------------
157// Misc
158// ----------------------------------------------------------------------------
159
160static jint android_view_GLES20Canvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) {
161    return Caches::getInstance().maxTextureSize;
162}
163
164static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject clazz) {
165    return Caches::getInstance().maxTextureSize;
166}
167
168// ----------------------------------------------------------------------------
169// State
170// ----------------------------------------------------------------------------
171
172static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, jlong rendererPtr,
173        jint flags) {
174    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
175    return renderer->save(flags);
176}
177
178static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz,
179        jlong rendererPtr) {
180    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
181    return renderer->getSaveCount();
182}
183
184static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz,
185        jlong rendererPtr) {
186    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
187    renderer->restore();
188}
189
190static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
191        jlong rendererPtr, jint saveCount) {
192    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
193    renderer->restoreToCount(saveCount);
194}
195
196// ----------------------------------------------------------------------------
197// Layers
198// ----------------------------------------------------------------------------
199
200static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
201        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
202        jlong paintPtr, jint saveFlags) {
203    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
204    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
205    return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
206}
207
208static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
209        jlong rendererPtr, jlong paintPtr, jint saveFlags) {
210    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
211    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
212    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
213    return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
214            paint, saveFlags);
215}
216
217static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
218        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
219        jint alpha, jint saveFlags) {
220    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
221    return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
222}
223
224static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
225        jlong rendererPtr, jint alpha, jint saveFlags) {
226    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
227    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
228    return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
229            alpha, saveFlags);
230}
231
232// ----------------------------------------------------------------------------
233// Clipping
234// ----------------------------------------------------------------------------
235
236static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
237        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom) {
238    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
239    const bool result = renderer->quickRejectConservative(left, top, right, bottom);
240    return result ? JNI_TRUE : JNI_FALSE;
241}
242
243static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
244        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
245        jint op) {
246    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
247    const bool result = renderer->clipRect(left, top, right, bottom,
248                                           static_cast<SkRegion::Op>(op));
249    return result ? JNI_TRUE : JNI_FALSE;
250}
251
252static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
253        jlong rendererPtr, jint left, jint top, jint right, jint bottom,
254        jint op) {
255    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
256    const bool result = renderer->clipRect(float(left), float(top), float(right),
257                                           float(bottom),
258                                           static_cast<SkRegion::Op>(op));
259    return result ? JNI_TRUE : JNI_FALSE;
260}
261
262static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
263        jlong rendererPtr, jlong pathPtr, jint op) {
264    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
265    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
266    const bool result = renderer->clipPath(path, static_cast<SkRegion::Op>(op));
267    return result ? JNI_TRUE : JNI_FALSE;
268}
269
270static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
271        jlong rendererPtr, jlong regionPtr, jint op) {
272    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
273    SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
274    const bool result = renderer->clipRegion(region, static_cast<SkRegion::Op>(op));
275    return result ? JNI_TRUE : JNI_FALSE;
276}
277
278static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
279        jlong rendererPtr, jobject rect) {
280    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
281    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
282
283    env->CallVoidMethod(rect, gRectClassInfo.set,
284            int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
285
286    return !bounds.isEmpty() ? JNI_TRUE : JNI_FALSE;
287}
288
289// ----------------------------------------------------------------------------
290// Transforms
291// ----------------------------------------------------------------------------
292
293static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz,
294        jlong rendererPtr, jfloat dx, jfloat dy) {
295    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
296    renderer->translate(dx, dy);
297}
298
299static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz,
300        jlong rendererPtr, jfloat degrees) {
301    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
302    renderer->rotate(degrees);
303}
304
305static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz,
306        jlong rendererPtr, jfloat sx, jfloat sy) {
307    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
308    renderer->scale(sx, sy);
309}
310
311static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz,
312        jlong rendererPtr, jfloat sx, jfloat sy) {
313    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
314    renderer->skew(sx, sy);
315}
316
317static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz,
318        jlong rendererPtr, jlong matrixPtr) {
319    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
320    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
321    renderer->setMatrix(matrix ? *matrix : SkMatrix::I());
322}
323
324static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz,
325        jlong rendererPtr, jlong matrixPtr) {
326    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
327    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
328    renderer->getMatrix(matrix);
329}
330
331static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
332        jlong rendererPtr, jlong matrixPtr) {
333    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
334    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
335    renderer->concatMatrix(*matrix);
336}
337
338// ----------------------------------------------------------------------------
339// Drawing
340// ----------------------------------------------------------------------------
341
342static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
343        jlong rendererPtr, jlong bitmapPtr, jbyteArray buffer,
344        jfloat left, jfloat top, jlong paintPtr) {
345    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
346    // This object allows the renderer to allocate a global JNI ref to the buffer object.
347    JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
348
349    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
350    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
351    renderer->drawBitmap(bitmap, left, top, paint);
352}
353
354static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz,
355        jlong rendererPtr, jlong bitmapPtr, jbyteArray buffer,
356        float srcLeft, float srcTop, float srcRight, float srcBottom,
357        float dstLeft, float dstTop, float dstRight, float dstBottom, jlong paintPtr) {
358    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
359    // This object allows the renderer to allocate a global JNI ref to the buffer object.
360    JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
361
362    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
363    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
364    renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
365            dstLeft, dstTop, dstRight, dstBottom, paint);
366}
367
368static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject clazz,
369        jlong rendererPtr, jlong bitmapPtr, jbyteArray buffer,
370        jlong matrixPtr, jlong paintPtr) {
371    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
372    // This object allows the renderer to allocate a global JNI ref to the buffer object.
373    JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
374
375    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
376    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
377    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
378    renderer->drawBitmap(bitmap, *matrix, paint);
379}
380
381static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
382        jlong rendererPtr, jintArray colors, jint offset, jint stride,
383        jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, jlong paintPtr) {
384    // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
385    // correct the alphaType to kOpaque_SkAlphaType.
386    const SkImageInfo info = SkImageInfo::Make(width, height,
387                               hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
388                               kPremul_SkAlphaType);
389    SkBitmap* bitmap = new SkBitmap;
390    if (!bitmap->allocPixels(info)) {
391        delete bitmap;
392        return;
393    }
394
395    if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap)) {
396        delete bitmap;
397        return;
398    }
399
400    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
401    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
402    renderer->drawBitmapData(bitmap, left, top, paint);
403
404    // Note - bitmap isn't deleted as DisplayListRenderer owns it now
405}
406
407static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
408        jlong rendererPtr, jlong bitmapPtr, jbyteArray buffer,
409        jint meshWidth, jint meshHeight, jfloatArray vertices, jint offset, jintArray colors,
410        jint colorOffset, jlong paintPtr) {
411    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
412    // This object allows the renderer to allocate a global JNI ref to the buffer object.
413    JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
414
415    jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL;
416    jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
417
418    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
419    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
420    renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint);
421
422    if (vertices) env->ReleaseFloatArrayElements(vertices, verticesArray, 0);
423    if (colors) env->ReleaseIntArrayElements(colors, colorsArray, 0);
424}
425
426static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
427        jlong rendererPtr, jlong bitmapPtr, jbyteArray buffer, jlong patchPtr,
428        float left, float top, float right, float bottom, jlong paintPtr) {
429    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
430    // This object allows the renderer to allocate a global JNI ref to the buffer object.
431    JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
432
433    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
434    Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr);
435    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
436    renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
437}
438
439static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
440        jlong rendererPtr, jint color, jint modeHandle) {
441    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
442    SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
443    renderer->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
444}
445
446static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
447        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
448        jlong paintPtr) {
449    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
450    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
451    renderer->drawRect(left, top, right, bottom, paint);
452}
453
454static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz,
455        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
456        jfloat rx, jfloat ry, jlong paintPtr) {
457    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
458    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
459    renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
460}
461
462static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
463        jlong rendererPtr, jfloat x, jfloat y, jfloat radius, jlong paintPtr) {
464    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
465    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
466    renderer->drawCircle(x, y, radius, paint);
467}
468
469static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
470        jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
471    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
472    CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
473    CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
474    CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
475    CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
476    renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
477}
478
479static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
480        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
481        jlong paintPtr) {
482    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
483    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
484    renderer->drawOval(left, top, right, bottom, paint);
485}
486
487static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz,
488        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
489        jfloat startAngle, jfloat sweepAngle, jboolean useCenter, jlong paintPtr) {
490    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
491    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
492    renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
493}
494
495static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
496        jlong rendererPtr, jlong regionPtr, jlong paintPtr) {
497    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
498    SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
499    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
500    if (paint->getStyle() != Paint::kFill_Style ||
501            (paint->isAntiAlias() && !renderer->isCurrentTransformSimple())) {
502        SkRegion::Iterator it(*region);
503        while (!it.done()) {
504            const SkIRect& r = it.rect();
505            renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
506            it.next();
507        }
508    } else {
509        int count = 0;
510        Vector<float> rects;
511        SkRegion::Iterator it(*region);
512        while (!it.done()) {
513            const SkIRect& r = it.rect();
514            rects.push(r.fLeft);
515            rects.push(r.fTop);
516            rects.push(r.fRight);
517            rects.push(r.fBottom);
518            count += 4;
519            it.next();
520        }
521        renderer->drawRects(rects.array(), count, paint);
522    }
523}
524
525static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
526        jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
527    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
528    jfloat* storage = env->GetFloatArrayElements(points, NULL);
529    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
530    renderer->drawPoints(storage + offset, count, paint);
531    env->ReleaseFloatArrayElements(points, storage, 0);
532}
533
534static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
535        jlong rendererPtr, jlong pathPtr, jlong paintPtr) {
536    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
537    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
538    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
539    renderer->drawPath(path, paint);
540}
541
542static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
543        jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
544    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
545    jfloat* storage = env->GetFloatArrayElements(points, NULL);
546    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
547    renderer->drawLines(storage + offset, count, paint);
548    env->ReleaseFloatArrayElements(points, storage, 0);
549}
550
551// ----------------------------------------------------------------------------
552// Draw filters
553// ----------------------------------------------------------------------------
554
555static void android_view_GLES20Canvas_setupPaintFilter(JNIEnv* env, jobject clazz,
556        jlong rendererPtr, jint clearBits, jint setBits) {
557    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
558    renderer->setupPaintFilter(clearBits, setBits);
559}
560
561static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject clazz,
562        jlong rendererPtr) {
563    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
564    renderer->resetPaintFilter();
565}
566
567// ----------------------------------------------------------------------------
568// Text
569// ----------------------------------------------------------------------------
570
571class RenderTextFunctor {
572public:
573    RenderTextFunctor(const Layout& layout, DisplayListRenderer* renderer, jfloat x, jfloat y,
574                Paint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
575                uirenderer::Rect& bounds)
576            : layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
577            pos(pos), totalAdvance(totalAdvance), bounds(bounds) { }
578    void operator()(size_t start, size_t end) {
579        for (size_t i = start; i < end; i++) {
580            glyphs[i] = layout.getGlyphId(i);
581            pos[2 * i] = layout.getX(i);
582            pos[2 * i + 1] = layout.getY(i);
583        }
584        size_t glyphsCount = end - start;
585        int bytesCount = glyphsCount * sizeof(jchar);
586        renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
587            x, y, pos + 2 * start, paint, totalAdvance, bounds);
588    }
589private:
590    const Layout& layout;
591    DisplayListRenderer* renderer;
592    jfloat x;
593    jfloat y;
594    Paint* paint;
595    uint16_t* glyphs;
596    float* pos;
597    float totalAdvance;
598    uirenderer::Rect& bounds;
599};
600
601static void renderTextLayout(DisplayListRenderer* renderer, Layout* layout,
602    jfloat x, jfloat y, Paint* paint) {
603    size_t nGlyphs = layout->nGlyphs();
604    float* pos = new float[nGlyphs * 2];
605    uint16_t* glyphs = new uint16_t[nGlyphs];
606    MinikinRect b;
607    layout->getBounds(&b);
608    android::uirenderer::Rect bounds(b.mLeft, b.mTop, b.mRight, b.mBottom);
609    bounds.translate(x, y);
610    float totalAdvance = layout->getAdvance();
611
612    RenderTextFunctor f(*layout, renderer, x, y, paint, glyphs, pos, totalAdvance, bounds);
613    MinikinUtils::forFontRun(*layout, paint, f);
614    delete[] glyphs;
615    delete[] pos;
616}
617
618static void renderText(DisplayListRenderer* renderer, const jchar* text, int count,
619        jfloat x, jfloat y, int bidiFlags, Paint* paint, TypefaceImpl* typeface) {
620    Layout layout;
621    MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
622    x += MinikinUtils::xOffsetForTextAlign(paint, layout);
623    renderTextLayout(renderer, &layout, x, y, paint);
624}
625
626class RenderTextOnPathFunctor {
627public:
628    RenderTextOnPathFunctor(const Layout& layout, DisplayListRenderer* renderer, float hOffset,
629                float vOffset, Paint* paint, SkPath* path)
630            : layout(layout), renderer(renderer), hOffset(hOffset), vOffset(vOffset),
631                paint(paint), path(path) {
632    }
633    void operator()(size_t start, size_t end) {
634        uint16_t glyphs[1];
635        for (size_t i = start; i < end; i++) {
636            glyphs[0] = layout.getGlyphId(i);
637            float x = hOffset + layout.getX(i);
638            float y = vOffset + layout.getY(i);
639            renderer->drawTextOnPath((const char*) glyphs, sizeof(glyphs), 1, path, x, y, paint);
640        }
641    }
642private:
643    const Layout& layout;
644    DisplayListRenderer* renderer;
645    float hOffset;
646    float vOffset;
647    Paint* paint;
648    SkPath* path;
649};
650
651static void renderTextOnPath(DisplayListRenderer* renderer, const jchar* text, int count,
652        SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, Paint* paint,
653        TypefaceImpl* typeface) {
654    Layout layout;
655    MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
656    hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
657    Paint::Align align = paint->getTextAlign();
658    paint->setTextAlign(Paint::kLeft_Align);
659
660    RenderTextOnPathFunctor f(layout, renderer, hOffset, vOffset, paint, path);
661    MinikinUtils::forFontRun(layout, paint, f);
662    paint->setTextAlign(align);
663}
664
665static void renderTextRun(DisplayListRenderer* renderer, const jchar* text,
666        jint start, jint count, jint contextCount, jfloat x, jfloat y,
667        int bidiFlags, Paint* paint, TypefaceImpl* typeface) {
668    Layout layout;
669    MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, start, count, contextCount);
670    x += MinikinUtils::xOffsetForTextAlign(paint, layout);
671    renderTextLayout(renderer, &layout, x, y, paint);
672}
673
674static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
675        jlong rendererPtr, jcharArray text, jint index, jint count,
676        jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
677    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
678    jchar* textArray = env->GetCharArrayElements(text, NULL);
679    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
680    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
681
682    renderText(renderer, textArray + index, count, x, y, bidiFlags, paint, typeface);
683    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
684}
685
686static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
687        jlong rendererPtr, jstring text, jint start, jint end,
688        jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
689    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
690    const jchar* textArray = env->GetStringChars(text, NULL);
691    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
692    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
693
694    renderText(renderer, textArray + start, end - start, x, y, bidiFlags, paint, typeface);
695    env->ReleaseStringChars(text, textArray);
696}
697
698static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
699        jlong rendererPtr, jcharArray text, jint index, jint count,
700        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
701        jlong typefacePtr) {
702    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
703    jchar* textArray = env->GetCharArrayElements(text, NULL);
704    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
705    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
706    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
707
708    renderTextOnPath(renderer, textArray + index, count, path,
709            hOffset, vOffset, bidiFlags, paint, typeface);
710    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
711}
712
713static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
714        jlong rendererPtr, jstring text, jint start, jint end,
715        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
716        jlong typefacePtr) {
717    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
718    const jchar* textArray = env->GetStringChars(text, NULL);
719    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
720    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
721    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
722
723    renderTextOnPath(renderer, textArray + start, end - start, path,
724            hOffset, vOffset, bidiFlags, paint, typeface);
725    env->ReleaseStringChars(text, textArray);
726}
727
728static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
729        jlong rendererPtr, jcharArray text, jint index, jint count,
730        jint contextIndex, jint contextCount, jfloat x, jfloat y, jboolean isRtl,
731        jlong paintPtr, jlong typefacePtr) {
732    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
733    jchar* textArray = env->GetCharArrayElements(text, NULL);
734    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
735    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
736
737    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
738    renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
739            count, contextCount, x, y, bidiFlags, paint, typeface);
740    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
741 }
742
743static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
744        jlong rendererPtr, jstring text, jint start, jint end,
745        jint contextStart, int contextEnd, jfloat x, jfloat y, jboolean isRtl,
746        jlong paintPtr, jlong typefacePtr) {
747    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
748    const jchar* textArray = env->GetStringChars(text, NULL);
749    jint count = end - start;
750    jint contextCount = contextEnd - contextStart;
751    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
752    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
753
754    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
755    renderTextRun(renderer, textArray + contextStart, start - contextStart,
756            count, contextCount, x, y, bidiFlags, paint, typeface);
757    env->ReleaseStringChars(text, textArray);
758}
759
760// ----------------------------------------------------------------------------
761// Display lists
762// ----------------------------------------------------------------------------
763
764static jlong android_view_GLES20Canvas_finishRecording(JNIEnv* env,
765        jobject clazz, jlong rendererPtr) {
766    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
767    return reinterpret_cast<jlong>(renderer->finishRecording());
768}
769
770static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jobject clazz) {
771    return reinterpret_cast<jlong>(new DisplayListRenderer);
772}
773
774static jint android_view_GLES20Canvas_drawRenderNode(JNIEnv* env,
775        jobject clazz, jlong rendererPtr, jlong renderNodePtr,
776        jobject dirty, jint flags) {
777    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
778    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
779    android::uirenderer::Rect bounds;
780    status_t status = renderer->drawRenderNode(renderNode, bounds, flags);
781    if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
782        env->CallVoidMethod(dirty, gRectClassInfo.set,
783                int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
784    }
785    return status;
786}
787
788// ----------------------------------------------------------------------------
789// Layers
790// ----------------------------------------------------------------------------
791
792static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
793        jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
794    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
795    Layer* layer = reinterpret_cast<Layer*>(layerPtr);
796    renderer->drawLayer(layer, x, y);
797}
798
799#endif // USE_OPENGL_RENDERER
800
801// ----------------------------------------------------------------------------
802// Common
803// ----------------------------------------------------------------------------
804
805static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz) {
806#ifdef USE_OPENGL_RENDERER
807    char prop[PROPERTY_VALUE_MAX];
808    if (property_get("ro.kernel.qemu", prop, NULL) == 0) {
809        // not in the emulator
810        return JNI_TRUE;
811    }
812    // In the emulator this property will be set to 1 when hardware GLES is
813    // enabled, 0 otherwise. On old emulator versions it will be undefined.
814    property_get("ro.kernel.qemu.gles", prop, "0");
815    return atoi(prop) == 1 ? JNI_TRUE : JNI_FALSE;
816#else
817    return JNI_FALSE;
818#endif
819}
820
821// ----------------------------------------------------------------------------
822// Logging
823// ----------------------------------------------------------------------------
824
825static void
826android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
827#ifdef USE_OPENGL_RENDERER
828    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
829    android::uirenderer::RenderNode::outputLogBuffer(fd);
830#endif // USE_OPENGL_RENDERER
831}
832
833// ----------------------------------------------------------------------------
834// JNI Glue
835// ----------------------------------------------------------------------------
836
837const char* const kClassPathName = "android/view/GLES20Canvas";
838
839static JNINativeMethod gMethods[] = {
840    { "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
841
842#ifdef USE_OPENGL_RENDERER
843
844    { "nDestroyRenderer",   "(J)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
845    { "nSetViewport",       "(JII)V",          (void*) android_view_GLES20Canvas_setViewport },
846    { "nSetHighContrastText","(JZ)V",          (void*) android_view_GLES20Canvas_setHighContrastText },
847    { "nPrepare",           "(JZ)I",           (void*) android_view_GLES20Canvas_prepare },
848    { "nPrepareDirty",      "(JIIIIZ)I",       (void*) android_view_GLES20Canvas_prepareDirty },
849    { "nFinish",            "(J)V",            (void*) android_view_GLES20Canvas_finish },
850    { "nSetProperty",           "(Ljava/lang/String;Ljava/lang/String;)V",
851            (void*) android_view_GLES20Canvas_setProperty },
852
853    { "nCallDrawGLFunction", "(JJ)I",          (void*) android_view_GLES20Canvas_callDrawGLFunction },
854
855    { "nSave",              "(JI)I",           (void*) android_view_GLES20Canvas_save },
856    { "nRestore",           "(J)V",            (void*) android_view_GLES20Canvas_restore },
857    { "nRestoreToCount",    "(JI)V",           (void*) android_view_GLES20Canvas_restoreToCount },
858    { "nGetSaveCount",      "(J)I",            (void*) android_view_GLES20Canvas_getSaveCount },
859
860    { "nSaveLayer",         "(JFFFFJI)I",      (void*) android_view_GLES20Canvas_saveLayer },
861    { "nSaveLayer",         "(JJI)I",          (void*) android_view_GLES20Canvas_saveLayerClip },
862    { "nSaveLayerAlpha",    "(JFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
863    { "nSaveLayerAlpha",    "(JII)I",          (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
864
865    { "nQuickReject",       "(JFFFF)Z",        (void*) android_view_GLES20Canvas_quickReject },
866    { "nClipRect",          "(JFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
867    { "nClipRect",          "(JIIIII)Z",       (void*) android_view_GLES20Canvas_clipRect },
868    { "nClipPath",          "(JJI)Z",          (void*) android_view_GLES20Canvas_clipPath },
869    { "nClipRegion",        "(JJI)Z",          (void*) android_view_GLES20Canvas_clipRegion },
870
871    { "nTranslate",         "(JFF)V",          (void*) android_view_GLES20Canvas_translate },
872    { "nRotate",            "(JF)V",           (void*) android_view_GLES20Canvas_rotate },
873    { "nScale",             "(JFF)V",          (void*) android_view_GLES20Canvas_scale },
874    { "nSkew",              "(JFF)V",          (void*) android_view_GLES20Canvas_skew },
875
876    { "nSetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_setMatrix },
877    { "nGetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_getMatrix },
878    { "nConcatMatrix",      "(JJ)V",           (void*) android_view_GLES20Canvas_concatMatrix },
879
880    { "nDrawBitmap",        "(JJ[BFFJ)V",      (void*) android_view_GLES20Canvas_drawBitmap },
881    { "nDrawBitmap",        "(JJ[BFFFFFFFFJ)V",(void*) android_view_GLES20Canvas_drawBitmapRect },
882    { "nDrawBitmap",        "(JJ[BJJ)V",       (void*) android_view_GLES20Canvas_drawBitmapMatrix },
883    { "nDrawBitmap",        "(J[IIIFFIIZJ)V",  (void*) android_view_GLES20Canvas_drawBitmapData },
884
885    { "nDrawBitmapMesh",    "(JJ[BII[FI[IIJ)V",(void*) android_view_GLES20Canvas_drawBitmapMesh },
886
887    { "nDrawPatch",         "(JJ[BJFFFFJ)V",   (void*) android_view_GLES20Canvas_drawPatch },
888
889    { "nDrawColor",         "(JII)V",          (void*) android_view_GLES20Canvas_drawColor },
890    { "nDrawRect",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawRect },
891    { "nDrawRects",         "(JJJ)V",          (void*) android_view_GLES20Canvas_drawRegionAsRects },
892    { "nDrawRoundRect",     "(JFFFFFFJ)V",     (void*) android_view_GLES20Canvas_drawRoundRect },
893    { "nDrawCircle",        "(JFFFJ)V",        (void*) android_view_GLES20Canvas_drawCircle },
894    { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_GLES20Canvas_drawCircleProps },
895    { "nDrawOval",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawOval },
896    { "nDrawArc",           "(JFFFFFFZJ)V",    (void*) android_view_GLES20Canvas_drawArc },
897    { "nDrawPoints",        "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawPoints },
898
899    { "nDrawPath",          "(JJJ)V",          (void*) android_view_GLES20Canvas_drawPath },
900    { "nDrawLines",         "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawLines },
901
902    { "nSetupPaintFilter",  "(JII)V",          (void*) android_view_GLES20Canvas_setupPaintFilter },
903    { "nResetPaintFilter",  "(J)V",            (void*) android_view_GLES20Canvas_resetPaintFilter },
904
905    { "nDrawText",          "(J[CIIFFIJJ)V",   (void*) android_view_GLES20Canvas_drawTextArray },
906    { "nDrawText",          "(JLjava/lang/String;IIFFIJJ)V",
907            (void*) android_view_GLES20Canvas_drawText },
908
909    { "nDrawTextOnPath",    "(J[CIIJFFIJJ)V",  (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
910    { "nDrawTextOnPath",    "(JLjava/lang/String;IIJFFIJJ)V",
911            (void*) android_view_GLES20Canvas_drawTextOnPath },
912
913    { "nDrawTextRun",       "(J[CIIIIFFZJJ)V",  (void*) android_view_GLES20Canvas_drawTextRunArray },
914    { "nDrawTextRun",       "(JLjava/lang/String;IIIIFFZJJ)V",
915            (void*) android_view_GLES20Canvas_drawTextRun },
916
917    { "nGetClipBounds",     "(JLandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds },
918
919    { "nFinishRecording",   "(J)J",      (void*) android_view_GLES20Canvas_finishRecording },
920    { "nDrawRenderNode",    "(JJLandroid/graphics/Rect;I)I", (void*) android_view_GLES20Canvas_drawRenderNode },
921
922    { "nCreateDisplayListRenderer", "()J",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
923
924    { "nDrawLayer",              "(JJFF)V",    (void*) android_view_GLES20Canvas_drawLayer },
925
926    { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_GLES20Canvas_getMaxTextureWidth },
927    { "nGetMaximumTextureHeight", "()I",       (void*) android_view_GLES20Canvas_getMaxTextureHeight },
928
929#endif
930};
931
932static JNINativeMethod gActivityThreadMethods[] = {
933    { "dumpGraphicsInfo",        "(Ljava/io/FileDescriptor;)V",
934                                               (void*) android_app_ActivityThread_dumpGraphics }
935};
936
937
938#ifdef USE_OPENGL_RENDERER
939    #define FIND_CLASS(var, className) \
940            var = env->FindClass(className); \
941            LOG_FATAL_IF(! var, "Unable to find class " className);
942
943    #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
944            var = env->GetMethodID(clazz, methodName, methodDescriptor); \
945            LOG_FATAL_IF(! var, "Unable to find method " methodName);
946#else
947    #define FIND_CLASS(var, className)
948    #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor)
949#endif
950
951int register_android_view_GLES20Canvas(JNIEnv* env) {
952    jclass clazz;
953    FIND_CLASS(clazz, "android/graphics/Rect");
954    GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V");
955
956    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
957}
958
959const char* const kActivityThreadPathName = "android/app/ActivityThread";
960
961int register_android_app_ActivityThread(JNIEnv* env) {
962    return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName,
963            gActivityThreadMethods, NELEM(gActivityThreadMethods));
964}
965
966};
967