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