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