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