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