blob: d6991e610bb9e5018b80229297214c484103083a [file] [log] [blame]
Romain Guye4d01122010-06-16 18:44:05 -07001/*
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
Romain Guya1db5742010-07-20 13:09:13 -070017#define LOG_TAG "OpenGLRenderer"
18
Romain Guye4d01122010-06-16 18:44:05 -070019#include "jni.h"
Patrick Dubroye4ac2d62010-12-01 11:23:13 -080020#include "GraphicsJNI.h"
Romain Guye4d01122010-06-16 18:44:05 -070021#include <nativehelper/JNIHelp.h>
22#include <android_runtime/AndroidRuntime.h>
Romain Guydeba7852010-07-07 17:54:48 -070023#include <utils/ResourceTypes.h>
Romain Guye4d01122010-06-16 18:44:05 -070024
Romain Guyce0537b2010-06-29 21:05:21 -070025#include <SkBitmap.h>
Romain Guyc7d53492010-06-25 13:41:57 -070026#include <SkCanvas.h>
Romain Guyf6a11b82010-06-23 17:47:49 -070027#include <SkMatrix.h>
Romain Guyc7d53492010-06-25 13:41:57 -070028#include <SkPaint.h>
Romain Guy079ba2c2010-07-16 14:12:24 -070029#include <SkRegion.h>
Romain Guya1db5742010-07-20 13:09:13 -070030#include <SkScalerContext.h>
Romain Guy61c8c9c2010-08-09 20:48:09 -070031#include <SkTemplates.h>
Romain Guy85bf02f2010-06-22 13:11:24 -070032#include <SkXfermode.h>
Romain Guye4d01122010-06-16 18:44:05 -070033
Romain Guyb051e892010-09-28 19:09:36 -070034#include <DisplayListRenderer.h>
Romain Guy6c319ca2011-01-11 14:29:25 -080035#include <LayerRenderer.h>
Romain Guye2d345e2010-09-24 18:39:22 -070036#include <OpenGLDebugRenderer.h>
Romain Guy85bf02f2010-06-22 13:11:24 -070037#include <OpenGLRenderer.h>
Romain Guy06f96e22010-07-30 19:18:16 -070038#include <SkiaShader.h>
Romain Guydb1938e2010-08-02 18:50:22 -070039#include <SkiaColorFilter.h>
Romain Guy9d5316e2010-06-24 19:30:36 -070040#include <Rect.h>
Romain Guy85bf02f2010-06-22 13:11:24 -070041
Romain Guye8e62a42010-07-23 18:55:21 -070042#include "TextLayout.h"
43
Romain Guye4d01122010-06-16 18:44:05 -070044namespace android {
45
Romain Guy9d5316e2010-06-24 19:30:36 -070046using namespace uirenderer;
47
Romain Guy16393512010-08-08 00:14:31 -070048/**
49 * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
50 * devices. This means all the logic must be compiled only when the
51 * preprocessor variable USE_OPENGL_RENDERER is defined.
52 */
53#ifdef USE_OPENGL_RENDERER
54
Romain Guybdb801ca2010-10-04 17:22:29 -070055///////////////////////////////////////////////////////////////////////////////
56// Defines
57///////////////////////////////////////////////////////////////////////////////
58
59// Debug
Romain Guye2d345e2010-09-24 18:39:22 -070060#define DEBUG_RENDERER 0
Romain Guybdb801ca2010-10-04 17:22:29 -070061#define PROFILE_RENDERER 0
62
63// Debug
64#if DEBUG_RENDERER
65 #define RENDERER_LOGD(...) LOGD(__VA_ARGS__)
66#else
67 #define RENDERER_LOGD(...)
68#endif
Romain Guye2d345e2010-09-24 18:39:22 -070069
Romain Guy9d5316e2010-06-24 19:30:36 -070070// ----------------------------------------------------------------------------
Romain Guy9d5316e2010-06-24 19:30:36 -070071
72static struct {
Romain Guy7ae7ac42010-06-25 13:46:18 -070073 jclass clazz;
74 jmethodID set;
Romain Guy9d5316e2010-06-24 19:30:36 -070075} gRectClassInfo;
76
Romain Guye4d01122010-06-16 18:44:05 -070077// ----------------------------------------------------------------------------
78// Constructors
79// ----------------------------------------------------------------------------
80
Romain Guy6c319ca2011-01-11 14:29:25 -080081static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
Romain Guybdb801ca2010-10-04 17:22:29 -070082 RENDERER_LOGD("Create OpenGLRenderer");
83#if PROFILE_RENDERER
Romain Guye2d345e2010-09-24 18:39:22 -070084 return new OpenGLDebugRenderer;
85#else
Romain Guy85bf02f2010-06-22 13:11:24 -070086 return new OpenGLRenderer;
Romain Guye2d345e2010-09-24 18:39:22 -070087#endif
Romain Guye4d01122010-06-16 18:44:05 -070088}
89
Chet Haase5c13d892010-10-08 08:37:55 -070090static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
Romain Guyf6a11b82010-06-23 17:47:49 -070091 OpenGLRenderer* renderer) {
Romain Guybdb801ca2010-10-04 17:22:29 -070092 RENDERER_LOGD("Destroy OpenGLRenderer");
Romain Guyf6a11b82010-06-23 17:47:49 -070093 delete renderer;
Romain Guye4d01122010-06-16 18:44:05 -070094}
95
96// ----------------------------------------------------------------------------
97// Setup
98// ----------------------------------------------------------------------------
99
Romain Guyce0537b2010-06-29 21:05:21 -0700100static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject canvas,
Romain Guyf6a11b82010-06-23 17:47:49 -0700101 OpenGLRenderer* renderer, jint width, jint height) {
102 renderer->setViewport(width, height);
Romain Guye4d01122010-06-16 18:44:05 -0700103}
104
Romain Guyce0537b2010-06-29 21:05:21 -0700105static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject canvas,
Romain Guy6b7bd242010-10-06 19:49:23 -0700106 OpenGLRenderer* renderer, jboolean opaque) {
107 renderer->prepare(opaque);
Romain Guye4d01122010-06-16 18:44:05 -0700108}
109
Romain Guyb025b9c2010-09-16 14:16:48 -0700110static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject canvas,
111 OpenGLRenderer* renderer) {
112 renderer->finish();
113}
114
Romain Guyda8532c2010-08-31 11:50:35 -0700115static void android_view_GLES20Canvas_acquireContext(JNIEnv* env, jobject canvas,
116 OpenGLRenderer* renderer) {
117 renderer->acquireContext();
118}
119
120static void android_view_GLES20Canvas_releaseContext(JNIEnv* env, jobject canvas,
121 OpenGLRenderer* renderer) {
122 renderer->releaseContext();
123}
124
Romain Guye4d01122010-06-16 18:44:05 -0700125// ----------------------------------------------------------------------------
Romain Guybb9524b2010-06-22 18:56:38 -0700126// State
127// ----------------------------------------------------------------------------
128
Romain Guyce0537b2010-06-29 21:05:21 -0700129static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer,
Romain Guybb9524b2010-06-22 18:56:38 -0700130 jint flags) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700131 return renderer->save(flags);
Romain Guybb9524b2010-06-22 18:56:38 -0700132}
133
Romain Guyce0537b2010-06-29 21:05:21 -0700134static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject canvas,
Romain Guyf6a11b82010-06-23 17:47:49 -0700135 OpenGLRenderer* renderer) {
136 return renderer->getSaveCount();
Romain Guybb9524b2010-06-22 18:56:38 -0700137}
138
Romain Guyce0537b2010-06-29 21:05:21 -0700139static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject canvas,
Romain Guyf6a11b82010-06-23 17:47:49 -0700140 OpenGLRenderer* renderer) {
141 renderer->restore();
Romain Guybb9524b2010-06-22 18:56:38 -0700142}
143
Romain Guyce0537b2010-06-29 21:05:21 -0700144static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject canvas,
Romain Guyf6a11b82010-06-23 17:47:49 -0700145 OpenGLRenderer* renderer, jint saveCount) {
146 renderer->restoreToCount(saveCount);
Romain Guybb9524b2010-06-22 18:56:38 -0700147}
148
149// ----------------------------------------------------------------------------
Romain Guybd6b79b2010-06-26 00:13:53 -0700150// Layers
151// ----------------------------------------------------------------------------
152
Romain Guyce0537b2010-06-29 21:05:21 -0700153static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject canvas,
Romain Guybd6b79b2010-06-26 00:13:53 -0700154 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
155 SkPaint* paint, jint saveFlags) {
156 return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
157}
158
Romain Guyce0537b2010-06-29 21:05:21 -0700159static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject canvas,
Romain Guybd6b79b2010-06-26 00:13:53 -0700160 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
161 jint alpha, jint saveFlags) {
162 return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
163}
164
165// ----------------------------------------------------------------------------
Romain Guybb9524b2010-06-22 18:56:38 -0700166// Clipping
167// ----------------------------------------------------------------------------
168
Romain Guyce0537b2010-06-29 21:05:21 -0700169static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject canvas,
Romain Guyc7d53492010-06-25 13:41:57 -0700170 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
171 SkCanvas::EdgeType edge) {
172 return renderer->quickReject(left, top, right, bottom);
173}
174
Romain Guyce0537b2010-06-29 21:05:21 -0700175static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject canvas,
Romain Guy079ba2c2010-07-16 14:12:24 -0700176 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
177 SkRegion::Op op) {
178 return renderer->clipRect(left, top, right, bottom, op);
Romain Guybb9524b2010-06-22 18:56:38 -0700179}
180
Romain Guyce0537b2010-06-29 21:05:21 -0700181static bool android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject canvas,
Romain Guy079ba2c2010-07-16 14:12:24 -0700182 OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom,
183 SkRegion::Op op) {
184 return renderer->clipRect(float(left), float(top), float(right), float(bottom), op);
Romain Guyf6a11b82010-06-23 17:47:49 -0700185}
Romain Guybb9524b2010-06-22 18:56:38 -0700186
Romain Guyce0537b2010-06-29 21:05:21 -0700187static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject canvas,
Romain Guy9d5316e2010-06-24 19:30:36 -0700188 OpenGLRenderer* renderer, jobject rect) {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700189 const android::uirenderer::Rect& bounds(renderer->getClipBounds());
Romain Guy9d5316e2010-06-24 19:30:36 -0700190
Romain Guy7ae7ac42010-06-25 13:46:18 -0700191 env->CallVoidMethod(rect, gRectClassInfo.set,
192 int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
Romain Guy9d5316e2010-06-24 19:30:36 -0700193
Romain Guy7ae7ac42010-06-25 13:46:18 -0700194 return !bounds.isEmpty();
Romain Guy9d5316e2010-06-24 19:30:36 -0700195}
196
Romain Guyf6a11b82010-06-23 17:47:49 -0700197// ----------------------------------------------------------------------------
198// Transforms
199// ----------------------------------------------------------------------------
200
Romain Guyce0537b2010-06-29 21:05:21 -0700201static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject canvas,
Romain Guyf6a11b82010-06-23 17:47:49 -0700202 OpenGLRenderer* renderer, jfloat dx, jfloat dy) {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700203 renderer->translate(dx, dy);
Romain Guyf6a11b82010-06-23 17:47:49 -0700204}
205
Romain Guyce0537b2010-06-29 21:05:21 -0700206static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject canvas,
Romain Guyf6a11b82010-06-23 17:47:49 -0700207 OpenGLRenderer* renderer, jfloat degrees) {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700208 renderer->rotate(degrees);
Romain Guyf6a11b82010-06-23 17:47:49 -0700209}
210
Romain Guyce0537b2010-06-29 21:05:21 -0700211static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject canvas,
Romain Guyf6a11b82010-06-23 17:47:49 -0700212 OpenGLRenderer* renderer, jfloat sx, jfloat sy) {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700213 renderer->scale(sx, sy);
Romain Guyf6a11b82010-06-23 17:47:49 -0700214}
215
Romain Guyce0537b2010-06-29 21:05:21 -0700216static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject canvas,
Romain Guyf6a11b82010-06-23 17:47:49 -0700217 OpenGLRenderer* renderer, SkMatrix* matrix) {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700218 renderer->setMatrix(matrix);
Romain Guyf6a11b82010-06-23 17:47:49 -0700219}
220
Romain Guy41030da2010-10-13 13:40:37 -0700221static const float* android_view_GLES20Canvas_getNativeMatrix(JNIEnv* env,
222 jobject canvas, OpenGLRenderer* renderer) {
223 return renderer->getMatrix();
224}
225
Romain Guyce0537b2010-06-29 21:05:21 -0700226static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject canvas,
Romain Guyf6a11b82010-06-23 17:47:49 -0700227 OpenGLRenderer* renderer, SkMatrix* matrix) {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700228 renderer->getMatrix(matrix);
Romain Guyf6a11b82010-06-23 17:47:49 -0700229}
230
Romain Guyce0537b2010-06-29 21:05:21 -0700231static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject canvas,
Romain Guyf6a11b82010-06-23 17:47:49 -0700232 OpenGLRenderer* renderer, SkMatrix* matrix) {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700233 renderer->concatMatrix(matrix);
Romain Guybb9524b2010-06-22 18:56:38 -0700234}
235
236// ----------------------------------------------------------------------------
237// Drawing
Romain Guy85bf02f2010-06-22 13:11:24 -0700238// ----------------------------------------------------------------------------
239
Romain Guyce0537b2010-06-29 21:05:21 -0700240static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject canvas,
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800241 OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer, float left,
242 float top, SkPaint* paint) {
243 // This object allows the renderer to allocate a global JNI ref to the buffer object.
244 JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
245
Romain Guydbd77cd2010-07-09 10:36:05 -0700246 renderer->drawBitmap(bitmap, left, top, paint);
Romain Guy85bf02f2010-06-22 13:11:24 -0700247}
248
Romain Guyce0537b2010-06-29 21:05:21 -0700249static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject canvas,
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800250 OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
Romain Guyce0537b2010-06-29 21:05:21 -0700251 float srcLeft, float srcTop, float srcRight, float srcBottom,
Romain Guydbd77cd2010-07-09 10:36:05 -0700252 float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint) {
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800253 // This object allows the renderer to allocate a global JNI ref to the buffer object.
254 JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
255
Romain Guydbd77cd2010-07-09 10:36:05 -0700256 renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
257 dstLeft, dstTop, dstRight, dstBottom, paint);
Romain Guyf86ef572010-07-01 11:05:42 -0700258}
Romain Guy8ba548f2010-06-30 19:21:21 -0700259
Romain Guyf86ef572010-07-01 11:05:42 -0700260static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject canvas,
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800261 OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer, SkMatrix* matrix,
262 SkPaint* paint) {
263 // This object allows the renderer to allocate a global JNI ref to the buffer object.
264 JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
265
Romain Guydbd77cd2010-07-09 10:36:05 -0700266 renderer->drawBitmap(bitmap, matrix, paint);
Romain Guyce0537b2010-06-29 21:05:21 -0700267}
268
Romain Guydeba7852010-07-07 17:54:48 -0700269static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject canvas,
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800270 OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer, jbyteArray chunks,
Romain Guydbd77cd2010-07-09 10:36:05 -0700271 float left, float top, float right, float bottom, SkPaint* paint) {
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800272 // This object allows the renderer to allocate a global JNI ref to the buffer object.
273 JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
274
Romain Guydeba7852010-07-07 17:54:48 -0700275 jbyte* storage = env->GetByteArrayElements(chunks, NULL);
276 Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(storage);
277 Res_png_9patch::deserialize(patch);
278
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800279 renderer->drawPatch(bitmap, &patch->xDivs[0], &patch->yDivs[0],
280 &patch->colors[0], patch->numXDivs, patch->numYDivs, patch->numColors,
Romain Guy4bb94202010-10-12 15:59:26 -0700281 left, top, right, bottom, paint);
Romain Guydeba7852010-07-07 17:54:48 -0700282
Romain Guydeba7852010-07-07 17:54:48 -0700283 env->ReleaseByteArrayElements(chunks, storage, 0);
284}
285
Romain Guyce0537b2010-06-29 21:05:21 -0700286static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject canvas,
287 OpenGLRenderer* renderer, jint color, SkXfermode::Mode mode) {
288 renderer->drawColor(color, mode);
289}
290
291static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject canvas,
Romain Guyc7d53492010-06-25 13:41:57 -0700292 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
293 SkPaint* paint) {
294 renderer->drawRect(left, top, right, bottom, paint);
295}
296
Romain Guya48a1a82010-08-10 14:59:15 -0700297static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject canvas,
298 OpenGLRenderer* renderer, SkRegion* region, SkPaint* paint) {
299 SkRegion::Iterator it(*region);
300 while (!it.done()) {
301 const SkIRect& r = it.rect();
302 renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
303 it.next();
304 }
305}
306
Romain Guy7fbcc042010-08-04 15:40:07 -0700307static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject canvas,
308 OpenGLRenderer* renderer, SkPath* path, SkPaint* paint) {
309 renderer->drawPath(path, paint);
310}
311
Romain Guy759ea802010-09-16 20:49:46 -0700312static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject canvas,
313 OpenGLRenderer* renderer, jfloatArray points, jint offset, jint count, SkPaint* paint) {
314 jfloat* storage = env->GetFloatArrayElements(points, NULL);
315
316 renderer->drawLines(storage + offset, count, paint);
317
318 env->ReleaseFloatArrayElements(points, storage, 0);
319}
320
Romain Guy85bf02f2010-06-22 13:11:24 -0700321// ----------------------------------------------------------------------------
Romain Guydb1938e2010-08-02 18:50:22 -0700322// Shaders and color filters
Romain Guyd27977d2010-07-14 19:18:51 -0700323// ----------------------------------------------------------------------------
324
Romain Guydb1938e2010-08-02 18:50:22 -0700325static void android_view_GLES20Canvas_resetModifiers(JNIEnv* env, jobject canvas,
Romain Guyd27977d2010-07-14 19:18:51 -0700326 OpenGLRenderer* renderer) {
327 renderer->resetShader();
Romain Guydb1938e2010-08-02 18:50:22 -0700328 renderer->resetColorFilter();
Romain Guy1e45aae2010-08-13 19:39:53 -0700329 renderer->resetShadow();
Romain Guyd27977d2010-07-14 19:18:51 -0700330}
331
Romain Guy06f96e22010-07-30 19:18:16 -0700332static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject canvas,
333 OpenGLRenderer* renderer, SkiaShader* shader) {
334 renderer->setupShader(shader);
Romain Guy7fac2e12010-07-16 17:10:13 -0700335}
336
Romain Guydb1938e2010-08-02 18:50:22 -0700337static void android_view_GLES20Canvas_setupColorFilter(JNIEnv* env, jobject canvas,
338 OpenGLRenderer* renderer, SkiaColorFilter* filter) {
339 renderer->setupColorFilter(filter);
340}
341
Romain Guy1e45aae2010-08-13 19:39:53 -0700342static void android_view_GLES20Canvas_setupShadow(JNIEnv* env, jobject canvas,
343 OpenGLRenderer* renderer, jfloat radius, jfloat dx, jfloat dy, jint color) {
344 renderer->setupShadow(radius, dx, dy, color);
345}
346
Romain Guyd27977d2010-07-14 19:18:51 -0700347// ----------------------------------------------------------------------------
Romain Guya1db5742010-07-20 13:09:13 -0700348// Text
349// ----------------------------------------------------------------------------
350
Romain Guye8e62a42010-07-23 18:55:21 -0700351static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
352 jfloat x, jfloat y, int flags, SkPaint* paint) {
353 const jchar *workText;
Romain Guy92262982010-07-26 11:17:54 -0700354 jchar* buffer = NULL;
Romain Guye8e62a42010-07-23 18:55:21 -0700355 int32_t workBytes;
Romain Guy92262982010-07-26 11:17:54 -0700356 if (TextLayout::prepareText(paint, text, count, flags, &workText, &workBytes, &buffer)) {
Romain Guye8e62a42010-07-23 18:55:21 -0700357 renderer->drawText((const char*) workText, workBytes, count, x, y, paint);
Romain Guy92262982010-07-26 11:17:54 -0700358 free(buffer);
Romain Guye8e62a42010-07-23 18:55:21 -0700359 }
360}
361
Romain Guy61c8c9c2010-08-09 20:48:09 -0700362static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
363 jint start, jint count, jint contextCount, jfloat x, jfloat y,
364 int flags, SkPaint* paint) {
365 uint8_t rtl = flags & 0x1;
366 if (rtl) {
367 SkAutoSTMalloc<80, jchar> buffer(contextCount);
368 jchar* shaped = buffer.get();
369 if (TextLayout::prepareRtlTextRun(text, start, count, contextCount, shaped)) {
370 renderer->drawText((const char*) shaped, count << 1, count, x, y, paint);
371 } else {
372 LOGW("drawTextRun error");
373 }
374 } else {
375 renderer->drawText((const char*) (text + start), count << 1, count, x, y, paint);
376 }
377}
378
Romain Guya1db5742010-07-20 13:09:13 -0700379static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject canvas,
380 OpenGLRenderer* renderer, jcharArray text, int index, int count,
381 jfloat x, jfloat y, int flags, SkPaint* paint) {
382 jchar* textArray = env->GetCharArrayElements(text, NULL);
Romain Guye8e62a42010-07-23 18:55:21 -0700383 renderText(renderer, textArray + index, count, x, y, flags, paint);
Romain Guya1db5742010-07-20 13:09:13 -0700384 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
385}
386
387static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject canvas,
388 OpenGLRenderer* renderer, jstring text, int start, int end,
389 jfloat x, jfloat y, int flags, SkPaint* paint) {
390 const jchar* textArray = env->GetStringChars(text, NULL);
Romain Guye8e62a42010-07-23 18:55:21 -0700391 renderText(renderer, textArray + start, end - start, x, y, flags, paint);
Romain Guya1db5742010-07-20 13:09:13 -0700392 env->ReleaseStringChars(text, textArray);
393}
394
Romain Guy61c8c9c2010-08-09 20:48:09 -0700395static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject canvas,
396 OpenGLRenderer* renderer, jcharArray text, int index, int count,
397 int contextIndex, int contextCount, jfloat x, jfloat y, int dirFlags,
398 SkPaint* paint) {
399 jchar* textArray = env->GetCharArrayElements(text, NULL);
400 renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
401 count, contextCount, x, y, dirFlags, paint);
402 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
403 }
404
405static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject canvas,
406 OpenGLRenderer* renderer, jstring text, int start, int end,
407 int contextStart, int contextEnd, jfloat x, jfloat y, int dirFlags,
408 SkPaint* paint) {
409 const jchar* textArray = env->GetStringChars(text, NULL);
410 jint count = end - start;
411 jint contextCount = contextEnd - contextStart;
412 renderTextRun(renderer, textArray + contextStart, start - contextStart,
413 count, contextCount, x, y, dirFlags, paint);
414 env->ReleaseStringChars(text, textArray);
415}
416
Romain Guyb051e892010-09-28 19:09:36 -0700417// ----------------------------------------------------------------------------
418// Display lists
419// ----------------------------------------------------------------------------
420
Chet Haase5977baa2011-01-05 18:01:22 -0800421static DisplayList* android_view_GLES20Canvas_getDisplayList(JNIEnv* env,
Romain Guyb051e892010-09-28 19:09:36 -0700422 jobject canvas, DisplayListRenderer* renderer) {
423 return renderer->getDisplayList();
424}
425
Chet Haase5977baa2011-01-05 18:01:22 -0800426static OpenGLRenderer* android_view_GLES20Canvas_getDisplayListRenderer(JNIEnv* env,
427 jobject clazz, DisplayListRenderer* renderer) {
428 if (renderer == NULL) {
429 renderer = new DisplayListRenderer;
430 } else {
431 renderer->reset();
432 }
433 return renderer;
434}
435
Romain Guyb051e892010-09-28 19:09:36 -0700436static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env,
Chet Haase5c13d892010-10-08 08:37:55 -0700437 jobject clazz, DisplayList* displayList) {
Romain Guyb051e892010-09-28 19:09:36 -0700438 delete displayList;
439}
440
441static void android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
442 jobject canvas, OpenGLRenderer* renderer, DisplayList* displayList) {
Romain Guy0fe478e2010-11-08 12:08:41 -0800443 renderer->drawDisplayList(displayList);
Romain Guyb051e892010-09-28 19:09:36 -0700444}
445
Romain Guy6c319ca2011-01-11 14:29:25 -0800446// ----------------------------------------------------------------------------
447// Layers
448// ----------------------------------------------------------------------------
449
450static void android_view_GLES20Canvas_interrupt(JNIEnv* env, jobject canvas,
451 OpenGLRenderer* renderer) {
452 renderer->interrupt();
453}
454
455static void android_view_GLES20Canvas_resume(JNIEnv* env, jobject canvas,
456 OpenGLRenderer* renderer) {
457 renderer->resume();
458}
459
460static OpenGLRenderer* android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env,
461 jobject clazz, jint fbo) {
462 return new LayerRenderer(fbo);
463}
464
465static jint android_view_GLES20Canvas_createLayer(JNIEnv* env,
466 jobject clazz, jint width, jint height, jintArray layerInfo) {
467 uint32_t layerWidth = 0;
468 uint32_t layerHeight = 0;
469 GLuint textureId = 0;
470
471 jint layerId = LayerRenderer::createLayer(width, height,
472 &layerWidth, &layerHeight, &textureId);
473
474 if (layerId) {
475 jint* storage = env->GetIntArrayElements(layerInfo, NULL);
476 storage[0] = layerWidth;
477 storage[1] = layerHeight;
478 storage[2] = textureId;
479 env->ReleaseIntArrayElements(layerInfo, storage, 0);
480 }
481
482 return layerId;
483}
484
485static void android_view_GLES20Canvas_resizeLayer(JNIEnv* env,
486 jobject clazz, jint layerId, jint layerTextureId, jint width, jint height,
487 jintArray layerInfo) {
488 uint32_t layerWidth = 0;
489 uint32_t layerHeight = 0;
490
491 LayerRenderer::resizeLayer(layerId, layerTextureId, width, height, &layerWidth, &layerHeight);
492
493 jint* storage = env->GetIntArrayElements(layerInfo, NULL);
494 storage[0] = layerWidth;
495 storage[1] = layerHeight;
496 env->ReleaseIntArrayElements(layerInfo, storage, 0);
497}
498
499static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env,
500 jobject clazz, jint layerId, jint layerTextureId) {
501 LayerRenderer::destroyLayer(layerId, layerTextureId);
502}
503
504static void android_view_GLES20Canvas_drawLayer(JNIEnv* env,
505 jobject canvas, OpenGLRenderer* renderer,
506 jfloat left, jfloat top, jfloat right, jfloat bottom,
507 jint layerTexture, jfloat u, jfloat v, SkPaint* paint) {
508 renderer->drawLayer(layerTexture, left, top, right, bottom, u, v, paint);
509}
510
Romain Guy16393512010-08-08 00:14:31 -0700511#endif // USE_OPENGL_RENDERER
512
513// ----------------------------------------------------------------------------
514// Common
515// ----------------------------------------------------------------------------
516
517static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz) {
518#ifdef USE_OPENGL_RENDERER
519 return JNI_TRUE;
520#else
521 return JNI_FALSE;
522#endif
523}
524
Romain Guya1db5742010-07-20 13:09:13 -0700525// ----------------------------------------------------------------------------
Romain Guye4d01122010-06-16 18:44:05 -0700526// JNI Glue
527// ----------------------------------------------------------------------------
528
529const char* const kClassPathName = "android/view/GLES20Canvas";
530
531static JNINativeMethod gMethods[] = {
Romain Guy61c8c9c2010-08-09 20:48:09 -0700532 { "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable },
533
Romain Guy16393512010-08-08 00:14:31 -0700534#ifdef USE_OPENGL_RENDERER
Romain Guy61c8c9c2010-08-09 20:48:09 -0700535 { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer },
536 { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer },
537 { "nSetViewport", "(III)V", (void*) android_view_GLES20Canvas_setViewport },
Romain Guy6b7bd242010-10-06 19:49:23 -0700538 { "nPrepare", "(IZ)V", (void*) android_view_GLES20Canvas_prepare },
Romain Guyb025b9c2010-09-16 14:16:48 -0700539 { "nFinish", "(I)V", (void*) android_view_GLES20Canvas_finish },
Romain Guyda8532c2010-08-31 11:50:35 -0700540 { "nAcquireContext", "(I)V", (void*) android_view_GLES20Canvas_acquireContext },
541 { "nReleaseContext", "(I)V", (void*) android_view_GLES20Canvas_releaseContext },
Romain Guy16393512010-08-08 00:14:31 -0700542
Romain Guy61c8c9c2010-08-09 20:48:09 -0700543 { "nSave", "(II)I", (void*) android_view_GLES20Canvas_save },
544 { "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore },
545 { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Canvas_restoreToCount },
546 { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Canvas_getSaveCount },
Romain Guy85bf02f2010-06-22 13:11:24 -0700547
Romain Guy61c8c9c2010-08-09 20:48:09 -0700548 { "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayer },
549 { "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayerAlpha },
Romain Guybb9524b2010-06-22 18:56:38 -0700550
Romain Guy61c8c9c2010-08-09 20:48:09 -0700551 { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject },
552 { "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF },
553 { "nClipRect", "(IIIIII)Z", (void*) android_view_GLES20Canvas_clipRect },
Romain Guyc7d53492010-06-25 13:41:57 -0700554
Romain Guy61c8c9c2010-08-09 20:48:09 -0700555 { "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate },
556 { "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate },
557 { "nScale", "(IFF)V", (void*) android_view_GLES20Canvas_scale },
Romain Guyc7d53492010-06-25 13:41:57 -0700558
Romain Guy61c8c9c2010-08-09 20:48:09 -0700559 { "nSetMatrix", "(II)V", (void*) android_view_GLES20Canvas_setMatrix },
Romain Guy41030da2010-10-13 13:40:37 -0700560 { "nGetMatrix", "(I)I", (void*) android_view_GLES20Canvas_getNativeMatrix },
Romain Guy61c8c9c2010-08-09 20:48:09 -0700561 { "nGetMatrix", "(II)V", (void*) android_view_GLES20Canvas_getMatrix },
562 { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Canvas_concatMatrix },
Romain Guyc7d53492010-06-25 13:41:57 -0700563
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800564 { "nDrawBitmap", "(II[BFFI)V", (void*) android_view_GLES20Canvas_drawBitmap },
565 { "nDrawBitmap", "(II[BFFFFFFFFI)V", (void*) android_view_GLES20Canvas_drawBitmapRect },
566 { "nDrawBitmap", "(II[BII)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix },
567 { "nDrawPatch", "(II[B[BFFFFI)V", (void*) android_view_GLES20Canvas_drawPatch },
568
Romain Guy61c8c9c2010-08-09 20:48:09 -0700569 { "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor },
570 { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect },
Romain Guya48a1a82010-08-10 14:59:15 -0700571 { "nDrawRects", "(III)V", (void*) android_view_GLES20Canvas_drawRects },
Romain Guy61c8c9c2010-08-09 20:48:09 -0700572 { "nDrawPath", "(III)V", (void*) android_view_GLES20Canvas_drawPath },
Romain Guy759ea802010-09-16 20:49:46 -0700573 { "nDrawLines", "(I[FIII)V", (void*) android_view_GLES20Canvas_drawLines },
Romain Guybd6b79b2010-06-26 00:13:53 -0700574
Romain Guy61c8c9c2010-08-09 20:48:09 -0700575 { "nResetModifiers", "(I)V", (void*) android_view_GLES20Canvas_resetModifiers },
576 { "nSetupShader", "(II)V", (void*) android_view_GLES20Canvas_setupShader },
577 { "nSetupColorFilter", "(II)V", (void*) android_view_GLES20Canvas_setupColorFilter },
Romain Guy1e45aae2010-08-13 19:39:53 -0700578 { "nSetupShadow", "(IFFFI)V", (void*) android_view_GLES20Canvas_setupShadow },
Romain Guybb9524b2010-06-22 18:56:38 -0700579
Romain Guy61c8c9c2010-08-09 20:48:09 -0700580 { "nDrawText", "(I[CIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArray },
581 { "nDrawText", "(ILjava/lang/String;IIFFII)V",
Romain Guya1db5742010-07-20 13:09:13 -0700582 (void*) android_view_GLES20Canvas_drawText },
583
Romain Guy61c8c9c2010-08-09 20:48:09 -0700584 { "nDrawTextRun", "(I[CIIIIFFII)V", (void*) android_view_GLES20Canvas_drawTextRunArray },
585 { "nDrawTextRun", "(ILjava/lang/String;IIIIFFII)V",
586 (void*) android_view_GLES20Canvas_drawTextRun },
587
Romain Guyfb8b7632010-08-23 21:05:08 -0700588 { "nGetClipBounds", "(ILandroid/graphics/Rect;)Z",
Romain Guyce0537b2010-06-29 21:05:21 -0700589 (void*) android_view_GLES20Canvas_getClipBounds },
Romain Guyb051e892010-09-28 19:09:36 -0700590
Romain Guy6c319ca2011-01-11 14:29:25 -0800591 { "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList },
592 { "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList },
593 { "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer },
594 { "nDrawDisplayList", "(II)V", (void*) android_view_GLES20Canvas_drawDisplayList },
595
596 { "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt },
597 { "nResume", "(I)V", (void*) android_view_GLES20Canvas_resume },
598
599 { "nCreateLayerRenderer", "(I)I", (void*) android_view_GLES20Canvas_createLayerRenderer },
600 { "nCreateLayer", "(II[I)I", (void*) android_view_GLES20Canvas_createLayer },
601 { "nResizeLayer", "(IIII[I)V", (void*) android_view_GLES20Canvas_resizeLayer },
602 { "nDestroyLayer", "(II)V", (void*) android_view_GLES20Canvas_destroyLayer },
603 { "nDrawLayer", "(IFFFFIFFI)V",
604 (void*) android_view_GLES20Canvas_drawLayer },
Romain Guyb051e892010-09-28 19:09:36 -0700605
Romain Guy16393512010-08-08 00:14:31 -0700606#endif
Romain Guye4d01122010-06-16 18:44:05 -0700607};
608
Romain Guy16393512010-08-08 00:14:31 -0700609#ifdef USE_OPENGL_RENDERER
610 #define FIND_CLASS(var, className) \
611 var = env->FindClass(className); \
612 LOG_FATAL_IF(! var, "Unable to find class " className); \
613 var = jclass(env->NewGlobalRef(var));
614
615 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
616 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
617 LOG_FATAL_IF(! var, "Unable to find method " methodName);
618#else
619 #define FIND_CLASS(var, className)
620 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor)
621#endif
Romain Guy9d5316e2010-06-24 19:30:36 -0700622
Romain Guye4d01122010-06-16 18:44:05 -0700623int register_android_view_GLES20Canvas(JNIEnv* env) {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700624 FIND_CLASS(gRectClassInfo.clazz, "android/graphics/Rect");
625 GET_METHOD_ID(gRectClassInfo.set, gRectClassInfo.clazz, "set", "(IIII)V");
Romain Guy9d5316e2010-06-24 19:30:36 -0700626
Romain Guye4d01122010-06-16 18:44:05 -0700627 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
628}
629
630};