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