PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/core/jni/android/graphics/Bitmap.cpp

http://github.com/android/platform_frameworks_base
C++ | 1225 lines | 983 code | 184 blank | 58 comment | 155 complexity | 167f6793db67f1bf29ad0b4f1bd0710e MD5 | raw file
Possible License(s): BitTorrent-1.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, CC0-1.0
  1. #define LOG_TAG "Bitmap"
  2. #include "Bitmap.h"
  3. #include "GraphicBuffer.h"
  4. #include "SkBitmap.h"
  5. #include "SkPixelRef.h"
  6. #include "SkImageEncoder.h"
  7. #include "SkImageInfo.h"
  8. #include "SkColor.h"
  9. #include "SkColorSpace.h"
  10. #include "GraphicsJNI.h"
  11. #include "SkStream.h"
  12. #include <binder/Parcel.h>
  13. #include "android_os_Parcel.h"
  14. #include "android_util_Binder.h"
  15. #include "android_nio_utils.h"
  16. #include "CreateJavaOutputStreamAdaptor.h"
  17. #include <hwui/Paint.h>
  18. #include <hwui/Bitmap.h>
  19. #include <renderthread/RenderProxy.h>
  20. #include <utils/Color.h>
  21. #include <android_runtime/android_hardware_HardwareBuffer.h>
  22. #include <private/android/AHardwareBufferHelpers.h>
  23. #include "core_jni_helpers.h"
  24. #include <jni.h>
  25. #include <string.h>
  26. #include <memory>
  27. #include <string>
  28. #define DEBUG_PARCEL 0
  29. #define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
  30. static jclass gBitmap_class;
  31. static jfieldID gBitmap_nativePtr;
  32. static jmethodID gBitmap_constructorMethodID;
  33. static jmethodID gBitmap_reinitMethodID;
  34. namespace android {
  35. class BitmapWrapper {
  36. public:
  37. explicit BitmapWrapper(Bitmap* bitmap)
  38. : mBitmap(bitmap) { }
  39. void freePixels() {
  40. mInfo = mBitmap->info();
  41. mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
  42. mAllocationSize = mBitmap->getAllocationByteCount();
  43. mRowBytes = mBitmap->rowBytes();
  44. mGenerationId = mBitmap->getGenerationID();
  45. mIsHardware = mBitmap->isHardware();
  46. mBitmap.reset();
  47. }
  48. bool valid() {
  49. return mBitmap != nullptr;
  50. }
  51. Bitmap& bitmap() {
  52. assertValid();
  53. return *mBitmap;
  54. }
  55. void assertValid() {
  56. LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
  57. }
  58. void getSkBitmap(SkBitmap* outBitmap) {
  59. assertValid();
  60. mBitmap->getSkBitmap(outBitmap);
  61. }
  62. bool hasHardwareMipMap() {
  63. if (mBitmap) {
  64. return mBitmap->hasHardwareMipMap();
  65. }
  66. return mHasHardwareMipMap;
  67. }
  68. void setHasHardwareMipMap(bool hasMipMap) {
  69. assertValid();
  70. mBitmap->setHasHardwareMipMap(hasMipMap);
  71. }
  72. void setAlphaType(SkAlphaType alphaType) {
  73. assertValid();
  74. mBitmap->setAlphaType(alphaType);
  75. }
  76. void setColorSpace(sk_sp<SkColorSpace> colorSpace) {
  77. assertValid();
  78. mBitmap->setColorSpace(colorSpace);
  79. }
  80. const SkImageInfo& info() {
  81. if (mBitmap) {
  82. return mBitmap->info();
  83. }
  84. return mInfo;
  85. }
  86. size_t getAllocationByteCount() const {
  87. if (mBitmap) {
  88. return mBitmap->getAllocationByteCount();
  89. }
  90. return mAllocationSize;
  91. }
  92. size_t rowBytes() const {
  93. if (mBitmap) {
  94. return mBitmap->rowBytes();
  95. }
  96. return mRowBytes;
  97. }
  98. uint32_t getGenerationID() const {
  99. if (mBitmap) {
  100. return mBitmap->getGenerationID();
  101. }
  102. return mGenerationId;
  103. }
  104. bool isHardware() {
  105. if (mBitmap) {
  106. return mBitmap->isHardware();
  107. }
  108. return mIsHardware;
  109. }
  110. ~BitmapWrapper() { }
  111. private:
  112. sk_sp<Bitmap> mBitmap;
  113. SkImageInfo mInfo;
  114. bool mHasHardwareMipMap;
  115. size_t mAllocationSize;
  116. size_t mRowBytes;
  117. uint32_t mGenerationId;
  118. bool mIsHardware;
  119. };
  120. // Convenience class that does not take a global ref on the pixels, relying
  121. // on the caller already having a local JNI ref
  122. class LocalScopedBitmap {
  123. public:
  124. explicit LocalScopedBitmap(jlong bitmapHandle)
  125. : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
  126. BitmapWrapper* operator->() {
  127. return mBitmapWrapper;
  128. }
  129. void* pixels() {
  130. return mBitmapWrapper->bitmap().pixels();
  131. }
  132. bool valid() {
  133. return mBitmapWrapper && mBitmapWrapper->valid();
  134. }
  135. private:
  136. BitmapWrapper* mBitmapWrapper;
  137. };
  138. namespace bitmap {
  139. // Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
  140. static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
  141. // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
  142. // irrelevant. This just tests to ensure that the SkAlphaType is not
  143. // opposite of isPremultiplied.
  144. if (isPremultiplied) {
  145. SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
  146. } else {
  147. SkASSERT(info.alphaType() != kPremul_SkAlphaType);
  148. }
  149. }
  150. void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
  151. bool isPremultiplied)
  152. {
  153. // The caller needs to have already set the alpha type properly, so the
  154. // native SkBitmap stays in sync with the Java Bitmap.
  155. assert_premultiplied(info, isPremultiplied);
  156. env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
  157. info.width(), info.height(), isPremultiplied);
  158. }
  159. jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
  160. int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
  161. int density) {
  162. bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
  163. bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
  164. // The caller needs to have already set the alpha type properly, so the
  165. // native SkBitmap stays in sync with the Java Bitmap.
  166. assert_premultiplied(bitmap->info(), isPremultiplied);
  167. bool fromMalloc = bitmap->pixelStorageType() == PixelStorageType::Heap;
  168. BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
  169. if (!isMutable) {
  170. bitmapWrapper->bitmap().setImmutable();
  171. }
  172. jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
  173. reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
  174. isPremultiplied, ninePatchChunk, ninePatchInsets, fromMalloc);
  175. if (env->ExceptionCheck() != 0) {
  176. ALOGE("*** Uncaught exception returned from Java call!\n");
  177. env->ExceptionDescribe();
  178. }
  179. return obj;
  180. }
  181. void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
  182. LocalScopedBitmap bitmap(bitmapHandle);
  183. bitmap->getSkBitmap(outBitmap);
  184. }
  185. Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
  186. SkASSERT(env);
  187. SkASSERT(bitmap);
  188. SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
  189. jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
  190. LocalScopedBitmap localBitmap(bitmapHandle);
  191. return localBitmap->bitmap();
  192. }
  193. Bitmap& toBitmap(jlong bitmapHandle) {
  194. LocalScopedBitmap localBitmap(bitmapHandle);
  195. return localBitmap->bitmap();
  196. }
  197. void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
  198. SkASSERT(info);
  199. SkASSERT(env);
  200. SkASSERT(bitmap);
  201. SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
  202. jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
  203. LocalScopedBitmap localBitmap(bitmapHandle);
  204. const SkImageInfo& imageInfo = localBitmap->info();
  205. info->width = imageInfo.width();
  206. info->height = imageInfo.height();
  207. info->stride = localBitmap->rowBytes();
  208. info->flags = 0;
  209. switch (imageInfo.colorType()) {
  210. case kN32_SkColorType:
  211. info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
  212. break;
  213. case kRGB_565_SkColorType:
  214. info->format = ANDROID_BITMAP_FORMAT_RGB_565;
  215. break;
  216. case kARGB_4444_SkColorType:
  217. info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
  218. break;
  219. case kAlpha_8_SkColorType:
  220. info->format = ANDROID_BITMAP_FORMAT_A_8;
  221. break;
  222. default:
  223. info->format = ANDROID_BITMAP_FORMAT_NONE;
  224. break;
  225. }
  226. }
  227. void* lockPixels(JNIEnv* env, jobject bitmap) {
  228. SkASSERT(env);
  229. SkASSERT(bitmap);
  230. SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
  231. jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
  232. LocalScopedBitmap localBitmap(bitmapHandle);
  233. if (!localBitmap->valid()) return nullptr;
  234. SkPixelRef& pixelRef = localBitmap->bitmap();
  235. if (!pixelRef.pixels()) {
  236. return nullptr;
  237. }
  238. pixelRef.ref();
  239. return pixelRef.pixels();
  240. }
  241. bool unlockPixels(JNIEnv* env, jobject bitmap) {
  242. SkASSERT(env);
  243. SkASSERT(bitmap);
  244. SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
  245. jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
  246. LocalScopedBitmap localBitmap(bitmapHandle);
  247. if (!localBitmap->valid()) return false;
  248. SkPixelRef& pixelRef = localBitmap->bitmap();
  249. pixelRef.notifyPixelsChanged();
  250. pixelRef.unref();
  251. return true;
  252. }
  253. } // namespace bitmap
  254. } // namespace android
  255. using namespace android;
  256. using namespace android::bitmap;
  257. bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
  258. int x, int y, int width, int height, SkBitmap* dstBitmap) {
  259. const jint* array = env->GetIntArrayElements(srcColors, NULL);
  260. const SkColor* src = (const SkColor*)array + srcOffset;
  261. auto sRGB = SkColorSpace::MakeSRGB();
  262. SkImageInfo srcInfo = SkImageInfo::Make(
  263. width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
  264. SkPixmap srcPM(srcInfo, src, srcStride * 4);
  265. dstBitmap->writePixels(srcPM, x, y);
  266. env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
  267. return true;
  268. }
  269. ///////////////////////////////////////////////////////////////////////////////
  270. ///////////////////////////////////////////////////////////////////////////////
  271. static int getPremulBitmapCreateFlags(bool isMutable) {
  272. int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
  273. if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
  274. return flags;
  275. }
  276. static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
  277. jint offset, jint stride, jint width, jint height,
  278. jint configHandle, jboolean isMutable,
  279. jlong colorSpacePtr) {
  280. SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
  281. if (NULL != jColors) {
  282. size_t n = env->GetArrayLength(jColors);
  283. if (n < SkAbs32(stride) * (size_t)height) {
  284. doThrowAIOOBE(env);
  285. return NULL;
  286. }
  287. }
  288. // ARGB_4444 is a deprecated format, convert automatically to 8888
  289. if (colorType == kARGB_4444_SkColorType) {
  290. colorType = kN32_SkColorType;
  291. }
  292. sk_sp<SkColorSpace> colorSpace;
  293. if (colorType == kAlpha_8_SkColorType) {
  294. colorSpace = nullptr;
  295. } else {
  296. colorSpace = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
  297. }
  298. SkBitmap bitmap;
  299. bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
  300. colorSpace));
  301. sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap);
  302. if (!nativeBitmap) {
  303. ALOGE("OOM allocating Bitmap with dimensions %i x %i", width, height);
  304. doThrowOOME(env);
  305. return NULL;
  306. }
  307. if (jColors != NULL) {
  308. GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, &bitmap);
  309. }
  310. return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
  311. }
  312. static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
  313. SkBitmap::Allocator* alloc) {
  314. SkPixmap srcPM;
  315. if (!src.peekPixels(&srcPM)) {
  316. return false;
  317. }
  318. SkImageInfo dstInfo = srcPM.info().makeColorType(dstCT);
  319. switch (dstCT) {
  320. case kRGB_565_SkColorType:
  321. dstInfo = dstInfo.makeAlphaType(kOpaque_SkAlphaType);
  322. break;
  323. case kAlpha_8_SkColorType:
  324. dstInfo = dstInfo.makeColorSpace(nullptr);
  325. break;
  326. default:
  327. break;
  328. }
  329. if (!dstInfo.colorSpace() && dstCT != kAlpha_8_SkColorType) {
  330. dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGB());
  331. }
  332. if (!dst->setInfo(dstInfo)) {
  333. return false;
  334. }
  335. if (!dst->tryAllocPixels(alloc)) {
  336. return false;
  337. }
  338. SkPixmap dstPM;
  339. if (!dst->peekPixels(&dstPM)) {
  340. return false;
  341. }
  342. return srcPM.readPixels(dstPM);
  343. }
  344. static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
  345. jint dstConfigHandle, jboolean isMutable) {
  346. SkBitmap src;
  347. reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
  348. if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
  349. sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
  350. if (!bitmap.get()) {
  351. return NULL;
  352. }
  353. return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
  354. }
  355. SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
  356. SkBitmap result;
  357. HeapAllocator allocator;
  358. if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
  359. return NULL;
  360. }
  361. auto bitmap = allocator.getStorageObjAndReset();
  362. return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
  363. }
  364. static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
  365. SkBitmap result;
  366. AshmemPixelAllocator allocator(env);
  367. if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
  368. return NULL;
  369. }
  370. auto bitmap = allocator.getStorageObjAndReset();
  371. bitmap->setImmutable();
  372. return bitmap;
  373. }
  374. static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
  375. SkBitmap src;
  376. reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
  377. SkColorType dstCT = src.colorType();
  378. auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
  379. jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
  380. return ret;
  381. }
  382. static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
  383. SkBitmap src;
  384. reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
  385. SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
  386. auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
  387. jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
  388. return ret;
  389. }
  390. static void Bitmap_destruct(BitmapWrapper* bitmap) {
  391. delete bitmap;
  392. }
  393. static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
  394. return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
  395. }
  396. static void Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
  397. LocalScopedBitmap bitmap(bitmapHandle);
  398. bitmap->freePixels();
  399. }
  400. static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
  401. jint width, jint height, jint configHandle, jboolean requestPremul) {
  402. LocalScopedBitmap bitmap(bitmapHandle);
  403. bitmap->assertValid();
  404. SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
  405. // ARGB_4444 is a deprecated format, convert automatically to 8888
  406. if (colorType == kARGB_4444_SkColorType) {
  407. colorType = kN32_SkColorType;
  408. }
  409. size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
  410. if (requestedSize > bitmap->getAllocationByteCount()) {
  411. // done in native as there's no way to get BytesPerPixel in Java
  412. doThrowIAE(env, "Bitmap not large enough to support new configuration");
  413. return;
  414. }
  415. SkAlphaType alphaType;
  416. if (bitmap->info().colorType() != kRGB_565_SkColorType
  417. && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
  418. // If the original bitmap was set to opaque, keep that setting, unless it
  419. // was 565, which is required to be opaque.
  420. alphaType = kOpaque_SkAlphaType;
  421. } else {
  422. // Otherwise respect the premultiplied request.
  423. alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
  424. }
  425. bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
  426. sk_ref_sp(bitmap->info().colorSpace())));
  427. }
  428. // These must match the int values in Bitmap.java
  429. enum JavaEncodeFormat {
  430. kJPEG_JavaEncodeFormat = 0,
  431. kPNG_JavaEncodeFormat = 1,
  432. kWEBP_JavaEncodeFormat = 2
  433. };
  434. static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
  435. jint format, jint quality,
  436. jobject jstream, jbyteArray jstorage) {
  437. SkEncodedImageFormat fm;
  438. switch (format) {
  439. case kJPEG_JavaEncodeFormat:
  440. fm = SkEncodedImageFormat::kJPEG;
  441. break;
  442. case kPNG_JavaEncodeFormat:
  443. fm = SkEncodedImageFormat::kPNG;
  444. break;
  445. case kWEBP_JavaEncodeFormat:
  446. fm = SkEncodedImageFormat::kWEBP;
  447. break;
  448. default:
  449. return JNI_FALSE;
  450. }
  451. LocalScopedBitmap bitmap(bitmapHandle);
  452. if (!bitmap.valid()) {
  453. return JNI_FALSE;
  454. }
  455. std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
  456. if (!strm.get()) {
  457. return JNI_FALSE;
  458. }
  459. SkBitmap skbitmap;
  460. bitmap->getSkBitmap(&skbitmap);
  461. if (skbitmap.colorType() == kRGBA_F16_SkColorType) {
  462. // Convert to P3 before encoding. This matches SkAndroidCodec::computeOutputColorSpace
  463. // for wide gamuts.
  464. auto cs = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
  465. auto info = skbitmap.info().makeColorType(kRGBA_8888_SkColorType)
  466. .makeColorSpace(std::move(cs));
  467. SkBitmap p3;
  468. if (!p3.tryAllocPixels(info)) {
  469. return JNI_FALSE;
  470. }
  471. SkPixmap pm;
  472. SkAssertResult(p3.peekPixels(&pm)); // should always work if tryAllocPixels() did.
  473. if (!skbitmap.readPixels(pm)) {
  474. return JNI_FALSE;
  475. }
  476. skbitmap = p3;
  477. }
  478. return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
  479. }
  480. static inline void bitmapErase(SkBitmap bitmap, const SkColor4f& color,
  481. const sk_sp<SkColorSpace>& colorSpace) {
  482. SkPaint p;
  483. p.setColor4f(color, colorSpace.get());
  484. p.setBlendMode(SkBlendMode::kSrc);
  485. SkCanvas canvas(bitmap);
  486. canvas.drawPaint(p);
  487. }
  488. static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
  489. LocalScopedBitmap bitmap(bitmapHandle);
  490. SkBitmap skBitmap;
  491. bitmap->getSkBitmap(&skBitmap);
  492. bitmapErase(skBitmap, SkColor4f::FromColor(color), SkColorSpace::MakeSRGB());
  493. }
  494. static void Bitmap_eraseLong(JNIEnv* env, jobject, jlong bitmapHandle,
  495. jlong colorSpaceHandle, jlong colorLong) {
  496. LocalScopedBitmap bitmap(bitmapHandle);
  497. SkBitmap skBitmap;
  498. bitmap->getSkBitmap(&skBitmap);
  499. SkColor4f color = GraphicsJNI::convertColorLong(colorLong);
  500. sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
  501. bitmapErase(skBitmap, color, cs);
  502. }
  503. static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
  504. LocalScopedBitmap bitmap(bitmapHandle);
  505. return static_cast<jint>(bitmap->rowBytes());
  506. }
  507. static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
  508. LocalScopedBitmap bitmap(bitmapHandle);
  509. if (bitmap->isHardware()) {
  510. return GraphicsJNI::hardwareLegacyBitmapConfig();
  511. }
  512. return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
  513. }
  514. static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
  515. LocalScopedBitmap bitmap(bitmapHandle);
  516. return static_cast<jint>(bitmap->getGenerationID());
  517. }
  518. static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
  519. LocalScopedBitmap bitmap(bitmapHandle);
  520. if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
  521. return JNI_TRUE;
  522. }
  523. return JNI_FALSE;
  524. }
  525. static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
  526. LocalScopedBitmap bitmap(bitmapHandle);
  527. return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
  528. }
  529. static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
  530. jboolean hasAlpha, jboolean requestPremul) {
  531. LocalScopedBitmap bitmap(bitmapHandle);
  532. if (hasAlpha) {
  533. bitmap->setAlphaType(
  534. requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
  535. } else {
  536. bitmap->setAlphaType(kOpaque_SkAlphaType);
  537. }
  538. }
  539. static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
  540. jboolean isPremul) {
  541. LocalScopedBitmap bitmap(bitmapHandle);
  542. if (!bitmap->info().isOpaque()) {
  543. if (isPremul) {
  544. bitmap->setAlphaType(kPremul_SkAlphaType);
  545. } else {
  546. bitmap->setAlphaType(kUnpremul_SkAlphaType);
  547. }
  548. }
  549. }
  550. static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
  551. LocalScopedBitmap bitmap(bitmapHandle);
  552. return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
  553. }
  554. static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
  555. jboolean hasMipMap) {
  556. LocalScopedBitmap bitmap(bitmapHandle);
  557. bitmap->setHasHardwareMipMap(hasMipMap);
  558. }
  559. ///////////////////////////////////////////////////////////////////////////////
  560. // This is the maximum possible size because the SkColorSpace must be
  561. // representable (and therefore serializable) using a matrix and numerical
  562. // transfer function. If we allow more color space representations in the
  563. // framework, we may need to update this maximum size.
  564. static constexpr uint32_t kMaxColorSpaceSerializedBytes = 80;
  565. static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
  566. if (parcel == NULL) {
  567. SkDebugf("-------- unparcel parcel is NULL\n");
  568. return NULL;
  569. }
  570. android::Parcel* p = android::parcelForJavaObject(env, parcel);
  571. const bool isMutable = p->readInt32() != 0;
  572. const SkColorType colorType = (SkColorType)p->readInt32();
  573. const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
  574. const uint32_t colorSpaceSize = p->readUint32();
  575. sk_sp<SkColorSpace> colorSpace;
  576. if (colorSpaceSize > 0) {
  577. if (colorSpaceSize > kMaxColorSpaceSerializedBytes) {
  578. ALOGD("Bitmap_createFromParcel: Serialized SkColorSpace is larger than expected: "
  579. "%d bytes\n", colorSpaceSize);
  580. }
  581. const void* data = p->readInplace(colorSpaceSize);
  582. if (data) {
  583. colorSpace = SkColorSpace::Deserialize(data, colorSpaceSize);
  584. } else {
  585. ALOGD("Bitmap_createFromParcel: Unable to read serialized SkColorSpace data\n");
  586. }
  587. }
  588. const int width = p->readInt32();
  589. const int height = p->readInt32();
  590. const int rowBytes = p->readInt32();
  591. const int density = p->readInt32();
  592. if (kN32_SkColorType != colorType &&
  593. kRGBA_F16_SkColorType != colorType &&
  594. kRGB_565_SkColorType != colorType &&
  595. kARGB_4444_SkColorType != colorType &&
  596. kAlpha_8_SkColorType != colorType) {
  597. SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
  598. return NULL;
  599. }
  600. std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
  601. if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
  602. rowBytes)) {
  603. return NULL;
  604. }
  605. // Read the bitmap blob.
  606. size_t size = bitmap->computeByteSize();
  607. android::Parcel::ReadableBlob blob;
  608. android::status_t status = p->readBlob(size, &blob);
  609. if (status) {
  610. doThrowRE(env, "Could not read bitmap blob.");
  611. return NULL;
  612. }
  613. // Map the bitmap in place from the ashmem region if possible otherwise copy.
  614. sk_sp<Bitmap> nativeBitmap;
  615. if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
  616. #if DEBUG_PARCEL
  617. ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
  618. "(fds %s)",
  619. isMutable ? "mutable" : "immutable",
  620. blob.isMutable() ? "mutable" : "immutable",
  621. p->allowFds() ? "allowed" : "forbidden");
  622. #endif
  623. // Dup the file descriptor so we can keep a reference to it after the Parcel
  624. // is disposed.
  625. int dupFd = fcntl(blob.fd(), F_DUPFD_CLOEXEC, 0);
  626. if (dupFd < 0) {
  627. ALOGE("Error allocating dup fd. Error:%d", errno);
  628. blob.release();
  629. doThrowRE(env, "Could not allocate dup blob fd.");
  630. return NULL;
  631. }
  632. // Map the pixels in place and take ownership of the ashmem region. We must also respect the
  633. // rowBytes value already set on the bitmap instead of attempting to compute our own.
  634. nativeBitmap = Bitmap::createFrom(bitmap->info(), bitmap->rowBytes(), dupFd,
  635. const_cast<void*>(blob.data()), size, !isMutable);
  636. if (!nativeBitmap) {
  637. close(dupFd);
  638. blob.release();
  639. doThrowRE(env, "Could not allocate ashmem pixel ref.");
  640. return NULL;
  641. }
  642. // Clear the blob handle, don't release it.
  643. blob.clear();
  644. } else {
  645. #if DEBUG_PARCEL
  646. if (blob.fd() >= 0) {
  647. ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
  648. "from immutable blob (fds %s)",
  649. p->allowFds() ? "allowed" : "forbidden");
  650. } else {
  651. ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
  652. "(fds %s)",
  653. blob.isMutable() ? "mutable" : "immutable",
  654. p->allowFds() ? "allowed" : "forbidden");
  655. }
  656. #endif
  657. // Copy the pixels into a new buffer.
  658. nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get());
  659. if (!nativeBitmap) {
  660. blob.release();
  661. doThrowRE(env, "Could not allocate java pixel ref.");
  662. return NULL;
  663. }
  664. memcpy(bitmap->getPixels(), blob.data(), size);
  665. // Release the blob handle.
  666. blob.release();
  667. }
  668. return createBitmap(env, nativeBitmap.release(),
  669. getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
  670. }
  671. static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
  672. jlong bitmapHandle,
  673. jboolean isMutable, jint density,
  674. jobject parcel) {
  675. if (parcel == NULL) {
  676. SkDebugf("------- writeToParcel null parcel\n");
  677. return JNI_FALSE;
  678. }
  679. android::Parcel* p = android::parcelForJavaObject(env, parcel);
  680. SkBitmap bitmap;
  681. auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
  682. bitmapWrapper->getSkBitmap(&bitmap);
  683. p->writeInt32(isMutable);
  684. p->writeInt32(bitmap.colorType());
  685. p->writeInt32(bitmap.alphaType());
  686. SkColorSpace* colorSpace = bitmap.colorSpace();
  687. if (colorSpace != nullptr) {
  688. sk_sp<SkData> data = colorSpace->serialize();
  689. size_t size = data->size();
  690. p->writeUint32(size);
  691. if (size > 0) {
  692. if (size > kMaxColorSpaceSerializedBytes) {
  693. ALOGD("Bitmap_writeToParcel: Serialized SkColorSpace is larger than expected: "
  694. "%zu bytes\n", size);
  695. }
  696. p->write(data->data(), size);
  697. }
  698. } else {
  699. p->writeUint32(0);
  700. }
  701. p->writeInt32(bitmap.width());
  702. p->writeInt32(bitmap.height());
  703. p->writeInt32(bitmap.rowBytes());
  704. p->writeInt32(density);
  705. // Transfer the underlying ashmem region if we have one and it's immutable.
  706. android::status_t status;
  707. int fd = bitmapWrapper->bitmap().getAshmemFd();
  708. if (fd >= 0 && !isMutable && p->allowFds()) {
  709. #if DEBUG_PARCEL
  710. ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
  711. "immutable blob (fds %s)",
  712. p->allowFds() ? "allowed" : "forbidden");
  713. #endif
  714. status = p->writeDupImmutableBlobFileDescriptor(fd);
  715. if (status) {
  716. doThrowRE(env, "Could not write bitmap blob file descriptor.");
  717. return JNI_FALSE;
  718. }
  719. return JNI_TRUE;
  720. }
  721. // Copy the bitmap to a new blob.
  722. bool mutableCopy = isMutable;
  723. #if DEBUG_PARCEL
  724. ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
  725. isMutable ? "mutable" : "immutable",
  726. mutableCopy ? "mutable" : "immutable",
  727. p->allowFds() ? "allowed" : "forbidden");
  728. #endif
  729. size_t size = bitmap.computeByteSize();
  730. android::Parcel::WritableBlob blob;
  731. status = p->writeBlob(size, mutableCopy, &blob);
  732. if (status) {
  733. doThrowRE(env, "Could not copy bitmap to parcel blob.");
  734. return JNI_FALSE;
  735. }
  736. const void* pSrc = bitmap.getPixels();
  737. if (pSrc == NULL) {
  738. memset(blob.data(), 0, size);
  739. } else {
  740. memcpy(blob.data(), pSrc, size);
  741. }
  742. blob.release();
  743. return JNI_TRUE;
  744. }
  745. static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
  746. jlong srcHandle, jlong paintHandle,
  747. jintArray offsetXY) {
  748. SkBitmap src;
  749. reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
  750. const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
  751. SkIPoint offset;
  752. SkBitmap dst;
  753. HeapAllocator allocator;
  754. src.extractAlpha(&dst, paint, &allocator, &offset);
  755. // If Skia can't allocate pixels for destination bitmap, it resets
  756. // it, that is set its pixels buffer to NULL, and zero width and height.
  757. if (dst.getPixels() == NULL && src.getPixels() != NULL) {
  758. doThrowOOME(env, "failed to allocate pixels for alpha");
  759. return NULL;
  760. }
  761. if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
  762. int* array = env->GetIntArrayElements(offsetXY, NULL);
  763. array[0] = offset.fX;
  764. array[1] = offset.fY;
  765. env->ReleaseIntArrayElements(offsetXY, array, 0);
  766. }
  767. return createBitmap(env, allocator.getStorageObjAndReset(),
  768. getPremulBitmapCreateFlags(true));
  769. }
  770. ///////////////////////////////////////////////////////////////////////////////
  771. static jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
  772. LocalScopedBitmap bitmapHolder(bitmapHandle);
  773. if (!bitmapHolder.valid()) return JNI_TRUE;
  774. SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
  775. return colorSpace == nullptr || colorSpace->isSRGB();
  776. }
  777. static jboolean Bitmap_isSRGBLinear(JNIEnv* env, jobject, jlong bitmapHandle) {
  778. LocalScopedBitmap bitmapHolder(bitmapHandle);
  779. if (!bitmapHolder.valid()) return JNI_FALSE;
  780. SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
  781. sk_sp<SkColorSpace> srgbLinear = SkColorSpace::MakeSRGBLinear();
  782. return colorSpace == srgbLinear.get() ? JNI_TRUE : JNI_FALSE;
  783. }
  784. static jobject Bitmap_computeColorSpace(JNIEnv* env, jobject, jlong bitmapHandle) {
  785. LocalScopedBitmap bitmapHolder(bitmapHandle);
  786. if (!bitmapHolder.valid()) return nullptr;
  787. SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
  788. if (colorSpace == nullptr) return nullptr;
  789. return GraphicsJNI::getColorSpace(env, colorSpace, bitmapHolder->info().colorType());
  790. }
  791. static void Bitmap_setColorSpace(JNIEnv* env, jobject, jlong bitmapHandle, jlong colorSpacePtr) {
  792. LocalScopedBitmap bitmapHolder(bitmapHandle);
  793. sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
  794. bitmapHolder->setColorSpace(cs);
  795. }
  796. ///////////////////////////////////////////////////////////////////////////////
  797. static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
  798. jint x, jint y) {
  799. SkBitmap bitmap;
  800. reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
  801. auto sRGB = SkColorSpace::MakeSRGB();
  802. SkImageInfo dstInfo = SkImageInfo::Make(
  803. 1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
  804. SkColor dst;
  805. bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
  806. return static_cast<jint>(dst);
  807. }
  808. static jlong Bitmap_getColor(JNIEnv* env, jobject, jlong bitmapHandle,
  809. jint x, jint y) {
  810. SkBitmap bitmap;
  811. reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
  812. SkImageInfo dstInfo = SkImageInfo::Make(
  813. 1, 1, kRGBA_F16_SkColorType, kUnpremul_SkAlphaType, bitmap.refColorSpace());
  814. uint64_t dst;
  815. bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
  816. return static_cast<jlong>(dst);
  817. }
  818. static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
  819. jintArray pixelArray, jint offset, jint stride,
  820. jint x, jint y, jint width, jint height) {
  821. SkBitmap bitmap;
  822. reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
  823. auto sRGB = SkColorSpace::MakeSRGB();
  824. SkImageInfo dstInfo = SkImageInfo::Make(
  825. width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
  826. jint* dst = env->GetIntArrayElements(pixelArray, NULL);
  827. bitmap.readPixels(dstInfo, dst + offset, stride * 4, x, y);
  828. env->ReleaseIntArrayElements(pixelArray, dst, 0);
  829. }
  830. ///////////////////////////////////////////////////////////////////////////////
  831. static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
  832. jint x, jint y, jint colorHandle) {
  833. SkBitmap bitmap;
  834. reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
  835. SkColor color = static_cast<SkColor>(colorHandle);
  836. auto sRGB = SkColorSpace::MakeSRGB();
  837. SkImageInfo srcInfo = SkImageInfo::Make(
  838. 1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
  839. SkPixmap srcPM(srcInfo, &color, srcInfo.minRowBytes());
  840. bitmap.writePixels(srcPM, x, y);
  841. }
  842. static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
  843. jintArray pixelArray, jint offset, jint stride,
  844. jint x, jint y, jint width, jint height) {
  845. SkBitmap bitmap;
  846. reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
  847. GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
  848. x, y, width, height, &bitmap);
  849. }
  850. static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
  851. jlong bitmapHandle, jobject jbuffer) {
  852. SkBitmap bitmap;
  853. reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
  854. const void* src = bitmap.getPixels();
  855. if (NULL != src) {
  856. android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
  857. // the java side has already checked that buffer is large enough
  858. memcpy(abp.pointer(), src, bitmap.computeByteSize());
  859. }
  860. }
  861. static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
  862. jlong bitmapHandle, jobject jbuffer) {
  863. SkBitmap bitmap;
  864. reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
  865. void* dst = bitmap.getPixels();
  866. if (NULL != dst) {
  867. android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
  868. // the java side has already checked that buffer is large enough
  869. memcpy(dst, abp.pointer(), bitmap.computeByteSize());
  870. bitmap.notifyPixelsChanged();
  871. }
  872. }
  873. static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) {
  874. SkBitmap bm0;
  875. SkBitmap bm1;
  876. LocalScopedBitmap bitmap0(bm0Handle);
  877. LocalScopedBitmap bitmap1(bm1Handle);
  878. // Paying the price for making Hardware Bitmap as Config:
  879. // later check for colorType will pass successfully,
  880. // because Hardware Config internally may be RGBA8888 or smth like that.
  881. if (bitmap0->isHardware() != bitmap1->isHardware()) {
  882. return JNI_FALSE;
  883. }
  884. bitmap0->bitmap().getSkBitmap(&bm0);
  885. bitmap1->bitmap().getSkBitmap(&bm1);
  886. if (bm0.width() != bm1.width()
  887. || bm0.height() != bm1.height()
  888. || bm0.colorType() != bm1.colorType()
  889. || bm0.alphaType() != bm1.alphaType()
  890. || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) {
  891. return JNI_FALSE;
  892. }
  893. // if we can't load the pixels, return false
  894. if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
  895. return JNI_FALSE;
  896. }
  897. // now compare each scanline. We can't do the entire buffer at once,
  898. // since we don't care about the pixel values that might extend beyond
  899. // the width (since the scanline might be larger than the logical width)
  900. const int h = bm0.height();
  901. const size_t size = bm0.width() * bm0.bytesPerPixel();
  902. for (int y = 0; y < h; y++) {
  903. // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
  904. // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
  905. // and bm1 both have pixel data() (have passed NULL == getPixels() check),
  906. // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
  907. // to warn user those 2 unrecognized config bitmaps may be different.
  908. void *bm0Addr = bm0.getAddr(0, y);
  909. void *bm1Addr = bm1.getAddr(0, y);
  910. if(bm0Addr == NULL || bm1Addr == NULL) {
  911. return JNI_FALSE;
  912. }
  913. if (memcmp(bm0Addr, bm1Addr, size) != 0) {
  914. return JNI_FALSE;
  915. }
  916. }
  917. return JNI_TRUE;
  918. }
  919. static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
  920. LocalScopedBitmap bitmapHandle(bitmapPtr);
  921. if (!bitmapHandle.valid()) return;
  922. android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
  923. }
  924. static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
  925. LocalScopedBitmap bitmapHandle(bitmapPtr);
  926. return static_cast<jint>(bitmapHandle->getAllocationByteCount());
  927. }
  928. static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
  929. LocalScopedBitmap bitmapHandle(bitmapPtr);
  930. LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
  931. "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
  932. Bitmap& hwuiBitmap = bitmapHandle->bitmap();
  933. SkBitmap src;
  934. hwuiBitmap.getSkBitmap(&src);
  935. if (src.pixelRef() == nullptr) {
  936. doThrowRE(env, "Could not copy a hardware bitmap.");
  937. return NULL;
  938. }
  939. sk_sp<Bitmap> bitmap = Bitmap::createFrom(src.info(), *src.pixelRef());
  940. return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
  941. }
  942. static jobject Bitmap_wrapHardwareBufferBitmap(JNIEnv* env, jobject, jobject hardwareBuffer,
  943. jlong colorSpacePtr) {
  944. AHardwareBuffer* hwBuf = android_hardware_HardwareBuffer_getNativeHardwareBuffer(env,
  945. hardwareBuffer);
  946. sp<GraphicBuffer> buffer(AHardwareBuffer_to_GraphicBuffer(hwBuf));
  947. SkColorType ct = uirenderer::PixelFormatToColorType(buffer->getPixelFormat());
  948. sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, ct,
  949. GraphicsJNI::getNativeColorSpace(colorSpacePtr));
  950. if (!bitmap.get()) {
  951. ALOGW("failed to create hardware bitmap from hardware buffer");
  952. return NULL;
  953. }
  954. return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
  955. }
  956. static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
  957. LocalScopedBitmap bitmapHandle(bitmapPtr);
  958. LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
  959. "Hardware config is only supported config in Bitmap_getGraphicBuffer");
  960. Bitmap& hwuiBitmap = bitmapHandle->bitmap();
  961. sp<GraphicBuffer> buffer(hwuiBitmap.graphicBuffer());
  962. return createJavaGraphicBuffer(env, buffer);
  963. }
  964. static jboolean Bitmap_isImmutable(jlong bitmapHandle) {
  965. LocalScopedBitmap bitmapHolder(bitmapHandle);
  966. if (!bitmapHolder.valid()) return JNI_FALSE;
  967. return bitmapHolder->bitmap().isImmutable() ? JNI_TRUE : JNI_FALSE;
  968. }
  969. static void Bitmap_setImmutable(JNIEnv* env, jobject, jlong bitmapHandle) {
  970. LocalScopedBitmap bitmapHolder(bitmapHandle);
  971. if (!bitmapHolder.valid()) return;
  972. return bitmapHolder->bitmap().setImmutable();
  973. }
  974. ///////////////////////////////////////////////////////////////////////////////
  975. static const JNINativeMethod gBitmapMethods[] = {
  976. { "nativeCreate", "([IIIIIIZJ)Landroid/graphics/Bitmap;",
  977. (void*)Bitmap_creator },
  978. { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
  979. (void*)Bitmap_copy },
  980. { "nativeCopyAshmem", "(J)Landroid/graphics/Bitmap;",
  981. (void*)Bitmap_copyAshmem },
  982. { "nativeCopyAshmemConfig", "(JI)Landroid/graphics/Bitmap;",
  983. (void*)Bitmap_copyAshmemConfig },
  984. { "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
  985. { "nativeRecycle", "(J)V", (void*)Bitmap_recycle },
  986. { "nativeReconfigure", "(JIIIZ)V", (void*)Bitmap_reconfigure },
  987. { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
  988. (void*)Bitmap_compress },
  989. { "nativeErase", "(JI)V", (void*)Bitmap_erase },
  990. { "nativeErase", "(JJJ)V", (void*)Bitmap_eraseLong },
  991. { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
  992. { "nativeConfig", "(J)I", (void*)Bitmap_config },
  993. { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
  994. { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},
  995. { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},
  996. { "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied},
  997. { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
  998. { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
  999. { "nativeCreateFromParcel",
  1000. "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
  1001. (void*)Bitmap_createFromParcel },
  1002. { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",
  1003. (void*)Bitmap_writeToParcel },
  1004. { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
  1005. (void*)Bitmap_extractAlpha },
  1006. { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
  1007. { "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel },
  1008. { "nativeGetColor", "(JII)J", (void*)Bitmap_getColor },
  1009. { "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels },
  1010. { "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel },
  1011. { "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels },
  1012. { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
  1013. (void*)Bitmap_copyPixelsToBuffer },
  1014. { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
  1015. (void*)Bitmap_copyPixelsFromBuffer },
  1016. { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
  1017. { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
  1018. { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
  1019. { "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
  1020. (void*)Bitmap_copyPreserveInternalConfig },
  1021. { "nativeWrapHardwareBufferBitmap", "(Landroid/hardware/HardwareBuffer;J)Landroid/graphics/Bitmap;",
  1022. (void*) Bitmap_wrapHardwareBufferBitmap },
  1023. { "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
  1024. (void*) Bitmap_createGraphicBufferHandle },
  1025. { "nativeComputeColorSpace", "(J)Landroid/graphics/ColorSpace;", (void*)Bitmap_computeColorSpace },
  1026. { "nativeSetColorSpace", "(JJ)V", (void*)Bitmap_setColorSpace },
  1027. { "nativeIsSRGB", "(J)Z", (void*)Bitmap_isSRGB },
  1028. { "nativeIsSRGBLinear", "(J)Z", (void*)Bitmap_isSRGBLinear},
  1029. { "nativeSetImmutable", "(J)V", (void*)Bitmap_setImmutable},
  1030. // ------------ @CriticalNative ----------------
  1031. { "nativeIsImmutable", "(J)Z", (void*)Bitmap_isImmutable}
  1032. };
  1033. int register_android_graphics_Bitmap(JNIEnv* env)
  1034. {
  1035. gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap"));
  1036. gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J");
  1037. gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
  1038. gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V");
  1039. return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
  1040. NELEM(gBitmapMethods));
  1041. }