Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "OpenGLRenderer"
     18 
     19 #include "jni.h"
     20 #include "GraphicsJNI.h"
     21 #include <nativehelper/JNIHelp.h>
     22 
     23 #include <android_runtime/AndroidRuntime.h>
     24 
     25 #include <androidfw/ResourceTypes.h>
     26 
     27 #include <private/hwui/DrawGlInfo.h>
     28 
     29 #include <cutils/properties.h>
     30 
     31 #include <SkBitmap.h>
     32 #include <SkCanvas.h>
     33 #include <SkImageInfo.h>
     34 #include <SkMatrix.h>
     35 #include <SkPorterDuff.h>
     36 #include <SkRegion.h>
     37 #include <SkScalerContext.h>
     38 #include <SkTemplates.h>
     39 #include <SkXfermode.h>
     40 
     41 #include <DisplayListRenderer.h>
     42 #include <Rect.h>
     43 #include <RenderNode.h>
     44 #include <CanvasProperty.h>
     45 #include <Paint.h>
     46 #include <renderthread/RenderProxy.h>
     47 
     48 #include "MinikinUtils.h"
     49 
     50 namespace android {
     51 
     52 using namespace uirenderer;
     53 
     54 /**
     55  * Note: DisplayListRenderer JNI layer is generated and compiled only on supported
     56  *       devices. This means all the logic must be compiled only when the
     57  *       preprocessor variable USE_OPENGL_RENDERER is defined.
     58  */
     59 #ifdef USE_OPENGL_RENDERER
     60 
     61 // ----------------------------------------------------------------------------
     62 // Defines
     63 // ----------------------------------------------------------------------------
     64 
     65 // Debug
     66 #define DEBUG_RENDERER 0
     67 
     68 // Debug
     69 #if DEBUG_RENDERER
     70     #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__)
     71 #else
     72     #define RENDERER_LOGD(...)
     73 #endif
     74 
     75 // ----------------------------------------------------------------------------
     76 
     77 static struct {
     78     jmethodID set;
     79 } gRectClassInfo;
     80 
     81 // ----------------------------------------------------------------------------
     82 // Constructors
     83 // ----------------------------------------------------------------------------
     84 
     85 static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
     86         jlong rendererPtr) {
     87     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     88     RENDERER_LOGD("Destroy DisplayListRenderer");
     89     delete renderer;
     90 }
     91 
     92 // ----------------------------------------------------------------------------
     93 // Setup
     94 // ----------------------------------------------------------------------------
     95 
     96 static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz,
     97         jlong rendererPtr, jint width, jint height) {
     98     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     99     renderer->setViewport(width, height);
    100 }
    101 
    102 static void android_view_GLES20Canvas_setHighContrastText(JNIEnv* env, jobject clazz,
    103         jlong rendererPtr, jboolean highContrastText) {
    104     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    105     renderer->setHighContrastText(highContrastText);
    106 }
    107 
    108 static void android_view_GLES20Canvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
    109         jlong rendererPtr, jboolean reorderEnable) {
    110     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    111     renderer->insertReorderBarrier(reorderEnable);
    112 }
    113 
    114 static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
    115         jlong rendererPtr, jboolean opaque) {
    116     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    117     return renderer->prepare(opaque);
    118 }
    119 
    120 static int android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
    121         jlong rendererPtr, jint left, jint top, jint right, jint bottom,
    122         jboolean opaque) {
    123     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    124     return renderer->prepareDirty(left, top, right, bottom, opaque);
    125 }
    126 
    127 static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
    128         jlong rendererPtr) {
    129     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    130     renderer->finish();
    131 }
    132 
    133 static void android_view_GLES20Canvas_setProperty(JNIEnv* env,
    134         jobject clazz, jstring name, jstring value) {
    135     if (!Caches::hasInstance()) {
    136         ALOGW("can't set property, no Caches instance");
    137         return;
    138     }
    139 
    140     if (name == NULL || value == NULL) {
    141         ALOGW("can't set prop, null passed");
    142     }
    143 
    144     const char* nameCharArray = env->GetStringUTFChars(name, NULL);
    145     const char* valueCharArray = env->GetStringUTFChars(value, NULL);
    146     Caches::getInstance().setTempProperty(nameCharArray, valueCharArray);
    147     env->ReleaseStringUTFChars(name, nameCharArray);
    148     env->ReleaseStringUTFChars(name, valueCharArray);
    149 }
    150 
    151 // ----------------------------------------------------------------------------
    152 // Functor
    153 // ----------------------------------------------------------------------------
    154 
    155 static jint android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
    156         jlong rendererPtr, jlong functorPtr) {
    157     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    158     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
    159     android::uirenderer::Rect dirty;
    160     return renderer->callDrawGLFunction(functor, dirty);
    161 }
    162 
    163 // ----------------------------------------------------------------------------
    164 // Misc
    165 // ----------------------------------------------------------------------------
    166 
    167 static jint android_view_GLES20Canvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) {
    168     return Caches::getInstance().maxTextureSize;
    169 }
    170 
    171 static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject clazz) {
    172     return Caches::getInstance().maxTextureSize;
    173 }
    174 
    175 // ----------------------------------------------------------------------------
    176 // State
    177 // ----------------------------------------------------------------------------
    178 
    179 static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, jlong rendererPtr,
    180         jint flags) {
    181     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    182     return renderer->save(flags);
    183 }
    184 
    185 static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz,
    186         jlong rendererPtr) {
    187     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    188     return renderer->getSaveCount();
    189 }
    190 
    191 static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz,
    192         jlong rendererPtr) {
    193     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    194     renderer->restore();
    195 }
    196 
    197 static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
    198         jlong rendererPtr, jint saveCount) {
    199     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    200     renderer->restoreToCount(saveCount);
    201 }
    202 
    203 // ----------------------------------------------------------------------------
    204 // Layers
    205 // ----------------------------------------------------------------------------
    206 
    207 static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
    208         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
    209         jlong paintPtr, jint saveFlags) {
    210     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    211     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    212     return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
    213 }
    214 
    215 static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
    216         jlong rendererPtr, jlong paintPtr, jint saveFlags) {
    217     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    218     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    219     const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
    220     return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
    221             paint, saveFlags);
    222 }
    223 
    224 static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
    225         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
    226         jint alpha, jint saveFlags) {
    227     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    228     return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
    229 }
    230 
    231 static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
    232         jlong rendererPtr, jint alpha, jint saveFlags) {
    233     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    234     const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
    235     return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
    236             alpha, saveFlags);
    237 }
    238 
    239 // ----------------------------------------------------------------------------
    240 // Clipping
    241 // ----------------------------------------------------------------------------
    242 
    243 static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
    244         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom) {
    245     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    246     const bool result = renderer->quickRejectConservative(left, top, right, bottom);
    247     return result ? JNI_TRUE : JNI_FALSE;
    248 }
    249 
    250 static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
    251         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
    252         jint op) {
    253     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    254     const bool result = renderer->clipRect(left, top, right, bottom,
    255                                            static_cast<SkRegion::Op>(op));
    256     return result ? JNI_TRUE : JNI_FALSE;
    257 }
    258 
    259 static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
    260         jlong rendererPtr, jint left, jint top, jint right, jint bottom,
    261         jint op) {
    262     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    263     const bool result = renderer->clipRect(float(left), float(top), float(right),
    264                                            float(bottom),
    265                                            static_cast<SkRegion::Op>(op));
    266     return result ? JNI_TRUE : JNI_FALSE;
    267 }
    268 
    269 static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
    270         jlong rendererPtr, jlong pathPtr, jint op) {
    271     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    272     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
    273     const bool result = renderer->clipPath(path, static_cast<SkRegion::Op>(op));
    274     return result ? JNI_TRUE : JNI_FALSE;
    275 }
    276 
    277 static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
    278         jlong rendererPtr, jlong regionPtr, jint op) {
    279     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    280     SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
    281     const bool result = renderer->clipRegion(region, static_cast<SkRegion::Op>(op));
    282     return result ? JNI_TRUE : JNI_FALSE;
    283 }
    284 
    285 static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
    286         jlong rendererPtr, jobject rect) {
    287     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    288     const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
    289 
    290     env->CallVoidMethod(rect, gRectClassInfo.set,
    291             int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
    292 
    293     return !bounds.isEmpty() ? JNI_TRUE : JNI_FALSE;
    294 }
    295 
    296 // ----------------------------------------------------------------------------
    297 // Transforms
    298 // ----------------------------------------------------------------------------
    299 
    300 static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz,
    301         jlong rendererPtr, jfloat dx, jfloat dy) {
    302     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    303     renderer->translate(dx, dy);
    304 }
    305 
    306 static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz,
    307         jlong rendererPtr, jfloat degrees) {
    308     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    309     renderer->rotate(degrees);
    310 }
    311 
    312 static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz,
    313         jlong rendererPtr, jfloat sx, jfloat sy) {
    314     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    315     renderer->scale(sx, sy);
    316 }
    317 
    318 static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz,
    319         jlong rendererPtr, jfloat sx, jfloat sy) {
    320     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    321     renderer->skew(sx, sy);
    322 }
    323 
    324 static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz,
    325         jlong rendererPtr, jlong matrixPtr) {
    326     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    327     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
    328     renderer->setMatrix(matrix ? *matrix : SkMatrix::I());
    329 }
    330 
    331 static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz,
    332         jlong rendererPtr, jlong matrixPtr) {
    333     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    334     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
    335     renderer->getMatrix(matrix);
    336 }
    337 
    338 static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
    339         jlong rendererPtr, jlong matrixPtr) {
    340     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    341     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
    342     renderer->concatMatrix(*matrix);
    343 }
    344 
    345 // ----------------------------------------------------------------------------
    346 // Drawing
    347 // ----------------------------------------------------------------------------
    348 
    349 static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
    350         jlong rendererPtr, jlong bitmapPtr, jfloat left, jfloat top, jlong paintPtr) {
    351     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
    352 
    353     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    354     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    355 
    356     // apply transform directly to canvas, so it affects shaders correctly
    357     renderer->save(SkCanvas::kMatrix_SaveFlag);
    358     renderer->translate(left, top);
    359     renderer->drawBitmap(bitmap, paint);
    360     renderer->restore();
    361 }
    362 
    363 static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz,
    364         jlong rendererPtr, jlong bitmapPtr,
    365         float srcLeft, float srcTop, float srcRight, float srcBottom,
    366         float dstLeft, float dstTop, float dstRight, float dstBottom, jlong paintPtr) {
    367     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
    368 
    369     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    370     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    371     renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
    372             dstLeft, dstTop, dstRight, dstBottom, paint);
    373 }
    374 
    375 static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject clazz,
    376         jlong rendererPtr, jlong bitmapPtr, jlong matrixPtr, jlong paintPtr) {
    377     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
    378 
    379     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    380     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
    381     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    382 
    383     // apply transform directly to canvas, so it affects shaders correctly
    384     renderer->save(SkCanvas::kMatrix_SaveFlag);
    385     renderer->concatMatrix(*matrix);
    386     renderer->drawBitmap(bitmap, paint);
    387     renderer->restore();
    388 }
    389 
    390 static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
    391         jlong rendererPtr, jintArray colors, jint offset, jint stride,
    392         jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, jlong paintPtr) {
    393     // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
    394     // correct the alphaType to kOpaque_SkAlphaType.
    395     const SkImageInfo info = SkImageInfo::Make(width, height,
    396                                hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
    397                                kPremul_SkAlphaType);
    398     SkBitmap* bitmap = new SkBitmap;
    399     if (!bitmap->allocPixels(info)) {
    400         delete bitmap;
    401         return;
    402     }
    403 
    404     if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap)) {
    405         delete bitmap;
    406         return;
    407     }
    408 
    409     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    410     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    411 
    412     // apply transform directly to canvas, so it affects shaders correctly
    413     renderer->save(SkCanvas::kMatrix_SaveFlag);
    414     renderer->translate(left, top);
    415     renderer->drawBitmapData(bitmap, paint);
    416     renderer->restore();
    417 
    418     // Note - bitmap isn't deleted as DisplayListRenderer owns it now
    419 }
    420 
    421 static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
    422         jlong rendererPtr, jlong bitmapPtr, jint meshWidth, jint meshHeight,
    423         jfloatArray vertices, jint offset, jintArray colors, jint colorOffset, jlong paintPtr) {
    424     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
    425 
    426     jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL;
    427     jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
    428 
    429     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    430     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    431     renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint);
    432 
    433     if (vertices) env->ReleaseFloatArrayElements(vertices, verticesArray, 0);
    434     if (colors) env->ReleaseIntArrayElements(colors, colorsArray, 0);
    435 }
    436 
    437 static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
    438         jlong rendererPtr, jlong bitmapPtr, jlong patchPtr,
    439         float left, float top, float right, float bottom, jlong paintPtr) {
    440     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
    441 
    442     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    443     Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr);
    444     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    445     renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
    446 }
    447 
    448 static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
    449         jlong rendererPtr, jint color, jint modeHandle) {
    450     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    451     SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
    452     renderer->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
    453 }
    454 
    455 static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
    456         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
    457         jlong paintPtr) {
    458     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    459     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    460     renderer->drawRect(left, top, right, bottom, paint);
    461 }
    462 
    463 static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz,
    464         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
    465         jfloat rx, jfloat ry, jlong paintPtr) {
    466     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    467     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    468     renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
    469 }
    470 
    471 static void android_view_GLES20Canvas_drawRoundRectProps(JNIEnv* env, jobject clazz,
    472         jlong rendererPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
    473         jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) {
    474     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    475     CanvasPropertyPrimitive* leftProp = reinterpret_cast<CanvasPropertyPrimitive*>(leftPropPtr);
    476     CanvasPropertyPrimitive* topProp = reinterpret_cast<CanvasPropertyPrimitive*>(topPropPtr);
    477     CanvasPropertyPrimitive* rightProp = reinterpret_cast<CanvasPropertyPrimitive*>(rightPropPtr);
    478     CanvasPropertyPrimitive* bottomProp = reinterpret_cast<CanvasPropertyPrimitive*>(bottomPropPtr);
    479     CanvasPropertyPrimitive* rxProp = reinterpret_cast<CanvasPropertyPrimitive*>(rxPropPtr);
    480     CanvasPropertyPrimitive* ryProp = reinterpret_cast<CanvasPropertyPrimitive*>(ryPropPtr);
    481     CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
    482     renderer->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp);
    483 }
    484 
    485 static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
    486         jlong rendererPtr, jfloat x, jfloat y, jfloat radius, jlong paintPtr) {
    487     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    488     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    489     renderer->drawCircle(x, y, radius, paint);
    490 }
    491 
    492 static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
    493         jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
    494     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    495     CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
    496     CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
    497     CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
    498     CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
    499     renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
    500 }
    501 
    502 static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
    503         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
    504         jlong paintPtr) {
    505     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    506     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    507     renderer->drawOval(left, top, right, bottom, paint);
    508 }
    509 
    510 static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz,
    511         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
    512         jfloat startAngle, jfloat sweepAngle, jboolean useCenter, jlong paintPtr) {
    513     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    514     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    515     renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
    516 }
    517 
    518 static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
    519         jlong rendererPtr, jlong regionPtr, jlong paintPtr) {
    520     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    521     SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
    522     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    523     if (paint->getStyle() != Paint::kFill_Style ||
    524             (paint->isAntiAlias() && !renderer->isCurrentTransformSimple())) {
    525         SkRegion::Iterator it(*region);
    526         while (!it.done()) {
    527             const SkIRect& r = it.rect();
    528             renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
    529             it.next();
    530         }
    531     } else {
    532         int count = 0;
    533         Vector<float> rects;
    534         SkRegion::Iterator it(*region);
    535         while (!it.done()) {
    536             const SkIRect& r = it.rect();
    537             rects.push(r.fLeft);
    538             rects.push(r.fTop);
    539             rects.push(r.fRight);
    540             rects.push(r.fBottom);
    541             count += 4;
    542             it.next();
    543         }
    544         renderer->drawRects(rects.array(), count, paint);
    545     }
    546 }
    547 
    548 static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
    549         jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
    550     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    551     jfloat* storage = env->GetFloatArrayElements(points, NULL);
    552     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    553     renderer->drawPoints(storage + offset, count, paint);
    554     env->ReleaseFloatArrayElements(points, storage, 0);
    555 }
    556 
    557 static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
    558         jlong rendererPtr, jlong pathPtr, jlong paintPtr) {
    559     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    560     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
    561     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    562     renderer->drawPath(path, paint);
    563 }
    564 
    565 static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
    566         jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
    567     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    568     jfloat* storage = env->GetFloatArrayElements(points, NULL);
    569     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    570     renderer->drawLines(storage + offset, count, paint);
    571     env->ReleaseFloatArrayElements(points, storage, 0);
    572 }
    573 
    574 // ----------------------------------------------------------------------------
    575 // Draw filters
    576 // ----------------------------------------------------------------------------
    577 
    578 static void android_view_GLES20Canvas_setupPaintFilter(JNIEnv* env, jobject clazz,
    579         jlong rendererPtr, jint clearBits, jint setBits) {
    580     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    581     renderer->setupPaintFilter(clearBits, setBits);
    582 }
    583 
    584 static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject clazz,
    585         jlong rendererPtr) {
    586     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    587     renderer->resetPaintFilter();
    588 }
    589 
    590 // ----------------------------------------------------------------------------
    591 // Text
    592 // ----------------------------------------------------------------------------
    593 
    594 class RenderTextFunctor {
    595 public:
    596     RenderTextFunctor(const Layout& layout, DisplayListRenderer* renderer, jfloat x, jfloat y,
    597                 Paint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
    598                 uirenderer::Rect& bounds)
    599             : layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
    600             pos(pos), totalAdvance(totalAdvance), bounds(bounds) { }
    601     void operator()(size_t start, size_t end) {
    602         for (size_t i = start; i < end; i++) {
    603             glyphs[i] = layout.getGlyphId(i);
    604             pos[2 * i] = layout.getX(i);
    605             pos[2 * i + 1] = layout.getY(i);
    606         }
    607         size_t glyphsCount = end - start;
    608         int bytesCount = glyphsCount * sizeof(jchar);
    609         renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
    610             x, y, pos + 2 * start, paint, totalAdvance, bounds);
    611     }
    612 private:
    613     const Layout& layout;
    614     DisplayListRenderer* renderer;
    615     jfloat x;
    616     jfloat y;
    617     Paint* paint;
    618     uint16_t* glyphs;
    619     float* pos;
    620     float totalAdvance;
    621     uirenderer::Rect& bounds;
    622 };
    623 
    624 static void renderTextLayout(DisplayListRenderer* renderer, Layout* layout,
    625     jfloat x, jfloat y, Paint* paint) {
    626     size_t nGlyphs = layout->nGlyphs();
    627     float* pos = new float[nGlyphs * 2];
    628     uint16_t* glyphs = new uint16_t[nGlyphs];
    629     MinikinRect b;
    630     layout->getBounds(&b);
    631     android::uirenderer::Rect bounds(b.mLeft, b.mTop, b.mRight, b.mBottom);
    632     bounds.translate(x, y);
    633     float totalAdvance = layout->getAdvance();
    634 
    635     RenderTextFunctor f(*layout, renderer, x, y, paint, glyphs, pos, totalAdvance, bounds);
    636     MinikinUtils::forFontRun(*layout, paint, f);
    637     delete[] glyphs;
    638     delete[] pos;
    639 }
    640 
    641 static void renderText(DisplayListRenderer* renderer, const jchar* text, int count,
    642         jfloat x, jfloat y, int bidiFlags, Paint* paint, TypefaceImpl* typeface) {
    643     Layout layout;
    644     MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
    645     x += MinikinUtils::xOffsetForTextAlign(paint, layout);
    646     renderTextLayout(renderer, &layout, x, y, paint);
    647 }
    648 
    649 class RenderTextOnPathFunctor {
    650 public:
    651     RenderTextOnPathFunctor(const Layout& layout, DisplayListRenderer* renderer, float hOffset,
    652                 float vOffset, Paint* paint, SkPath* path)
    653             : layout(layout), renderer(renderer), hOffset(hOffset), vOffset(vOffset),
    654                 paint(paint), path(path) {
    655     }
    656     void operator()(size_t start, size_t end) {
    657         uint16_t glyphs[1];
    658         for (size_t i = start; i < end; i++) {
    659             glyphs[0] = layout.getGlyphId(i);
    660             float x = hOffset + layout.getX(i);
    661             float y = vOffset + layout.getY(i);
    662             renderer->drawTextOnPath((const char*) glyphs, sizeof(glyphs), 1, path, x, y, paint);
    663         }
    664     }
    665 private:
    666     const Layout& layout;
    667     DisplayListRenderer* renderer;
    668     float hOffset;
    669     float vOffset;
    670     Paint* paint;
    671     SkPath* path;
    672 };
    673 
    674 static void renderTextOnPath(DisplayListRenderer* renderer, const jchar* text, int count,
    675         SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, Paint* paint,
    676         TypefaceImpl* typeface) {
    677     Layout layout;
    678     MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
    679     hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
    680     Paint::Align align = paint->getTextAlign();
    681     paint->setTextAlign(Paint::kLeft_Align);
    682 
    683     RenderTextOnPathFunctor f(layout, renderer, hOffset, vOffset, paint, path);
    684     MinikinUtils::forFontRun(layout, paint, f);
    685     paint->setTextAlign(align);
    686 }
    687 
    688 static void renderTextRun(DisplayListRenderer* renderer, const jchar* text,
    689         jint start, jint count, jint contextCount, jfloat x, jfloat y,
    690         int bidiFlags, Paint* paint, TypefaceImpl* typeface) {
    691     Layout layout;
    692     MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, start, count, contextCount);
    693     x += MinikinUtils::xOffsetForTextAlign(paint, layout);
    694     renderTextLayout(renderer, &layout, x, y, paint);
    695 }
    696 
    697 static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
    698         jlong rendererPtr, jcharArray text, jint index, jint count,
    699         jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
    700     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    701     jchar* textArray = env->GetCharArrayElements(text, NULL);
    702     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    703     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
    704 
    705     renderText(renderer, textArray + index, count, x, y, bidiFlags, paint, typeface);
    706     env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
    707 }
    708 
    709 static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
    710         jlong rendererPtr, jstring text, jint start, jint end,
    711         jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
    712     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    713     const jchar* textArray = env->GetStringChars(text, NULL);
    714     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    715     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
    716 
    717     renderText(renderer, textArray + start, end - start, x, y, bidiFlags, paint, typeface);
    718     env->ReleaseStringChars(text, textArray);
    719 }
    720 
    721 static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
    722         jlong rendererPtr, jcharArray text, jint index, jint count,
    723         jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
    724         jlong typefacePtr) {
    725     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    726     jchar* textArray = env->GetCharArrayElements(text, NULL);
    727     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
    728     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    729     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
    730 
    731     renderTextOnPath(renderer, textArray + index, count, path,
    732             hOffset, vOffset, bidiFlags, paint, typeface);
    733     env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
    734 }
    735 
    736 static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
    737         jlong rendererPtr, jstring text, jint start, jint end,
    738         jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
    739         jlong typefacePtr) {
    740     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    741     const jchar* textArray = env->GetStringChars(text, NULL);
    742     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
    743     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    744     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
    745 
    746     renderTextOnPath(renderer, textArray + start, end - start, path,
    747             hOffset, vOffset, bidiFlags, paint, typeface);
    748     env->ReleaseStringChars(text, textArray);
    749 }
    750 
    751 static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
    752         jlong rendererPtr, jcharArray text, jint index, jint count,
    753         jint contextIndex, jint contextCount, jfloat x, jfloat y, jboolean isRtl,
    754         jlong paintPtr, jlong typefacePtr) {
    755     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    756     jchar* textArray = env->GetCharArrayElements(text, NULL);
    757     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    758     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
    759 
    760     int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
    761     renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
    762             count, contextCount, x, y, bidiFlags, paint, typeface);
    763     env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
    764  }
    765 
    766 static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
    767         jlong rendererPtr, jstring text, jint start, jint end,
    768         jint contextStart, int contextEnd, jfloat x, jfloat y, jboolean isRtl,
    769         jlong paintPtr, jlong typefacePtr) {
    770     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    771     const jchar* textArray = env->GetStringChars(text, NULL);
    772     jint count = end - start;
    773     jint contextCount = contextEnd - contextStart;
    774     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
    775     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
    776 
    777     int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
    778     renderTextRun(renderer, textArray + contextStart, start - contextStart,
    779             count, contextCount, x, y, bidiFlags, paint, typeface);
    780     env->ReleaseStringChars(text, textArray);
    781 }
    782 
    783 // ----------------------------------------------------------------------------
    784 // Display lists
    785 // ----------------------------------------------------------------------------
    786 
    787 static jlong android_view_GLES20Canvas_finishRecording(JNIEnv* env,
    788         jobject clazz, jlong rendererPtr) {
    789     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    790     return reinterpret_cast<jlong>(renderer->finishRecording());
    791 }
    792 
    793 static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jobject clazz) {
    794     return reinterpret_cast<jlong>(new DisplayListRenderer);
    795 }
    796 
    797 static jint android_view_GLES20Canvas_drawRenderNode(JNIEnv* env,
    798         jobject clazz, jlong rendererPtr, jlong renderNodePtr,
    799         jobject dirty, jint flags) {
    800     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    801     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
    802     android::uirenderer::Rect bounds;
    803     status_t status = renderer->drawRenderNode(renderNode, bounds, flags);
    804     if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
    805         env->CallVoidMethod(dirty, gRectClassInfo.set,
    806                 int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
    807     }
    808     return status;
    809 }
    810 
    811 // ----------------------------------------------------------------------------
    812 // Layers
    813 // ----------------------------------------------------------------------------
    814 
    815 static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
    816         jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
    817     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
    818     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
    819     renderer->drawLayer(layer, x, y);
    820 }
    821 
    822 #endif // USE_OPENGL_RENDERER
    823 
    824 // ----------------------------------------------------------------------------
    825 // Common
    826 // ----------------------------------------------------------------------------
    827 
    828 static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz) {
    829 #ifdef USE_OPENGL_RENDERER
    830     char prop[PROPERTY_VALUE_MAX];
    831     if (property_get("ro.kernel.qemu", prop, NULL) == 0) {
    832         // not in the emulator
    833         return JNI_TRUE;
    834     }
    835     // In the emulator this property will be set to 1 when hardware GLES is
    836     // enabled, 0 otherwise. On old emulator versions it will be undefined.
    837     property_get("ro.kernel.qemu.gles", prop, "0");
    838     return atoi(prop) == 1 ? JNI_TRUE : JNI_FALSE;
    839 #else
    840     return JNI_FALSE;
    841 #endif
    842 }
    843 
    844 // ----------------------------------------------------------------------------
    845 // Logging
    846 // ----------------------------------------------------------------------------
    847 
    848 static void
    849 android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
    850 #ifdef USE_OPENGL_RENDERER
    851     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
    852     android::uirenderer::renderthread::RenderProxy::outputLogBuffer(fd);
    853 #endif // USE_OPENGL_RENDERER
    854 }
    855 
    856 // ----------------------------------------------------------------------------
    857 // JNI Glue
    858 // ----------------------------------------------------------------------------
    859 
    860 const char* const kClassPathName = "android/view/GLES20Canvas";
    861 
    862 static JNINativeMethod gMethods[] = {
    863     { "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
    864 
    865 #ifdef USE_OPENGL_RENDERER
    866 
    867     { "nDestroyRenderer",   "(J)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
    868     { "nSetViewport",       "(JII)V",          (void*) android_view_GLES20Canvas_setViewport },
    869     { "nSetHighContrastText","(JZ)V",          (void*) android_view_GLES20Canvas_setHighContrastText },
    870     { "nInsertReorderBarrier","(JZ)V",         (void*) android_view_GLES20Canvas_insertReorderBarrier },
    871     { "nPrepare",           "(JZ)I",           (void*) android_view_GLES20Canvas_prepare },
    872     { "nPrepareDirty",      "(JIIIIZ)I",       (void*) android_view_GLES20Canvas_prepareDirty },
    873     { "nFinish",            "(J)V",            (void*) android_view_GLES20Canvas_finish },
    874     { "nSetProperty",           "(Ljava/lang/String;Ljava/lang/String;)V",
    875             (void*) android_view_GLES20Canvas_setProperty },
    876 
    877     { "nCallDrawGLFunction", "(JJ)I",          (void*) android_view_GLES20Canvas_callDrawGLFunction },
    878 
    879     { "nSave",              "(JI)I",           (void*) android_view_GLES20Canvas_save },
    880     { "nRestore",           "(J)V",            (void*) android_view_GLES20Canvas_restore },
    881     { "nRestoreToCount",    "(JI)V",           (void*) android_view_GLES20Canvas_restoreToCount },
    882     { "nGetSaveCount",      "(J)I",            (void*) android_view_GLES20Canvas_getSaveCount },
    883 
    884     { "nSaveLayer",         "(JFFFFJI)I",      (void*) android_view_GLES20Canvas_saveLayer },
    885     { "nSaveLayer",         "(JJI)I",          (void*) android_view_GLES20Canvas_saveLayerClip },
    886     { "nSaveLayerAlpha",    "(JFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
    887     { "nSaveLayerAlpha",    "(JII)I",          (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
    888 
    889     { "nQuickReject",       "(JFFFF)Z",        (void*) android_view_GLES20Canvas_quickReject },
    890     { "nClipRect",          "(JFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
    891     { "nClipRect",          "(JIIIII)Z",       (void*) android_view_GLES20Canvas_clipRect },
    892     { "nClipPath",          "(JJI)Z",          (void*) android_view_GLES20Canvas_clipPath },
    893     { "nClipRegion",        "(JJI)Z",          (void*) android_view_GLES20Canvas_clipRegion },
    894 
    895     { "nTranslate",         "(JFF)V",          (void*) android_view_GLES20Canvas_translate },
    896     { "nRotate",            "(JF)V",           (void*) android_view_GLES20Canvas_rotate },
    897     { "nScale",             "(JFF)V",          (void*) android_view_GLES20Canvas_scale },
    898     { "nSkew",              "(JFF)V",          (void*) android_view_GLES20Canvas_skew },
    899 
    900     { "nSetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_setMatrix },
    901     { "nGetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_getMatrix },
    902     { "nConcatMatrix",      "(JJ)V",           (void*) android_view_GLES20Canvas_concatMatrix },
    903 
    904     { "nDrawBitmap",        "(JJFFJ)V",      (void*) android_view_GLES20Canvas_drawBitmap },
    905     { "nDrawBitmap",        "(JJFFFFFFFFJ)V",(void*) android_view_GLES20Canvas_drawBitmapRect },
    906     { "nDrawBitmap",        "(JJJJ)V",       (void*) android_view_GLES20Canvas_drawBitmapMatrix },
    907     { "nDrawBitmap",        "(J[IIIFFIIZJ)V",  (void*) android_view_GLES20Canvas_drawBitmapData },
    908 
    909     { "nDrawBitmapMesh",    "(JJII[FI[IIJ)V",(void*) android_view_GLES20Canvas_drawBitmapMesh },
    910 
    911     { "nDrawPatch",         "(JJJFFFFJ)V",   (void*) android_view_GLES20Canvas_drawPatch },
    912 
    913     { "nDrawColor",         "(JII)V",          (void*) android_view_GLES20Canvas_drawColor },
    914     { "nDrawRect",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawRect },
    915     { "nDrawRects",         "(JJJ)V",          (void*) android_view_GLES20Canvas_drawRegionAsRects },
    916     { "nDrawRoundRect",     "(JFFFFFFJ)V",     (void*) android_view_GLES20Canvas_drawRoundRect },
    917     { "nDrawRoundRect",     "(JJJJJJJJ)V",     (void*) android_view_GLES20Canvas_drawRoundRectProps },
    918     { "nDrawCircle",        "(JFFFJ)V",        (void*) android_view_GLES20Canvas_drawCircle },
    919     { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_GLES20Canvas_drawCircleProps },
    920     { "nDrawOval",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawOval },
    921     { "nDrawArc",           "(JFFFFFFZJ)V",    (void*) android_view_GLES20Canvas_drawArc },
    922     { "nDrawPoints",        "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawPoints },
    923 
    924     { "nDrawPath",          "(JJJ)V",          (void*) android_view_GLES20Canvas_drawPath },
    925     { "nDrawLines",         "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawLines },
    926 
    927     { "nSetupPaintFilter",  "(JII)V",          (void*) android_view_GLES20Canvas_setupPaintFilter },
    928     { "nResetPaintFilter",  "(J)V",            (void*) android_view_GLES20Canvas_resetPaintFilter },
    929 
    930     { "nDrawText",          "(J[CIIFFIJJ)V",   (void*) android_view_GLES20Canvas_drawTextArray },
    931     { "nDrawText",          "(JLjava/lang/String;IIFFIJJ)V",
    932             (void*) android_view_GLES20Canvas_drawText },
    933 
    934     { "nDrawTextOnPath",    "(J[CIIJFFIJJ)V",  (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
    935     { "nDrawTextOnPath",    "(JLjava/lang/String;IIJFFIJJ)V",
    936             (void*) android_view_GLES20Canvas_drawTextOnPath },
    937 
    938     { "nDrawTextRun",       "(J[CIIIIFFZJJ)V",  (void*) android_view_GLES20Canvas_drawTextRunArray },
    939     { "nDrawTextRun",       "(JLjava/lang/String;IIIIFFZJJ)V",
    940             (void*) android_view_GLES20Canvas_drawTextRun },
    941 
    942     { "nGetClipBounds",     "(JLandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds },
    943 
    944     { "nFinishRecording",   "(J)J",      (void*) android_view_GLES20Canvas_finishRecording },
    945     { "nDrawRenderNode",    "(JJLandroid/graphics/Rect;I)I", (void*) android_view_GLES20Canvas_drawRenderNode },
    946 
    947     { "nCreateDisplayListRenderer", "()J",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
    948 
    949     { "nDrawLayer",              "(JJFF)V",    (void*) android_view_GLES20Canvas_drawLayer },
    950 
    951     { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_GLES20Canvas_getMaxTextureWidth },
    952     { "nGetMaximumTextureHeight", "()I",       (void*) android_view_GLES20Canvas_getMaxTextureHeight },
    953 
    954 #endif
    955 };
    956 
    957 static JNINativeMethod gActivityThreadMethods[] = {
    958     { "dumpGraphicsInfo",        "(Ljava/io/FileDescriptor;)V",
    959                                                (void*) android_app_ActivityThread_dumpGraphics }
    960 };
    961 
    962 
    963 #ifdef USE_OPENGL_RENDERER
    964     #define FIND_CLASS(var, className) \
    965             var = env->FindClass(className); \
    966             LOG_FATAL_IF(! var, "Unable to find class " className);
    967 
    968     #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
    969             var = env->GetMethodID(clazz, methodName, methodDescriptor); \
    970             LOG_FATAL_IF(! var, "Unable to find method " methodName);
    971 #else
    972     #define FIND_CLASS(var, className)
    973     #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor)
    974 #endif
    975 
    976 int register_android_view_GLES20Canvas(JNIEnv* env) {
    977     jclass clazz;
    978     FIND_CLASS(clazz, "android/graphics/Rect");
    979     GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V");
    980 
    981     return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
    982 }
    983 
    984 const char* const kActivityThreadPathName = "android/app/ActivityThread";
    985 
    986 int register_android_app_ActivityThread(JNIEnv* env) {
    987     return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName,
    988             gActivityThreadMethods, NELEM(gActivityThreadMethods));
    989 }
    990 
    991 };
    992