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