android_view_GLES20Canvas.cpp revision 694b519ac647fe998fd396fe0784cc8e179aadc4
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 <nativehelper/JNIHelp.h> 21#include <android_runtime/AndroidRuntime.h> 22#include <utils/ResourceTypes.h> 23 24#include <SkBitmap.h> 25#include <SkCanvas.h> 26#include <SkMatrix.h> 27#include <SkPaint.h> 28#include <SkRegion.h> 29#include <SkScalerContext.h> 30#include <SkXfermode.h> 31 32#include <OpenGLRenderer.h> 33#include <Rect.h> 34#include <ui/Rect.h> 35 36namespace android { 37 38using namespace uirenderer; 39 40// ---------------------------------------------------------------------------- 41// Java APIs 42// ---------------------------------------------------------------------------- 43 44static struct { 45 jclass clazz; 46 jmethodID set; 47} gRectClassInfo; 48 49// ---------------------------------------------------------------------------- 50// Constructors 51// ---------------------------------------------------------------------------- 52 53static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject canvas) { 54 return new OpenGLRenderer; 55} 56 57static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject canvas, 58 OpenGLRenderer* renderer) { 59 delete renderer; 60} 61 62// ---------------------------------------------------------------------------- 63// Setup 64// ---------------------------------------------------------------------------- 65 66static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject canvas, 67 OpenGLRenderer* renderer, jint width, jint height) { 68 renderer->setViewport(width, height); 69} 70 71static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject canvas, 72 OpenGLRenderer* renderer) { 73 renderer->prepare(); 74} 75 76// ---------------------------------------------------------------------------- 77// State 78// ---------------------------------------------------------------------------- 79 80static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer, 81 jint flags) { 82 return renderer->save(flags); 83} 84 85static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject canvas, 86 OpenGLRenderer* renderer) { 87 return renderer->getSaveCount(); 88} 89 90static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject canvas, 91 OpenGLRenderer* renderer) { 92 renderer->restore(); 93} 94 95static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject canvas, 96 OpenGLRenderer* renderer, jint saveCount) { 97 renderer->restoreToCount(saveCount); 98} 99 100// ---------------------------------------------------------------------------- 101// Layers 102// ---------------------------------------------------------------------------- 103 104static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject canvas, 105 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, 106 SkPaint* paint, jint saveFlags) { 107 return renderer->saveLayer(left, top, right, bottom, paint, saveFlags); 108} 109 110static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject canvas, 111 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, 112 jint alpha, jint saveFlags) { 113 return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags); 114} 115 116// ---------------------------------------------------------------------------- 117// Clipping 118// ---------------------------------------------------------------------------- 119 120static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject canvas, 121 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, 122 SkCanvas::EdgeType edge) { 123 return renderer->quickReject(left, top, right, bottom); 124} 125 126static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject canvas, 127 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, 128 SkRegion::Op op) { 129 return renderer->clipRect(left, top, right, bottom, op); 130} 131 132static bool android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject canvas, 133 OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom, 134 SkRegion::Op op) { 135 return renderer->clipRect(float(left), float(top), float(right), float(bottom), op); 136} 137 138static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject canvas, 139 OpenGLRenderer* renderer, jobject rect) { 140 const android::uirenderer::Rect& bounds(renderer->getClipBounds()); 141 142 env->CallVoidMethod(rect, gRectClassInfo.set, 143 int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom)); 144 145 return !bounds.isEmpty(); 146} 147 148// ---------------------------------------------------------------------------- 149// Transforms 150// ---------------------------------------------------------------------------- 151 152static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject canvas, 153 OpenGLRenderer* renderer, jfloat dx, jfloat dy) { 154 renderer->translate(dx, dy); 155} 156 157static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject canvas, 158 OpenGLRenderer* renderer, jfloat degrees) { 159 renderer->rotate(degrees); 160} 161 162static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject canvas, 163 OpenGLRenderer* renderer, jfloat sx, jfloat sy) { 164 renderer->scale(sx, sy); 165} 166 167static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject canvas, 168 OpenGLRenderer* renderer, SkMatrix* matrix) { 169 renderer->setMatrix(matrix); 170} 171 172static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject canvas, 173 OpenGLRenderer* renderer, SkMatrix* matrix) { 174 renderer->getMatrix(matrix); 175} 176 177static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject canvas, 178 OpenGLRenderer* renderer, SkMatrix* matrix) { 179 renderer->concatMatrix(matrix); 180} 181 182// ---------------------------------------------------------------------------- 183// Drawing 184// ---------------------------------------------------------------------------- 185 186static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject canvas, 187 OpenGLRenderer* renderer, SkBitmap* bitmap, float left, float top, SkPaint* paint) { 188 renderer->drawBitmap(bitmap, left, top, paint); 189} 190 191static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject canvas, 192 OpenGLRenderer* renderer, SkBitmap* bitmap, 193 float srcLeft, float srcTop, float srcRight, float srcBottom, 194 float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint) { 195 renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, 196 dstLeft, dstTop, dstRight, dstBottom, paint); 197} 198 199static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject canvas, 200 OpenGLRenderer* renderer, SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) { 201 renderer->drawBitmap(bitmap, matrix, paint); 202} 203 204static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject canvas, 205 OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray chunks, 206 float left, float top, float right, float bottom, SkPaint* paint) { 207 jbyte* storage = env->GetByteArrayElements(chunks, NULL); 208 Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(storage); 209 Res_png_9patch::deserialize(patch); 210 211 renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint); 212 213 env->ReleaseByteArrayElements(chunks, storage, 0); 214} 215 216static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject canvas, 217 OpenGLRenderer* renderer, jint color, SkXfermode::Mode mode) { 218 renderer->drawColor(color, mode); 219} 220 221static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject canvas, 222 OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom, 223 SkPaint* paint) { 224 renderer->drawRect(left, top, right, bottom, paint); 225} 226 227// ---------------------------------------------------------------------------- 228// Shaders 229// ---------------------------------------------------------------------------- 230 231static void android_view_GLES20Canvas_resetShader(JNIEnv* env, jobject canvas, 232 OpenGLRenderer* renderer) { 233 renderer->resetShader(); 234} 235 236static void android_view_GLES20Canvas_setupBitmapShader(JNIEnv* env, jobject canvas, 237 OpenGLRenderer* renderer, SkShader* shader, SkBitmap* bitmap, 238 SkShader::TileMode tileX, SkShader::TileMode tileY, SkMatrix* matrix) { 239 renderer->setupBitmapShader(bitmap, tileX, tileY, matrix, 240 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 241} 242 243static void android_view_GLES20Canvas_setupLinearShader(JNIEnv* env, jobject canvas, 244 OpenGLRenderer* renderer, SkShader* shader, float* bounds, uint32_t* colors, 245 float* positions, int count, SkShader::TileMode tileMode, SkMatrix* matrix) { 246 renderer->setupLinearGradientShader(shader, bounds, colors, positions, count, 247 tileMode, matrix, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 248} 249 250// ---------------------------------------------------------------------------- 251// Text 252// ---------------------------------------------------------------------------- 253 254static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject canvas, 255 OpenGLRenderer* renderer, jcharArray text, int index, int count, 256 jfloat x, jfloat y, int flags, SkPaint* paint) { 257 jchar* textArray = env->GetCharArrayElements(text, NULL); 258 // TODO: Prepare the text for RTL 259 renderer->drawText((const char*) (textArray + index), count, x, y, paint); 260 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 261} 262 263static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject canvas, 264 OpenGLRenderer* renderer, jstring text, int start, int end, 265 jfloat x, jfloat y, int flags, SkPaint* paint) { 266 const jchar* textArray = env->GetStringChars(text, NULL); 267 // TODO: Prepare the text for RTL 268 renderer->drawText((const char*) (textArray + start), end - start, x, y, paint); 269 env->ReleaseStringChars(text, textArray); 270} 271 272// ---------------------------------------------------------------------------- 273// JNI Glue 274// ---------------------------------------------------------------------------- 275 276const char* const kClassPathName = "android/view/GLES20Canvas"; 277 278static JNINativeMethod gMethods[] = { 279 { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer }, 280 { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer }, 281 { "nSetViewport", "(III)V", (void*) android_view_GLES20Canvas_setViewport }, 282 { "nPrepare", "(I)V", (void*) android_view_GLES20Canvas_prepare }, 283 284 { "nSave", "(II)I", (void*) android_view_GLES20Canvas_save }, 285 { "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore }, 286 { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Canvas_restoreToCount }, 287 { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Canvas_getSaveCount }, 288 289 { "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayer }, 290 { "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayerAlpha }, 291 292 { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject }, 293 { "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF }, 294 { "nClipRect", "(IIIIII)Z", (void*) android_view_GLES20Canvas_clipRect }, 295 296 { "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate }, 297 { "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate }, 298 { "nScale", "(IFF)V", (void*) android_view_GLES20Canvas_scale }, 299 300 { "nSetMatrix", "(II)V", (void*) android_view_GLES20Canvas_setMatrix }, 301 { "nGetMatrix", "(II)V", (void*) android_view_GLES20Canvas_getMatrix }, 302 { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Canvas_concatMatrix }, 303 304 { "nDrawBitmap", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawBitmap }, 305 { "nDrawBitmap", "(IIFFFFFFFFI)V", (void*) android_view_GLES20Canvas_drawBitmapRect }, 306 { "nDrawBitmap", "(IIII)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix }, 307 { "nDrawPatch", "(II[BFFFFI)V", (void*) android_view_GLES20Canvas_drawPatch }, 308 { "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor }, 309 { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect }, 310 311 { "nResetShader", "(I)V", (void*) android_view_GLES20Canvas_resetShader }, 312 { "nSetupBitmapShader", "(IIIIII)V", (void*) android_view_GLES20Canvas_setupBitmapShader }, 313 { "nSetupLinearShader", "(IIIIIIII)V", (void*) android_view_GLES20Canvas_setupLinearShader }, 314 315 { "nDrawText", "(I[CIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArray }, 316 { "nDrawText", "(ILjava/lang/String;IIFFII)V", 317 (void*) android_view_GLES20Canvas_drawText }, 318 319 { "nGetClipBounds", "(ILandroid/graphics/Rect;)Z", 320 (void*) android_view_GLES20Canvas_getClipBounds }, 321}; 322 323#define FIND_CLASS(var, className) \ 324 var = env->FindClass(className); \ 325 LOG_FATAL_IF(! var, "Unable to find class " className); \ 326 var = jclass(env->NewGlobalRef(var)); 327 328#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 329 var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 330 LOG_FATAL_IF(! var, "Unable to find method " methodName); 331 332int register_android_view_GLES20Canvas(JNIEnv* env) { 333 FIND_CLASS(gRectClassInfo.clazz, "android/graphics/Rect"); 334 GET_METHOD_ID(gRectClassInfo.set, gRectClassInfo.clazz, "set", "(IIII)V"); 335 336 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 337} 338 339}; 340