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