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