1 #define LOG_TAG "GraphicsJNI" 2 3 #include <unistd.h> 4 #include <sys/mman.h> 5 6 #include "jni.h" 7 #include <nativehelper/JNIHelp.h> 8 #include "GraphicsJNI.h" 9 #include "core_jni_helpers.h" 10 11 #include "SkCanvas.h" 12 #include "SkMath.h" 13 #include "SkRegion.h" 14 #include <android_runtime/AndroidRuntime.h> 15 #include <cutils/ashmem.h> 16 #include <hwui/Canvas.h> 17 18 using namespace android; 19 20 void doThrowNPE(JNIEnv* env) { 21 jniThrowNullPointerException(env, NULL); 22 } 23 24 void doThrowAIOOBE(JNIEnv* env) { 25 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 26 } 27 28 void doThrowRE(JNIEnv* env, const char* msg) { 29 jniThrowRuntimeException(env, msg); 30 } 31 32 void doThrowIAE(JNIEnv* env, const char* msg) { 33 jniThrowException(env, "java/lang/IllegalArgumentException", msg); 34 } 35 36 void doThrowISE(JNIEnv* env, const char* msg) { 37 jniThrowException(env, "java/lang/IllegalStateException", msg); 38 } 39 40 void doThrowOOME(JNIEnv* env, const char* msg) { 41 jniThrowException(env, "java/lang/OutOfMemoryError", msg); 42 } 43 44 void doThrowIOE(JNIEnv* env, const char* msg) { 45 jniThrowException(env, "java/io/IOException", msg); 46 } 47 48 bool GraphicsJNI::hasException(JNIEnv *env) { 49 if (env->ExceptionCheck() != 0) { 50 ALOGE("*** Uncaught exception returned from Java call!\n"); 51 env->ExceptionDescribe(); 52 return true; 53 } 54 return false; 55 } 56 57 /////////////////////////////////////////////////////////////////////////////// 58 59 AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array, 60 int minLength, JNIAccess access) 61 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 62 ALOG_ASSERT(env); 63 if (array) { 64 fLen = env->GetArrayLength(array); 65 if (fLen < minLength) { 66 LOG_ALWAYS_FATAL("bad length"); 67 } 68 fPtr = env->GetFloatArrayElements(array, NULL); 69 } 70 fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0; 71 } 72 73 AutoJavaFloatArray::~AutoJavaFloatArray() { 74 if (fPtr) { 75 fEnv->ReleaseFloatArrayElements(fArray, fPtr, fReleaseMode); 76 } 77 } 78 79 AutoJavaIntArray::AutoJavaIntArray(JNIEnv* env, jintArray array, 80 int minLength) 81 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 82 ALOG_ASSERT(env); 83 if (array) { 84 fLen = env->GetArrayLength(array); 85 if (fLen < minLength) { 86 LOG_ALWAYS_FATAL("bad length"); 87 } 88 fPtr = env->GetIntArrayElements(array, NULL); 89 } 90 } 91 92 AutoJavaIntArray::~AutoJavaIntArray() { 93 if (fPtr) { 94 fEnv->ReleaseIntArrayElements(fArray, fPtr, 0); 95 } 96 } 97 98 AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array, 99 int minLength, JNIAccess access) 100 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 101 ALOG_ASSERT(env); 102 if (array) { 103 fLen = env->GetArrayLength(array); 104 if (fLen < minLength) { 105 LOG_ALWAYS_FATAL("bad length"); 106 } 107 fPtr = env->GetShortArrayElements(array, NULL); 108 } 109 fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0; 110 } 111 112 AutoJavaShortArray::~AutoJavaShortArray() { 113 if (fPtr) { 114 fEnv->ReleaseShortArrayElements(fArray, fPtr, fReleaseMode); 115 } 116 } 117 118 AutoJavaByteArray::AutoJavaByteArray(JNIEnv* env, jbyteArray array, 119 int minLength) 120 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 121 ALOG_ASSERT(env); 122 if (array) { 123 fLen = env->GetArrayLength(array); 124 if (fLen < minLength) { 125 LOG_ALWAYS_FATAL("bad length"); 126 } 127 fPtr = env->GetByteArrayElements(array, NULL); 128 } 129 } 130 131 AutoJavaByteArray::~AutoJavaByteArray() { 132 if (fPtr) { 133 fEnv->ReleaseByteArrayElements(fArray, fPtr, 0); 134 } 135 } 136 137 /////////////////////////////////////////////////////////////////////////////// 138 139 static jclass gRect_class; 140 static jfieldID gRect_leftFieldID; 141 static jfieldID gRect_topFieldID; 142 static jfieldID gRect_rightFieldID; 143 static jfieldID gRect_bottomFieldID; 144 145 static jclass gRectF_class; 146 static jfieldID gRectF_leftFieldID; 147 static jfieldID gRectF_topFieldID; 148 static jfieldID gRectF_rightFieldID; 149 static jfieldID gRectF_bottomFieldID; 150 151 static jclass gPoint_class; 152 static jfieldID gPoint_xFieldID; 153 static jfieldID gPoint_yFieldID; 154 155 static jclass gPointF_class; 156 static jfieldID gPointF_xFieldID; 157 static jfieldID gPointF_yFieldID; 158 159 static jclass gBitmapConfig_class; 160 static jfieldID gBitmapConfig_nativeInstanceID; 161 162 static jclass gBitmapRegionDecoder_class; 163 static jmethodID gBitmapRegionDecoder_constructorMethodID; 164 165 static jclass gCanvas_class; 166 static jfieldID gCanvas_nativeInstanceID; 167 168 static jclass gPicture_class; 169 static jfieldID gPicture_nativeInstanceID; 170 171 static jclass gRegion_class; 172 static jfieldID gRegion_nativeInstanceID; 173 static jmethodID gRegion_constructorMethodID; 174 175 static jclass gByte_class; 176 static jobject gVMRuntime; 177 static jclass gVMRuntime_class; 178 static jmethodID gVMRuntime_newNonMovableArray; 179 static jmethodID gVMRuntime_addressOf; 180 181 static jclass gColorSpace_class; 182 static jmethodID gColorSpace_getMethodID; 183 static jmethodID gColorSpace_matchMethodID; 184 185 static jclass gColorSpaceRGB_class; 186 static jmethodID gColorSpaceRGB_constructorMethodID; 187 188 static jclass gColorSpace_Named_class; 189 static jfieldID gColorSpace_Named_sRGBFieldID; 190 static jfieldID gColorSpace_Named_ExtendedSRGBFieldID; 191 static jfieldID gColorSpace_Named_LinearSRGBFieldID; 192 static jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID; 193 194 static jclass gTransferParameters_class; 195 static jmethodID gTransferParameters_constructorMethodID; 196 197 /////////////////////////////////////////////////////////////////////////////// 198 199 void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B) 200 { 201 ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); 202 203 *L = env->GetIntField(obj, gRect_leftFieldID); 204 *T = env->GetIntField(obj, gRect_topFieldID); 205 *R = env->GetIntField(obj, gRect_rightFieldID); 206 *B = env->GetIntField(obj, gRect_bottomFieldID); 207 } 208 209 void GraphicsJNI::set_jrect(JNIEnv* env, jobject obj, int L, int T, int R, int B) 210 { 211 ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); 212 213 env->SetIntField(obj, gRect_leftFieldID, L); 214 env->SetIntField(obj, gRect_topFieldID, T); 215 env->SetIntField(obj, gRect_rightFieldID, R); 216 env->SetIntField(obj, gRect_bottomFieldID, B); 217 } 218 219 SkIRect* GraphicsJNI::jrect_to_irect(JNIEnv* env, jobject obj, SkIRect* ir) 220 { 221 ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); 222 223 ir->set(env->GetIntField(obj, gRect_leftFieldID), 224 env->GetIntField(obj, gRect_topFieldID), 225 env->GetIntField(obj, gRect_rightFieldID), 226 env->GetIntField(obj, gRect_bottomFieldID)); 227 return ir; 228 } 229 230 void GraphicsJNI::irect_to_jrect(const SkIRect& ir, JNIEnv* env, jobject obj) 231 { 232 ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); 233 234 env->SetIntField(obj, gRect_leftFieldID, ir.fLeft); 235 env->SetIntField(obj, gRect_topFieldID, ir.fTop); 236 env->SetIntField(obj, gRect_rightFieldID, ir.fRight); 237 env->SetIntField(obj, gRect_bottomFieldID, ir.fBottom); 238 } 239 240 SkRect* GraphicsJNI::jrectf_to_rect(JNIEnv* env, jobject obj, SkRect* r) 241 { 242 ALOG_ASSERT(env->IsInstanceOf(obj, gRectF_class)); 243 244 r->set(env->GetFloatField(obj, gRectF_leftFieldID), 245 env->GetFloatField(obj, gRectF_topFieldID), 246 env->GetFloatField(obj, gRectF_rightFieldID), 247 env->GetFloatField(obj, gRectF_bottomFieldID)); 248 return r; 249 } 250 251 SkRect* GraphicsJNI::jrect_to_rect(JNIEnv* env, jobject obj, SkRect* r) 252 { 253 ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); 254 255 r->set(SkIntToScalar(env->GetIntField(obj, gRect_leftFieldID)), 256 SkIntToScalar(env->GetIntField(obj, gRect_topFieldID)), 257 SkIntToScalar(env->GetIntField(obj, gRect_rightFieldID)), 258 SkIntToScalar(env->GetIntField(obj, gRect_bottomFieldID))); 259 return r; 260 } 261 262 void GraphicsJNI::rect_to_jrectf(const SkRect& r, JNIEnv* env, jobject obj) 263 { 264 ALOG_ASSERT(env->IsInstanceOf(obj, gRectF_class)); 265 266 env->SetFloatField(obj, gRectF_leftFieldID, SkScalarToFloat(r.fLeft)); 267 env->SetFloatField(obj, gRectF_topFieldID, SkScalarToFloat(r.fTop)); 268 env->SetFloatField(obj, gRectF_rightFieldID, SkScalarToFloat(r.fRight)); 269 env->SetFloatField(obj, gRectF_bottomFieldID, SkScalarToFloat(r.fBottom)); 270 } 271 272 SkIPoint* GraphicsJNI::jpoint_to_ipoint(JNIEnv* env, jobject obj, SkIPoint* point) 273 { 274 ALOG_ASSERT(env->IsInstanceOf(obj, gPoint_class)); 275 276 point->set(env->GetIntField(obj, gPoint_xFieldID), 277 env->GetIntField(obj, gPoint_yFieldID)); 278 return point; 279 } 280 281 void GraphicsJNI::ipoint_to_jpoint(const SkIPoint& ir, JNIEnv* env, jobject obj) 282 { 283 ALOG_ASSERT(env->IsInstanceOf(obj, gPoint_class)); 284 285 env->SetIntField(obj, gPoint_xFieldID, ir.fX); 286 env->SetIntField(obj, gPoint_yFieldID, ir.fY); 287 } 288 289 SkPoint* GraphicsJNI::jpointf_to_point(JNIEnv* env, jobject obj, SkPoint* point) 290 { 291 ALOG_ASSERT(env->IsInstanceOf(obj, gPointF_class)); 292 293 point->set(env->GetIntField(obj, gPointF_xFieldID), 294 env->GetIntField(obj, gPointF_yFieldID)); 295 return point; 296 } 297 298 void GraphicsJNI::point_to_jpointf(const SkPoint& r, JNIEnv* env, jobject obj) 299 { 300 ALOG_ASSERT(env->IsInstanceOf(obj, gPointF_class)); 301 302 env->SetFloatField(obj, gPointF_xFieldID, SkScalarToFloat(r.fX)); 303 env->SetFloatField(obj, gPointF_yFieldID, SkScalarToFloat(r.fY)); 304 } 305 306 // See enum values in GraphicsJNI.h 307 jint GraphicsJNI::colorTypeToLegacyBitmapConfig(SkColorType colorType) { 308 switch (colorType) { 309 case kRGBA_F16_SkColorType: 310 return kRGBA_16F_LegacyBitmapConfig; 311 case kN32_SkColorType: 312 return kARGB_8888_LegacyBitmapConfig; 313 case kARGB_4444_SkColorType: 314 return kARGB_4444_LegacyBitmapConfig; 315 case kRGB_565_SkColorType: 316 return kRGB_565_LegacyBitmapConfig; 317 case kAlpha_8_SkColorType: 318 return kA8_LegacyBitmapConfig; 319 case kUnknown_SkColorType: 320 default: 321 break; 322 } 323 return kNo_LegacyBitmapConfig; 324 } 325 326 SkColorType GraphicsJNI::legacyBitmapConfigToColorType(jint legacyConfig) { 327 const uint8_t gConfig2ColorType[] = { 328 kUnknown_SkColorType, 329 kAlpha_8_SkColorType, 330 kUnknown_SkColorType, // Previously kIndex_8_SkColorType, 331 kRGB_565_SkColorType, 332 kARGB_4444_SkColorType, 333 kN32_SkColorType, 334 kRGBA_F16_SkColorType, 335 kN32_SkColorType 336 }; 337 338 if (legacyConfig < 0 || legacyConfig > kLastEnum_LegacyBitmapConfig) { 339 legacyConfig = kNo_LegacyBitmapConfig; 340 } 341 return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]); 342 } 343 344 void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) { 345 bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap); 346 } 347 348 SkColorType GraphicsJNI::getNativeBitmapColorType(JNIEnv* env, jobject jconfig) { 349 ALOG_ASSERT(env); 350 if (NULL == jconfig) { 351 return kUnknown_SkColorType; 352 } 353 ALOG_ASSERT(env->IsInstanceOf(jconfig, gBitmapConfig_class)); 354 int c = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID); 355 return legacyBitmapConfigToColorType(c); 356 } 357 358 bool GraphicsJNI::isHardwareConfig(JNIEnv* env, jobject jconfig) { 359 ALOG_ASSERT(env); 360 if (NULL == jconfig) { 361 return false; 362 } 363 int c = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID); 364 return c == kHardware_LegacyBitmapConfig; 365 } 366 367 jint GraphicsJNI::hardwareLegacyBitmapConfig() { 368 return kHardware_LegacyBitmapConfig; 369 } 370 371 android::Canvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) { 372 ALOG_ASSERT(env); 373 ALOG_ASSERT(canvas); 374 ALOG_ASSERT(env->IsInstanceOf(canvas, gCanvas_class)); 375 jlong canvasHandle = env->GetLongField(canvas, gCanvas_nativeInstanceID); 376 if (!canvasHandle) { 377 return NULL; 378 } 379 return reinterpret_cast<android::Canvas*>(canvasHandle); 380 } 381 382 SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region) 383 { 384 ALOG_ASSERT(env); 385 ALOG_ASSERT(region); 386 ALOG_ASSERT(env->IsInstanceOf(region, gRegion_class)); 387 jlong regionHandle = env->GetLongField(region, gRegion_nativeInstanceID); 388 SkRegion* r = reinterpret_cast<SkRegion*>(regionHandle); 389 ALOG_ASSERT(r); 390 return r; 391 } 392 393 /////////////////////////////////////////////////////////////////////////////////////////// 394 395 jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap) 396 { 397 ALOG_ASSERT(bitmap != NULL); 398 399 jobject obj = env->NewObject(gBitmapRegionDecoder_class, 400 gBitmapRegionDecoder_constructorMethodID, 401 reinterpret_cast<jlong>(bitmap)); 402 hasException(env); // For the side effect of logging. 403 return obj; 404 } 405 406 jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region) 407 { 408 ALOG_ASSERT(region != NULL); 409 jobject obj = env->NewObject(gRegion_class, gRegion_constructorMethodID, 410 reinterpret_cast<jlong>(region), 0); 411 hasException(env); // For the side effect of logging. 412 return obj; 413 } 414 415 /////////////////////////////////////////////////////////////////////////////// 416 417 jobject GraphicsJNI::getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace, 418 SkColorType decodeColorType) { 419 if (!decodeColorSpace || decodeColorType == kAlpha_8_SkColorType) { 420 return nullptr; 421 } 422 423 // Special checks for the common sRGB cases and their extended variants. 424 jobject namedCS = nullptr; 425 sk_sp<SkColorSpace> srgbLinear = SkColorSpace::MakeSRGBLinear(); 426 if (decodeColorType == kRGBA_F16_SkColorType) { 427 // An F16 Bitmap will always report that it is EXTENDED if 428 // it matches a ColorSpace that has an EXTENDED variant. 429 if (decodeColorSpace->isSRGB()) { 430 namedCS = env->GetStaticObjectField(gColorSpace_Named_class, 431 gColorSpace_Named_ExtendedSRGBFieldID); 432 } else if (decodeColorSpace == srgbLinear.get()) { 433 namedCS = env->GetStaticObjectField(gColorSpace_Named_class, 434 gColorSpace_Named_LinearExtendedSRGBFieldID); 435 } 436 } else if (decodeColorSpace->isSRGB()) { 437 namedCS = env->GetStaticObjectField(gColorSpace_Named_class, 438 gColorSpace_Named_sRGBFieldID); 439 } else if (decodeColorSpace == srgbLinear.get()) { 440 namedCS = env->GetStaticObjectField(gColorSpace_Named_class, 441 gColorSpace_Named_LinearSRGBFieldID); 442 } 443 444 if (namedCS) { 445 return env->CallStaticObjectMethod(gColorSpace_class, gColorSpace_getMethodID, namedCS); 446 } 447 448 // Try to match against known RGB color spaces using the CIE XYZ D50 449 // conversion matrix and numerical transfer function parameters 450 skcms_Matrix3x3 xyzMatrix; 451 LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix)); 452 453 skcms_TransferFunction transferParams; 454 // We can only handle numerical transfer functions at the moment 455 LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams)); 456 457 jobject params = env->NewObject(gTransferParameters_class, 458 gTransferParameters_constructorMethodID, 459 transferParams.a, transferParams.b, transferParams.c, 460 transferParams.d, transferParams.e, transferParams.f, 461 transferParams.g); 462 463 jfloatArray xyzArray = env->NewFloatArray(9); 464 jfloat xyz[9] = { 465 xyzMatrix.vals[0][0], 466 xyzMatrix.vals[1][0], 467 xyzMatrix.vals[2][0], 468 xyzMatrix.vals[0][1], 469 xyzMatrix.vals[1][1], 470 xyzMatrix.vals[2][1], 471 xyzMatrix.vals[0][2], 472 xyzMatrix.vals[1][2], 473 xyzMatrix.vals[2][2] 474 }; 475 env->SetFloatArrayRegion(xyzArray, 0, 9, xyz); 476 477 jobject colorSpace = env->CallStaticObjectMethod(gColorSpace_class, 478 gColorSpace_matchMethodID, xyzArray, params); 479 480 if (colorSpace == nullptr) { 481 // We couldn't find an exact match, let's create a new color space 482 // instance with the 3x3 conversion matrix and transfer function 483 colorSpace = env->NewObject(gColorSpaceRGB_class, 484 gColorSpaceRGB_constructorMethodID, 485 env->NewStringUTF("Unknown"), xyzArray, params); 486 } 487 488 env->DeleteLocalRef(xyzArray); 489 return colorSpace; 490 } 491 492 /////////////////////////////////////////////////////////////////////////////// 493 bool HeapAllocator::allocPixelRef(SkBitmap* bitmap) { 494 mStorage = android::Bitmap::allocateHeapBitmap(bitmap); 495 return !!mStorage; 496 } 497 498 //////////////////////////////////////////////////////////////////////////////// 499 500 RecyclingClippingPixelAllocator::RecyclingClippingPixelAllocator( 501 android::Bitmap* recycledBitmap, size_t recycledBytes) 502 : mRecycledBitmap(recycledBitmap) 503 , mRecycledBytes(recycledBytes) 504 , mSkiaBitmap(nullptr) 505 , mNeedsCopy(false) 506 {} 507 508 RecyclingClippingPixelAllocator::~RecyclingClippingPixelAllocator() {} 509 510 bool RecyclingClippingPixelAllocator::allocPixelRef(SkBitmap* bitmap) { 511 // Ensure that the caller did not pass in a NULL bitmap to the constructor or this 512 // function. 513 LOG_ALWAYS_FATAL_IF(!mRecycledBitmap); 514 LOG_ALWAYS_FATAL_IF(!bitmap); 515 mSkiaBitmap = bitmap; 516 517 // This behaves differently than the RecyclingPixelAllocator. For backwards 518 // compatibility, the original color type of the recycled bitmap must be maintained. 519 if (mRecycledBitmap->info().colorType() != bitmap->colorType()) { 520 return false; 521 } 522 523 // The Skia bitmap specifies the width and height needed by the decoder. 524 // mRecycledBitmap specifies the width and height of the bitmap that we 525 // want to reuse. Neither can be changed. We will try to find a way 526 // to reuse the memory. 527 const int maxWidth = SkTMax(bitmap->width(), mRecycledBitmap->info().width()); 528 const int maxHeight = SkTMax(bitmap->height(), mRecycledBitmap->info().height()); 529 const SkImageInfo maxInfo = bitmap->info().makeWH(maxWidth, maxHeight); 530 const size_t rowBytes = maxInfo.minRowBytes(); 531 const size_t bytesNeeded = maxInfo.computeByteSize(rowBytes); 532 if (bytesNeeded <= mRecycledBytes) { 533 // Here we take advantage of reconfigure() to reset the rowBytes 534 // of mRecycledBitmap. It is very important that we pass in 535 // mRecycledBitmap->info() for the SkImageInfo. According to the 536 // specification for BitmapRegionDecoder, we are not allowed to change 537 // the SkImageInfo. 538 // We can (must) preserve the color space since it doesn't affect the 539 // storage needs 540 mRecycledBitmap->reconfigure( 541 mRecycledBitmap->info().makeColorSpace(bitmap->refColorSpace()), 542 rowBytes); 543 544 // Give the bitmap the same pixelRef as mRecycledBitmap. 545 // skbug.com/4538: We also need to make sure that the rowBytes on the pixel ref 546 // match the rowBytes on the bitmap. 547 bitmap->setInfo(bitmap->info(), rowBytes); 548 bitmap->setPixelRef(sk_ref_sp(mRecycledBitmap), 0, 0); 549 550 // Make sure that the recycled bitmap has the correct alpha type. 551 mRecycledBitmap->setAlphaType(bitmap->alphaType()); 552 553 bitmap->notifyPixelsChanged(); 554 mNeedsCopy = false; 555 556 // TODO: If the dimensions of the SkBitmap are smaller than those of 557 // mRecycledBitmap, should we zero the memory in mRecycledBitmap? 558 return true; 559 } 560 561 // In the event that mRecycledBitmap is not large enough, allocate new memory 562 // on the heap. 563 SkBitmap::HeapAllocator heapAllocator; 564 565 // We will need to copy from heap memory to mRecycledBitmap's memory after the 566 // decode is complete. 567 mNeedsCopy = true; 568 569 return heapAllocator.allocPixelRef(bitmap); 570 } 571 572 void RecyclingClippingPixelAllocator::copyIfNecessary() { 573 if (mNeedsCopy) { 574 mRecycledBitmap->ref(); 575 SkPixelRef* recycledPixels = mRecycledBitmap; 576 void* dst = recycledPixels->pixels(); 577 const size_t dstRowBytes = mRecycledBitmap->rowBytes(); 578 const size_t bytesToCopy = std::min(mRecycledBitmap->info().minRowBytes(), 579 mSkiaBitmap->info().minRowBytes()); 580 const int rowsToCopy = std::min(mRecycledBitmap->info().height(), 581 mSkiaBitmap->info().height()); 582 for (int y = 0; y < rowsToCopy; y++) { 583 memcpy(dst, mSkiaBitmap->getAddr(0, y), bytesToCopy); 584 dst = SkTAddOffset<void>(dst, dstRowBytes); 585 } 586 recycledPixels->notifyPixelsChanged(); 587 recycledPixels->unref(); 588 } 589 mRecycledBitmap = nullptr; 590 mSkiaBitmap = nullptr; 591 } 592 593 //////////////////////////////////////////////////////////////////////////////// 594 595 AshmemPixelAllocator::AshmemPixelAllocator(JNIEnv *env) { 596 LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&mJavaVM) != JNI_OK, 597 "env->GetJavaVM failed"); 598 } 599 600 bool AshmemPixelAllocator::allocPixelRef(SkBitmap* bitmap) { 601 mStorage = android::Bitmap::allocateAshmemBitmap(bitmap); 602 return !!mStorage; 603 } 604 605 //////////////////////////////////////////////////////////////////////////////// 606 607 int register_android_graphics_Graphics(JNIEnv* env) 608 { 609 jmethodID m; 610 jclass c; 611 612 gRect_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Rect")); 613 gRect_leftFieldID = GetFieldIDOrDie(env, gRect_class, "left", "I"); 614 gRect_topFieldID = GetFieldIDOrDie(env, gRect_class, "top", "I"); 615 gRect_rightFieldID = GetFieldIDOrDie(env, gRect_class, "right", "I"); 616 gRect_bottomFieldID = GetFieldIDOrDie(env, gRect_class, "bottom", "I"); 617 618 gRectF_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/RectF")); 619 gRectF_leftFieldID = GetFieldIDOrDie(env, gRectF_class, "left", "F"); 620 gRectF_topFieldID = GetFieldIDOrDie(env, gRectF_class, "top", "F"); 621 gRectF_rightFieldID = GetFieldIDOrDie(env, gRectF_class, "right", "F"); 622 gRectF_bottomFieldID = GetFieldIDOrDie(env, gRectF_class, "bottom", "F"); 623 624 gPoint_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Point")); 625 gPoint_xFieldID = GetFieldIDOrDie(env, gPoint_class, "x", "I"); 626 gPoint_yFieldID = GetFieldIDOrDie(env, gPoint_class, "y", "I"); 627 628 gPointF_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/PointF")); 629 gPointF_xFieldID = GetFieldIDOrDie(env, gPointF_class, "x", "F"); 630 gPointF_yFieldID = GetFieldIDOrDie(env, gPointF_class, "y", "F"); 631 632 gBitmapRegionDecoder_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/BitmapRegionDecoder")); 633 gBitmapRegionDecoder_constructorMethodID = GetMethodIDOrDie(env, gBitmapRegionDecoder_class, "<init>", "(J)V"); 634 635 gBitmapConfig_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap$Config")); 636 gBitmapConfig_nativeInstanceID = GetFieldIDOrDie(env, gBitmapConfig_class, "nativeInt", "I"); 637 638 gCanvas_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Canvas")); 639 gCanvas_nativeInstanceID = GetFieldIDOrDie(env, gCanvas_class, "mNativeCanvasWrapper", "J"); 640 641 gPicture_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Picture")); 642 gPicture_nativeInstanceID = GetFieldIDOrDie(env, gPicture_class, "mNativePicture", "J"); 643 644 gRegion_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Region")); 645 gRegion_nativeInstanceID = GetFieldIDOrDie(env, gRegion_class, "mNativeRegion", "J"); 646 gRegion_constructorMethodID = GetMethodIDOrDie(env, gRegion_class, "<init>", "(JI)V"); 647 648 c = env->FindClass("java/lang/Byte"); 649 gByte_class = (jclass) env->NewGlobalRef( 650 env->GetStaticObjectField(c, env->GetStaticFieldID(c, "TYPE", "Ljava/lang/Class;"))); 651 652 gVMRuntime_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "dalvik/system/VMRuntime")); 653 m = env->GetStaticMethodID(gVMRuntime_class, "getRuntime", "()Ldalvik/system/VMRuntime;"); 654 gVMRuntime = env->NewGlobalRef(env->CallStaticObjectMethod(gVMRuntime_class, m)); 655 gVMRuntime_newNonMovableArray = GetMethodIDOrDie(env, gVMRuntime_class, "newNonMovableArray", 656 "(Ljava/lang/Class;I)Ljava/lang/Object;"); 657 gVMRuntime_addressOf = GetMethodIDOrDie(env, gVMRuntime_class, "addressOf", "(Ljava/lang/Object;)J"); 658 659 gColorSpace_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ColorSpace")); 660 gColorSpace_getMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, 661 "get", "(Landroid/graphics/ColorSpace$Named;)Landroid/graphics/ColorSpace;"); 662 gColorSpace_matchMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "match", 663 "([FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/ColorSpace;"); 664 665 gColorSpaceRGB_class = MakeGlobalRefOrDie(env, 666 FindClassOrDie(env, "android/graphics/ColorSpace$Rgb")); 667 gColorSpaceRGB_constructorMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class, 668 "<init>", "(Ljava/lang/String;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)V"); 669 670 gColorSpace_Named_class = MakeGlobalRefOrDie(env, 671 FindClassOrDie(env, "android/graphics/ColorSpace$Named")); 672 gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env, 673 gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;"); 674 gColorSpace_Named_ExtendedSRGBFieldID = GetStaticFieldIDOrDie(env, 675 gColorSpace_Named_class, "EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;"); 676 gColorSpace_Named_LinearSRGBFieldID = GetStaticFieldIDOrDie(env, 677 gColorSpace_Named_class, "LINEAR_SRGB", "Landroid/graphics/ColorSpace$Named;"); 678 gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env, 679 gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;"); 680 681 gTransferParameters_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, 682 "android/graphics/ColorSpace$Rgb$TransferParameters")); 683 gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class, 684 "<init>", "(DDDDDDD)V"); 685 686 return 0; 687 } 688