Bitmap.cpp revision 95648b8a590995e57948ff2fd57d234bdbf30be0
1#define LOG_TAG "Bitmap" 2#include "Bitmap.h" 3 4#include "GraphicBuffer.h" 5#include "SkBitmap.h" 6#include "SkPixelRef.h" 7#include "SkImageEncoder.h" 8#include "SkImageInfo.h" 9#include "SkColor.h" 10#include "SkColorPriv.h" 11#include "SkColorSpace.h" 12#include "SkColorSpaceXform.h" 13#include "SkHalf.h" 14#include "SkMatrix44.h" 15#include "SkPM4f.h" 16#include "SkPM4fPriv.h" 17#include "GraphicsJNI.h" 18#include "SkDither.h" 19#include "SkUnPreMultiply.h" 20#include "SkStream.h" 21 22#include <binder/Parcel.h> 23#include "android_os_Parcel.h" 24#include "android_util_Binder.h" 25#include "android_nio_utils.h" 26#include "CreateJavaOutputStreamAdaptor.h" 27#include <hwui/Paint.h> 28#include <hwui/Bitmap.h> 29#include <renderthread/RenderProxy.h> 30 31#include "core_jni_helpers.h" 32 33#include <jni.h> 34#include <string.h> 35#include <memory> 36#include <string> 37 38#define DEBUG_PARCEL 0 39#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10)) 40 41static jclass gBitmap_class; 42static jfieldID gBitmap_nativePtr; 43static jmethodID gBitmap_constructorMethodID; 44static jmethodID gBitmap_reinitMethodID; 45static jmethodID gBitmap_getAllocationByteCountMethodID; 46 47namespace android { 48 49class BitmapWrapper { 50public: 51 BitmapWrapper(Bitmap* bitmap) 52 : mBitmap(bitmap) { } 53 54 void freePixels() { 55 mInfo = mBitmap->info(); 56 mHasHardwareMipMap = mBitmap->hasHardwareMipMap(); 57 mAllocationSize = mBitmap->getAllocationByteCount(); 58 mRowBytes = mBitmap->rowBytes(); 59 mGenerationId = mBitmap->getGenerationID(); 60 mIsHardware = mBitmap->isHardware(); 61 mBitmap.reset(); 62 } 63 64 bool valid() { 65 return mBitmap; 66 } 67 68 Bitmap& bitmap() { 69 assertValid(); 70 return *mBitmap; 71 } 72 73 void assertValid() { 74 LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!"); 75 } 76 77 void getSkBitmap(SkBitmap* outBitmap) { 78 assertValid(); 79 mBitmap->getSkBitmap(outBitmap); 80 } 81 82 bool hasHardwareMipMap() { 83 if (mBitmap) { 84 return mBitmap->hasHardwareMipMap(); 85 } 86 return mHasHardwareMipMap; 87 } 88 89 void setHasHardwareMipMap(bool hasMipMap) { 90 assertValid(); 91 mBitmap->setHasHardwareMipMap(hasMipMap); 92 } 93 94 void setAlphaType(SkAlphaType alphaType) { 95 assertValid(); 96 mBitmap->setAlphaType(alphaType); 97 } 98 99 const SkImageInfo& info() { 100 if (mBitmap) { 101 return mBitmap->info(); 102 } 103 return mInfo; 104 } 105 106 size_t getAllocationByteCount() const { 107 if (mBitmap) { 108 return mBitmap->getAllocationByteCount(); 109 } 110 return mAllocationSize; 111 } 112 113 size_t rowBytes() const { 114 if (mBitmap) { 115 return mBitmap->rowBytes(); 116 } 117 return mRowBytes; 118 } 119 120 uint32_t getGenerationID() const { 121 if (mBitmap) { 122 return mBitmap->getGenerationID(); 123 } 124 return mGenerationId; 125 } 126 127 bool isHardware() { 128 if (mBitmap) { 129 return mBitmap->isHardware(); 130 } 131 return mIsHardware; 132 } 133 134 ~BitmapWrapper() { } 135 136private: 137 sk_sp<Bitmap> mBitmap; 138 SkImageInfo mInfo; 139 bool mHasHardwareMipMap; 140 size_t mAllocationSize; 141 size_t mRowBytes; 142 uint32_t mGenerationId; 143 bool mIsHardware; 144}; 145 146// Convenience class that does not take a global ref on the pixels, relying 147// on the caller already having a local JNI ref 148class LocalScopedBitmap { 149public: 150 explicit LocalScopedBitmap(jlong bitmapHandle) 151 : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {} 152 153 BitmapWrapper* operator->() { 154 return mBitmapWrapper; 155 } 156 157 void* pixels() { 158 return mBitmapWrapper->bitmap().pixels(); 159 } 160 161 bool valid() { 162 return mBitmapWrapper && mBitmapWrapper->valid(); 163 } 164 165private: 166 BitmapWrapper* mBitmapWrapper; 167}; 168 169namespace bitmap { 170 171// Assert that bitmap's SkAlphaType is consistent with isPremultiplied. 172static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) { 173 // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is 174 // irrelevant. This just tests to ensure that the SkAlphaType is not 175 // opposite of isPremultiplied. 176 if (isPremultiplied) { 177 SkASSERT(info.alphaType() != kUnpremul_SkAlphaType); 178 } else { 179 SkASSERT(info.alphaType() != kPremul_SkAlphaType); 180 } 181} 182 183void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info, 184 bool isPremultiplied) 185{ 186 // The caller needs to have already set the alpha type properly, so the 187 // native SkBitmap stays in sync with the Java Bitmap. 188 assert_premultiplied(info, isPremultiplied); 189 190 env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID, 191 info.width(), info.height(), isPremultiplied); 192} 193 194int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap) 195{ 196 return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID); 197} 198 199jobject createBitmap(JNIEnv* env, Bitmap* bitmap, 200 int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets, 201 int density) { 202 bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable; 203 bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied; 204 // The caller needs to have already set the alpha type properly, so the 205 // native SkBitmap stays in sync with the Java Bitmap. 206 assert_premultiplied(bitmap->info(), isPremultiplied); 207 BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap); 208 jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID, 209 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density, 210 isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets); 211 212 if (env->ExceptionCheck() != 0) { 213 ALOGE("*** Uncaught exception returned from Java call!\n"); 214 env->ExceptionDescribe(); 215 } 216 return obj; 217} 218 219void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) { 220 LocalScopedBitmap bitmap(bitmapHandle); 221 bitmap->getSkBitmap(outBitmap); 222} 223 224Bitmap& toBitmap(JNIEnv* env, jobject bitmap) { 225 SkASSERT(env); 226 SkASSERT(bitmap); 227 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class)); 228 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr); 229 LocalScopedBitmap localBitmap(bitmapHandle); 230 return localBitmap->bitmap(); 231} 232 233Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) { 234 SkASSERT(env); 235 LocalScopedBitmap localBitmap(bitmapHandle); 236 return localBitmap->bitmap(); 237} 238 239void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) { 240 SkASSERT(info); 241 SkASSERT(env); 242 SkASSERT(bitmap); 243 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class)); 244 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr); 245 LocalScopedBitmap localBitmap(bitmapHandle); 246 247 const SkImageInfo& imageInfo = localBitmap->info(); 248 info->width = imageInfo.width(); 249 info->height = imageInfo.height(); 250 info->stride = localBitmap->rowBytes(); 251 info->flags = 0; 252 switch (imageInfo.colorType()) { 253 case kN32_SkColorType: 254 info->format = ANDROID_BITMAP_FORMAT_RGBA_8888; 255 break; 256 case kRGB_565_SkColorType: 257 info->format = ANDROID_BITMAP_FORMAT_RGB_565; 258 break; 259 case kARGB_4444_SkColorType: 260 info->format = ANDROID_BITMAP_FORMAT_RGBA_4444; 261 break; 262 case kAlpha_8_SkColorType: 263 info->format = ANDROID_BITMAP_FORMAT_A_8; 264 break; 265 default: 266 info->format = ANDROID_BITMAP_FORMAT_NONE; 267 break; 268 } 269} 270 271void* lockPixels(JNIEnv* env, jobject bitmap) { 272 SkASSERT(env); 273 SkASSERT(bitmap); 274 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class)); 275 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr); 276 277 LocalScopedBitmap localBitmap(bitmapHandle); 278 if (!localBitmap->valid()) return nullptr; 279 280 SkPixelRef& pixelRef = localBitmap->bitmap(); 281 pixelRef.lockPixels(); 282 if (!pixelRef.pixels()) { 283 pixelRef.unlockPixels(); 284 return nullptr; 285 } 286 pixelRef.ref(); 287 return pixelRef.pixels(); 288} 289 290bool unlockPixels(JNIEnv* env, jobject bitmap) { 291 SkASSERT(env); 292 SkASSERT(bitmap); 293 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class)); 294 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr); 295 296 LocalScopedBitmap localBitmap(bitmapHandle); 297 if (!localBitmap->valid()) return false; 298 299 SkPixelRef& pixelRef = localBitmap->bitmap(); 300 pixelRef.notifyPixelsChanged(); 301 pixelRef.unlockPixels(); 302 pixelRef.unref(); 303 return true; 304} 305 306} // namespace bitmap 307 308} // namespace android 309 310using namespace android; 311using namespace android::bitmap; 312 313/////////////////////////////////////////////////////////////////////////////// 314// Conversions to/from SkColor, for get/setPixels, and the create method, which 315// is basically like setPixels 316 317typedef void (*FromColorProc)(void* dst, const SkColor src[], int width, 318 int x, int y); 319 320static void FromColor_F16(void* dst, const SkColor src[], int width, 321 int, int) { 322 uint64_t* d = (uint64_t*)dst; 323 324 for (int i = 0; i < width; i++) { 325 *d++ = SkColor4f::FromColor(*src++).premul().toF16(); 326 } 327} 328 329static void FromColor_F16_Raw(void* dst, const SkColor src[], int width, 330 int, int) { 331 uint64_t* d = (uint64_t*)dst; 332 333 for (int i = 0; i < width; i++) { 334 const float* color = SkColor4f::FromColor(*src++).vec(); 335 uint16_t* scratch = reinterpret_cast<uint16_t*>(d++); 336 for (int i = 0; i < 4; ++i) { 337 scratch[i] = SkFloatToHalf(color[i]); 338 } 339 } 340} 341 342static void FromColor_D32(void* dst, const SkColor src[], int width, 343 int, int) { 344 SkPMColor* d = (SkPMColor*)dst; 345 346 for (int i = 0; i < width; i++) { 347 *d++ = SkPreMultiplyColor(*src++); 348 } 349} 350 351static void FromColor_D32_Raw(void* dst, const SkColor src[], int width, 352 int, int) { 353 // Needed to thwart the unreachable code detection from clang. 354 static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER; 355 356 // SkColor's ordering may be different from SkPMColor 357 if (sk_color_ne_zero) { 358 memcpy(dst, src, width * sizeof(SkColor)); 359 return; 360 } 361 362 // order isn't same, repack each pixel manually 363 SkPMColor* d = (SkPMColor*)dst; 364 for (int i = 0; i < width; i++) { 365 SkColor c = *src++; 366 *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c), 367 SkColorGetG(c), SkColorGetB(c)); 368 } 369} 370 371static void FromColor_D565(void* dst, const SkColor src[], int width, 372 int x, int y) { 373 uint16_t* d = (uint16_t*)dst; 374 375 DITHER_565_SCAN(y); 376 for (int stop = x + width; x < stop; x++) { 377 SkColor c = *src++; 378 *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c), 379 DITHER_VALUE(x)); 380 } 381} 382 383static void FromColor_D4444(void* dst, const SkColor src[], int width, 384 int x, int y) { 385 SkPMColor16* d = (SkPMColor16*)dst; 386 387 DITHER_4444_SCAN(y); 388 for (int stop = x + width; x < stop; x++) { 389 SkPMColor pmc = SkPreMultiplyColor(*src++); 390 *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x)); 391// *d++ = SkPixel32ToPixel4444(pmc); 392 } 393} 394 395static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width, 396 int x, int y) { 397 SkPMColor16* d = (SkPMColor16*)dst; 398 399 DITHER_4444_SCAN(y); 400 for (int stop = x + width; x < stop; x++) { 401 SkColor c = *src++; 402 403 // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied 404 SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c), 405 SkColorGetG(c), SkColorGetB(c)); 406 *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x)); 407// *d++ = SkPixel32ToPixel4444(pmc); 408 } 409} 410 411static void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) { 412 uint8_t* d = (uint8_t*)dst; 413 414 for (int stop = x + width; x < stop; x++) { 415 *d++ = SkColorGetA(*src++); 416 } 417} 418 419// can return NULL 420static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) { 421 switch (bitmap.colorType()) { 422 case kN32_SkColorType: 423 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw; 424 case kARGB_4444_SkColorType: 425 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 : 426 FromColor_D4444_Raw; 427 case kRGB_565_SkColorType: 428 return FromColor_D565; 429 case kAlpha_8_SkColorType: 430 return FromColor_DA8; 431 case kRGBA_F16_SkColorType: 432 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw; 433 default: 434 break; 435 } 436 return NULL; 437} 438 439bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride, 440 int x, int y, int width, int height, const SkBitmap& dstBitmap) { 441 SkAutoLockPixels alp(dstBitmap); 442 void* dst = dstBitmap.getPixels(); 443 FromColorProc proc = ChooseFromColorProc(dstBitmap); 444 445 if (NULL == dst || NULL == proc) { 446 return false; 447 } 448 449 const jint* array = env->GetIntArrayElements(srcColors, NULL); 450 const SkColor* src = (const SkColor*)array + srcOffset; 451 452 // reset to to actual choice from caller 453 dst = dstBitmap.getAddr(x, y); 454 455 SkColorSpace* colorSpace = dstBitmap.colorSpace(); 456 if (dstBitmap.colorType() == kRGBA_F16_SkColorType || 457 GraphicsJNI::isColorSpaceSRGB(colorSpace)) { 458 // now copy/convert each scanline 459 for (int y = 0; y < height; y++) { 460 proc(dst, src, width, x, y); 461 src += srcStride; 462 dst = (char*)dst + dstBitmap.rowBytes(); 463 } 464 } else { 465 auto sRGB = SkColorSpace::MakeSRGB(); 466 auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace); 467 468 std::unique_ptr<SkColor[]> row(new SkColor[width]); 469 470 // now copy/convert each scanline 471 for (int y = 0; y < height; y++) { 472 memcpy(row.get(), src, sizeof(SkColor) * width); 473 xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), 474 SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width, 475 SkAlphaType::kUnpremul_SkAlphaType); 476 477 proc(dst, row.get(), width, x, y); 478 src += srcStride; 479 dst = (char*)dst + dstBitmap.rowBytes(); 480 } 481 } 482 483 dstBitmap.notifyPixelsChanged(); 484 485 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT); 486 return true; 487} 488 489//////////////////// ToColor procs 490 491typedef void (*ToColorProc)(SkColor dst[], const void* src, int width, 492 SkColorTable*); 493 494static void ToColor_F16_Alpha(SkColor dst[], const void* src, int width, 495 SkColorTable*) { 496 SkASSERT(width > 0); 497 uint64_t* s = (uint64_t*)src; 498 do { 499 *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor(); 500 } while (--width != 0); 501} 502 503static void ToColor_F16_Raw(SkColor dst[], const void* src, int width, 504 SkColorTable*) { 505 SkASSERT(width > 0); 506 uint64_t* s = (uint64_t*)src; 507 do { 508 *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++))); 509 } while (--width != 0); 510} 511 512static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width, 513 SkColorTable*) { 514 SkASSERT(width > 0); 515 const SkPMColor* s = (const SkPMColor*)src; 516 do { 517 *dst++ = SkUnPreMultiply::PMColorToColor(*s++); 518 } while (--width != 0); 519} 520 521static void ToColor_S32_Raw(SkColor dst[], const void* src, int width, 522 SkColorTable*) { 523 SkASSERT(width > 0); 524 const SkPMColor* s = (const SkPMColor*)src; 525 do { 526 SkPMColor c = *s++; 527 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c), 528 SkGetPackedG32(c), SkGetPackedB32(c)); 529 } while (--width != 0); 530} 531 532static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width, 533 SkColorTable*) { 534 SkASSERT(width > 0); 535 const SkPMColor* s = (const SkPMColor*)src; 536 do { 537 SkPMColor c = *s++; 538 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c), 539 SkGetPackedB32(c)); 540 } while (--width != 0); 541} 542 543static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width, 544 SkColorTable*) { 545 SkASSERT(width > 0); 546 const SkPMColor16* s = (const SkPMColor16*)src; 547 do { 548 *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++)); 549 } while (--width != 0); 550} 551 552static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width, 553 SkColorTable*) { 554 SkASSERT(width > 0); 555 const SkPMColor16* s = (const SkPMColor16*)src; 556 do { 557 SkPMColor c = SkPixel4444ToPixel32(*s++); 558 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c), 559 SkGetPackedG32(c), SkGetPackedB32(c)); 560 } while (--width != 0); 561} 562 563static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width, 564 SkColorTable*) { 565 SkASSERT(width > 0); 566 const SkPMColor16* s = (const SkPMColor16*)src; 567 do { 568 SkPMColor c = SkPixel4444ToPixel32(*s++); 569 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c), 570 SkGetPackedB32(c)); 571 } while (--width != 0); 572} 573 574static void ToColor_S565(SkColor dst[], const void* src, int width, 575 SkColorTable*) { 576 SkASSERT(width > 0); 577 const uint16_t* s = (const uint16_t*)src; 578 do { 579 uint16_t c = *s++; 580 *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c), 581 SkPacked16ToB32(c)); 582 } while (--width != 0); 583} 584 585static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width, 586 SkColorTable* ctable) { 587 SkASSERT(width > 0); 588 const uint8_t* s = (const uint8_t*)src; 589 const SkPMColor* colors = ctable->readColors(); 590 do { 591 *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]); 592 } while (--width != 0); 593} 594 595static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width, 596 SkColorTable* ctable) { 597 SkASSERT(width > 0); 598 const uint8_t* s = (const uint8_t*)src; 599 const SkPMColor* colors = ctable->readColors(); 600 do { 601 SkPMColor c = colors[*s++]; 602 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c), 603 SkGetPackedG32(c), SkGetPackedB32(c)); 604 } while (--width != 0); 605} 606 607static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width, 608 SkColorTable* ctable) { 609 SkASSERT(width > 0); 610 const uint8_t* s = (const uint8_t*)src; 611 const SkPMColor* colors = ctable->readColors(); 612 do { 613 SkPMColor c = colors[*s++]; 614 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c), 615 SkGetPackedB32(c)); 616 } while (--width != 0); 617} 618 619static void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) { 620 SkASSERT(width > 0); 621 const uint8_t* s = (const uint8_t*)src; 622 do { 623 uint8_t c = *s++; 624 *dst++ = SkColorSetARGB(c, 0, 0, 0); 625 } while (--width != 0); 626} 627 628// can return NULL 629static ToColorProc ChooseToColorProc(const SkBitmap& src) { 630 switch (src.colorType()) { 631 case kN32_SkColorType: 632 switch (src.alphaType()) { 633 case kOpaque_SkAlphaType: 634 return ToColor_S32_Opaque; 635 case kPremul_SkAlphaType: 636 return ToColor_S32_Alpha; 637 case kUnpremul_SkAlphaType: 638 return ToColor_S32_Raw; 639 default: 640 return NULL; 641 } 642 case kARGB_4444_SkColorType: 643 switch (src.alphaType()) { 644 case kOpaque_SkAlphaType: 645 return ToColor_S4444_Opaque; 646 case kPremul_SkAlphaType: 647 return ToColor_S4444_Alpha; 648 case kUnpremul_SkAlphaType: 649 return ToColor_S4444_Raw; 650 default: 651 return NULL; 652 } 653 case kRGB_565_SkColorType: 654 return ToColor_S565; 655 case kIndex_8_SkColorType: 656 if (src.getColorTable() == NULL) { 657 return NULL; 658 } 659 switch (src.alphaType()) { 660 case kOpaque_SkAlphaType: 661 return ToColor_SI8_Opaque; 662 case kPremul_SkAlphaType: 663 return ToColor_SI8_Alpha; 664 case kUnpremul_SkAlphaType: 665 return ToColor_SI8_Raw; 666 default: 667 return NULL; 668 } 669 case kAlpha_8_SkColorType: 670 return ToColor_SA8; 671 case kRGBA_F16_SkColorType: 672 switch (src.alphaType()) { 673 case kOpaque_SkAlphaType: 674 return ToColor_F16_Raw; 675 case kPremul_SkAlphaType: 676 return ToColor_F16_Alpha; 677 case kUnpremul_SkAlphaType: 678 return ToColor_F16_Raw; 679 default: 680 return NULL; 681 } 682 default: 683 break; 684 } 685 return NULL; 686} 687 688static void ToF16_SA8(void* dst, const void* src, int width) { 689 SkASSERT(width > 0); 690 uint64_t* d = (uint64_t*)dst; 691 const uint8_t* s = (const uint8_t*)src; 692 693 for (int i = 0; i < width; i++) { 694 uint8_t c = *s++; 695 SkPM4f a; 696 a.fVec[SkPM4f::R] = 0.0f; 697 a.fVec[SkPM4f::G] = 0.0f; 698 a.fVec[SkPM4f::B] = 0.0f; 699 a.fVec[SkPM4f::A] = c / 255.0f; 700 *d++ = a.toF16(); 701 } 702} 703 704/////////////////////////////////////////////////////////////////////////////// 705/////////////////////////////////////////////////////////////////////////////// 706 707static int getPremulBitmapCreateFlags(bool isMutable) { 708 int flags = android::bitmap::kBitmapCreateFlag_Premultiplied; 709 if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable; 710 return flags; 711} 712 713static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, 714 jint offset, jint stride, jint width, jint height, 715 jint configHandle, jboolean isMutable, 716 jfloatArray xyzD50, jobject transferParameters) { 717 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle); 718 if (NULL != jColors) { 719 size_t n = env->GetArrayLength(jColors); 720 if (n < SkAbs32(stride) * (size_t)height) { 721 doThrowAIOOBE(env); 722 return NULL; 723 } 724 } 725 726 // ARGB_4444 is a deprecated format, convert automatically to 8888 727 if (colorType == kARGB_4444_SkColorType) { 728 colorType = kN32_SkColorType; 729 } 730 731 SkBitmap bitmap; 732 sk_sp<SkColorSpace> colorSpace; 733 734 if (colorType != kN32_SkColorType || xyzD50 == nullptr || transferParameters == nullptr) { 735 colorSpace = GraphicsJNI::colorSpaceForType(colorType); 736 } else { 737 SkColorSpaceTransferFn p = GraphicsJNI::getNativeTransferParameters(env, transferParameters); 738 SkMatrix44 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50); 739 colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix); 740 } 741 742 bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType, colorSpace)); 743 744 sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL); 745 if (!nativeBitmap) { 746 return NULL; 747 } 748 749 if (jColors != NULL) { 750 GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap); 751 } 752 753 return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable)); 754} 755 756static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src, 757 SkBitmap::Allocator* alloc) { 758 // Skia does not support copying from kAlpha8 to types that are not alpha only. 759 // We will handle this case here. 760 if (kAlpha_8_SkColorType == src.colorType() && kAlpha_8_SkColorType != dstCT) { 761 SkAutoPixmapUnlock srcUnlocker; 762 if (!src.requestLock(&srcUnlocker)) { 763 return false; 764 } 765 SkPixmap srcPixmap = srcUnlocker.pixmap(); 766 767 SkImageInfo dstInfo = src.info().makeColorType(dstCT); 768 if (dstCT == kRGBA_F16_SkColorType) { 769 dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGBLinear()); 770 } 771 if (!dst->setInfo(dstInfo)) { 772 return false; 773 } 774 if (!dst->tryAllocPixels(alloc, nullptr)) { 775 return false; 776 } 777 778 switch (dstCT) { 779 case kRGBA_8888_SkColorType: 780 case kBGRA_8888_SkColorType: { 781 for (int y = 0; y < src.height(); y++) { 782 const uint8_t* srcRow = srcPixmap.addr8(0, y); 783 uint32_t* dstRow = dst->getAddr32(0, y); 784 ToColor_SA8(dstRow, srcRow, src.width(), nullptr); 785 } 786 return true; 787 } 788 case kRGB_565_SkColorType: { 789 for (int y = 0; y < src.height(); y++) { 790 uint16_t* dstRow = dst->getAddr16(0, y); 791 memset(dstRow, 0, sizeof(uint16_t) * src.width()); 792 } 793 return true; 794 } 795 case kRGBA_F16_SkColorType: { 796 for (int y = 0; y < src.height(); y++) { 797 const uint8_t* srcRow = srcPixmap.addr8(0, y); 798 void* dstRow = dst->getAddr(0, y); 799 ToF16_SA8(dstRow, srcRow, src.width()); 800 } 801 return true; 802 } 803 default: 804 return false; 805 } 806 } 807 808 return src.copyTo(dst, dstCT, alloc); 809} 810 811static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle, 812 jint dstConfigHandle, jboolean isMutable) { 813 SkBitmap src; 814 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src); 815 if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) { 816 sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src)); 817 if (!bitmap.get()) { 818 return NULL; 819 } 820 return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable)); 821 } 822 823 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle); 824 SkBitmap result; 825 HeapAllocator allocator; 826 827 if (!bitmapCopyTo(&result, dstCT, src, &allocator)) { 828 return NULL; 829 } 830 auto bitmap = allocator.getStorageObjAndReset(); 831 return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable)); 832} 833 834static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) { 835 SkBitmap result; 836 837 AshmemPixelAllocator allocator(env); 838 if (!bitmapCopyTo(&result, dstCT, src, &allocator)) { 839 return NULL; 840 } 841 auto bitmap = allocator.getStorageObjAndReset(); 842 bitmap->setImmutable(); 843 return bitmap; 844} 845 846static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) { 847 SkBitmap src; 848 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src); 849 SkColorType dstCT = src.colorType(); 850 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT); 851 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false)); 852 return ret; 853} 854 855static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) { 856 SkBitmap src; 857 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src); 858 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle); 859 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT); 860 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false)); 861 return ret; 862} 863 864static void Bitmap_destruct(BitmapWrapper* bitmap) { 865 delete bitmap; 866} 867 868static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) { 869 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct)); 870} 871 872static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) { 873 LocalScopedBitmap bitmap(bitmapHandle); 874 bitmap->freePixels(); 875 return JNI_TRUE; 876} 877 878static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle, 879 jint width, jint height, jint configHandle, jboolean requestPremul) { 880 LocalScopedBitmap bitmap(bitmapHandle); 881 bitmap->assertValid(); 882 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle); 883 884 // ARGB_4444 is a deprecated format, convert automatically to 8888 885 if (colorType == kARGB_4444_SkColorType) { 886 colorType = kN32_SkColorType; 887 } 888 size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType); 889 if (requestedSize > bitmap->getAllocationByteCount()) { 890 // done in native as there's no way to get BytesPerPixel in Java 891 doThrowIAE(env, "Bitmap not large enough to support new configuration"); 892 return; 893 } 894 SkAlphaType alphaType; 895 if (bitmap->info().colorType() != kRGB_565_SkColorType 896 && bitmap->info().alphaType() == kOpaque_SkAlphaType) { 897 // If the original bitmap was set to opaque, keep that setting, unless it 898 // was 565, which is required to be opaque. 899 alphaType = kOpaque_SkAlphaType; 900 } else { 901 // Otherwise respect the premultiplied request. 902 alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType; 903 } 904 bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType, 905 sk_ref_sp(bitmap->info().colorSpace()))); 906} 907 908// These must match the int values in Bitmap.java 909enum JavaEncodeFormat { 910 kJPEG_JavaEncodeFormat = 0, 911 kPNG_JavaEncodeFormat = 1, 912 kWEBP_JavaEncodeFormat = 2 913}; 914 915static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle, 916 jint format, jint quality, 917 jobject jstream, jbyteArray jstorage) { 918 SkEncodedImageFormat fm; 919 switch (format) { 920 case kJPEG_JavaEncodeFormat: 921 fm = SkEncodedImageFormat::kJPEG; 922 break; 923 case kPNG_JavaEncodeFormat: 924 fm = SkEncodedImageFormat::kPNG; 925 break; 926 case kWEBP_JavaEncodeFormat: 927 fm = SkEncodedImageFormat::kWEBP; 928 break; 929 default: 930 return JNI_FALSE; 931 } 932 933 LocalScopedBitmap bitmap(bitmapHandle); 934 if (!bitmap.valid()) { 935 return JNI_FALSE; 936 } 937 938 std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage)); 939 if (!strm.get()) { 940 return JNI_FALSE; 941 } 942 943 SkBitmap skbitmap; 944 bitmap->getSkBitmap(&skbitmap); 945 return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE; 946} 947 948static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) { 949 LocalScopedBitmap bitmap(bitmapHandle); 950 SkBitmap skBitmap; 951 bitmap->getSkBitmap(&skBitmap); 952 skBitmap.eraseColor(color); 953} 954 955static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) { 956 LocalScopedBitmap bitmap(bitmapHandle); 957 return static_cast<jint>(bitmap->rowBytes()); 958} 959 960static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) { 961 LocalScopedBitmap bitmap(bitmapHandle); 962 if (bitmap->isHardware()) { 963 return GraphicsJNI::hardwareLegacyBitmapConfig(); 964 } 965 return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType()); 966} 967 968static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) { 969 LocalScopedBitmap bitmap(bitmapHandle); 970 return static_cast<jint>(bitmap->getGenerationID()); 971} 972 973static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) { 974 LocalScopedBitmap bitmap(bitmapHandle); 975 if (bitmap->info().alphaType() == kPremul_SkAlphaType) { 976 return JNI_TRUE; 977 } 978 return JNI_FALSE; 979} 980 981static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) { 982 LocalScopedBitmap bitmap(bitmapHandle); 983 return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE; 984} 985 986static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle, 987 jboolean hasAlpha, jboolean requestPremul) { 988 LocalScopedBitmap bitmap(bitmapHandle); 989 if (hasAlpha) { 990 bitmap->setAlphaType( 991 requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); 992 } else { 993 bitmap->setAlphaType(kOpaque_SkAlphaType); 994 } 995} 996 997static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle, 998 jboolean isPremul) { 999 LocalScopedBitmap bitmap(bitmapHandle); 1000 if (!bitmap->info().isOpaque()) { 1001 if (isPremul) { 1002 bitmap->setAlphaType(kPremul_SkAlphaType); 1003 } else { 1004 bitmap->setAlphaType(kUnpremul_SkAlphaType); 1005 } 1006 } 1007} 1008 1009static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) { 1010 LocalScopedBitmap bitmap(bitmapHandle); 1011 return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE; 1012} 1013 1014static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle, 1015 jboolean hasMipMap) { 1016 LocalScopedBitmap bitmap(bitmapHandle); 1017 bitmap->setHasHardwareMipMap(hasMipMap); 1018} 1019 1020/////////////////////////////////////////////////////////////////////////////// 1021 1022static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { 1023 if (parcel == NULL) { 1024 SkDebugf("-------- unparcel parcel is NULL\n"); 1025 return NULL; 1026 } 1027 1028 android::Parcel* p = android::parcelForJavaObject(env, parcel); 1029 1030 const bool isMutable = p->readInt32() != 0; 1031 const SkColorType colorType = (SkColorType)p->readInt32(); 1032 const SkAlphaType alphaType = (SkAlphaType)p->readInt32(); 1033 const uint32_t colorSpaceSize = p->readUint32(); 1034 sk_sp<SkColorSpace> colorSpace; 1035 if (kRGBA_F16_SkColorType == colorType) { 1036 colorSpace = SkColorSpace::MakeSRGBLinear(); 1037 } else if (colorSpaceSize > 0) { 1038 colorSpace = SkColorSpace::Deserialize(p->readInplace(colorSpaceSize), colorSpaceSize); 1039 } 1040 const int width = p->readInt32(); 1041 const int height = p->readInt32(); 1042 const int rowBytes = p->readInt32(); 1043 const int density = p->readInt32(); 1044 1045 if (kN32_SkColorType != colorType && 1046 kRGBA_F16_SkColorType != colorType && 1047 kRGB_565_SkColorType != colorType && 1048 kARGB_4444_SkColorType != colorType && 1049 kIndex_8_SkColorType != colorType && 1050 kAlpha_8_SkColorType != colorType) { 1051 SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType); 1052 return NULL; 1053 } 1054 1055 std::unique_ptr<SkBitmap> bitmap(new SkBitmap); 1056 if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace), 1057 rowBytes)) { 1058 return NULL; 1059 } 1060 1061 SkColorTable* ctable = NULL; 1062 if (colorType == kIndex_8_SkColorType) { 1063 int count = p->readInt32(); 1064 if (count < 0 || count > 256) { 1065 // The data is corrupt, since SkColorTable enforces a value between 0 and 256, 1066 // inclusive. 1067 return NULL; 1068 } 1069 if (count > 0) { 1070 size_t size = count * sizeof(SkPMColor); 1071 const SkPMColor* src = (const SkPMColor*)p->readInplace(size); 1072 if (src == NULL) { 1073 return NULL; 1074 } 1075 ctable = new SkColorTable(src, count); 1076 } 1077 } 1078 1079 // Read the bitmap blob. 1080 size_t size = bitmap->getSize(); 1081 android::Parcel::ReadableBlob blob; 1082 android::status_t status = p->readBlob(size, &blob); 1083 if (status) { 1084 SkSafeUnref(ctable); 1085 doThrowRE(env, "Could not read bitmap blob."); 1086 return NULL; 1087 } 1088 1089 // Map the bitmap in place from the ashmem region if possible otherwise copy. 1090 sk_sp<Bitmap> nativeBitmap; 1091 if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) { 1092#if DEBUG_PARCEL 1093 ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob " 1094 "(fds %s)", 1095 isMutable ? "mutable" : "immutable", 1096 blob.isMutable() ? "mutable" : "immutable", 1097 p->allowFds() ? "allowed" : "forbidden"); 1098#endif 1099 // Dup the file descriptor so we can keep a reference to it after the Parcel 1100 // is disposed. 1101 int dupFd = dup(blob.fd()); 1102 if (dupFd < 0) { 1103 ALOGE("Error allocating dup fd. Error:%d", errno); 1104 blob.release(); 1105 SkSafeUnref(ctable); 1106 doThrowRE(env, "Could not allocate dup blob fd."); 1107 return NULL; 1108 } 1109 1110 // Map the pixels in place and take ownership of the ashmem region. 1111 nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(), 1112 ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable)); 1113 SkSafeUnref(ctable); 1114 if (!nativeBitmap) { 1115 close(dupFd); 1116 blob.release(); 1117 doThrowRE(env, "Could not allocate ashmem pixel ref."); 1118 return NULL; 1119 } 1120 1121 // Clear the blob handle, don't release it. 1122 blob.clear(); 1123 } else { 1124#if DEBUG_PARCEL 1125 if (blob.fd() >= 0) { 1126 ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap " 1127 "from immutable blob (fds %s)", 1128 p->allowFds() ? "allowed" : "forbidden"); 1129 } else { 1130 ALOGD("Bitmap.createFromParcel: copied contents from %s blob " 1131 "(fds %s)", 1132 blob.isMutable() ? "mutable" : "immutable", 1133 p->allowFds() ? "allowed" : "forbidden"); 1134 } 1135#endif 1136 1137 // Copy the pixels into a new buffer. 1138 nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable); 1139 SkSafeUnref(ctable); 1140 if (!nativeBitmap) { 1141 blob.release(); 1142 doThrowRE(env, "Could not allocate java pixel ref."); 1143 return NULL; 1144 } 1145 bitmap->lockPixels(); 1146 memcpy(bitmap->getPixels(), blob.data(), size); 1147 bitmap->unlockPixels(); 1148 1149 // Release the blob handle. 1150 blob.release(); 1151 } 1152 1153 return createBitmap(env, nativeBitmap.release(), 1154 getPremulBitmapCreateFlags(isMutable), NULL, NULL, density); 1155} 1156 1157static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, 1158 jlong bitmapHandle, 1159 jboolean isMutable, jint density, 1160 jobject parcel) { 1161 if (parcel == NULL) { 1162 SkDebugf("------- writeToParcel null parcel\n"); 1163 return JNI_FALSE; 1164 } 1165 1166 android::Parcel* p = android::parcelForJavaObject(env, parcel); 1167 SkBitmap bitmap; 1168 1169 auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle); 1170 bitmapWrapper->getSkBitmap(&bitmap); 1171 1172 p->writeInt32(isMutable); 1173 p->writeInt32(bitmap.colorType()); 1174 p->writeInt32(bitmap.alphaType()); 1175 SkColorSpace* colorSpace = bitmap.colorSpace(); 1176 if (colorSpace != nullptr && bitmap.colorType() != kRGBA_F16_SkColorType) { 1177 sk_sp<SkData> data = colorSpace->serialize(); 1178 size_t size = data->size(); 1179 p->writeUint32(size); 1180 if (size > 0) { 1181 p->write(data->data(), size); 1182 } 1183 } else { 1184 p->writeUint32(0); 1185 } 1186 p->writeInt32(bitmap.width()); 1187 p->writeInt32(bitmap.height()); 1188 p->writeInt32(bitmap.rowBytes()); 1189 p->writeInt32(density); 1190 1191 if (bitmap.colorType() == kIndex_8_SkColorType) { 1192 // The bitmap needs to be locked to access its color table. 1193 SkAutoLockPixels alp(bitmap); 1194 SkColorTable* ctable = bitmap.getColorTable(); 1195 if (ctable != NULL) { 1196 int count = ctable->count(); 1197 p->writeInt32(count); 1198 memcpy(p->writeInplace(count * sizeof(SkPMColor)), 1199 ctable->readColors(), count * sizeof(SkPMColor)); 1200 } else { 1201 p->writeInt32(0); // indicate no ctable 1202 } 1203 } 1204 1205 // Transfer the underlying ashmem region if we have one and it's immutable. 1206 android::status_t status; 1207 int fd = bitmapWrapper->bitmap().getAshmemFd(); 1208 if (fd >= 0 && !isMutable && p->allowFds()) { 1209#if DEBUG_PARCEL 1210 ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as " 1211 "immutable blob (fds %s)", 1212 p->allowFds() ? "allowed" : "forbidden"); 1213#endif 1214 1215 status = p->writeDupImmutableBlobFileDescriptor(fd); 1216 if (status) { 1217 doThrowRE(env, "Could not write bitmap blob file descriptor."); 1218 return JNI_FALSE; 1219 } 1220 return JNI_TRUE; 1221 } 1222 1223 // Copy the bitmap to a new blob. 1224 bool mutableCopy = isMutable; 1225#if DEBUG_PARCEL 1226 ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)", 1227 isMutable ? "mutable" : "immutable", 1228 mutableCopy ? "mutable" : "immutable", 1229 p->allowFds() ? "allowed" : "forbidden"); 1230#endif 1231 1232 size_t size = bitmap.getSize(); 1233 android::Parcel::WritableBlob blob; 1234 status = p->writeBlob(size, mutableCopy, &blob); 1235 if (status) { 1236 doThrowRE(env, "Could not copy bitmap to parcel blob."); 1237 return JNI_FALSE; 1238 } 1239 1240 bitmap.lockPixels(); 1241 const void* pSrc = bitmap.getPixels(); 1242 if (pSrc == NULL) { 1243 memset(blob.data(), 0, size); 1244 } else { 1245 memcpy(blob.data(), pSrc, size); 1246 } 1247 bitmap.unlockPixels(); 1248 1249 blob.release(); 1250 return JNI_TRUE; 1251} 1252 1253static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz, 1254 jlong srcHandle, jlong paintHandle, 1255 jintArray offsetXY) { 1256 SkBitmap src; 1257 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src); 1258 const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle); 1259 SkIPoint offset; 1260 SkBitmap dst; 1261 HeapAllocator allocator; 1262 1263 src.extractAlpha(&dst, paint, &allocator, &offset); 1264 // If Skia can't allocate pixels for destination bitmap, it resets 1265 // it, that is set its pixels buffer to NULL, and zero width and height. 1266 if (dst.getPixels() == NULL && src.getPixels() != NULL) { 1267 doThrowOOME(env, "failed to allocate pixels for alpha"); 1268 return NULL; 1269 } 1270 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) { 1271 int* array = env->GetIntArrayElements(offsetXY, NULL); 1272 array[0] = offset.fX; 1273 array[1] = offset.fY; 1274 env->ReleaseIntArrayElements(offsetXY, array, 0); 1275 } 1276 1277 return createBitmap(env, allocator.getStorageObjAndReset(), 1278 getPremulBitmapCreateFlags(true)); 1279} 1280 1281/////////////////////////////////////////////////////////////////////////////// 1282 1283static jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) { 1284 LocalScopedBitmap bitmapHolder(bitmapHandle); 1285 if (!bitmapHolder.valid()) return JNI_TRUE; 1286 1287 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace(); 1288 return GraphicsJNI::isColorSpaceSRGB(colorSpace); 1289} 1290 1291static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle, 1292 jfloatArray xyzArray, jfloatArray paramsArray) { 1293 1294 LocalScopedBitmap bitmapHolder(bitmapHandle); 1295 if (!bitmapHolder.valid()) return JNI_FALSE; 1296 1297 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace(); 1298 if (colorSpace == nullptr) return JNI_FALSE; 1299 1300 SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor); 1301 if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE; 1302 1303 jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL); 1304 xyz[0] = xyzMatrix.getFloat(0, 0); 1305 xyz[1] = xyzMatrix.getFloat(1, 0); 1306 xyz[2] = xyzMatrix.getFloat(2, 0); 1307 xyz[3] = xyzMatrix.getFloat(0, 1); 1308 xyz[4] = xyzMatrix.getFloat(1, 1); 1309 xyz[5] = xyzMatrix.getFloat(2, 1); 1310 xyz[6] = xyzMatrix.getFloat(0, 2); 1311 xyz[7] = xyzMatrix.getFloat(1, 2); 1312 xyz[8] = xyzMatrix.getFloat(2, 2); 1313 env->ReleaseFloatArrayElements(xyzArray, xyz, 0); 1314 1315 SkColorSpaceTransferFn transferParams; 1316 if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE; 1317 1318 jfloat* params = env->GetFloatArrayElements(paramsArray, NULL); 1319 params[0] = transferParams.fA; 1320 params[1] = transferParams.fB; 1321 params[2] = transferParams.fC; 1322 params[3] = transferParams.fD; 1323 params[4] = transferParams.fE; 1324 params[5] = transferParams.fF; 1325 params[6] = transferParams.fG; 1326 env->ReleaseFloatArrayElements(paramsArray, params, 0); 1327 1328 return JNI_TRUE; 1329} 1330 1331/////////////////////////////////////////////////////////////////////////////// 1332 1333static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle, 1334 jint x, jint y) { 1335 SkBitmap bitmap; 1336 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap); 1337 SkAutoLockPixels alp(bitmap); 1338 1339 ToColorProc proc = ChooseToColorProc(bitmap); 1340 if (NULL == proc) { 1341 return 0; 1342 } 1343 const void* src = bitmap.getAddr(x, y); 1344 if (NULL == src) { 1345 return 0; 1346 } 1347 1348 SkColor dst[1]; 1349 proc(dst, src, 1, bitmap.getColorTable()); 1350 1351 SkColorSpace* colorSpace = bitmap.colorSpace(); 1352 if (bitmap.colorType() != kRGBA_F16_SkColorType && 1353 !GraphicsJNI::isColorSpaceSRGB(colorSpace)) { 1354 auto sRGB = SkColorSpace::MakeSRGB(); 1355 auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get()); 1356 xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1357 SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1, 1358 SkAlphaType::kUnpremul_SkAlphaType); 1359 } 1360 1361 return static_cast<jint>(dst[0]); 1362} 1363 1364static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle, 1365 jintArray pixelArray, jint offset, jint stride, 1366 jint x, jint y, jint width, jint height) { 1367 SkBitmap bitmap; 1368 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap); 1369 SkAutoLockPixels alp(bitmap); 1370 1371 ToColorProc proc = ChooseToColorProc(bitmap); 1372 if (NULL == proc) { 1373 return; 1374 } 1375 const void* src = bitmap.getAddr(x, y); 1376 if (NULL == src) { 1377 return; 1378 } 1379 1380 SkColorTable* ctable = bitmap.getColorTable(); 1381 jint* dst = env->GetIntArrayElements(pixelArray, NULL); 1382 SkColor* d = (SkColor*)dst + offset; 1383 1384 SkColorSpace* colorSpace = bitmap.colorSpace(); 1385 if (bitmap.colorType() == kRGBA_F16_SkColorType || 1386 GraphicsJNI::isColorSpaceSRGB(colorSpace)) { 1387 while (--height >= 0) { 1388 proc(d, src, width, ctable); 1389 d += stride; 1390 src = (void*)((const char*)src + bitmap.rowBytes()); 1391 } 1392 } else { 1393 auto sRGB = SkColorSpace::MakeSRGB(); 1394 auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get()); 1395 1396 while (--height >= 0) { 1397 proc(d, src, width, ctable); 1398 1399 xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d, 1400 SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width, 1401 SkAlphaType::kUnpremul_SkAlphaType); 1402 1403 d += stride; 1404 src = (void*)((const char*)src + bitmap.rowBytes()); 1405 } 1406 } 1407 1408 env->ReleaseIntArrayElements(pixelArray, dst, 0); 1409} 1410 1411/////////////////////////////////////////////////////////////////////////////// 1412 1413static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle, 1414 jint x, jint y, jint colorHandle) { 1415 SkBitmap bitmap; 1416 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap); 1417 SkColor color = static_cast<SkColor>(colorHandle); 1418 SkAutoLockPixels alp(bitmap); 1419 if (NULL == bitmap.getPixels()) { 1420 return; 1421 } 1422 1423 FromColorProc proc = ChooseFromColorProc(bitmap); 1424 if (NULL == proc) { 1425 return; 1426 } 1427 1428 SkColorSpace* colorSpace = bitmap.colorSpace(); 1429 if (bitmap.colorType() != kRGBA_F16_SkColorType && 1430 !GraphicsJNI::isColorSpaceSRGB(colorSpace)) { 1431 auto sRGB = SkColorSpace::MakeSRGB(); 1432 auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace); 1433 xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1434 SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1, 1435 SkAlphaType::kUnpremul_SkAlphaType); 1436 } 1437 1438 proc(bitmap.getAddr(x, y), &color, 1, x, y); 1439 bitmap.notifyPixelsChanged(); 1440} 1441 1442static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle, 1443 jintArray pixelArray, jint offset, jint stride, 1444 jint x, jint y, jint width, jint height) { 1445 SkBitmap bitmap; 1446 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap); 1447 GraphicsJNI::SetPixels(env, pixelArray, offset, stride, 1448 x, y, width, height, bitmap); 1449} 1450 1451static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject, 1452 jlong bitmapHandle, jobject jbuffer) { 1453 SkBitmap bitmap; 1454 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap); 1455 SkAutoLockPixels alp(bitmap); 1456 const void* src = bitmap.getPixels(); 1457 1458 if (NULL != src) { 1459 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE); 1460 1461 // the java side has already checked that buffer is large enough 1462 memcpy(abp.pointer(), src, bitmap.getSize()); 1463 } 1464} 1465 1466static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject, 1467 jlong bitmapHandle, jobject jbuffer) { 1468 SkBitmap bitmap; 1469 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap); 1470 SkAutoLockPixels alp(bitmap); 1471 void* dst = bitmap.getPixels(); 1472 1473 if (NULL != dst) { 1474 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE); 1475 // the java side has already checked that buffer is large enough 1476 memcpy(dst, abp.pointer(), bitmap.getSize()); 1477 bitmap.notifyPixelsChanged(); 1478 } 1479} 1480 1481static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) { 1482 SkBitmap bm0; 1483 SkBitmap bm1; 1484 1485 LocalScopedBitmap bitmap0(bm0Handle); 1486 LocalScopedBitmap bitmap1(bm1Handle); 1487 1488 // Paying the price for making Hardware Bitmap as Config: 1489 // later check for colorType will pass successfully, 1490 // because Hardware Config internally may be RGBA8888 or smth like that. 1491 if (bitmap0->isHardware() != bitmap1->isHardware()) { 1492 return JNI_FALSE; 1493 } 1494 1495 bitmap0->bitmap().getSkBitmap(&bm0); 1496 bitmap1->bitmap().getSkBitmap(&bm1); 1497 if (bm0.width() != bm1.width() 1498 || bm0.height() != bm1.height() 1499 || bm0.colorType() != bm1.colorType() 1500 || bm0.alphaType() != bm1.alphaType() 1501 || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) { 1502 return JNI_FALSE; 1503 } 1504 1505 SkAutoLockPixels alp0(bm0); 1506 SkAutoLockPixels alp1(bm1); 1507 1508 // if we can't load the pixels, return false 1509 if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) { 1510 return JNI_FALSE; 1511 } 1512 1513 if (bm0.colorType() == kIndex_8_SkColorType) { 1514 SkColorTable* ct0 = bm0.getColorTable(); 1515 SkColorTable* ct1 = bm1.getColorTable(); 1516 if (NULL == ct0 || NULL == ct1) { 1517 return JNI_FALSE; 1518 } 1519 if (ct0->count() != ct1->count()) { 1520 return JNI_FALSE; 1521 } 1522 1523 const size_t size = ct0->count() * sizeof(SkPMColor); 1524 if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) { 1525 return JNI_FALSE; 1526 } 1527 } 1528 1529 // now compare each scanline. We can't do the entire buffer at once, 1530 // since we don't care about the pixel values that might extend beyond 1531 // the width (since the scanline might be larger than the logical width) 1532 const int h = bm0.height(); 1533 const size_t size = bm0.width() * bm0.bytesPerPixel(); 1534 for (int y = 0; y < h; y++) { 1535 // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config 1536 // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0 1537 // and bm1 both have pixel data() (have passed NULL == getPixels() check), 1538 // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE 1539 // to warn user those 2 unrecognized config bitmaps may be different. 1540 void *bm0Addr = bm0.getAddr(0, y); 1541 void *bm1Addr = bm1.getAddr(0, y); 1542 1543 if(bm0Addr == NULL || bm1Addr == NULL) { 1544 return JNI_FALSE; 1545 } 1546 1547 if (memcmp(bm0Addr, bm1Addr, size) != 0) { 1548 return JNI_FALSE; 1549 } 1550 } 1551 return JNI_TRUE; 1552} 1553 1554static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) { 1555 LocalScopedBitmap bitmapHandle(bitmapPtr); 1556 if (!bitmapHandle.valid()) return; 1557 android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap()); 1558} 1559 1560static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) { 1561 LocalScopedBitmap bitmapHandle(bitmapPtr); 1562 return static_cast<jint>(bitmapHandle->getAllocationByteCount()); 1563} 1564 1565static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) { 1566 LocalScopedBitmap bitmapHandle(bitmapPtr); 1567 LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(), 1568 "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig"); 1569 Bitmap& hwuiBitmap = bitmapHandle->bitmap(); 1570 SkBitmap src; 1571 hwuiBitmap.getSkBitmap(&src); 1572 1573 SkBitmap result; 1574 HeapAllocator allocator; 1575 if (!src.copyTo(&result, hwuiBitmap.info().colorType(), &allocator)) { 1576 doThrowRE(env, "Could not copy a hardware bitmap."); 1577 return NULL; 1578 } 1579 return createBitmap(env, allocator.getStorageObjAndReset(), getPremulBitmapCreateFlags(false)); 1580} 1581 1582static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) { 1583 sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer)); 1584 sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer); 1585 if (!bitmap.get()) { 1586 ALOGW("failed to create hardware bitmap from graphic buffer"); 1587 return NULL; 1588 } 1589 return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false)); 1590} 1591 1592static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) { 1593 LocalScopedBitmap bitmapHandle(bitmapPtr); 1594 LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(), 1595 "Hardware config is only supported config in Bitmap_getGraphicBuffer"); 1596 1597 Bitmap& hwuiBitmap = bitmapHandle->bitmap(); 1598 sp<GraphicBuffer> buffer(hwuiBitmap.graphicBuffer()); 1599 return createJavaGraphicBuffer(env, buffer); 1600} 1601 1602static void Bitmap_copyColorSpace(JNIEnv* env, jobject, jlong srcBitmapPtr, jlong dstBitmapPtr) { 1603 LocalScopedBitmap srcBitmapHandle(srcBitmapPtr); 1604 LocalScopedBitmap dstBitmapHandle(dstBitmapPtr); 1605 1606 dstBitmapHandle->bitmap().setColorSpace(srcBitmapHandle->bitmap().info().refColorSpace()); 1607} 1608 1609/////////////////////////////////////////////////////////////////////////////// 1610 1611static const JNINativeMethod gBitmapMethods[] = { 1612 { "nativeCreate", "([IIIIIIZ[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/Bitmap;", 1613 (void*)Bitmap_creator }, 1614 { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;", 1615 (void*)Bitmap_copy }, 1616 { "nativeCopyAshmem", "(J)Landroid/graphics/Bitmap;", 1617 (void*)Bitmap_copyAshmem }, 1618 { "nativeCopyAshmemConfig", "(JI)Landroid/graphics/Bitmap;", 1619 (void*)Bitmap_copyAshmemConfig }, 1620 { "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer }, 1621 { "nativeRecycle", "(J)Z", (void*)Bitmap_recycle }, 1622 { "nativeReconfigure", "(JIIIZ)V", (void*)Bitmap_reconfigure }, 1623 { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z", 1624 (void*)Bitmap_compress }, 1625 { "nativeErase", "(JI)V", (void*)Bitmap_erase }, 1626 { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes }, 1627 { "nativeConfig", "(J)I", (void*)Bitmap_config }, 1628 { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha }, 1629 { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied}, 1630 { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha}, 1631 { "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied}, 1632 { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap }, 1633 { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap }, 1634 { "nativeCreateFromParcel", 1635 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;", 1636 (void*)Bitmap_createFromParcel }, 1637 { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z", 1638 (void*)Bitmap_writeToParcel }, 1639 { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;", 1640 (void*)Bitmap_extractAlpha }, 1641 { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId }, 1642 { "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel }, 1643 { "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels }, 1644 { "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel }, 1645 { "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels }, 1646 { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V", 1647 (void*)Bitmap_copyPixelsToBuffer }, 1648 { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V", 1649 (void*)Bitmap_copyPixelsFromBuffer }, 1650 { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs }, 1651 { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw }, 1652 { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount }, 1653 { "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;", 1654 (void*)Bitmap_copyPreserveInternalConfig }, 1655 { "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;", 1656 (void*) Bitmap_createHardwareBitmap }, 1657 { "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;", 1658 (void*) Bitmap_createGraphicBufferHandle }, 1659 { "nativeGetColorSpace", "(J[F[F)Z", (void*)Bitmap_getColorSpace }, 1660 { "nativeIsSRGB", "(J)Z", (void*)Bitmap_isSRGB }, 1661 { "nativeCopyColorSpace", "(JJ)V", 1662 (void*)Bitmap_copyColorSpace }, 1663}; 1664 1665int register_android_graphics_Bitmap(JNIEnv* env) 1666{ 1667 gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap")); 1668 gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J"); 1669 gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V"); 1670 gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V"); 1671 gBitmap_getAllocationByteCountMethodID = GetMethodIDOrDie(env, gBitmap_class, "getAllocationByteCount", "()I"); 1672 return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods, 1673 NELEM(gBitmapMethods)); 1674} 1675