android_view_GLES20Canvas.cpp revision cce47eb580d666ead1f6095d1e3b65233592bbaa
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 <SkPaint.h>
36#include <SkPorterDuff.h>
37#include <SkRegion.h>
38#include <SkScalerContext.h>
39#include <SkTemplates.h>
40#include <SkXfermode.h>
41
42#include <DisplayListRenderer.h>
43#include <Rect.h>
44#include <RenderNode.h>
45#include <CanvasProperty.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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
502    if (paint->getStyle() != SkPaint::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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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    SkPaint* paint = reinterpret_cast<SkPaint*>(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                SkPaint* 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    SkPaint* 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, SkPaint* 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, SkPaint* paint, TypefaceImpl* typeface) {
622    Layout layout;
623    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
624    layout.doLayout(text, 0, count, count, css);
625    x += MinikinUtils::xOffsetForTextAlign(paint, layout);
626    renderTextLayout(renderer, &layout, x, y, paint);
627}
628
629class RenderTextOnPathFunctor {
630public:
631    RenderTextOnPathFunctor(const Layout& layout, DisplayListRenderer* renderer, float hOffset,
632                float vOffset, SkPaint* paint, SkPath* path)
633            : layout(layout), renderer(renderer), hOffset(hOffset), vOffset(vOffset),
634                paint(paint), path(path) {
635    }
636    void operator()(size_t start, size_t end) {
637        uint16_t glyphs[1];
638        for (size_t i = start; i < end; i++) {
639            glyphs[0] = layout.getGlyphId(i);
640            float x = hOffset + layout.getX(i);
641            float y = vOffset + layout.getY(i);
642            renderer->drawTextOnPath((const char*) glyphs, sizeof(glyphs), 1, path, x, y, paint);
643        }
644    }
645private:
646    const Layout& layout;
647    DisplayListRenderer* renderer;
648    float hOffset;
649    float vOffset;
650    SkPaint* paint;
651    SkPath* path;
652};
653
654static void renderTextOnPath(DisplayListRenderer* renderer, const jchar* text, int count,
655        SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, SkPaint* paint,
656        TypefaceImpl* typeface) {
657    Layout layout;
658    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
659    layout.doLayout(text, 0, count, count, css);
660    hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
661    SkPaint::Align align = paint->getTextAlign();
662    paint->setTextAlign(SkPaint::kLeft_Align);
663
664    RenderTextOnPathFunctor f(layout, renderer, hOffset, vOffset, paint, path);
665    MinikinUtils::forFontRun(layout, paint, f);
666    paint->setTextAlign(align);
667}
668
669static void renderTextRun(DisplayListRenderer* renderer, const jchar* text,
670        jint start, jint count, jint contextCount, jfloat x, jfloat y,
671        int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
672    Layout layout;
673    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
674    layout.doLayout(text, start, count, contextCount, css);
675    x += MinikinUtils::xOffsetForTextAlign(paint, layout);
676    renderTextLayout(renderer, &layout, x, y, paint);
677}
678
679static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
680        jlong rendererPtr, jcharArray text, jint index, jint count,
681        jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
682    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
683    jchar* textArray = env->GetCharArrayElements(text, NULL);
684    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
685    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
686
687    renderText(renderer, textArray + index, count, x, y, bidiFlags, paint, typeface);
688    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
689}
690
691static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
692        jlong rendererPtr, jstring text, jint start, jint end,
693        jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
694    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
695    const jchar* textArray = env->GetStringChars(text, NULL);
696    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
697    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
698
699    renderText(renderer, textArray + start, end - start, x, y, bidiFlags, paint, typeface);
700    env->ReleaseStringChars(text, textArray);
701}
702
703static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
704        jlong rendererPtr, jcharArray text, jint index, jint count,
705        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
706        jlong typefacePtr) {
707    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
708    jchar* textArray = env->GetCharArrayElements(text, NULL);
709    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
710    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
711    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
712
713    renderTextOnPath(renderer, textArray + index, count, path,
714            hOffset, vOffset, bidiFlags, paint, typeface);
715    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
716}
717
718static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
719        jlong rendererPtr, jstring text, jint start, jint end,
720        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
721        jlong typefacePtr) {
722    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
723    const jchar* textArray = env->GetStringChars(text, NULL);
724    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
725    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
726    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
727
728    renderTextOnPath(renderer, textArray + start, end - start, path,
729            hOffset, vOffset, bidiFlags, paint, typeface);
730    env->ReleaseStringChars(text, textArray);
731}
732
733static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
734        jlong rendererPtr, jcharArray text, jint index, jint count,
735        jint contextIndex, jint contextCount, jfloat x, jfloat y, jboolean isRtl,
736        jlong paintPtr, jlong typefacePtr) {
737    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
738    jchar* textArray = env->GetCharArrayElements(text, NULL);
739    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
740    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
741
742    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
743    renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
744            count, contextCount, x, y, bidiFlags, paint, typeface);
745    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
746 }
747
748static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
749        jlong rendererPtr, jstring text, jint start, jint end,
750        jint contextStart, int contextEnd, jfloat x, jfloat y, jboolean isRtl,
751        jlong paintPtr, jlong typefacePtr) {
752    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
753    const jchar* textArray = env->GetStringChars(text, NULL);
754    jint count = end - start;
755    jint contextCount = contextEnd - contextStart;
756    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
757    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
758
759    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
760    renderTextRun(renderer, textArray + contextStart, start - contextStart,
761            count, contextCount, x, y, bidiFlags, paint, typeface);
762    env->ReleaseStringChars(text, textArray);
763}
764
765// ----------------------------------------------------------------------------
766// Display lists
767// ----------------------------------------------------------------------------
768
769static jlong android_view_GLES20Canvas_finishRecording(JNIEnv* env,
770        jobject clazz, jlong rendererPtr) {
771    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
772    return reinterpret_cast<jlong>(renderer->finishRecording());
773}
774
775static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jobject clazz) {
776    return reinterpret_cast<jlong>(new DisplayListRenderer);
777}
778
779static jint android_view_GLES20Canvas_drawRenderNode(JNIEnv* env,
780        jobject clazz, jlong rendererPtr, jlong renderNodePtr,
781        jobject dirty, jint flags) {
782    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
783    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
784    android::uirenderer::Rect bounds;
785    status_t status = renderer->drawRenderNode(renderNode, bounds, flags);
786    if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
787        env->CallVoidMethod(dirty, gRectClassInfo.set,
788                int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
789    }
790    return status;
791}
792
793// ----------------------------------------------------------------------------
794// Layers
795// ----------------------------------------------------------------------------
796
797static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
798        jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
799    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
800    Layer* layer = reinterpret_cast<Layer*>(layerPtr);
801    renderer->drawLayer(layer, x, y);
802}
803
804#endif // USE_OPENGL_RENDERER
805
806// ----------------------------------------------------------------------------
807// Common
808// ----------------------------------------------------------------------------
809
810static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz) {
811#ifdef USE_OPENGL_RENDERER
812    char prop[PROPERTY_VALUE_MAX];
813    if (property_get("ro.kernel.qemu", prop, NULL) == 0) {
814        // not in the emulator
815        return JNI_TRUE;
816    }
817    // In the emulator this property will be set to 1 when hardware GLES is
818    // enabled, 0 otherwise. On old emulator versions it will be undefined.
819    property_get("ro.kernel.qemu.gles", prop, "0");
820    return atoi(prop) == 1 ? JNI_TRUE : JNI_FALSE;
821#else
822    return JNI_FALSE;
823#endif
824}
825
826// ----------------------------------------------------------------------------
827// Logging
828// ----------------------------------------------------------------------------
829
830static void
831android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
832#ifdef USE_OPENGL_RENDERER
833    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
834    android::uirenderer::RenderNode::outputLogBuffer(fd);
835#endif // USE_OPENGL_RENDERER
836}
837
838// ----------------------------------------------------------------------------
839// JNI Glue
840// ----------------------------------------------------------------------------
841
842const char* const kClassPathName = "android/view/GLES20Canvas";
843
844static JNINativeMethod gMethods[] = {
845    { "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
846
847#ifdef USE_OPENGL_RENDERER
848
849    { "nDestroyRenderer",   "(J)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
850    { "nSetViewport",       "(JII)V",          (void*) android_view_GLES20Canvas_setViewport },
851    { "nSetHighContrastText","(JZ)V",          (void*) android_view_GLES20Canvas_setHighContrastText },
852    { "nPrepare",           "(JZ)I",           (void*) android_view_GLES20Canvas_prepare },
853    { "nPrepareDirty",      "(JIIIIZ)I",       (void*) android_view_GLES20Canvas_prepareDirty },
854    { "nFinish",            "(J)V",            (void*) android_view_GLES20Canvas_finish },
855    { "nSetProperty",           "(Ljava/lang/String;Ljava/lang/String;)V",
856            (void*) android_view_GLES20Canvas_setProperty },
857
858    { "nCallDrawGLFunction", "(JJ)I",          (void*) android_view_GLES20Canvas_callDrawGLFunction },
859
860    { "nSave",              "(JI)I",           (void*) android_view_GLES20Canvas_save },
861    { "nRestore",           "(J)V",            (void*) android_view_GLES20Canvas_restore },
862    { "nRestoreToCount",    "(JI)V",           (void*) android_view_GLES20Canvas_restoreToCount },
863    { "nGetSaveCount",      "(J)I",            (void*) android_view_GLES20Canvas_getSaveCount },
864
865    { "nSaveLayer",         "(JFFFFJI)I",      (void*) android_view_GLES20Canvas_saveLayer },
866    { "nSaveLayer",         "(JJI)I",          (void*) android_view_GLES20Canvas_saveLayerClip },
867    { "nSaveLayerAlpha",    "(JFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
868    { "nSaveLayerAlpha",    "(JII)I",          (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
869
870    { "nQuickReject",       "(JFFFF)Z",        (void*) android_view_GLES20Canvas_quickReject },
871    { "nClipRect",          "(JFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
872    { "nClipRect",          "(JIIIII)Z",       (void*) android_view_GLES20Canvas_clipRect },
873    { "nClipPath",          "(JJI)Z",          (void*) android_view_GLES20Canvas_clipPath },
874    { "nClipRegion",        "(JJI)Z",          (void*) android_view_GLES20Canvas_clipRegion },
875
876    { "nTranslate",         "(JFF)V",          (void*) android_view_GLES20Canvas_translate },
877    { "nRotate",            "(JF)V",           (void*) android_view_GLES20Canvas_rotate },
878    { "nScale",             "(JFF)V",          (void*) android_view_GLES20Canvas_scale },
879    { "nSkew",              "(JFF)V",          (void*) android_view_GLES20Canvas_skew },
880
881    { "nSetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_setMatrix },
882    { "nGetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_getMatrix },
883    { "nConcatMatrix",      "(JJ)V",           (void*) android_view_GLES20Canvas_concatMatrix },
884
885    { "nDrawBitmap",        "(JJ[BFFJ)V",      (void*) android_view_GLES20Canvas_drawBitmap },
886    { "nDrawBitmap",        "(JJ[BFFFFFFFFJ)V",(void*) android_view_GLES20Canvas_drawBitmapRect },
887    { "nDrawBitmap",        "(JJ[BJJ)V",       (void*) android_view_GLES20Canvas_drawBitmapMatrix },
888    { "nDrawBitmap",        "(J[IIIFFIIZJ)V",  (void*) android_view_GLES20Canvas_drawBitmapData },
889
890    { "nDrawBitmapMesh",    "(JJ[BII[FI[IIJ)V",(void*) android_view_GLES20Canvas_drawBitmapMesh },
891
892    { "nDrawPatch",         "(JJ[BJFFFFJ)V",   (void*) android_view_GLES20Canvas_drawPatch },
893
894    { "nDrawColor",         "(JII)V",          (void*) android_view_GLES20Canvas_drawColor },
895    { "nDrawRect",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawRect },
896    { "nDrawRects",         "(JJJ)V",          (void*) android_view_GLES20Canvas_drawRegionAsRects },
897    { "nDrawRoundRect",     "(JFFFFFFJ)V",     (void*) android_view_GLES20Canvas_drawRoundRect },
898    { "nDrawCircle",        "(JFFFJ)V",        (void*) android_view_GLES20Canvas_drawCircle },
899    { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_GLES20Canvas_drawCircleProps },
900    { "nDrawOval",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawOval },
901    { "nDrawArc",           "(JFFFFFFZJ)V",    (void*) android_view_GLES20Canvas_drawArc },
902    { "nDrawPoints",        "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawPoints },
903
904    { "nDrawPath",          "(JJJ)V",          (void*) android_view_GLES20Canvas_drawPath },
905    { "nDrawLines",         "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawLines },
906
907    { "nSetupPaintFilter",  "(JII)V",          (void*) android_view_GLES20Canvas_setupPaintFilter },
908    { "nResetPaintFilter",  "(J)V",            (void*) android_view_GLES20Canvas_resetPaintFilter },
909
910    { "nDrawText",          "(J[CIIFFIJJ)V",   (void*) android_view_GLES20Canvas_drawTextArray },
911    { "nDrawText",          "(JLjava/lang/String;IIFFIJJ)V",
912            (void*) android_view_GLES20Canvas_drawText },
913
914    { "nDrawTextOnPath",    "(J[CIIJFFIJJ)V",  (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
915    { "nDrawTextOnPath",    "(JLjava/lang/String;IIJFFIJJ)V",
916            (void*) android_view_GLES20Canvas_drawTextOnPath },
917
918    { "nDrawTextRun",       "(J[CIIIIFFZJJ)V",  (void*) android_view_GLES20Canvas_drawTextRunArray },
919    { "nDrawTextRun",       "(JLjava/lang/String;IIIIFFZJJ)V",
920            (void*) android_view_GLES20Canvas_drawTextRun },
921
922    { "nGetClipBounds",     "(JLandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds },
923
924    { "nFinishRecording",   "(J)J",      (void*) android_view_GLES20Canvas_finishRecording },
925    { "nDrawRenderNode",    "(JJLandroid/graphics/Rect;I)I", (void*) android_view_GLES20Canvas_drawRenderNode },
926
927    { "nCreateDisplayListRenderer", "()J",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
928
929    { "nDrawLayer",              "(JJFF)V",    (void*) android_view_GLES20Canvas_drawLayer },
930
931    { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_GLES20Canvas_getMaxTextureWidth },
932    { "nGetMaximumTextureHeight", "()I",       (void*) android_view_GLES20Canvas_getMaxTextureHeight },
933
934#endif
935};
936
937static JNINativeMethod gActivityThreadMethods[] = {
938    { "dumpGraphicsInfo",        "(Ljava/io/FileDescriptor;)V",
939                                               (void*) android_app_ActivityThread_dumpGraphics }
940};
941
942
943#ifdef USE_OPENGL_RENDERER
944    #define FIND_CLASS(var, className) \
945            var = env->FindClass(className); \
946            LOG_FATAL_IF(! var, "Unable to find class " className);
947
948    #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
949            var = env->GetMethodID(clazz, methodName, methodDescriptor); \
950            LOG_FATAL_IF(! var, "Unable to find method " methodName);
951#else
952    #define FIND_CLASS(var, className)
953    #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor)
954#endif
955
956int register_android_view_GLES20Canvas(JNIEnv* env) {
957    jclass clazz;
958    FIND_CLASS(clazz, "android/graphics/Rect");
959    GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V");
960
961    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
962}
963
964const char* const kActivityThreadPathName = "android/app/ActivityThread";
965
966int register_android_app_ActivityThread(JNIEnv* env) {
967    return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName,
968            gActivityThreadMethods, NELEM(gActivityThreadMethods));
969}
970
971};
972