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