blob: 2dec4b399e57652bf8af6aac91aadba809c6623d [file] [log] [blame]
John Reckf29ed282015-04-07 07:32:03 -07001#define LOG_TAG "Bitmap"
John Reckf29ed282015-04-07 07:32:03 -07002#include "Bitmap.h"
3
Chris Craik32054b02014-05-09 13:58:56 -07004#include "SkBitmap.h"
5#include "SkPixelRef.h"
6#include "SkImageEncoder.h"
Leon Scroggins III57ee6202014-06-04 18:51:07 -04007#include "SkImageInfo.h"
Romain Guy9505a652016-12-14 09:43:50 -08008#include "SkColor.h"
Romain Guyce217fa2017-03-08 15:58:06 -08009#include "SkColorSpace.h"
Chris Craik32054b02014-05-09 13:58:56 -070010#include "GraphicsJNI.h"
Chris Craik32054b02014-05-09 13:58:56 -070011#include "SkStream.h"
Leon Scroggins III94d294b2019-09-06 13:22:46 -040012#include "SkWebpEncoder.h"
Chris Craik32054b02014-05-09 13:58:56 -070013
Chris Craik32054b02014-05-09 13:58:56 -070014#include "android_os_Parcel.h"
15#include "android_util_Binder.h"
16#include "android_nio_utils.h"
17#include "CreateJavaOutputStreamAdaptor.h"
sergeyvdccca442016-03-21 15:38:21 -070018#include <hwui/Paint.h>
sergeyvc1c54062016-10-19 18:47:26 -070019#include <hwui/Bitmap.h>
Derek Sollenberger6e35e632019-01-22 13:56:25 -050020#include <utils/Color.h>
Chris Craik32054b02014-05-09 13:58:56 -070021
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010022#ifdef __ANDROID__ // Layoutlib does not support graphic buffer, parcel or render thread
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010023#include <binder/Parcel.h>
24#include <renderthread/RenderProxy.h>
Derek Sollenbergere78f7c92019-07-31 15:18:47 -040025#include <android_runtime/android_graphics_GraphicBuffer.h>
rennb2e9f522018-09-26 10:49:00 -070026#include <android_runtime/android_hardware_HardwareBuffer.h>
rennb2e9f522018-09-26 10:49:00 -070027#include <private/android/AHardwareBufferHelpers.h>
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010028#endif
rennb2e9f522018-09-26 10:49:00 -070029
Andreas Gampeed6b9df2014-11-20 22:02:20 -080030#include "core_jni_helpers.h"
31
Chris Craik32054b02014-05-09 13:58:56 -070032#include <jni.h>
Romain Guyce217fa2017-03-08 15:58:06 -080033#include <string.h>
Riley Andrews39d7f302014-11-13 17:43:25 -080034#include <memory>
35#include <string>
Chris Craik32054b02014-05-09 13:58:56 -070036
Jeff Browna316c5d2015-06-05 15:14:06 -070037#define DEBUG_PARCEL 0
Riley Andrews8cee7c12015-11-01 23:36:04 -080038#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
Jeff Browna316c5d2015-06-05 15:14:06 -070039
sergeyvc69853c2016-10-07 14:14:09 -070040static jclass gBitmap_class;
41static jfieldID gBitmap_nativePtr;
42static jmethodID gBitmap_constructorMethodID;
43static jmethodID gBitmap_reinitMethodID;
sergeyvc69853c2016-10-07 14:14:09 -070044
John Reckf29ed282015-04-07 07:32:03 -070045namespace android {
46
sergeyvc1c54062016-10-19 18:47:26 -070047class BitmapWrapper {
John Reckf29ed282015-04-07 07:32:03 -070048public:
Chih-Hung Hsieh0727be12018-12-20 13:43:46 -080049 explicit BitmapWrapper(Bitmap* bitmap)
sergeyvc1c54062016-10-19 18:47:26 -070050 : mBitmap(bitmap) { }
sergeyvc69853c2016-10-07 14:14:09 -070051
52 void freePixels() {
sergeyvc1c54062016-10-19 18:47:26 -070053 mInfo = mBitmap->info();
54 mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
55 mAllocationSize = mBitmap->getAllocationByteCount();
56 mRowBytes = mBitmap->rowBytes();
57 mGenerationId = mBitmap->getGenerationID();
sergeyv15a10852016-12-27 14:32:03 -080058 mIsHardware = mBitmap->isHardware();
sergeyvc1c54062016-10-19 18:47:26 -070059 mBitmap.reset();
John Reckf29ed282015-04-07 07:32:03 -070060 }
61
sergeyvc69853c2016-10-07 14:14:09 -070062 bool valid() {
Ben Wagner6b62ac02018-05-29 14:16:02 -040063 return mBitmap != nullptr;
John Reckf29ed282015-04-07 07:32:03 -070064 }
65
sergeyvaed7f582016-10-14 16:30:21 -070066 Bitmap& bitmap() {
67 assertValid();
68 return *mBitmap;
69 }
sergeyvc69853c2016-10-07 14:14:09 -070070
71 void assertValid() {
72 LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
73 }
74
75 void getSkBitmap(SkBitmap* outBitmap) {
76 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070077 mBitmap->getSkBitmap(outBitmap);
sergeyvc69853c2016-10-07 14:14:09 -070078 }
79
80 bool hasHardwareMipMap() {
sergeyvc1c54062016-10-19 18:47:26 -070081 if (mBitmap) {
82 return mBitmap->hasHardwareMipMap();
John Reckf29ed282015-04-07 07:32:03 -070083 }
John Reckf29ed282015-04-07 07:32:03 -070084 return mHasHardwareMipMap;
85 }
86
87 void setHasHardwareMipMap(bool hasMipMap) {
sergeyvc69853c2016-10-07 14:14:09 -070088 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070089 mBitmap->setHasHardwareMipMap(hasMipMap);
John Reckf29ed282015-04-07 07:32:03 -070090 }
91
sergeyvc69853c2016-10-07 14:14:09 -070092 void setAlphaType(SkAlphaType alphaType) {
93 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070094 mBitmap->setAlphaType(alphaType);
John Reckf29ed282015-04-07 07:32:03 -070095 }
96
Derek Sollenberger202084c2019-01-14 13:55:08 -050097 void setColorSpace(sk_sp<SkColorSpace> colorSpace) {
98 assertValid();
99 mBitmap->setColorSpace(colorSpace);
100 }
101
sergeyvc69853c2016-10-07 14:14:09 -0700102 const SkImageInfo& info() {
sergeyvc1c54062016-10-19 18:47:26 -0700103 if (mBitmap) {
104 return mBitmap->info();
sergeyvc69853c2016-10-07 14:14:09 -0700105 }
106 return mInfo;
John Reckf29ed282015-04-07 07:32:03 -0700107 }
108
sergeyvc69853c2016-10-07 14:14:09 -0700109 size_t getAllocationByteCount() const {
sergeyvc1c54062016-10-19 18:47:26 -0700110 if (mBitmap) {
111 return mBitmap->getAllocationByteCount();
sergeyvc69853c2016-10-07 14:14:09 -0700112 }
113 return mAllocationSize;
John Reckf29ed282015-04-07 07:32:03 -0700114 }
115
sergeyvc69853c2016-10-07 14:14:09 -0700116 size_t rowBytes() const {
sergeyvc1c54062016-10-19 18:47:26 -0700117 if (mBitmap) {
118 return mBitmap->rowBytes();
sergeyvc69853c2016-10-07 14:14:09 -0700119 }
120 return mRowBytes;
121 }
122
123 uint32_t getGenerationID() const {
sergeyvc1c54062016-10-19 18:47:26 -0700124 if (mBitmap) {
125 return mBitmap->getGenerationID();
sergeyvc69853c2016-10-07 14:14:09 -0700126 }
127 return mGenerationId;
128 }
129
sergeyv15a10852016-12-27 14:32:03 -0800130 bool isHardware() {
131 if (mBitmap) {
132 return mBitmap->isHardware();
133 }
134 return mIsHardware;
135 }
136
sergeyvc1c54062016-10-19 18:47:26 -0700137 ~BitmapWrapper() { }
sergeyvc69853c2016-10-07 14:14:09 -0700138
John Reckf29ed282015-04-07 07:32:03 -0700139private:
sergeyvc1c54062016-10-19 18:47:26 -0700140 sk_sp<Bitmap> mBitmap;
sergeyvc69853c2016-10-07 14:14:09 -0700141 SkImageInfo mInfo;
142 bool mHasHardwareMipMap;
143 size_t mAllocationSize;
144 size_t mRowBytes;
145 uint32_t mGenerationId;
sergeyv15a10852016-12-27 14:32:03 -0800146 bool mIsHardware;
John Reckf29ed282015-04-07 07:32:03 -0700147};
148
John Reckf29ed282015-04-07 07:32:03 -0700149// Convenience class that does not take a global ref on the pixels, relying
150// on the caller already having a local JNI ref
151class LocalScopedBitmap {
152public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -0700153 explicit LocalScopedBitmap(jlong bitmapHandle)
sergeyvc1c54062016-10-19 18:47:26 -0700154 : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
John Reckf29ed282015-04-07 07:32:03 -0700155
sergeyvc1c54062016-10-19 18:47:26 -0700156 BitmapWrapper* operator->() {
157 return mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700158 }
159
160 void* pixels() {
sergeyvaed7f582016-10-14 16:30:21 -0700161 return mBitmapWrapper->bitmap().pixels();
John Reckf29ed282015-04-07 07:32:03 -0700162 }
163
164 bool valid() {
sergeyvc1c54062016-10-19 18:47:26 -0700165 return mBitmapWrapper && mBitmapWrapper->valid();
John Reckf29ed282015-04-07 07:32:03 -0700166 }
167
168private:
sergeyvc1c54062016-10-19 18:47:26 -0700169 BitmapWrapper* mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700170};
171
sergeyvc69853c2016-10-07 14:14:09 -0700172namespace bitmap {
173
174// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
175static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
176 // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
177 // irrelevant. This just tests to ensure that the SkAlphaType is not
178 // opposite of isPremultiplied.
179 if (isPremultiplied) {
180 SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
181 } else {
182 SkASSERT(info.alphaType() != kPremul_SkAlphaType);
183 }
184}
185
186void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
187 bool isPremultiplied)
188{
189 // The caller needs to have already set the alpha type properly, so the
190 // native SkBitmap stays in sync with the Java Bitmap.
191 assert_premultiplied(info, isPremultiplied);
192
193 env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
194 info.width(), info.height(), isPremultiplied);
195}
196
sergeyvc1c54062016-10-19 18:47:26 -0700197jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
sergeyvc69853c2016-10-07 14:14:09 -0700198 int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
199 int density) {
200 bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
201 bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
202 // The caller needs to have already set the alpha type properly, so the
203 // native SkBitmap stays in sync with the Java Bitmap.
sergeyvc1c54062016-10-19 18:47:26 -0700204 assert_premultiplied(bitmap->info(), isPremultiplied);
Leon Scroggins IIIbbdb7312019-01-31 14:35:54 -0500205 bool fromMalloc = bitmap->pixelStorageType() == PixelStorageType::Heap;
sergeyvc1c54062016-10-19 18:47:26 -0700206 BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
Nader Jawade7b51292018-04-12 17:55:31 -0700207 if (!isMutable) {
208 bitmapWrapper->bitmap().setImmutable();
209 }
sergeyvc69853c2016-10-07 14:14:09 -0700210 jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
sergeyvc1c54062016-10-19 18:47:26 -0700211 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
Leon Scroggins IIIbbdb7312019-01-31 14:35:54 -0500212 isPremultiplied, ninePatchChunk, ninePatchInsets, fromMalloc);
sergeyvc69853c2016-10-07 14:14:09 -0700213
214 if (env->ExceptionCheck() != 0) {
215 ALOGE("*** Uncaught exception returned from Java call!\n");
216 env->ExceptionDescribe();
217 }
218 return obj;
219}
220
221void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
222 LocalScopedBitmap bitmap(bitmapHandle);
223 bitmap->getSkBitmap(outBitmap);
224}
225
Leon Scroggins III71fae622019-03-26 16:28:41 -0400226Bitmap& toBitmap(jlong bitmapHandle) {
sergeyv5fd2a1c2016-10-20 15:04:28 -0700227 LocalScopedBitmap localBitmap(bitmapHandle);
228 return localBitmap->bitmap();
229}
230
sergeyvc69853c2016-10-07 14:14:09 -0700231} // namespace bitmap
232
233} // namespace android
234
235using namespace android;
236using namespace android::bitmap;
237
Derek Sollenberger6c41ab12019-11-08 08:50:58 -0500238Bitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
239 SkASSERT(env);
240 SkASSERT(bitmap);
241 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
242 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
243 LocalScopedBitmap localBitmap(bitmapHandle);
244 return localBitmap.valid() ? &localBitmap->bitmap() : nullptr;
245}
246
247SkImageInfo GraphicsJNI::getBitmapInfo(JNIEnv* env, jobject bitmap, uint32_t* outRowBytes) {
248 SkASSERT(env);
249 SkASSERT(bitmap);
250 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
251 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
252 LocalScopedBitmap localBitmap(bitmapHandle);
253 if (outRowBytes) {
254 *outRowBytes = localBitmap->rowBytes();
255 }
256 return localBitmap->info();
257}
258
Chris Craik32054b02014-05-09 13:58:56 -0700259bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
Brian Osman91c9c282018-08-17 16:57:15 -0400260 int x, int y, int width, int height, SkBitmap* dstBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700261 const jint* array = env->GetIntArrayElements(srcColors, NULL);
262 const SkColor* src = (const SkColor*)array + srcOffset;
263
Brian Osman91c9c282018-08-17 16:57:15 -0400264 auto sRGB = SkColorSpace::MakeSRGB();
265 SkImageInfo srcInfo = SkImageInfo::Make(
266 width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
267 SkPixmap srcPM(srcInfo, src, srcStride * 4);
Romain Guyce217fa2017-03-08 15:58:06 -0800268
Brian Osman91c9c282018-08-17 16:57:15 -0400269 dstBitmap->writePixels(srcPM, x, y);
Chris Craik32054b02014-05-09 13:58:56 -0700270
Romain Guy9505a652016-12-14 09:43:50 -0800271 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
Chris Craik32054b02014-05-09 13:58:56 -0700272 return true;
273}
274
Chris Craik32054b02014-05-09 13:58:56 -0700275///////////////////////////////////////////////////////////////////////////////
276///////////////////////////////////////////////////////////////////////////////
277
278static int getPremulBitmapCreateFlags(bool isMutable) {
sergeyvc69853c2016-10-07 14:14:09 -0700279 int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
280 if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
Chris Craik32054b02014-05-09 13:58:56 -0700281 return flags;
282}
283
284static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
285 jint offset, jint stride, jint width, jint height,
Romain Guy82426562017-04-04 19:38:50 -0700286 jint configHandle, jboolean isMutable,
Leon Scroggins III0e443d12018-12-19 11:38:35 -0500287 jlong colorSpacePtr) {
Mike Reed1103b322014-07-08 12:36:44 -0400288 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700289 if (NULL != jColors) {
290 size_t n = env->GetArrayLength(jColors);
291 if (n < SkAbs32(stride) * (size_t)height) {
292 doThrowAIOOBE(env);
293 return NULL;
294 }
295 }
296
297 // ARGB_4444 is a deprecated format, convert automatically to 8888
Mike Reedb9330552014-06-16 17:31:48 -0400298 if (colorType == kARGB_4444_SkColorType) {
299 colorType = kN32_SkColorType;
Chris Craik32054b02014-05-09 13:58:56 -0700300 }
301
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500302 sk_sp<SkColorSpace> colorSpace;
303 if (colorType == kAlpha_8_SkColorType) {
304 colorSpace = nullptr;
305 } else {
306 colorSpace = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
307 }
308
Chris Craik32054b02014-05-09 13:58:56 -0700309 SkBitmap bitmap;
Leon Scroggins III0e443d12018-12-19 11:38:35 -0500310 bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500311 colorSpace));
Chris Craik32054b02014-05-09 13:58:56 -0700312
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400313 sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700314 if (!nativeBitmap) {
Leon Scroggins IIIf3a02992017-10-03 14:00:20 -0400315 ALOGE("OOM allocating Bitmap with dimensions %i x %i", width, height);
316 doThrowOOME(env);
Chris Craik32054b02014-05-09 13:58:56 -0700317 return NULL;
318 }
319
320 if (jColors != NULL) {
Brian Osman91c9c282018-08-17 16:57:15 -0400321 GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, &bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700322 }
323
sergeyvc36bd6c2016-10-11 15:49:16 -0700324 return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700325}
326
Matt Sarett5320a722017-03-20 13:51:29 -0400327static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
328 SkBitmap::Allocator* alloc) {
Matt Sarette9834402017-04-25 13:49:42 -0400329 SkPixmap srcPM;
330 if (!src.peekPixels(&srcPM)) {
331 return false;
332 }
333
334 SkImageInfo dstInfo = srcPM.info().makeColorType(dstCT);
335 switch (dstCT) {
336 case kRGB_565_SkColorType:
Brian Osmanbaf13e82018-09-21 11:21:30 -0400337 dstInfo = dstInfo.makeAlphaType(kOpaque_SkAlphaType);
Matt Sarette9834402017-04-25 13:49:42 -0400338 break;
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500339 case kAlpha_8_SkColorType:
340 dstInfo = dstInfo.makeColorSpace(nullptr);
Matt Sarette9834402017-04-25 13:49:42 -0400341 break;
342 default:
343 break;
344 }
345
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500346 if (!dstInfo.colorSpace() && dstCT != kAlpha_8_SkColorType) {
347 dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGB());
348 }
349
Matt Sarette9834402017-04-25 13:49:42 -0400350 if (!dst->setInfo(dstInfo)) {
351 return false;
352 }
Mike Reed81397c42017-07-18 17:04:16 -0400353 if (!dst->tryAllocPixels(alloc)) {
Matt Sarette9834402017-04-25 13:49:42 -0400354 return false;
355 }
356
Matt Sarette9834402017-04-25 13:49:42 -0400357 SkPixmap dstPM;
358 if (!dst->peekPixels(&dstPM)) {
359 return false;
360 }
361
Matt Sarette9834402017-04-25 13:49:42 -0400362 return srcPM.readPixels(dstPM);
Matt Sarett5320a722017-03-20 13:51:29 -0400363}
364
Chris Craik32054b02014-05-09 13:58:56 -0700365static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
366 jint dstConfigHandle, jboolean isMutable) {
John Reckf29ed282015-04-07 07:32:03 -0700367 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700368 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
sergeyv05126d12016-12-15 19:50:15 -0800369 if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
370 sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
371 if (!bitmap.get()) {
372 return NULL;
373 }
sergeyv656117b2017-02-28 15:25:10 -0800374 return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
sergeyv05126d12016-12-15 19:50:15 -0800375 }
376
Mike Reed1103b322014-07-08 12:36:44 -0400377 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyv45082182016-09-29 18:25:40 -0700378 SkBitmap result;
379 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700380
Matt Sarett5320a722017-03-20 13:51:29 -0400381 if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
Chris Craik32054b02014-05-09 13:58:56 -0700382 return NULL;
383 }
sergeyvc1c54062016-10-19 18:47:26 -0700384 auto bitmap = allocator.getStorageObjAndReset();
385 return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700386}
387
sergeyvc1c54062016-10-19 18:47:26 -0700388static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700389 SkBitmap result;
390
391 AshmemPixelAllocator allocator(env);
Matt Sarett5320a722017-03-20 13:51:29 -0400392 if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700393 return NULL;
394 }
sergeyvc1c54062016-10-19 18:47:26 -0700395 auto bitmap = allocator.getStorageObjAndReset();
396 bitmap->setImmutable();
397 return bitmap;
Winsona5fdde92016-04-14 15:27:15 -0700398}
399
400static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
401 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700402 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700403 SkColorType dstCT = src.colorType();
sergeyvc1c54062016-10-19 18:47:26 -0700404 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
405 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Winsona5fdde92016-04-14 15:27:15 -0700406 return ret;
407}
408
409static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
410 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700411 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700412 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyvc1c54062016-10-19 18:47:26 -0700413 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
414 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Riley Andrews721ae5f2015-05-11 16:08:22 -0700415 return ret;
416}
417
sergeyvc1c54062016-10-19 18:47:26 -0700418static void Bitmap_destruct(BitmapWrapper* bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700419 delete bitmap;
Chris Craik32054b02014-05-09 13:58:56 -0700420}
421
Richard Uhler775873a2015-12-29 12:37:39 -0800422static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
423 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
424}
425
Leon Scroggins IIIf8adae12018-05-24 15:25:08 -0400426static void Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700427 LocalScopedBitmap bitmap(bitmapHandle);
428 bitmap->freePixels();
Chris Craik32054b02014-05-09 13:58:56 -0700429}
430
431static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
sergeyv45082182016-09-29 18:25:40 -0700432 jint width, jint height, jint configHandle, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700433 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700434 bitmap->assertValid();
Mike Reed1103b322014-07-08 12:36:44 -0400435 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400436
437 // ARGB_4444 is a deprecated format, convert automatically to 8888
438 if (colorType == kARGB_4444_SkColorType) {
439 colorType = kN32_SkColorType;
440 }
sergeyv45082182016-09-29 18:25:40 -0700441 size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
442 if (requestedSize > bitmap->getAllocationByteCount()) {
Chris Craik32054b02014-05-09 13:58:56 -0700443 // done in native as there's no way to get BytesPerPixel in Java
444 doThrowIAE(env, "Bitmap not large enough to support new configuration");
445 return;
446 }
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400447 SkAlphaType alphaType;
John Reckf29ed282015-04-07 07:32:03 -0700448 if (bitmap->info().colorType() != kRGB_565_SkColorType
449 && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400450 // If the original bitmap was set to opaque, keep that setting, unless it
451 // was 565, which is required to be opaque.
452 alphaType = kOpaque_SkAlphaType;
453 } else {
454 // Otherwise respect the premultiplied request.
455 alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
456 }
sergeyvaed7f582016-10-14 16:30:21 -0700457 bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
sergeyv7d5219f2016-11-03 16:18:16 -0700458 sk_ref_sp(bitmap->info().colorSpace())));
Chris Craik32054b02014-05-09 13:58:56 -0700459}
460
461// These must match the int values in Bitmap.java
462enum JavaEncodeFormat {
463 kJPEG_JavaEncodeFormat = 0,
464 kPNG_JavaEncodeFormat = 1,
Leon Scroggins III94d294b2019-09-06 13:22:46 -0400465 kWEBP_JavaEncodeFormat = 2,
466 kWEBP_LOSSY_JavaEncodeFormat = 3,
467 kWEBP_LOSSLESS_JavaEncodeFormat = 4,
Chris Craik32054b02014-05-09 13:58:56 -0700468};
469
470static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
471 jint format, jint quality,
472 jobject jstream, jbyteArray jstorage) {
Hal Canary10219fb2016-11-23 20:41:22 -0500473 LocalScopedBitmap bitmap(bitmapHandle);
John Reckf29ed282015-04-07 07:32:03 -0700474 if (!bitmap.valid()) {
475 return JNI_FALSE;
476 }
477
John Reckf29ed282015-04-07 07:32:03 -0700478 std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
479 if (!strm.get()) {
480 return JNI_FALSE;
481 }
Chris Craik32054b02014-05-09 13:58:56 -0700482
Hal Canary10219fb2016-11-23 20:41:22 -0500483 SkBitmap skbitmap;
484 bitmap->getSkBitmap(&skbitmap);
Leon Scroggins III48562102018-03-09 11:59:17 -0500485 if (skbitmap.colorType() == kRGBA_F16_SkColorType) {
486 // Convert to P3 before encoding. This matches SkAndroidCodec::computeOutputColorSpace
487 // for wide gamuts.
Brian Osmanbe8fac262019-01-14 17:02:23 -0500488 auto cs = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
Leon Scroggins III48562102018-03-09 11:59:17 -0500489 auto info = skbitmap.info().makeColorType(kRGBA_8888_SkColorType)
490 .makeColorSpace(std::move(cs));
491 SkBitmap p3;
492 if (!p3.tryAllocPixels(info)) {
493 return JNI_FALSE;
494 }
Mike Klein4801a432018-10-03 10:38:32 -0400495
496 SkPixmap pm;
497 SkAssertResult(p3.peekPixels(&pm)); // should always work if tryAllocPixels() did.
498 if (!skbitmap.readPixels(pm)) {
Leon Scroggins III48562102018-03-09 11:59:17 -0500499 return JNI_FALSE;
500 }
501 skbitmap = p3;
502 }
Leon Scroggins III94d294b2019-09-06 13:22:46 -0400503 SkEncodedImageFormat fm;
504 switch (format) {
505 case kJPEG_JavaEncodeFormat:
506 fm = SkEncodedImageFormat::kJPEG;
507 break;
508 case kPNG_JavaEncodeFormat:
509 fm = SkEncodedImageFormat::kPNG;
510 break;
511 case kWEBP_JavaEncodeFormat:
512 fm = SkEncodedImageFormat::kWEBP;
513 break;
514 case kWEBP_LOSSY_JavaEncodeFormat:
515 case kWEBP_LOSSLESS_JavaEncodeFormat: {
516 SkWebpEncoder::Options options;
517 options.fQuality = quality;
518 options.fCompression = format == kWEBP_LOSSY_JavaEncodeFormat ?
519 SkWebpEncoder::Compression::kLossy : SkWebpEncoder::Compression::kLossless;
520 return SkWebpEncoder::Encode(strm.get(), skbitmap.pixmap(), options) ?
521 JNI_TRUE : JNI_FALSE;
522 }
523 default:
524 return JNI_FALSE;
525 }
526
Hal Canary10219fb2016-11-23 20:41:22 -0500527 return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700528}
529
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500530static inline void bitmapErase(SkBitmap bitmap, const SkColor4f& color,
531 const sk_sp<SkColorSpace>& colorSpace) {
532 SkPaint p;
533 p.setColor4f(color, colorSpace.get());
534 p.setBlendMode(SkBlendMode::kSrc);
535 SkCanvas canvas(bitmap);
536 canvas.drawPaint(p);
537}
538
Chris Craik32054b02014-05-09 13:58:56 -0700539static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
John Reckf29ed282015-04-07 07:32:03 -0700540 LocalScopedBitmap bitmap(bitmapHandle);
541 SkBitmap skBitmap;
542 bitmap->getSkBitmap(&skBitmap);
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500543 bitmapErase(skBitmap, SkColor4f::FromColor(color), SkColorSpace::MakeSRGB());
544}
545
Leon Scroggins III94ba1002019-01-17 13:34:51 -0500546static void Bitmap_eraseLong(JNIEnv* env, jobject, jlong bitmapHandle,
547 jlong colorSpaceHandle, jlong colorLong) {
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500548 LocalScopedBitmap bitmap(bitmapHandle);
549 SkBitmap skBitmap;
550 bitmap->getSkBitmap(&skBitmap);
Leon Scroggins III0e443d12018-12-19 11:38:35 -0500551
Leon Scroggins III94ba1002019-01-17 13:34:51 -0500552 SkColor4f color = GraphicsJNI::convertColorLong(colorLong);
Leon Scroggins III0e443d12018-12-19 11:38:35 -0500553 sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500554 bitmapErase(skBitmap, color, cs);
Chris Craik32054b02014-05-09 13:58:56 -0700555}
556
557static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700558 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700559 return static_cast<jint>(bitmap->rowBytes());
560}
561
562static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700563 LocalScopedBitmap bitmap(bitmapHandle);
sergeyv15a10852016-12-27 14:32:03 -0800564 if (bitmap->isHardware()) {
sergeyv19b4b012016-12-13 16:06:00 -0800565 return GraphicsJNI::hardwareLegacyBitmapConfig();
566 }
John Reckf29ed282015-04-07 07:32:03 -0700567 return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
Chris Craik32054b02014-05-09 13:58:56 -0700568}
569
570static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700571 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700572 return static_cast<jint>(bitmap->getGenerationID());
Chris Craik32054b02014-05-09 13:58:56 -0700573}
574
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400575static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700576 LocalScopedBitmap bitmap(bitmapHandle);
577 if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400578 return JNI_TRUE;
579 }
580 return JNI_FALSE;
581}
582
Chris Craik32054b02014-05-09 13:58:56 -0700583static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700584 LocalScopedBitmap bitmap(bitmapHandle);
585 return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700586}
587
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400588static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
589 jboolean hasAlpha, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700590 LocalScopedBitmap bitmap(bitmapHandle);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400591 if (hasAlpha) {
John Reck0781a2f2015-05-27 16:29:17 -0700592 bitmap->setAlphaType(
John Reckf29ed282015-04-07 07:32:03 -0700593 requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
Chris Craik32054b02014-05-09 13:58:56 -0700594 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700595 bitmap->setAlphaType(kOpaque_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400596 }
597}
598
599static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
600 jboolean isPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700601 LocalScopedBitmap bitmap(bitmapHandle);
602 if (!bitmap->info().isOpaque()) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400603 if (isPremul) {
John Reck0781a2f2015-05-27 16:29:17 -0700604 bitmap->setAlphaType(kPremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400605 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700606 bitmap->setAlphaType(kUnpremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400607 }
Chris Craik32054b02014-05-09 13:58:56 -0700608 }
609}
610
611static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700612 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700613 return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
614}
615
616static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
617 jboolean hasMipMap) {
John Reckf29ed282015-04-07 07:32:03 -0700618 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700619 bitmap->setHasHardwareMipMap(hasMipMap);
620}
621
622///////////////////////////////////////////////////////////////////////////////
623
Matt Sarett3ca39752017-05-26 10:55:38 -0400624// This is the maximum possible size because the SkColorSpace must be
625// representable (and therefore serializable) using a matrix and numerical
626// transfer function. If we allow more color space representations in the
627// framework, we may need to update this maximum size.
628static constexpr uint32_t kMaxColorSpaceSerializedBytes = 80;
629
Chris Craik32054b02014-05-09 13:58:56 -0700630static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100631#ifdef __ANDROID__ // Layoutlib does not support parcel
Chris Craik32054b02014-05-09 13:58:56 -0700632 if (parcel == NULL) {
633 SkDebugf("-------- unparcel parcel is NULL\n");
634 return NULL;
635 }
636
637 android::Parcel* p = android::parcelForJavaObject(env, parcel);
638
Mike Reedb9330552014-06-16 17:31:48 -0400639 const bool isMutable = p->readInt32() != 0;
640 const SkColorType colorType = (SkColorType)p->readInt32();
641 const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
Romain Guy5acc4762017-03-07 15:29:27 -0800642 const uint32_t colorSpaceSize = p->readUint32();
643 sk_sp<SkColorSpace> colorSpace;
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500644 if (colorSpaceSize > 0) {
Matt Sarett3ca39752017-05-26 10:55:38 -0400645 if (colorSpaceSize > kMaxColorSpaceSerializedBytes) {
646 ALOGD("Bitmap_createFromParcel: Serialized SkColorSpace is larger than expected: "
647 "%d bytes\n", colorSpaceSize);
648 }
649
650 const void* data = p->readInplace(colorSpaceSize);
651 if (data) {
652 colorSpace = SkColorSpace::Deserialize(data, colorSpaceSize);
653 } else {
654 ALOGD("Bitmap_createFromParcel: Unable to read serialized SkColorSpace data\n");
655 }
Romain Guy5acc4762017-03-07 15:29:27 -0800656 }
Mike Reedb9330552014-06-16 17:31:48 -0400657 const int width = p->readInt32();
658 const int height = p->readInt32();
659 const int rowBytes = p->readInt32();
660 const int density = p->readInt32();
Chris Craik32054b02014-05-09 13:58:56 -0700661
Mike Reedb9330552014-06-16 17:31:48 -0400662 if (kN32_SkColorType != colorType &&
Romain Guy9505a652016-12-14 09:43:50 -0800663 kRGBA_F16_SkColorType != colorType &&
Mike Reedb9330552014-06-16 17:31:48 -0400664 kRGB_565_SkColorType != colorType &&
665 kARGB_4444_SkColorType != colorType &&
Mike Reedb9330552014-06-16 17:31:48 -0400666 kAlpha_8_SkColorType != colorType) {
667 SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
Chris Craik32054b02014-05-09 13:58:56 -0700668 return NULL;
669 }
670
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400671 std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
Romain Guy9505a652016-12-14 09:43:50 -0800672 if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
673 rowBytes)) {
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400674 return NULL;
675 }
Chris Craik32054b02014-05-09 13:58:56 -0700676
Jeff Browna316c5d2015-06-05 15:14:06 -0700677 // Read the bitmap blob.
Mike Reed7569de02017-10-06 16:25:49 -0400678 size_t size = bitmap->computeByteSize();
Jeff Browna316c5d2015-06-05 15:14:06 -0700679 android::Parcel::ReadableBlob blob;
680 android::status_t status = p->readBlob(size, &blob);
681 if (status) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700682 doThrowRE(env, "Could not read bitmap blob.");
Chris Craik32054b02014-05-09 13:58:56 -0700683 return NULL;
684 }
685
Jeff Browna316c5d2015-06-05 15:14:06 -0700686 // Map the bitmap in place from the ashmem region if possible otherwise copy.
sergeyvc1c54062016-10-19 18:47:26 -0700687 sk_sp<Bitmap> nativeBitmap;
Riley Andrews8cee7c12015-11-01 23:36:04 -0800688 if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700689#if DEBUG_PARCEL
690 ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
691 "(fds %s)",
692 isMutable ? "mutable" : "immutable",
693 blob.isMutable() ? "mutable" : "immutable",
694 p->allowFds() ? "allowed" : "forbidden");
695#endif
696 // Dup the file descriptor so we can keep a reference to it after the Parcel
697 // is disposed.
Nick Kralevich07f1c1d2019-01-14 13:42:22 -0800698 int dupFd = fcntl(blob.fd(), F_DUPFD_CLOEXEC, 0);
Jeff Browna316c5d2015-06-05 15:14:06 -0700699 if (dupFd < 0) {
Erik Wolsheimer211abad2015-11-13 11:54:47 -0800700 ALOGE("Error allocating dup fd. Error:%d", errno);
Jeff Browna316c5d2015-06-05 15:14:06 -0700701 blob.release();
Jeff Browna316c5d2015-06-05 15:14:06 -0700702 doThrowRE(env, "Could not allocate dup blob fd.");
703 return NULL;
704 }
705
Derek Sollenbergere2169482018-11-20 10:57:20 -0500706 // Map the pixels in place and take ownership of the ashmem region. We must also respect the
707 // rowBytes value already set on the bitmap instead of attempting to compute our own.
708 nativeBitmap = Bitmap::createFrom(bitmap->info(), bitmap->rowBytes(), dupFd,
709 const_cast<void*>(blob.data()), size, !isMutable);
Jeff Browna316c5d2015-06-05 15:14:06 -0700710 if (!nativeBitmap) {
711 close(dupFd);
712 blob.release();
713 doThrowRE(env, "Could not allocate ashmem pixel ref.");
714 return NULL;
715 }
716
717 // Clear the blob handle, don't release it.
718 blob.clear();
719 } else {
720#if DEBUG_PARCEL
721 if (blob.fd() >= 0) {
722 ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
723 "from immutable blob (fds %s)",
724 p->allowFds() ? "allowed" : "forbidden");
725 } else {
726 ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
727 "(fds %s)",
728 blob.isMutable() ? "mutable" : "immutable",
729 p->allowFds() ? "allowed" : "forbidden");
730 }
731#endif
732
733 // Copy the pixels into a new buffer.
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400734 nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get());
Jeff Browna316c5d2015-06-05 15:14:06 -0700735 if (!nativeBitmap) {
736 blob.release();
737 doThrowRE(env, "Could not allocate java pixel ref.");
738 return NULL;
739 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700740 memcpy(bitmap->getPixels(), blob.data(), size);
Jeff Browna316c5d2015-06-05 15:14:06 -0700741
742 // Release the blob handle.
743 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700744 }
Chris Craik32054b02014-05-09 13:58:56 -0700745
sergeyvc36bd6c2016-10-11 15:49:16 -0700746 return createBitmap(env, nativeBitmap.release(),
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400747 getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100748#else
749 doThrowRE(env, "Cannot use parcels outside of Android");
750 return NULL;
751#endif
Chris Craik32054b02014-05-09 13:58:56 -0700752}
753
754static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
755 jlong bitmapHandle,
756 jboolean isMutable, jint density,
757 jobject parcel) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100758#ifdef __ANDROID__ // Layoutlib does not support parcel
Chris Craik32054b02014-05-09 13:58:56 -0700759 if (parcel == NULL) {
760 SkDebugf("------- writeToParcel null parcel\n");
761 return JNI_FALSE;
762 }
763
764 android::Parcel* p = android::parcelForJavaObject(env, parcel);
John Reckf29ed282015-04-07 07:32:03 -0700765 SkBitmap bitmap;
Riley Andrews39d7f302014-11-13 17:43:25 -0800766
sergeyvc1c54062016-10-19 18:47:26 -0700767 auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
768 bitmapWrapper->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700769
770 p->writeInt32(isMutable);
John Reckf29ed282015-04-07 07:32:03 -0700771 p->writeInt32(bitmap.colorType());
772 p->writeInt32(bitmap.alphaType());
Romain Guy5acc4762017-03-07 15:29:27 -0800773 SkColorSpace* colorSpace = bitmap.colorSpace();
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500774 if (colorSpace != nullptr) {
Romain Guy5acc4762017-03-07 15:29:27 -0800775 sk_sp<SkData> data = colorSpace->serialize();
776 size_t size = data->size();
777 p->writeUint32(size);
778 if (size > 0) {
Matt Sarett3ca39752017-05-26 10:55:38 -0400779 if (size > kMaxColorSpaceSerializedBytes) {
780 ALOGD("Bitmap_writeToParcel: Serialized SkColorSpace is larger than expected: "
781 "%zu bytes\n", size);
782 }
783
Romain Guy5acc4762017-03-07 15:29:27 -0800784 p->write(data->data(), size);
785 }
786 } else {
787 p->writeUint32(0);
788 }
John Reckf29ed282015-04-07 07:32:03 -0700789 p->writeInt32(bitmap.width());
790 p->writeInt32(bitmap.height());
791 p->writeInt32(bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -0700792 p->writeInt32(density);
793
Jeff Browna316c5d2015-06-05 15:14:06 -0700794 // Transfer the underlying ashmem region if we have one and it's immutable.
795 android::status_t status;
sergeyvaed7f582016-10-14 16:30:21 -0700796 int fd = bitmapWrapper->bitmap().getAshmemFd();
Jeff Browna316c5d2015-06-05 15:14:06 -0700797 if (fd >= 0 && !isMutable && p->allowFds()) {
798#if DEBUG_PARCEL
799 ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
800 "immutable blob (fds %s)",
801 p->allowFds() ? "allowed" : "forbidden");
802#endif
803
804 status = p->writeDupImmutableBlobFileDescriptor(fd);
805 if (status) {
806 doThrowRE(env, "Could not write bitmap blob file descriptor.");
Riley Andrews39d7f302014-11-13 17:43:25 -0800807 return JNI_FALSE;
808 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700809 return JNI_TRUE;
Riley Andrews39d7f302014-11-13 17:43:25 -0800810 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700811
812 // Copy the bitmap to a new blob.
813 bool mutableCopy = isMutable;
814#if DEBUG_PARCEL
815 ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
816 isMutable ? "mutable" : "immutable",
817 mutableCopy ? "mutable" : "immutable",
818 p->allowFds() ? "allowed" : "forbidden");
819#endif
820
Mike Reed7569de02017-10-06 16:25:49 -0400821 size_t size = bitmap.computeByteSize();
Jeff Browna316c5d2015-06-05 15:14:06 -0700822 android::Parcel::WritableBlob blob;
823 status = p->writeBlob(size, mutableCopy, &blob);
824 if (status) {
825 doThrowRE(env, "Could not copy bitmap to parcel blob.");
826 return JNI_FALSE;
827 }
828
Jeff Browna316c5d2015-06-05 15:14:06 -0700829 const void* pSrc = bitmap.getPixels();
830 if (pSrc == NULL) {
831 memset(blob.data(), 0, size);
832 } else {
833 memcpy(blob.data(), pSrc, size);
834 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700835
836 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700837 return JNI_TRUE;
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100838#else
839 doThrowRE(env, "Cannot use parcels outside of Android");
840 return JNI_FALSE;
841#endif
Chris Craik32054b02014-05-09 13:58:56 -0700842}
843
844static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
845 jlong srcHandle, jlong paintHandle,
846 jintArray offsetXY) {
John Reckf29ed282015-04-07 07:32:03 -0700847 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700848 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400849 const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700850 SkIPoint offset;
John Reckf29ed282015-04-07 07:32:03 -0700851 SkBitmap dst;
sergeyv45082182016-09-29 18:25:40 -0700852 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700853
John Reckf29ed282015-04-07 07:32:03 -0700854 src.extractAlpha(&dst, paint, &allocator, &offset);
Chris Craik32054b02014-05-09 13:58:56 -0700855 // If Skia can't allocate pixels for destination bitmap, it resets
856 // it, that is set its pixels buffer to NULL, and zero width and height.
John Reckf29ed282015-04-07 07:32:03 -0700857 if (dst.getPixels() == NULL && src.getPixels() != NULL) {
Chris Craik32054b02014-05-09 13:58:56 -0700858 doThrowOOME(env, "failed to allocate pixels for alpha");
859 return NULL;
860 }
861 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
862 int* array = env->GetIntArrayElements(offsetXY, NULL);
863 array[0] = offset.fX;
864 array[1] = offset.fY;
865 env->ReleaseIntArrayElements(offsetXY, array, 0);
866 }
867
sergeyvc69853c2016-10-07 14:14:09 -0700868 return createBitmap(env, allocator.getStorageObjAndReset(),
John Reckf29ed282015-04-07 07:32:03 -0700869 getPremulBitmapCreateFlags(true));
Chris Craik32054b02014-05-09 13:58:56 -0700870}
871
872///////////////////////////////////////////////////////////////////////////////
873
Romain Guyefb4b062017-02-27 11:00:04 -0800874static jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
875 LocalScopedBitmap bitmapHolder(bitmapHandle);
876 if (!bitmapHolder.valid()) return JNI_TRUE;
877
878 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
Brian Osman91c9c282018-08-17 16:57:15 -0400879 return colorSpace == nullptr || colorSpace->isSRGB();
Romain Guyefb4b062017-02-27 11:00:04 -0800880}
881
Leon Scroggins IIIce89a6e2018-03-13 15:39:39 -0400882static jboolean Bitmap_isSRGBLinear(JNIEnv* env, jobject, jlong bitmapHandle) {
883 LocalScopedBitmap bitmapHolder(bitmapHandle);
884 if (!bitmapHolder.valid()) return JNI_FALSE;
885
886 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
887 sk_sp<SkColorSpace> srgbLinear = SkColorSpace::MakeSRGBLinear();
888 return colorSpace == srgbLinear.get() ? JNI_TRUE : JNI_FALSE;
889}
890
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500891static jobject Bitmap_computeColorSpace(JNIEnv* env, jobject, jlong bitmapHandle) {
Romain Guyefb4b062017-02-27 11:00:04 -0800892 LocalScopedBitmap bitmapHolder(bitmapHandle);
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500893 if (!bitmapHolder.valid()) return nullptr;
Romain Guyefb4b062017-02-27 11:00:04 -0800894
895 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500896 if (colorSpace == nullptr) return nullptr;
Romain Guyefb4b062017-02-27 11:00:04 -0800897
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500898 return GraphicsJNI::getColorSpace(env, colorSpace, bitmapHolder->info().colorType());
Romain Guyefb4b062017-02-27 11:00:04 -0800899}
900
Derek Sollenberger202084c2019-01-14 13:55:08 -0500901static void Bitmap_setColorSpace(JNIEnv* env, jobject, jlong bitmapHandle, jlong colorSpacePtr) {
902 LocalScopedBitmap bitmapHolder(bitmapHandle);
903 sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
904 bitmapHolder->setColorSpace(cs);
905}
906
Romain Guyefb4b062017-02-27 11:00:04 -0800907///////////////////////////////////////////////////////////////////////////////
908
Chris Craik32054b02014-05-09 13:58:56 -0700909static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400910 jint x, jint y) {
John Reckf29ed282015-04-07 07:32:03 -0700911 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700912 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700913
Brian Osman91c9c282018-08-17 16:57:15 -0400914 auto sRGB = SkColorSpace::MakeSRGB();
915 SkImageInfo dstInfo = SkImageInfo::Make(
916 1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
Chris Craik32054b02014-05-09 13:58:56 -0700917
Brian Osman91c9c282018-08-17 16:57:15 -0400918 SkColor dst;
919 bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
920 return static_cast<jint>(dst);
Chris Craik32054b02014-05-09 13:58:56 -0700921}
922
Leon Scroggins III870053d2019-01-24 08:37:27 -0500923static jlong Bitmap_getColor(JNIEnv* env, jobject, jlong bitmapHandle,
924 jint x, jint y) {
925 SkBitmap bitmap;
926 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
927
928 SkImageInfo dstInfo = SkImageInfo::Make(
929 1, 1, kRGBA_F16_SkColorType, kUnpremul_SkAlphaType, bitmap.refColorSpace());
930
931 uint64_t dst;
932 bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
933 return static_cast<jlong>(dst);
934}
935
Chris Craik32054b02014-05-09 13:58:56 -0700936static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
937 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400938 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -0700939 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700940 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700941
Brian Osman91c9c282018-08-17 16:57:15 -0400942 auto sRGB = SkColorSpace::MakeSRGB();
943 SkImageInfo dstInfo = SkImageInfo::Make(
944 width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
Chris Craik32054b02014-05-09 13:58:56 -0700945
Chris Craik32054b02014-05-09 13:58:56 -0700946 jint* dst = env->GetIntArrayElements(pixelArray, NULL);
Brian Osman91c9c282018-08-17 16:57:15 -0400947 bitmap.readPixels(dstInfo, dst + offset, stride * 4, x, y);
Chris Craik32054b02014-05-09 13:58:56 -0700948 env->ReleaseIntArrayElements(pixelArray, dst, 0);
949}
950
951///////////////////////////////////////////////////////////////////////////////
952
953static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400954 jint x, jint y, jint colorHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700955 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700956 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700957 SkColor color = static_cast<SkColor>(colorHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700958
Brian Osman91c9c282018-08-17 16:57:15 -0400959 auto sRGB = SkColorSpace::MakeSRGB();
960 SkImageInfo srcInfo = SkImageInfo::Make(
961 1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
962 SkPixmap srcPM(srcInfo, &color, srcInfo.minRowBytes());
Chris Craik32054b02014-05-09 13:58:56 -0700963
Brian Osman91c9c282018-08-17 16:57:15 -0400964 bitmap.writePixels(srcPM, x, y);
Chris Craik32054b02014-05-09 13:58:56 -0700965}
966
967static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
968 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400969 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -0700970 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700971 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700972 GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
Brian Osman91c9c282018-08-17 16:57:15 -0400973 x, y, width, height, &bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700974}
975
976static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
977 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -0700978 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700979 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700980 const void* src = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -0700981
982 if (NULL != src) {
983 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
984
985 // the java side has already checked that buffer is large enough
Mike Reed7569de02017-10-06 16:25:49 -0400986 memcpy(abp.pointer(), src, bitmap.computeByteSize());
Chris Craik32054b02014-05-09 13:58:56 -0700987 }
988}
989
990static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
991 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -0700992 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700993 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700994 void* dst = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -0700995
996 if (NULL != dst) {
997 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
998 // the java side has already checked that buffer is large enough
Mike Reed7569de02017-10-06 16:25:49 -0400999 memcpy(dst, abp.pointer(), bitmap.computeByteSize());
John Reckf29ed282015-04-07 07:32:03 -07001000 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -07001001 }
1002}
1003
Chris Craik795bd0f2016-12-16 15:22:31 -08001004static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) {
John Reckf29ed282015-04-07 07:32:03 -07001005 SkBitmap bm0;
1006 SkBitmap bm1;
sergeyv1eabed32016-12-14 14:19:47 -08001007
1008 LocalScopedBitmap bitmap0(bm0Handle);
1009 LocalScopedBitmap bitmap1(bm1Handle);
1010
1011 // Paying the price for making Hardware Bitmap as Config:
1012 // later check for colorType will pass successfully,
1013 // because Hardware Config internally may be RGBA8888 or smth like that.
sergeyv15a10852016-12-27 14:32:03 -08001014 if (bitmap0->isHardware() != bitmap1->isHardware()) {
sergeyv1eabed32016-12-14 14:19:47 -08001015 return JNI_FALSE;
1016 }
1017
1018 bitmap0->bitmap().getSkBitmap(&bm0);
1019 bitmap1->bitmap().getSkBitmap(&bm1);
Chris Craik795bd0f2016-12-16 15:22:31 -08001020 if (bm0.width() != bm1.width()
1021 || bm0.height() != bm1.height()
1022 || bm0.colorType() != bm1.colorType()
1023 || bm0.alphaType() != bm1.alphaType()
1024 || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) {
Chris Craik32054b02014-05-09 13:58:56 -07001025 return JNI_FALSE;
1026 }
1027
Chris Craik32054b02014-05-09 13:58:56 -07001028 // if we can't load the pixels, return false
John Reckf29ed282015-04-07 07:32:03 -07001029 if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -07001030 return JNI_FALSE;
1031 }
1032
Chris Craik32054b02014-05-09 13:58:56 -07001033 // now compare each scanline. We can't do the entire buffer at once,
1034 // since we don't care about the pixel values that might extend beyond
1035 // the width (since the scanline might be larger than the logical width)
John Reckf29ed282015-04-07 07:32:03 -07001036 const int h = bm0.height();
1037 const size_t size = bm0.width() * bm0.bytesPerPixel();
Chris Craik32054b02014-05-09 13:58:56 -07001038 for (int y = 0; y < h; y++) {
henry.uh_chen53001ca2014-07-03 20:40:22 +08001039 // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
1040 // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
1041 // and bm1 both have pixel data() (have passed NULL == getPixels() check),
1042 // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
1043 // to warn user those 2 unrecognized config bitmaps may be different.
John Reckf29ed282015-04-07 07:32:03 -07001044 void *bm0Addr = bm0.getAddr(0, y);
1045 void *bm1Addr = bm1.getAddr(0, y);
henry.uh_chen53001ca2014-07-03 20:40:22 +08001046
1047 if(bm0Addr == NULL || bm1Addr == NULL) {
1048 return JNI_FALSE;
1049 }
1050
1051 if (memcmp(bm0Addr, bm1Addr, size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -07001052 return JNI_FALSE;
1053 }
1054 }
1055 return JNI_TRUE;
1056}
1057
John Reck43871902016-08-01 14:39:24 -07001058static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001059#ifdef __ANDROID__ // Layoutlib does not support render thread
John Reck43871902016-08-01 14:39:24 -07001060 LocalScopedBitmap bitmapHandle(bitmapPtr);
1061 if (!bitmapHandle.valid()) return;
sergeyvec4a4b12016-10-20 18:39:04 -07001062 android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001063#endif
John Reck43871902016-08-01 14:39:24 -07001064}
1065
sergeyv45082182016-09-29 18:25:40 -07001066static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1067 LocalScopedBitmap bitmapHandle(bitmapPtr);
1068 return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1069}
1070
sergeyv6e3658a2017-01-04 16:57:51 -08001071static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
sergeyv81f97ee2016-12-27 18:08:01 -08001072 LocalScopedBitmap bitmapHandle(bitmapPtr);
1073 LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1074 "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
1075 Bitmap& hwuiBitmap = bitmapHandle->bitmap();
1076 SkBitmap src;
1077 hwuiBitmap.getSkBitmap(&src);
1078
Derek Sollenbergere2169482018-11-20 10:57:20 -05001079 if (src.pixelRef() == nullptr) {
sergeyv81f97ee2016-12-27 18:08:01 -08001080 doThrowRE(env, "Could not copy a hardware bitmap.");
1081 return NULL;
1082 }
Derek Sollenbergere2169482018-11-20 10:57:20 -05001083
1084 sk_sp<Bitmap> bitmap = Bitmap::createFrom(src.info(), *src.pixelRef());
1085 return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
sergeyv81f97ee2016-12-27 18:08:01 -08001086}
1087
rennb2e9f522018-09-26 10:49:00 -07001088static jobject Bitmap_wrapHardwareBufferBitmap(JNIEnv* env, jobject, jobject hardwareBuffer,
Leon Scroggins III0e443d12018-12-19 11:38:35 -05001089 jlong colorSpacePtr) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001090#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
Derek Sollenbergere78f7c92019-07-31 15:18:47 -04001091 AHardwareBuffer* buffer = android_hardware_HardwareBuffer_getNativeHardwareBuffer(env,
rennb2e9f522018-09-26 10:49:00 -07001092 hardwareBuffer);
Derek Sollenbergere78f7c92019-07-31 15:18:47 -04001093 sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer,
1094 GraphicsJNI::getNativeColorSpace(colorSpacePtr));
rennb2e9f522018-09-26 10:49:00 -07001095 if (!bitmap.get()) {
1096 ALOGW("failed to create hardware bitmap from hardware buffer");
1097 return NULL;
1098 }
1099 return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001100#else
1101 return NULL;
1102#endif
rennb2e9f522018-09-26 10:49:00 -07001103}
1104
sergeyv6e3658a2017-01-04 16:57:51 -08001105static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001106#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
sergeyv6e3658a2017-01-04 16:57:51 -08001107 LocalScopedBitmap bitmapHandle(bitmapPtr);
1108 LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1109 "Hardware config is only supported config in Bitmap_getGraphicBuffer");
1110
Derek Sollenbergere78f7c92019-07-31 15:18:47 -04001111 Bitmap& bitmap = bitmapHandle->bitmap();
1112 return android_graphics_GraphicBuffer_createFromAHardwareBuffer(env, bitmap.hardwareBuffer());
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001113#else
1114 return NULL;
1115#endif
sergeyv6e3658a2017-01-04 16:57:51 -08001116}
1117
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001118static jboolean Bitmap_isImmutable(CRITICAL_JNI_PARAMS_COMMA jlong bitmapHandle) {
Nader Jawade7b51292018-04-12 17:55:31 -07001119 LocalScopedBitmap bitmapHolder(bitmapHandle);
1120 if (!bitmapHolder.valid()) return JNI_FALSE;
1121
1122 return bitmapHolder->bitmap().isImmutable() ? JNI_TRUE : JNI_FALSE;
1123}
1124
1125static void Bitmap_setImmutable(JNIEnv* env, jobject, jlong bitmapHandle) {
1126 LocalScopedBitmap bitmapHolder(bitmapHandle);
1127 if (!bitmapHolder.valid()) return;
1128
1129 return bitmapHolder->bitmap().setImmutable();
1130}
1131
Chris Craik32054b02014-05-09 13:58:56 -07001132///////////////////////////////////////////////////////////////////////////////
1133
Daniel Micay76f6a862015-09-19 17:31:01 -04001134static const JNINativeMethod gBitmapMethods[] = {
Leon Scroggins III0e443d12018-12-19 11:38:35 -05001135 { "nativeCreate", "([IIIIIIZJ)Landroid/graphics/Bitmap;",
Chris Craik32054b02014-05-09 13:58:56 -07001136 (void*)Bitmap_creator },
1137 { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
1138 (void*)Bitmap_copy },
Riley Andrews721ae5f2015-05-11 16:08:22 -07001139 { "nativeCopyAshmem", "(J)Landroid/graphics/Bitmap;",
1140 (void*)Bitmap_copyAshmem },
Winsona5fdde92016-04-14 15:27:15 -07001141 { "nativeCopyAshmemConfig", "(JI)Landroid/graphics/Bitmap;",
1142 (void*)Bitmap_copyAshmemConfig },
Richard Uhler775873a2015-12-29 12:37:39 -08001143 { "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
Leon Scroggins IIIf8adae12018-05-24 15:25:08 -04001144 { "nativeRecycle", "(J)V", (void*)Bitmap_recycle },
sergeyv45082182016-09-29 18:25:40 -07001145 { "nativeReconfigure", "(JIIIZ)V", (void*)Bitmap_reconfigure },
Chris Craik32054b02014-05-09 13:58:56 -07001146 { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
1147 (void*)Bitmap_compress },
1148 { "nativeErase", "(JI)V", (void*)Bitmap_erase },
Leon Scroggins III94ba1002019-01-17 13:34:51 -05001149 { "nativeErase", "(JJJ)V", (void*)Bitmap_eraseLong },
Chris Craik32054b02014-05-09 13:58:56 -07001150 { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
1151 { "nativeConfig", "(J)I", (void*)Bitmap_config },
1152 { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001153 { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},
1154 { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},
1155 { "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied},
Chris Craik32054b02014-05-09 13:58:56 -07001156 { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
1157 { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
1158 { "nativeCreateFromParcel",
1159 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1160 (void*)Bitmap_createFromParcel },
1161 { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",
1162 (void*)Bitmap_writeToParcel },
1163 { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
1164 (void*)Bitmap_extractAlpha },
1165 { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001166 { "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel },
Leon Scroggins III870053d2019-01-24 08:37:27 -05001167 { "nativeGetColor", "(JII)J", (void*)Bitmap_getColor },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001168 { "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1169 { "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel },
1170 { "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels },
Chris Craik32054b02014-05-09 13:58:56 -07001171 { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1172 (void*)Bitmap_copyPixelsToBuffer },
1173 { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1174 (void*)Bitmap_copyPixelsFromBuffer },
1175 { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
John Reck43871902016-08-01 14:39:24 -07001176 { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
sergeyv45082182016-09-29 18:25:40 -07001177 { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
sergeyv81f97ee2016-12-27 18:08:01 -08001178 { "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
sergeyv6e3658a2017-01-04 16:57:51 -08001179 (void*)Bitmap_copyPreserveInternalConfig },
Leon Scroggins III0e443d12018-12-19 11:38:35 -05001180 { "nativeWrapHardwareBufferBitmap", "(Landroid/hardware/HardwareBuffer;J)Landroid/graphics/Bitmap;",
rennb2e9f522018-09-26 10:49:00 -07001181 (void*) Bitmap_wrapHardwareBufferBitmap },
sergeyv6e3658a2017-01-04 16:57:51 -08001182 { "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
Romain Guyefb4b062017-02-27 11:00:04 -08001183 (void*) Bitmap_createGraphicBufferHandle },
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -05001184 { "nativeComputeColorSpace", "(J)Landroid/graphics/ColorSpace;", (void*)Bitmap_computeColorSpace },
Derek Sollenberger202084c2019-01-14 13:55:08 -05001185 { "nativeSetColorSpace", "(JJ)V", (void*)Bitmap_setColorSpace },
Romain Guyefb4b062017-02-27 11:00:04 -08001186 { "nativeIsSRGB", "(J)Z", (void*)Bitmap_isSRGB },
Leon Scroggins IIIce89a6e2018-03-13 15:39:39 -04001187 { "nativeIsSRGBLinear", "(J)Z", (void*)Bitmap_isSRGBLinear},
Nader Jawade7b51292018-04-12 17:55:31 -07001188 { "nativeSetImmutable", "(J)V", (void*)Bitmap_setImmutable},
1189
1190 // ------------ @CriticalNative ----------------
1191 { "nativeIsImmutable", "(J)Z", (void*)Bitmap_isImmutable}
1192
Chris Craik32054b02014-05-09 13:58:56 -07001193};
1194
Chris Craik32054b02014-05-09 13:58:56 -07001195int register_android_graphics_Bitmap(JNIEnv* env)
1196{
Romain Guy95648b82017-04-13 18:43:42 -07001197 gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap"));
1198 gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J");
Leon Scroggins IIIbbdb7312019-01-31 14:35:54 -05001199 gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
Romain Guy95648b82017-04-13 18:43:42 -07001200 gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001201 return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1202 NELEM(gBitmapMethods));
John Reck9192d5e2016-10-31 10:32:09 -07001203}