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