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