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