Graphics.cpp revision 42a1d08df7d417fd4e67eabc91ff05ee77fd9995
1#define LOG_TAG "GraphicsJNI" 2 3#include "jni.h" 4#include "JNIHelp.h" 5#include "GraphicsJNI.h" 6 7#include "SkCanvas.h" 8#include "SkDevice.h" 9#include "SkMath.h" 10#include "SkPicture.h" 11#include "SkRegion.h" 12#include <android_runtime/AndroidRuntime.h> 13 14void doThrowNPE(JNIEnv* env) { 15 jniThrowNullPointerException(env, NULL); 16} 17 18void doThrowAIOOBE(JNIEnv* env) { 19 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 20} 21 22void doThrowRE(JNIEnv* env, const char* msg) { 23 jniThrowRuntimeException(env, msg); 24} 25 26void doThrowIAE(JNIEnv* env, const char* msg) { 27 jniThrowException(env, "java/lang/IllegalArgumentException", msg); 28} 29 30void doThrowISE(JNIEnv* env, const char* msg) { 31 jniThrowException(env, "java/lang/IllegalStateException", msg); 32} 33 34void doThrowOOME(JNIEnv* env, const char* msg) { 35 jniThrowException(env, "java/lang/OutOfMemoryError", msg); 36} 37 38void doThrowIOE(JNIEnv* env, const char* msg) { 39 jniThrowException(env, "java/io/IOException", msg); 40} 41 42bool GraphicsJNI::hasException(JNIEnv *env) { 43 if (env->ExceptionCheck() != 0) { 44 ALOGE("*** Uncaught exception returned from Java call!\n"); 45 env->ExceptionDescribe(); 46 return true; 47 } 48 return false; 49} 50 51/////////////////////////////////////////////////////////////////////////////// 52 53AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array, 54 int minLength, JNIAccess access) 55: fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 56 SkASSERT(env); 57 if (array) { 58 fLen = env->GetArrayLength(array); 59 if (fLen < minLength) { 60 sk_throw(); 61 } 62 fPtr = env->GetFloatArrayElements(array, NULL); 63 } 64 fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0; 65} 66 67AutoJavaFloatArray::~AutoJavaFloatArray() { 68 if (fPtr) { 69 fEnv->ReleaseFloatArrayElements(fArray, fPtr, fReleaseMode); 70 } 71} 72 73AutoJavaIntArray::AutoJavaIntArray(JNIEnv* env, jintArray array, 74 int minLength) 75: fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 76 SkASSERT(env); 77 if (array) { 78 fLen = env->GetArrayLength(array); 79 if (fLen < minLength) { 80 sk_throw(); 81 } 82 fPtr = env->GetIntArrayElements(array, NULL); 83 } 84} 85 86AutoJavaIntArray::~AutoJavaIntArray() { 87 if (fPtr) { 88 fEnv->ReleaseIntArrayElements(fArray, fPtr, 0); 89 } 90} 91 92AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array, 93 int minLength, JNIAccess access) 94: fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 95 SkASSERT(env); 96 if (array) { 97 fLen = env->GetArrayLength(array); 98 if (fLen < minLength) { 99 sk_throw(); 100 } 101 fPtr = env->GetShortArrayElements(array, NULL); 102 } 103 fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0; 104} 105 106AutoJavaShortArray::~AutoJavaShortArray() { 107 if (fPtr) { 108 fEnv->ReleaseShortArrayElements(fArray, fPtr, fReleaseMode); 109 } 110} 111 112AutoJavaByteArray::AutoJavaByteArray(JNIEnv* env, jbyteArray array, 113 int minLength) 114: fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 115 SkASSERT(env); 116 if (array) { 117 fLen = env->GetArrayLength(array); 118 if (fLen < minLength) { 119 sk_throw(); 120 } 121 fPtr = env->GetByteArrayElements(array, NULL); 122 } 123} 124 125AutoJavaByteArray::~AutoJavaByteArray() { 126 if (fPtr) { 127 fEnv->ReleaseByteArrayElements(fArray, fPtr, 0); 128 } 129} 130 131/////////////////////////////////////////////////////////////////////////////// 132 133static jclass gRect_class; 134static jfieldID gRect_leftFieldID; 135static jfieldID gRect_topFieldID; 136static jfieldID gRect_rightFieldID; 137static jfieldID gRect_bottomFieldID; 138 139static jclass gRectF_class; 140static jfieldID gRectF_leftFieldID; 141static jfieldID gRectF_topFieldID; 142static jfieldID gRectF_rightFieldID; 143static jfieldID gRectF_bottomFieldID; 144 145static jclass gPoint_class; 146static jfieldID gPoint_xFieldID; 147static jfieldID gPoint_yFieldID; 148 149static jclass gPointF_class; 150static jfieldID gPointF_xFieldID; 151static jfieldID gPointF_yFieldID; 152 153static jclass gBitmap_class; 154static jfieldID gBitmap_nativeInstanceID; 155static jmethodID gBitmap_constructorMethodID; 156static jmethodID gBitmap_reinitMethodID; 157static jmethodID gBitmap_getAllocationByteCountMethodID; 158 159static jclass gBitmapConfig_class; 160static jfieldID gBitmapConfig_nativeInstanceID; 161 162static jclass gBitmapRegionDecoder_class; 163static jmethodID gBitmapRegionDecoder_constructorMethodID; 164 165static jclass gCanvas_class; 166static jfieldID gCanvas_nativeInstanceID; 167 168static jclass gPaint_class; 169static jfieldID gPaint_nativeInstanceID; 170static jfieldID gPaint_nativeTypefaceID; 171 172static jclass gPicture_class; 173static jfieldID gPicture_nativeInstanceID; 174 175static jclass gRegion_class; 176static jfieldID gRegion_nativeInstanceID; 177static jmethodID gRegion_constructorMethodID; 178 179static jclass gByte_class; 180static jobject gVMRuntime; 181static jclass gVMRuntime_class; 182static jmethodID gVMRuntime_newNonMovableArray; 183static jmethodID gVMRuntime_addressOf; 184 185/////////////////////////////////////////////////////////////////////////////// 186 187void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B) 188{ 189 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 190 191 *L = env->GetIntField(obj, gRect_leftFieldID); 192 *T = env->GetIntField(obj, gRect_topFieldID); 193 *R = env->GetIntField(obj, gRect_rightFieldID); 194 *B = env->GetIntField(obj, gRect_bottomFieldID); 195} 196 197void GraphicsJNI::set_jrect(JNIEnv* env, jobject obj, int L, int T, int R, int B) 198{ 199 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 200 201 env->SetIntField(obj, gRect_leftFieldID, L); 202 env->SetIntField(obj, gRect_topFieldID, T); 203 env->SetIntField(obj, gRect_rightFieldID, R); 204 env->SetIntField(obj, gRect_bottomFieldID, B); 205} 206 207SkIRect* GraphicsJNI::jrect_to_irect(JNIEnv* env, jobject obj, SkIRect* ir) 208{ 209 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 210 211 ir->set(env->GetIntField(obj, gRect_leftFieldID), 212 env->GetIntField(obj, gRect_topFieldID), 213 env->GetIntField(obj, gRect_rightFieldID), 214 env->GetIntField(obj, gRect_bottomFieldID)); 215 return ir; 216} 217 218void GraphicsJNI::irect_to_jrect(const SkIRect& ir, JNIEnv* env, jobject obj) 219{ 220 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 221 222 env->SetIntField(obj, gRect_leftFieldID, ir.fLeft); 223 env->SetIntField(obj, gRect_topFieldID, ir.fTop); 224 env->SetIntField(obj, gRect_rightFieldID, ir.fRight); 225 env->SetIntField(obj, gRect_bottomFieldID, ir.fBottom); 226} 227 228SkRect* GraphicsJNI::jrectf_to_rect(JNIEnv* env, jobject obj, SkRect* r) 229{ 230 SkASSERT(env->IsInstanceOf(obj, gRectF_class)); 231 232 r->set(env->GetFloatField(obj, gRectF_leftFieldID), 233 env->GetFloatField(obj, gRectF_topFieldID), 234 env->GetFloatField(obj, gRectF_rightFieldID), 235 env->GetFloatField(obj, gRectF_bottomFieldID)); 236 return r; 237} 238 239SkRect* GraphicsJNI::jrect_to_rect(JNIEnv* env, jobject obj, SkRect* r) 240{ 241 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 242 243 r->set(SkIntToScalar(env->GetIntField(obj, gRect_leftFieldID)), 244 SkIntToScalar(env->GetIntField(obj, gRect_topFieldID)), 245 SkIntToScalar(env->GetIntField(obj, gRect_rightFieldID)), 246 SkIntToScalar(env->GetIntField(obj, gRect_bottomFieldID))); 247 return r; 248} 249 250void GraphicsJNI::rect_to_jrectf(const SkRect& r, JNIEnv* env, jobject obj) 251{ 252 SkASSERT(env->IsInstanceOf(obj, gRectF_class)); 253 254 env->SetFloatField(obj, gRectF_leftFieldID, SkScalarToFloat(r.fLeft)); 255 env->SetFloatField(obj, gRectF_topFieldID, SkScalarToFloat(r.fTop)); 256 env->SetFloatField(obj, gRectF_rightFieldID, SkScalarToFloat(r.fRight)); 257 env->SetFloatField(obj, gRectF_bottomFieldID, SkScalarToFloat(r.fBottom)); 258} 259 260SkIPoint* GraphicsJNI::jpoint_to_ipoint(JNIEnv* env, jobject obj, SkIPoint* point) 261{ 262 SkASSERT(env->IsInstanceOf(obj, gPoint_class)); 263 264 point->set(env->GetIntField(obj, gPoint_xFieldID), 265 env->GetIntField(obj, gPoint_yFieldID)); 266 return point; 267} 268 269void GraphicsJNI::ipoint_to_jpoint(const SkIPoint& ir, JNIEnv* env, jobject obj) 270{ 271 SkASSERT(env->IsInstanceOf(obj, gPoint_class)); 272 273 env->SetIntField(obj, gPoint_xFieldID, ir.fX); 274 env->SetIntField(obj, gPoint_yFieldID, ir.fY); 275} 276 277SkPoint* GraphicsJNI::jpointf_to_point(JNIEnv* env, jobject obj, SkPoint* point) 278{ 279 SkASSERT(env->IsInstanceOf(obj, gPointF_class)); 280 281 point->set(env->GetIntField(obj, gPointF_xFieldID), 282 env->GetIntField(obj, gPointF_yFieldID)); 283 return point; 284} 285 286void GraphicsJNI::point_to_jpointf(const SkPoint& r, JNIEnv* env, jobject obj) 287{ 288 SkASSERT(env->IsInstanceOf(obj, gPointF_class)); 289 290 env->SetFloatField(obj, gPointF_xFieldID, SkScalarToFloat(r.fX)); 291 env->SetFloatField(obj, gPointF_yFieldID, SkScalarToFloat(r.fY)); 292} 293 294SkBitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) { 295 SkASSERT(env); 296 SkASSERT(bitmap); 297 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class)); 298 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativeInstanceID); 299 SkBitmap* b = reinterpret_cast<SkBitmap*>(bitmapHandle); 300 SkASSERT(b); 301 return b; 302} 303 304SkColorType GraphicsJNI::getNativeBitmapColorType(JNIEnv* env, jobject jconfig) { 305 SkASSERT(env); 306 if (NULL == jconfig) { 307 return kUnknown_SkColorType; 308 } 309 SkASSERT(env->IsInstanceOf(jconfig, gBitmapConfig_class)); 310 int c = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID); 311 if (c < 0 || c >= SkBitmap::kConfigCount) { 312 c = kUnknown_SkColorType; 313 } 314 return SkBitmapConfigToColorType(static_cast<SkBitmap::Config>(c)); 315} 316 317SkCanvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) { 318 SkASSERT(env); 319 SkASSERT(canvas); 320 SkASSERT(env->IsInstanceOf(canvas, gCanvas_class)); 321 jlong canvasHandle = env->GetLongField(canvas, gCanvas_nativeInstanceID); 322 SkCanvas* c = getNativeCanvas(canvasHandle); 323 SkASSERT(c); 324 return c; 325} 326 327SkPaint* GraphicsJNI::getNativePaint(JNIEnv* env, jobject paint) { 328 SkASSERT(env); 329 SkASSERT(paint); 330 SkASSERT(env->IsInstanceOf(paint, gPaint_class)); 331 jlong paintHandle = env->GetLongField(paint, gPaint_nativeInstanceID); 332 SkPaint* p = reinterpret_cast<SkPaint*>(paintHandle); 333 SkASSERT(p); 334 return p; 335} 336 337android::TypefaceImpl* GraphicsJNI::getNativeTypeface(JNIEnv* env, jobject paint) { 338 SkASSERT(env); 339 SkASSERT(paint); 340 SkASSERT(env->IsInstanceOf(paint, gPaint_class)); 341 jlong typefaceHandle = env->GetLongField(paint, gPaint_nativeTypefaceID); 342 android::TypefaceImpl* p = reinterpret_cast<android::TypefaceImpl*>(typefaceHandle); 343 SkASSERT(p); 344 return p; 345} 346 347SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region) 348{ 349 SkASSERT(env); 350 SkASSERT(region); 351 SkASSERT(env->IsInstanceOf(region, gRegion_class)); 352 jlong regionHandle = env->GetLongField(region, gRegion_nativeInstanceID); 353 SkRegion* r = reinterpret_cast<SkRegion*>(regionHandle); 354 SkASSERT(r); 355 return r; 356} 357 358/////////////////////////////////////////////////////////////////////////////////////////// 359 360// Assert that bitmap's SkAlphaType is consistent with isPremultiplied. 361static void assert_premultiplied(const SkBitmap& bitmap, bool isPremultiplied) { 362 // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is 363 // irrelevant. This just tests to ensure that the SkAlphaType is not 364 // opposite of isPremultiplied. 365 if (isPremultiplied) { 366 SkASSERT(bitmap.alphaType() != kUnpremul_SkAlphaType); 367 } else { 368 SkASSERT(bitmap.alphaType() != kPremul_SkAlphaType); 369 } 370} 371 372jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer, 373 int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density) 374{ 375 SkASSERT(bitmap); 376 SkASSERT(bitmap->pixelRef()); 377 bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable; 378 bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied; 379 380 // The caller needs to have already set the alpha type properly, so the 381 // native SkBitmap stays in sync with the Java Bitmap. 382 assert_premultiplied(*bitmap, isPremultiplied); 383 384 jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID, 385 reinterpret_cast<jlong>(bitmap), buffer, 386 bitmap->width(), bitmap->height(), density, isMutable, isPremultiplied, 387 ninepatch, layoutbounds); 388 hasException(env); // For the side effect of logging. 389 return obj; 390} 391 392jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, int bitmapCreateFlags, 393 jbyteArray ninepatch, int density) 394{ 395 return createBitmap(env, bitmap, NULL, bitmapCreateFlags, ninepatch, NULL, density); 396} 397 398void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap, 399 bool isPremultiplied) 400{ 401 // The caller needs to have already set the alpha type properly, so the 402 // native SkBitmap stays in sync with the Java Bitmap. 403 assert_premultiplied(*bitmap, isPremultiplied); 404 405 env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID, 406 bitmap->width(), bitmap->height(), isPremultiplied); 407} 408 409int GraphicsJNI::getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap) 410{ 411 return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID); 412} 413 414jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap) 415{ 416 SkASSERT(bitmap != NULL); 417 418 jobject obj = env->NewObject(gBitmapRegionDecoder_class, 419 gBitmapRegionDecoder_constructorMethodID, 420 reinterpret_cast<jlong>(bitmap)); 421 hasException(env); // For the side effect of logging. 422 return obj; 423} 424 425jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region) 426{ 427 SkASSERT(region != NULL); 428 jobject obj = env->NewObject(gRegion_class, gRegion_constructorMethodID, 429 reinterpret_cast<jlong>(region), 0); 430 hasException(env); // For the side effect of logging. 431 return obj; 432} 433 434static JNIEnv* vm2env(JavaVM* vm) 435{ 436 JNIEnv* env = NULL; 437 if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK || NULL == env) 438 { 439 SkDebugf("------- [%p] vm->GetEnv() failed\n", vm); 440 sk_throw(); 441 } 442 return env; 443} 444 445/////////////////////////////////////////////////////////////////////////////// 446 447AndroidPixelRef::AndroidPixelRef(JNIEnv* env, const SkImageInfo& info, void* storage, 448 size_t rowBytes, jbyteArray storageObj, SkColorTable* ctable) : 449 SkMallocPixelRef(info, storage, rowBytes, ctable, (storageObj == NULL)), 450 fWrappedPixelRef(NULL) { 451 SkASSERT(storage); 452 SkASSERT(env); 453 454 if (env->GetJavaVM(&fVM) != JNI_OK) { 455 SkDebugf("------ [%p] env->GetJavaVM failed\n", env); 456 sk_throw(); 457 } 458 fStorageObj = storageObj; 459 fHasGlobalRef = false; 460 fGlobalRefCnt = 0; 461 462 // If storageObj is NULL, the memory was NOT allocated on the Java heap 463 fOnJavaHeap = (storageObj != NULL); 464 465} 466 467AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, const SkImageInfo& info, 468 size_t rowBytes, SkColorTable* ctable) : 469 SkMallocPixelRef(info, wrappedPixelRef.getAddr(), rowBytes, ctable, false), 470 fWrappedPixelRef(wrappedPixelRef.fWrappedPixelRef ? 471 wrappedPixelRef.fWrappedPixelRef : &wrappedPixelRef) 472{ 473 SkASSERT(fWrappedPixelRef); 474 SkSafeRef(fWrappedPixelRef); 475 476 // don't need to initialize these, as all the relevant logic delegates to the wrapped ref 477 fStorageObj = NULL; 478 fHasGlobalRef = false; 479 fGlobalRefCnt = 0; 480 fOnJavaHeap = false; 481} 482 483AndroidPixelRef::~AndroidPixelRef() { 484 if (fWrappedPixelRef) { 485 SkSafeUnref(fWrappedPixelRef); 486 } else if (fOnJavaHeap) { 487 JNIEnv* env = vm2env(fVM); 488 489 if (fStorageObj && fHasGlobalRef) { 490 env->DeleteGlobalRef(fStorageObj); 491 } 492 fStorageObj = NULL; 493 } 494} 495jbyteArray AndroidPixelRef::getStorageObj() { 496 if (fWrappedPixelRef) { 497 return fWrappedPixelRef->fStorageObj; 498 } 499 return fStorageObj; 500} 501 502void AndroidPixelRef::setLocalJNIRef(jbyteArray arr) { 503 if (fWrappedPixelRef) { 504 // delegate java obj management to the wrapped ref 505 fWrappedPixelRef->setLocalJNIRef(arr); 506 } else if (!fHasGlobalRef) { 507 fStorageObj = arr; 508 } 509} 510 511void AndroidPixelRef::globalRef(void* localref) { 512 if (fWrappedPixelRef) { 513 // delegate java obj management to the wrapped ref 514 fWrappedPixelRef->globalRef(localref); 515 516 // Note: we only ref and unref the wrapped AndroidPixelRef so that 517 // bitmap->pixelRef()->globalRef() and globalUnref() can be used in a pair, even if 518 // the bitmap has its underlying AndroidPixelRef swapped out/wrapped 519 return; 520 } 521 if (fOnJavaHeap && sk_atomic_inc(&fGlobalRefCnt) == 0) { 522 JNIEnv *env = vm2env(fVM); 523 524 // If JNI ref was passed, it is always used 525 if (localref) fStorageObj = (jbyteArray) localref; 526 527 if (fStorageObj == NULL) { 528 SkDebugf("No valid local ref to create a JNI global ref\n"); 529 sk_throw(); 530 } 531 if (fHasGlobalRef) { 532 // This should never happen 533 SkDebugf("Already holding a JNI global ref"); 534 sk_throw(); 535 } 536 537 fStorageObj = (jbyteArray) env->NewGlobalRef(fStorageObj); 538 // TODO: Check for failure here 539 fHasGlobalRef = true; 540 } 541 ref(); 542} 543 544void AndroidPixelRef::globalUnref() { 545 if (fWrappedPixelRef) { 546 // delegate java obj management to the wrapped ref 547 fWrappedPixelRef->globalUnref(); 548 return; 549 } 550 if (fOnJavaHeap && sk_atomic_dec(&fGlobalRefCnt) == 1) { 551 JNIEnv *env = vm2env(fVM); 552 if (!fHasGlobalRef) { 553 SkDebugf("We don't have a global ref!"); 554 sk_throw(); 555 } 556 env->DeleteGlobalRef(fStorageObj); 557 fStorageObj = NULL; 558 fHasGlobalRef = false; 559 } 560 unref(); 561} 562 563/////////////////////////////////////////////////////////////////////////////// 564 565jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, 566 SkColorTable* ctable) { 567 const SkImageInfo& info = bitmap->info(); 568 if (info.fColorType == kUnknown_SkColorType) { 569 doThrowIAE(env, "unknown bitmap configuration"); 570 return NULL; 571 } 572 573 const size_t size = bitmap->getSize(); 574 jbyteArray arrayObj = (jbyteArray) env->CallObjectMethod(gVMRuntime, 575 gVMRuntime_newNonMovableArray, 576 gByte_class, size); 577 if (env->ExceptionCheck() != 0) { 578 return NULL; 579 } 580 SkASSERT(arrayObj); 581 jbyte* addr = (jbyte*) env->CallLongMethod(gVMRuntime, gVMRuntime_addressOf, arrayObj); 582 if (env->ExceptionCheck() != 0) { 583 return NULL; 584 } 585 SkASSERT(addr); 586 SkPixelRef* pr = new AndroidPixelRef(env, info, (void*) addr, 587 bitmap->rowBytes(), arrayObj, ctable); 588 bitmap->setPixelRef(pr)->unref(); 589 // since we're already allocated, we lockPixels right away 590 // HeapAllocator behaves this way too 591 bitmap->lockPixels(); 592 593 return arrayObj; 594} 595 596/////////////////////////////////////////////////////////////////////////////// 597 598JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env) 599 : fStorageObj(NULL), 600 fAllocCount(0) { 601 if (env->GetJavaVM(&fVM) != JNI_OK) { 602 SkDebugf("------ [%p] env->GetJavaVM failed\n", env); 603 sk_throw(); 604 } 605} 606 607bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) { 608 JNIEnv* env = vm2env(fVM); 609 610 fStorageObj = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable); 611 fAllocCount += 1; 612 return fStorageObj != NULL; 613} 614 615//////////////////////////////////////////////////////////////////////////////// 616 617JavaHeapBitmapRef::JavaHeapBitmapRef(JNIEnv* env, SkBitmap* nativeBitmap, jbyteArray buffer) { 618 fEnv = env; 619 fNativeBitmap = nativeBitmap; 620 fBuffer = buffer; 621 622 // If the buffer is NULL, the backing memory wasn't allocated on the Java heap 623 if (fBuffer) { 624 ((AndroidPixelRef*) fNativeBitmap->pixelRef())->setLocalJNIRef(fBuffer); 625 } 626} 627 628JavaHeapBitmapRef::~JavaHeapBitmapRef() { 629 if (fBuffer) { 630 ((AndroidPixelRef*) fNativeBitmap->pixelRef())->setLocalJNIRef(NULL); 631 } 632} 633 634//////////////////////////////////////////////////////////////////////////////// 635 636static jclass make_globalref(JNIEnv* env, const char classname[]) 637{ 638 jclass c = env->FindClass(classname); 639 SkASSERT(c); 640 return (jclass) env->NewGlobalRef(c); 641} 642 643static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, 644 const char fieldname[], const char type[]) 645{ 646 jfieldID id = env->GetFieldID(clazz, fieldname, type); 647 SkASSERT(id); 648 return id; 649} 650 651int register_android_graphics_Graphics(JNIEnv* env) 652{ 653 jmethodID m; 654 jclass c; 655 656 gRect_class = make_globalref(env, "android/graphics/Rect"); 657 gRect_leftFieldID = getFieldIDCheck(env, gRect_class, "left", "I"); 658 gRect_topFieldID = getFieldIDCheck(env, gRect_class, "top", "I"); 659 gRect_rightFieldID = getFieldIDCheck(env, gRect_class, "right", "I"); 660 gRect_bottomFieldID = getFieldIDCheck(env, gRect_class, "bottom", "I"); 661 662 gRectF_class = make_globalref(env, "android/graphics/RectF"); 663 gRectF_leftFieldID = getFieldIDCheck(env, gRectF_class, "left", "F"); 664 gRectF_topFieldID = getFieldIDCheck(env, gRectF_class, "top", "F"); 665 gRectF_rightFieldID = getFieldIDCheck(env, gRectF_class, "right", "F"); 666 gRectF_bottomFieldID = getFieldIDCheck(env, gRectF_class, "bottom", "F"); 667 668 gPoint_class = make_globalref(env, "android/graphics/Point"); 669 gPoint_xFieldID = getFieldIDCheck(env, gPoint_class, "x", "I"); 670 gPoint_yFieldID = getFieldIDCheck(env, gPoint_class, "y", "I"); 671 672 gPointF_class = make_globalref(env, "android/graphics/PointF"); 673 gPointF_xFieldID = getFieldIDCheck(env, gPointF_class, "x", "F"); 674 gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F"); 675 676 gBitmap_class = make_globalref(env, "android/graphics/Bitmap"); 677 gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "J"); 678 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(J[BIIIZZ[B[I)V"); 679 gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V"); 680 gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I"); 681 gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder"); 682 gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(J)V"); 683 684 gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config"); 685 gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class, 686 "nativeInt", "I"); 687 688 gCanvas_class = make_globalref(env, "android/graphics/Canvas"); 689 gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvasWrapper", "J"); 690 691 gPaint_class = make_globalref(env, "android/graphics/Paint"); 692 gPaint_nativeInstanceID = getFieldIDCheck(env, gPaint_class, "mNativePaint", "J"); 693 gPaint_nativeTypefaceID = getFieldIDCheck(env, gPaint_class, "mNativeTypeface", "J"); 694 695 gPicture_class = make_globalref(env, "android/graphics/Picture"); 696 gPicture_nativeInstanceID = getFieldIDCheck(env, gPicture_class, "mNativePicture", "J"); 697 698 gRegion_class = make_globalref(env, "android/graphics/Region"); 699 gRegion_nativeInstanceID = getFieldIDCheck(env, gRegion_class, "mNativeRegion", "J"); 700 gRegion_constructorMethodID = env->GetMethodID(gRegion_class, "<init>", 701 "(JI)V"); 702 703 c = env->FindClass("java/lang/Byte"); 704 gByte_class = (jclass) env->NewGlobalRef( 705 env->GetStaticObjectField(c, env->GetStaticFieldID(c, "TYPE", "Ljava/lang/Class;"))); 706 707 gVMRuntime_class = make_globalref(env, "dalvik/system/VMRuntime"); 708 m = env->GetStaticMethodID(gVMRuntime_class, "getRuntime", "()Ldalvik/system/VMRuntime;"); 709 gVMRuntime = env->NewGlobalRef(env->CallStaticObjectMethod(gVMRuntime_class, m)); 710 gVMRuntime_newNonMovableArray = env->GetMethodID(gVMRuntime_class, "newNonMovableArray", 711 "(Ljava/lang/Class;I)Ljava/lang/Object;"); 712 gVMRuntime_addressOf = env->GetMethodID(gVMRuntime_class, "addressOf", "(Ljava/lang/Object;)J"); 713 714 return 0; 715} 716