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