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