android_view_GLES20Canvas.cpp revision 6bfd7e7df3a9f9ea2f9e57a3552eed7f518be711
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
635// TODO: this is moving to MinikinUtils, remove with USE_MINIKIN ifdef
636static float xOffsetForTextAlign(SkPaint* paint, float totalAdvance) {
637    switch (paint->getTextAlign()) {
638        case SkPaint::kCenter_Align:
639            return -totalAdvance / 2.0f;
640            break;
641        case SkPaint::kRight_Align:
642            return -totalAdvance;
643            break;
644        default:
645            break;
646    }
647    return 0;
648}
649
650#ifdef USE_MINIKIN
651
652class RenderTextFunctor {
653public:
654    RenderTextFunctor(const Layout& layout, OpenGLRenderer* renderer, jfloat x, jfloat y,
655                SkPaint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
656                uirenderer::Rect& bounds)
657            : layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
658            pos(pos), totalAdvance(totalAdvance), bounds(bounds) { }
659    void operator()(SkTypeface* t, size_t start, size_t end) {
660        for (size_t i = start; i < end; i++) {
661            glyphs[i] = layout.getGlyphId(i);
662            pos[2 * i] = layout.getX(i);
663            pos[2 * i + 1] = layout.getY(i);
664        }
665        paint->setTypeface(t);
666        size_t glyphsCount = end - start;
667        int bytesCount = glyphsCount * sizeof(jchar);
668        renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
669            x, y, pos + 2 * start, paint, totalAdvance, bounds);
670    }
671private:
672    const Layout& layout;
673    OpenGLRenderer* renderer;
674    jfloat x;
675    jfloat y;
676    SkPaint* paint;
677    uint16_t* glyphs;
678    float* pos;
679    float totalAdvance;
680    uirenderer::Rect& bounds;
681};
682
683static void renderTextLayout(OpenGLRenderer* renderer, Layout* layout,
684    jfloat x, jfloat y, SkPaint* paint) {
685    size_t nGlyphs = layout->nGlyphs();
686    float* pos = new float[nGlyphs * 2];
687    uint16_t* glyphs = new uint16_t[nGlyphs];
688    MinikinRect b;
689    layout->getBounds(&b);
690    android::uirenderer::Rect bounds(b.mLeft, b.mTop, b.mRight, b.mBottom);
691    bounds.translate(x, y);
692    float totalAdvance = layout->getAdvance();
693
694    RenderTextFunctor f(*layout, renderer, x, y, paint, glyphs, pos, totalAdvance, bounds);
695    MinikinUtils::forFontRun(*layout, f);
696    delete[] glyphs;
697    delete[] pos;
698}
699#endif
700
701static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
702        jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
703#ifdef USE_MINIKIN
704    Layout layout;
705    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
706    layout.doLayout(text, 0, count, count, css);
707    x += xOffsetForTextAlign(paint, layout.getAdvance());
708    renderTextLayout(renderer, &layout, x, y, paint);
709#else
710    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
711            text, 0, count, count, flags);
712    if (value == NULL) {
713        return;
714    }
715    const jchar* glyphs = value->getGlyphs();
716    size_t glyphsCount = value->getGlyphsCount();
717    jfloat totalAdvance = value->getTotalAdvance();
718    x += xOffsetForTextAlign(paint, totalAdvance);
719    const float* positions = value->getPos();
720    int bytesCount = glyphsCount * sizeof(jchar);
721    const SkRect& r = value->getBounds();
722    android::uirenderer::Rect bounds(r.fLeft, r.fTop, r.fRight, r.fBottom);
723    bounds.translate(x, y);
724
725    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount,
726            x, y, positions, paint, totalAdvance, bounds);
727#endif
728}
729
730static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
731        SkPath* path, jfloat hOffset, jfloat vOffset, int flags, SkPaint* paint) {
732    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
733            text, 0, count, count, flags);
734    if (value == NULL) {
735        return;
736    }
737    const jchar* glyphs = value->getGlyphs();
738    size_t glyphsCount = value->getGlyphsCount();
739    int bytesCount = glyphsCount * sizeof(jchar);
740    renderer->drawTextOnPath((const char*) glyphs, bytesCount, glyphsCount, path,
741            hOffset, vOffset, paint);
742}
743
744static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
745        jint start, jint count, jint contextCount, jfloat x, jfloat y,
746        int flags, SkPaint* paint, TypefaceImpl* typeface) {
747#ifdef USE_MINIKIN
748    Layout layout;
749    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
750    layout.doLayout(text, start, count, contextCount, css);
751    x += xOffsetForTextAlign(paint, layout.getAdvance());
752    renderTextLayout(renderer, &layout, x, y, paint);
753#else
754    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
755            text, start, count, contextCount, flags);
756    if (value == NULL) {
757        return;
758    }
759    const jchar* glyphs = value->getGlyphs();
760    size_t glyphsCount = value->getGlyphsCount();
761    jfloat totalAdvance = value->getTotalAdvance();
762    x += xOffsetForTextAlign(paint, totalAdvance);
763    const float* positions = value->getPos();
764    int bytesCount = glyphsCount * sizeof(jchar);
765    const SkRect& r = value->getBounds();
766    android::uirenderer::Rect bounds(r.fLeft, r.fTop, r.fRight, r.fBottom);
767    bounds.translate(x, y);
768
769    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount,
770            x, y, positions, paint, totalAdvance, bounds);
771#endif
772}
773
774static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
775        jlong rendererPtr, jcharArray text, jint index, jint count,
776        jfloat x, jfloat y, jint flags, jlong paintPtr, jlong typefacePtr) {
777    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
778    jchar* textArray = env->GetCharArrayElements(text, NULL);
779    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
780    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
781
782    renderText(renderer, textArray + index, count, x, y, flags, paint, typeface);
783    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
784}
785
786static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
787        jlong rendererPtr, jstring text, jint start, jint end,
788        jfloat x, jfloat y, jint flags, jlong paintPtr, jlong typefacePtr) {
789    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
790    const jchar* textArray = env->GetStringChars(text, NULL);
791    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
792    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
793
794    renderText(renderer, textArray + start, end - start, x, y, flags, paint, typeface);
795    env->ReleaseStringChars(text, textArray);
796}
797
798static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
799        jlong rendererPtr, jcharArray text, jint index, jint count,
800        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint flags, jlong paintPtr) {
801    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
802    jchar* textArray = env->GetCharArrayElements(text, NULL);
803    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
804    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
805
806    renderTextOnPath(renderer, textArray + index, count, path,
807            hOffset, vOffset, flags, paint);
808    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
809}
810
811static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
812        jlong rendererPtr, jstring text, jint start, jint end,
813        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint flags, jlong paintPtr) {
814    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
815    const jchar* textArray = env->GetStringChars(text, NULL);
816    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
817    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
818
819    renderTextOnPath(renderer, textArray + start, end - start, path,
820            hOffset, vOffset, flags, paint);
821    env->ReleaseStringChars(text, textArray);
822}
823
824static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
825        jlong rendererPtr, jcharArray text, jint index, jint count,
826        jint contextIndex, jint contextCount, jfloat x, jfloat y, jint dirFlags,
827        jlong paintPtr, jlong typefacePtr) {
828    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
829    jchar* textArray = env->GetCharArrayElements(text, NULL);
830    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
831    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
832
833    renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
834            count, contextCount, x, y, dirFlags, paint, typeface);
835    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
836 }
837
838static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
839        jlong rendererPtr, jstring text, jint start, jint end,
840        jint contextStart, int contextEnd, jfloat x, jfloat y, jint dirFlags,
841        jlong paintPtr, jlong typefacePtr) {
842    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
843    const jchar* textArray = env->GetStringChars(text, NULL);
844    jint count = end - start;
845    jint contextCount = contextEnd - contextStart;
846    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
847    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
848
849    renderTextRun(renderer, textArray + contextStart, start - contextStart,
850            count, contextCount, x, y, dirFlags, paint, typeface);
851    env->ReleaseStringChars(text, textArray);
852}
853
854static void renderPosText(OpenGLRenderer* renderer, const jchar* text, int count,
855        const jfloat* positions, jint dirFlags, SkPaint* paint) {
856    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
857            text, 0, count, count, dirFlags);
858    if (value == NULL) {
859        return;
860    }
861    const jchar* glyphs = value->getGlyphs();
862    size_t glyphsCount = value->getGlyphsCount();
863    if (count < int(glyphsCount)) glyphsCount = count;
864    int bytesCount = glyphsCount * sizeof(jchar);
865
866    renderer->drawPosText((const char*) glyphs, bytesCount, glyphsCount, positions, paint);
867}
868
869static void android_view_GLES20Canvas_drawPosTextArray(JNIEnv* env, jobject clazz,
870        jlong rendererPtr, jcharArray text, jint index, jint count,
871        jfloatArray pos, jlong paintPtr) {
872    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
873    jchar* textArray = env->GetCharArrayElements(text, NULL);
874    jfloat* positions = env->GetFloatArrayElements(pos, NULL);
875    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
876
877    renderPosText(renderer, textArray + index, count, positions, kBidi_LTR, paint);
878
879    env->ReleaseFloatArrayElements(pos, positions, JNI_ABORT);
880    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
881}
882
883static void android_view_GLES20Canvas_drawPosText(JNIEnv* env, jobject clazz,
884        jlong rendererPtr, jstring text, jint start, jint end,
885        jfloatArray pos, jlong paintPtr) {
886    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
887    const jchar* textArray = env->GetStringChars(text, NULL);
888    jfloat* positions = env->GetFloatArrayElements(pos, NULL);
889    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
890
891    renderPosText(renderer, textArray + start, end - start, positions, kBidi_LTR, paint);
892
893    env->ReleaseFloatArrayElements(pos, positions, JNI_ABORT);
894    env->ReleaseStringChars(text, textArray);
895}
896
897// ----------------------------------------------------------------------------
898// Display lists
899// ----------------------------------------------------------------------------
900
901static jlong android_view_GLES20Canvas_finishRecording(JNIEnv* env,
902        jobject clazz, jlong rendererPtr) {
903    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
904    return reinterpret_cast<jlong>(renderer->finishRecording());
905}
906
907static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jobject clazz) {
908    return reinterpret_cast<jlong>(new DisplayListRenderer);
909}
910
911static jint android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
912        jobject clazz, jlong rendererPtr, jlong displayListPtr,
913        jobject dirty, jint flags) {
914    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
915    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
916    android::uirenderer::Rect bounds;
917    status_t status = renderer->drawDisplayList(displayList, bounds, flags);
918    if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
919        env->CallVoidMethod(dirty, gRectClassInfo.set,
920                int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
921    }
922    return status;
923}
924
925// ----------------------------------------------------------------------------
926// Layers
927// ----------------------------------------------------------------------------
928
929static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
930        jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
931    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
932    Layer* layer = reinterpret_cast<Layer*>(layerPtr);
933    renderer->drawLayer(layer, x, y);
934}
935
936static jboolean android_view_GLES20Canvas_copyLayer(JNIEnv* env, jobject clazz,
937        jlong layerPtr, jlong bitmapPtr) {
938    Layer* layer = reinterpret_cast<Layer*>(layerPtr);
939    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
940    return LayerRenderer::copyLayer(layer, bitmap);
941}
942
943static void android_view_GLES20Canvas_pushLayerUpdate(JNIEnv* env, jobject clazz,
944        jlong rendererPtr, jlong layerPtr) {
945    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
946    Layer* layer = reinterpret_cast<Layer*>(layerPtr);
947    renderer->pushLayerUpdate(layer);
948}
949
950static void android_view_GLES20Canvas_cancelLayerUpdate(JNIEnv* env, jobject clazz,
951        jlong rendererPtr, jlong layerPtr) {
952    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
953    Layer* layer = reinterpret_cast<Layer*>(layerPtr);
954    renderer->cancelLayerUpdate(layer);
955}
956
957static void android_view_GLES20Canvas_clearLayerUpdates(JNIEnv* env, jobject clazz,
958        jlong rendererPtr) {
959    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
960    renderer->clearLayerUpdates();
961}
962
963static void android_view_GLES20Canvas_flushLayerUpdates(JNIEnv* env, jobject clazz,
964        jlong rendererPtr) {
965    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
966    renderer->flushLayerUpdates();
967}
968
969#endif // USE_OPENGL_RENDERER
970
971// ----------------------------------------------------------------------------
972// Common
973// ----------------------------------------------------------------------------
974
975static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz) {
976#ifdef USE_OPENGL_RENDERER
977    char prop[PROPERTY_VALUE_MAX];
978    if (property_get("ro.kernel.qemu", prop, NULL) == 0) {
979        // not in the emulator
980        return JNI_TRUE;
981    }
982    // In the emulator this property will be set to 1 when hardware GLES is
983    // enabled, 0 otherwise. On old emulator versions it will be undefined.
984    property_get("ro.kernel.qemu.gles", prop, "0");
985    return atoi(prop) == 1 ? JNI_TRUE : JNI_FALSE;
986#else
987    return JNI_FALSE;
988#endif
989}
990
991// ----------------------------------------------------------------------------
992// Logging
993// ----------------------------------------------------------------------------
994
995static void
996android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
997#ifdef USE_OPENGL_RENDERER
998    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
999    android::uirenderer::RenderNode::outputLogBuffer(fd);
1000#endif // USE_OPENGL_RENDERER
1001}
1002
1003// ----------------------------------------------------------------------------
1004// JNI Glue
1005// ----------------------------------------------------------------------------
1006
1007const char* const kClassPathName = "android/view/GLES20Canvas";
1008
1009static JNINativeMethod gMethods[] = {
1010    { "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
1011
1012#ifdef USE_OPENGL_RENDERER
1013    { "nFlushCaches",       "(I)V",            (void*) android_view_GLES20Canvas_flushCaches },
1014    { "nInitCaches",        "()Z",             (void*) android_view_GLES20Canvas_initCaches },
1015    { "nTerminateCaches",   "()V",             (void*) android_view_GLES20Canvas_terminateCaches },
1016
1017    { "nInitAtlas",         "(Landroid/view/GraphicBuffer;[JI)V",
1018            (void*) android_view_GLES20Canvas_initAtlas },
1019
1020    { "nCreateRenderer",    "()J",             (void*) android_view_GLES20Canvas_createRenderer },
1021    { "nDestroyRenderer",   "(J)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
1022    { "nSetViewport",       "(JII)V",          (void*) android_view_GLES20Canvas_setViewport },
1023    { "nPrepare",           "(JZ)I",           (void*) android_view_GLES20Canvas_prepare },
1024    { "nPrepareDirty",      "(JIIIIZ)I",       (void*) android_view_GLES20Canvas_prepareDirty },
1025    { "nFinish",            "(J)V",            (void*) android_view_GLES20Canvas_finish },
1026    { "nSetProperty",           "(Ljava/lang/String;Ljava/lang/String;)V",
1027            (void*) android_view_GLES20Canvas_setProperty },
1028
1029
1030    { "nGetStencilSize",    "()I",             (void*) android_view_GLES20Canvas_getStencilSize },
1031
1032    { "nCallDrawGLFunction", "(JJ)I",          (void*) android_view_GLES20Canvas_callDrawGLFunction },
1033
1034    { "nSave",              "(JI)I",           (void*) android_view_GLES20Canvas_save },
1035    { "nRestore",           "(J)V",            (void*) android_view_GLES20Canvas_restore },
1036    { "nRestoreToCount",    "(JI)V",           (void*) android_view_GLES20Canvas_restoreToCount },
1037    { "nGetSaveCount",      "(J)I",            (void*) android_view_GLES20Canvas_getSaveCount },
1038
1039    { "nSaveLayer",         "(JFFFFJI)I",      (void*) android_view_GLES20Canvas_saveLayer },
1040    { "nSaveLayer",         "(JJI)I",          (void*) android_view_GLES20Canvas_saveLayerClip },
1041    { "nSaveLayerAlpha",    "(JFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
1042    { "nSaveLayerAlpha",    "(JII)I",          (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
1043
1044    { "nQuickReject",       "(JFFFF)Z",        (void*) android_view_GLES20Canvas_quickReject },
1045    { "nClipRect",          "(JFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
1046    { "nClipRect",          "(JIIIII)Z",       (void*) android_view_GLES20Canvas_clipRect },
1047    { "nClipPath",          "(JJI)Z",          (void*) android_view_GLES20Canvas_clipPath },
1048    { "nClipRegion",        "(JJI)Z",          (void*) android_view_GLES20Canvas_clipRegion },
1049
1050    { "nTranslate",         "(JFF)V",          (void*) android_view_GLES20Canvas_translate },
1051    { "nRotate",            "(JF)V",           (void*) android_view_GLES20Canvas_rotate },
1052    { "nScale",             "(JFF)V",          (void*) android_view_GLES20Canvas_scale },
1053    { "nSkew",              "(JFF)V",          (void*) android_view_GLES20Canvas_skew },
1054
1055    { "nSetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_setMatrix },
1056    { "nGetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_getMatrix },
1057    { "nConcatMatrix",      "(JJ)V",           (void*) android_view_GLES20Canvas_concatMatrix },
1058
1059    { "nDrawBitmap",        "(JJ[BFFJ)V",      (void*) android_view_GLES20Canvas_drawBitmap },
1060    { "nDrawBitmap",        "(JJ[BFFFFFFFFJ)V",(void*) android_view_GLES20Canvas_drawBitmapRect },
1061    { "nDrawBitmap",        "(JJ[BJJ)V",       (void*) android_view_GLES20Canvas_drawBitmapMatrix },
1062    { "nDrawBitmap",        "(J[IIIFFIIZJ)V",  (void*) android_view_GLES20Canvas_drawBitmapData },
1063
1064    { "nDrawBitmapMesh",    "(JJ[BII[FI[IIJ)V",(void*) android_view_GLES20Canvas_drawBitmapMesh },
1065
1066    { "nDrawPatch",         "(JJ[BJFFFFJ)V",   (void*) android_view_GLES20Canvas_drawPatch },
1067
1068    { "nDrawColor",         "(JII)V",          (void*) android_view_GLES20Canvas_drawColor },
1069    { "nDrawRect",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawRect },
1070    { "nDrawRects",         "(JJJ)V",          (void*) android_view_GLES20Canvas_drawRegionAsRects },
1071    { "nDrawRects",         "(J[FIJ)V",        (void*) android_view_GLES20Canvas_drawRects },
1072    { "nDrawRoundRect",     "(JFFFFFFJ)V",     (void*) android_view_GLES20Canvas_drawRoundRect },
1073    { "nDrawCircle",        "(JFFFJ)V",        (void*) android_view_GLES20Canvas_drawCircle },
1074    { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_GLES20Canvas_drawCircleProps },
1075    { "nDrawOval",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawOval },
1076    { "nDrawArc",           "(JFFFFFFZJ)V",    (void*) android_view_GLES20Canvas_drawArc },
1077    { "nDrawPoints",        "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawPoints },
1078
1079    { "nDrawPath",          "(JJJ)V",          (void*) android_view_GLES20Canvas_drawPath },
1080    { "nDrawLines",         "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawLines },
1081
1082    { "nSetupPaintFilter",  "(JII)V",          (void*) android_view_GLES20Canvas_setupPaintFilter },
1083    { "nResetPaintFilter",  "(J)V",            (void*) android_view_GLES20Canvas_resetPaintFilter },
1084
1085    { "nDrawText",          "(J[CIIFFIJJ)V",   (void*) android_view_GLES20Canvas_drawTextArray },
1086    { "nDrawText",          "(JLjava/lang/String;IIFFIJJ)V",
1087            (void*) android_view_GLES20Canvas_drawText },
1088
1089    { "nDrawTextOnPath",    "(J[CIIJFFIJ)V",   (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
1090    { "nDrawTextOnPath",    "(JLjava/lang/String;IIJFFIJ)V",
1091            (void*) android_view_GLES20Canvas_drawTextOnPath },
1092
1093    { "nDrawTextRun",       "(J[CIIIIFFIJJ)V",  (void*) android_view_GLES20Canvas_drawTextRunArray },
1094    { "nDrawTextRun",       "(JLjava/lang/String;IIIIFFIJJ)V",
1095            (void*) android_view_GLES20Canvas_drawTextRun },
1096
1097    { "nDrawPosText",       "(J[CII[FJ)V",     (void*) android_view_GLES20Canvas_drawPosTextArray },
1098    { "nDrawPosText",       "(JLjava/lang/String;II[FJ)V",
1099            (void*) android_view_GLES20Canvas_drawPosText },
1100
1101    { "nGetClipBounds",     "(JLandroid/graphics/Rect;)Z",
1102            (void*) android_view_GLES20Canvas_getClipBounds },
1103
1104    { "nFinishRecording",        "(J)J",      (void*) android_view_GLES20Canvas_finishRecording },
1105    { "nDrawDisplayList",        "(JJLandroid/graphics/Rect;I)I",
1106            (void*) android_view_GLES20Canvas_drawDisplayList },
1107
1108    { "nCreateDisplayListRenderer", "()J",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
1109
1110    { "nDrawLayer",              "(JJFF)V",    (void*) android_view_GLES20Canvas_drawLayer },
1111    { "nCopyLayer",              "(JJ)Z",      (void*) android_view_GLES20Canvas_copyLayer },
1112    { "nClearLayerUpdates",      "(J)V",       (void*) android_view_GLES20Canvas_clearLayerUpdates },
1113    { "nFlushLayerUpdates",      "(J)V",       (void*) android_view_GLES20Canvas_flushLayerUpdates },
1114    { "nPushLayerUpdate",        "(JJ)V",      (void*) android_view_GLES20Canvas_pushLayerUpdate },
1115    { "nCancelLayerUpdate",      "(JJ)V",      (void*) android_view_GLES20Canvas_cancelLayerUpdate },
1116
1117    { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_GLES20Canvas_getMaxTextureWidth },
1118    { "nGetMaximumTextureHeight", "()I",       (void*) android_view_GLES20Canvas_getMaxTextureHeight },
1119
1120#endif
1121};
1122
1123static JNINativeMethod gActivityThreadMethods[] = {
1124    { "dumpGraphicsInfo",        "(Ljava/io/FileDescriptor;)V",
1125                                               (void*) android_app_ActivityThread_dumpGraphics }
1126};
1127
1128
1129#ifdef USE_OPENGL_RENDERER
1130    #define FIND_CLASS(var, className) \
1131            var = env->FindClass(className); \
1132            LOG_FATAL_IF(! var, "Unable to find class " className);
1133
1134    #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
1135            var = env->GetMethodID(clazz, methodName, methodDescriptor); \
1136            LOG_FATAL_IF(! var, "Unable to find method " methodName);
1137#else
1138    #define FIND_CLASS(var, className)
1139    #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor)
1140#endif
1141
1142int register_android_view_GLES20Canvas(JNIEnv* env) {
1143    jclass clazz;
1144    FIND_CLASS(clazz, "android/graphics/Rect");
1145    GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V");
1146
1147    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
1148}
1149
1150const char* const kActivityThreadPathName = "android/app/ActivityThread";
1151
1152int register_android_app_ActivityThread(JNIEnv* env) {
1153    return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName,
1154            gActivityThreadMethods, NELEM(gActivityThreadMethods));
1155}
1156
1157};
1158