blob: ba669053ed63de0bc0d1af880f180930c2b35acf [file] [log] [blame]
Derek Sollenberger5368eda2019-10-25 11:20:03 -04001#undef LOG_TAG
John Reckf29ed282015-04-07 07:32:03 -07002#define LOG_TAG "Bitmap"
John Reckf29ed282015-04-07 07:32:03 -07003#include "Bitmap.h"
4
Chris Craik32054b02014-05-09 13:58:56 -07005#include "SkBitmap.h"
6#include "SkPixelRef.h"
7#include "SkImageEncoder.h"
Leon Scroggins III57ee6202014-06-04 18:51:07 -04008#include "SkImageInfo.h"
Romain Guy9505a652016-12-14 09:43:50 -08009#include "SkColor.h"
Romain Guyce217fa2017-03-08 15:58:06 -080010#include "SkColorSpace.h"
Chris Craik32054b02014-05-09 13:58:56 -070011#include "GraphicsJNI.h"
Chris Craik32054b02014-05-09 13:58:56 -070012#include "SkStream.h"
Leon Scroggins III94d294b2019-09-06 13:22:46 -040013#include "SkWebpEncoder.h"
Chris Craik32054b02014-05-09 13:58:56 -070014
Chris Craik32054b02014-05-09 13:58:56 -070015#include "android_nio_utils.h"
16#include "CreateJavaOutputStreamAdaptor.h"
sergeyvdccca442016-03-21 15:38:21 -070017#include <hwui/Paint.h>
sergeyvc1c54062016-10-19 18:47:26 -070018#include <hwui/Bitmap.h>
Derek Sollenberger6e35e632019-01-22 13:56:25 -050019#include <utils/Color.h>
Chris Craik32054b02014-05-09 13:58:56 -070020
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010021#ifdef __ANDROID__ // Layoutlib does not support graphic buffer, parcel or render thread
Derek Sollenberger42c50042020-02-18 14:51:17 -050022#include <private/android/AHardwareBufferHelpers.h>
Leon Scroggins III5a190b12020-02-18 13:52:18 -050023#include <binder/Parcel.h>
Leon Scroggins III898ce752020-02-18 12:22:17 -050024#include <dlfcn.h>
Leon Scroggins III5a190b12020-02-18 13:52:18 -050025#include <renderthread/RenderProxy.h>
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010026#endif
rennb2e9f522018-09-26 10:49:00 -070027
Romain Guyce217fa2017-03-08 15:58:06 -080028#include <string.h>
Riley Andrews39d7f302014-11-13 17:43:25 -080029#include <memory>
30#include <string>
Chris Craik32054b02014-05-09 13:58:56 -070031
Jeff Browna316c5d2015-06-05 15:14:06 -070032#define DEBUG_PARCEL 0
33
sergeyvc69853c2016-10-07 14:14:09 -070034static jclass gBitmap_class;
35static jfieldID gBitmap_nativePtr;
36static jmethodID gBitmap_constructorMethodID;
37static jmethodID gBitmap_reinitMethodID;
sergeyvc69853c2016-10-07 14:14:09 -070038
John Reckf29ed282015-04-07 07:32:03 -070039namespace android {
40
sergeyvc1c54062016-10-19 18:47:26 -070041class BitmapWrapper {
John Reckf29ed282015-04-07 07:32:03 -070042public:
Chih-Hung Hsieh0727be12018-12-20 13:43:46 -080043 explicit BitmapWrapper(Bitmap* bitmap)
sergeyvc1c54062016-10-19 18:47:26 -070044 : mBitmap(bitmap) { }
sergeyvc69853c2016-10-07 14:14:09 -070045
46 void freePixels() {
sergeyvc1c54062016-10-19 18:47:26 -070047 mInfo = mBitmap->info();
48 mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
49 mAllocationSize = mBitmap->getAllocationByteCount();
50 mRowBytes = mBitmap->rowBytes();
51 mGenerationId = mBitmap->getGenerationID();
sergeyv15a10852016-12-27 14:32:03 -080052 mIsHardware = mBitmap->isHardware();
sergeyvc1c54062016-10-19 18:47:26 -070053 mBitmap.reset();
John Reckf29ed282015-04-07 07:32:03 -070054 }
55
sergeyvc69853c2016-10-07 14:14:09 -070056 bool valid() {
Ben Wagner6b62ac02018-05-29 14:16:02 -040057 return mBitmap != nullptr;
John Reckf29ed282015-04-07 07:32:03 -070058 }
59
sergeyvaed7f582016-10-14 16:30:21 -070060 Bitmap& bitmap() {
61 assertValid();
62 return *mBitmap;
63 }
sergeyvc69853c2016-10-07 14:14:09 -070064
65 void assertValid() {
66 LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
67 }
68
69 void getSkBitmap(SkBitmap* outBitmap) {
70 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070071 mBitmap->getSkBitmap(outBitmap);
sergeyvc69853c2016-10-07 14:14:09 -070072 }
73
74 bool hasHardwareMipMap() {
sergeyvc1c54062016-10-19 18:47:26 -070075 if (mBitmap) {
76 return mBitmap->hasHardwareMipMap();
John Reckf29ed282015-04-07 07:32:03 -070077 }
John Reckf29ed282015-04-07 07:32:03 -070078 return mHasHardwareMipMap;
79 }
80
81 void setHasHardwareMipMap(bool hasMipMap) {
sergeyvc69853c2016-10-07 14:14:09 -070082 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070083 mBitmap->setHasHardwareMipMap(hasMipMap);
John Reckf29ed282015-04-07 07:32:03 -070084 }
85
sergeyvc69853c2016-10-07 14:14:09 -070086 void setAlphaType(SkAlphaType alphaType) {
87 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070088 mBitmap->setAlphaType(alphaType);
John Reckf29ed282015-04-07 07:32:03 -070089 }
90
Derek Sollenberger202084c2019-01-14 13:55:08 -050091 void setColorSpace(sk_sp<SkColorSpace> colorSpace) {
92 assertValid();
93 mBitmap->setColorSpace(colorSpace);
94 }
95
sergeyvc69853c2016-10-07 14:14:09 -070096 const SkImageInfo& info() {
sergeyvc1c54062016-10-19 18:47:26 -070097 if (mBitmap) {
98 return mBitmap->info();
sergeyvc69853c2016-10-07 14:14:09 -070099 }
100 return mInfo;
John Reckf29ed282015-04-07 07:32:03 -0700101 }
102
sergeyvc69853c2016-10-07 14:14:09 -0700103 size_t getAllocationByteCount() const {
sergeyvc1c54062016-10-19 18:47:26 -0700104 if (mBitmap) {
105 return mBitmap->getAllocationByteCount();
sergeyvc69853c2016-10-07 14:14:09 -0700106 }
107 return mAllocationSize;
John Reckf29ed282015-04-07 07:32:03 -0700108 }
109
sergeyvc69853c2016-10-07 14:14:09 -0700110 size_t rowBytes() const {
sergeyvc1c54062016-10-19 18:47:26 -0700111 if (mBitmap) {
112 return mBitmap->rowBytes();
sergeyvc69853c2016-10-07 14:14:09 -0700113 }
114 return mRowBytes;
115 }
116
117 uint32_t getGenerationID() const {
sergeyvc1c54062016-10-19 18:47:26 -0700118 if (mBitmap) {
119 return mBitmap->getGenerationID();
sergeyvc69853c2016-10-07 14:14:09 -0700120 }
121 return mGenerationId;
122 }
123
sergeyv15a10852016-12-27 14:32:03 -0800124 bool isHardware() {
125 if (mBitmap) {
126 return mBitmap->isHardware();
127 }
128 return mIsHardware;
129 }
130
sergeyvc1c54062016-10-19 18:47:26 -0700131 ~BitmapWrapper() { }
sergeyvc69853c2016-10-07 14:14:09 -0700132
John Reckf29ed282015-04-07 07:32:03 -0700133private:
sergeyvc1c54062016-10-19 18:47:26 -0700134 sk_sp<Bitmap> mBitmap;
sergeyvc69853c2016-10-07 14:14:09 -0700135 SkImageInfo mInfo;
136 bool mHasHardwareMipMap;
137 size_t mAllocationSize;
138 size_t mRowBytes;
139 uint32_t mGenerationId;
sergeyv15a10852016-12-27 14:32:03 -0800140 bool mIsHardware;
John Reckf29ed282015-04-07 07:32:03 -0700141};
142
John Reckf29ed282015-04-07 07:32:03 -0700143// Convenience class that does not take a global ref on the pixels, relying
144// on the caller already having a local JNI ref
145class LocalScopedBitmap {
146public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -0700147 explicit LocalScopedBitmap(jlong bitmapHandle)
sergeyvc1c54062016-10-19 18:47:26 -0700148 : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
John Reckf29ed282015-04-07 07:32:03 -0700149
sergeyvc1c54062016-10-19 18:47:26 -0700150 BitmapWrapper* operator->() {
151 return mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700152 }
153
154 void* pixels() {
sergeyvaed7f582016-10-14 16:30:21 -0700155 return mBitmapWrapper->bitmap().pixels();
John Reckf29ed282015-04-07 07:32:03 -0700156 }
157
158 bool valid() {
sergeyvc1c54062016-10-19 18:47:26 -0700159 return mBitmapWrapper && mBitmapWrapper->valid();
John Reckf29ed282015-04-07 07:32:03 -0700160 }
161
162private:
sergeyvc1c54062016-10-19 18:47:26 -0700163 BitmapWrapper* mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700164};
165
sergeyvc69853c2016-10-07 14:14:09 -0700166namespace bitmap {
167
168// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
169static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
170 // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
171 // irrelevant. This just tests to ensure that the SkAlphaType is not
172 // opposite of isPremultiplied.
173 if (isPremultiplied) {
174 SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
175 } else {
176 SkASSERT(info.alphaType() != kPremul_SkAlphaType);
177 }
178}
179
180void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
181 bool isPremultiplied)
182{
183 // The caller needs to have already set the alpha type properly, so the
184 // native SkBitmap stays in sync with the Java Bitmap.
185 assert_premultiplied(info, isPremultiplied);
186
187 env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
188 info.width(), info.height(), isPremultiplied);
189}
190
sergeyvc1c54062016-10-19 18:47:26 -0700191jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
sergeyvc69853c2016-10-07 14:14:09 -0700192 int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
193 int density) {
194 bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
195 bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
196 // The caller needs to have already set the alpha type properly, so the
197 // native SkBitmap stays in sync with the Java Bitmap.
sergeyvc1c54062016-10-19 18:47:26 -0700198 assert_premultiplied(bitmap->info(), isPremultiplied);
Leon Scroggins IIIbbdb7312019-01-31 14:35:54 -0500199 bool fromMalloc = bitmap->pixelStorageType() == PixelStorageType::Heap;
sergeyvc1c54062016-10-19 18:47:26 -0700200 BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
Nader Jawade7b51292018-04-12 17:55:31 -0700201 if (!isMutable) {
202 bitmapWrapper->bitmap().setImmutable();
203 }
sergeyvc69853c2016-10-07 14:14:09 -0700204 jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
sergeyvc1c54062016-10-19 18:47:26 -0700205 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
Leon Scroggins IIIbbdb7312019-01-31 14:35:54 -0500206 isPremultiplied, ninePatchChunk, ninePatchInsets, fromMalloc);
sergeyvc69853c2016-10-07 14:14:09 -0700207
208 if (env->ExceptionCheck() != 0) {
209 ALOGE("*** Uncaught exception returned from Java call!\n");
210 env->ExceptionDescribe();
211 }
212 return obj;
213}
214
215void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
216 LocalScopedBitmap bitmap(bitmapHandle);
217 bitmap->getSkBitmap(outBitmap);
218}
219
Leon Scroggins III71fae622019-03-26 16:28:41 -0400220Bitmap& toBitmap(jlong bitmapHandle) {
sergeyv5fd2a1c2016-10-20 15:04:28 -0700221 LocalScopedBitmap localBitmap(bitmapHandle);
222 return localBitmap->bitmap();
223}
224
sergeyvc69853c2016-10-07 14:14:09 -0700225} // namespace bitmap
226
227} // namespace android
228
229using namespace android;
230using namespace android::bitmap;
231
Derek Sollenberger6c41ab12019-11-08 08:50:58 -0500232Bitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
233 SkASSERT(env);
234 SkASSERT(bitmap);
235 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
236 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
237 LocalScopedBitmap localBitmap(bitmapHandle);
238 return localBitmap.valid() ? &localBitmap->bitmap() : nullptr;
239}
240
Leon Scroggins III84a2afc2020-01-19 19:27:16 -0500241SkImageInfo GraphicsJNI::getBitmapInfo(JNIEnv* env, jobject bitmap, uint32_t* outRowBytes,
242 bool* isHardware) {
Derek Sollenberger6c41ab12019-11-08 08:50:58 -0500243 SkASSERT(env);
244 SkASSERT(bitmap);
245 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
246 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
247 LocalScopedBitmap localBitmap(bitmapHandle);
248 if (outRowBytes) {
249 *outRowBytes = localBitmap->rowBytes();
250 }
Leon Scroggins III84a2afc2020-01-19 19:27:16 -0500251 if (isHardware) {
252 *isHardware = localBitmap->isHardware();
253 }
Derek Sollenberger6c41ab12019-11-08 08:50:58 -0500254 return localBitmap->info();
255}
256
Chris Craik32054b02014-05-09 13:58:56 -0700257bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
Brian Osman91c9c282018-08-17 16:57:15 -0400258 int x, int y, int width, int height, SkBitmap* dstBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700259 const jint* array = env->GetIntArrayElements(srcColors, NULL);
260 const SkColor* src = (const SkColor*)array + srcOffset;
261
Brian Osman91c9c282018-08-17 16:57:15 -0400262 auto sRGB = SkColorSpace::MakeSRGB();
263 SkImageInfo srcInfo = SkImageInfo::Make(
264 width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
265 SkPixmap srcPM(srcInfo, src, srcStride * 4);
Romain Guyce217fa2017-03-08 15:58:06 -0800266
Brian Osman91c9c282018-08-17 16:57:15 -0400267 dstBitmap->writePixels(srcPM, x, y);
Chris Craik32054b02014-05-09 13:58:56 -0700268
Romain Guy9505a652016-12-14 09:43:50 -0800269 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
Chris Craik32054b02014-05-09 13:58:56 -0700270 return true;
271}
272
Chris Craik32054b02014-05-09 13:58:56 -0700273///////////////////////////////////////////////////////////////////////////////
274///////////////////////////////////////////////////////////////////////////////
275
276static int getPremulBitmapCreateFlags(bool isMutable) {
sergeyvc69853c2016-10-07 14:14:09 -0700277 int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
278 if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
Chris Craik32054b02014-05-09 13:58:56 -0700279 return flags;
280}
281
282static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
283 jint offset, jint stride, jint width, jint height,
Romain Guy82426562017-04-04 19:38:50 -0700284 jint configHandle, jboolean isMutable,
Leon Scroggins III0e443d162018-12-19 11:38:35 -0500285 jlong colorSpacePtr) {
Mike Reed1103b322014-07-08 12:36:44 -0400286 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700287 if (NULL != jColors) {
288 size_t n = env->GetArrayLength(jColors);
289 if (n < SkAbs32(stride) * (size_t)height) {
290 doThrowAIOOBE(env);
291 return NULL;
292 }
293 }
294
295 // ARGB_4444 is a deprecated format, convert automatically to 8888
Mike Reedb9330552014-06-16 17:31:48 -0400296 if (colorType == kARGB_4444_SkColorType) {
297 colorType = kN32_SkColorType;
Chris Craik32054b02014-05-09 13:58:56 -0700298 }
299
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500300 sk_sp<SkColorSpace> colorSpace;
301 if (colorType == kAlpha_8_SkColorType) {
302 colorSpace = nullptr;
303 } else {
304 colorSpace = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
305 }
306
Chris Craik32054b02014-05-09 13:58:56 -0700307 SkBitmap bitmap;
Leon Scroggins III0e443d162018-12-19 11:38:35 -0500308 bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500309 colorSpace));
Chris Craik32054b02014-05-09 13:58:56 -0700310
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400311 sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700312 if (!nativeBitmap) {
Leon Scroggins IIIf3a02992017-10-03 14:00:20 -0400313 ALOGE("OOM allocating Bitmap with dimensions %i x %i", width, height);
314 doThrowOOME(env);
Chris Craik32054b02014-05-09 13:58:56 -0700315 return NULL;
316 }
317
318 if (jColors != NULL) {
Brian Osman91c9c282018-08-17 16:57:15 -0400319 GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, &bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700320 }
321
sergeyvc36bd6c2016-10-11 15:49:16 -0700322 return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700323}
324
Matt Sarett5320a722017-03-20 13:51:29 -0400325static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
326 SkBitmap::Allocator* alloc) {
Matt Sarette9834402017-04-25 13:49:42 -0400327 SkPixmap srcPM;
328 if (!src.peekPixels(&srcPM)) {
329 return false;
330 }
331
332 SkImageInfo dstInfo = srcPM.info().makeColorType(dstCT);
333 switch (dstCT) {
334 case kRGB_565_SkColorType:
Brian Osmanbaf13e82018-09-21 11:21:30 -0400335 dstInfo = dstInfo.makeAlphaType(kOpaque_SkAlphaType);
Matt Sarette9834402017-04-25 13:49:42 -0400336 break;
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500337 case kAlpha_8_SkColorType:
338 dstInfo = dstInfo.makeColorSpace(nullptr);
Matt Sarette9834402017-04-25 13:49:42 -0400339 break;
340 default:
341 break;
342 }
343
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500344 if (!dstInfo.colorSpace() && dstCT != kAlpha_8_SkColorType) {
345 dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGB());
346 }
347
Matt Sarette9834402017-04-25 13:49:42 -0400348 if (!dst->setInfo(dstInfo)) {
349 return false;
350 }
Mike Reed81397c42017-07-18 17:04:16 -0400351 if (!dst->tryAllocPixels(alloc)) {
Matt Sarette9834402017-04-25 13:49:42 -0400352 return false;
353 }
354
Matt Sarette9834402017-04-25 13:49:42 -0400355 SkPixmap dstPM;
356 if (!dst->peekPixels(&dstPM)) {
357 return false;
358 }
359
Matt Sarette9834402017-04-25 13:49:42 -0400360 return srcPM.readPixels(dstPM);
Matt Sarett5320a722017-03-20 13:51:29 -0400361}
362
Chris Craik32054b02014-05-09 13:58:56 -0700363static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
364 jint dstConfigHandle, jboolean isMutable) {
John Reckf29ed282015-04-07 07:32:03 -0700365 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700366 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
sergeyv05126d12016-12-15 19:50:15 -0800367 if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
368 sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
369 if (!bitmap.get()) {
370 return NULL;
371 }
sergeyv656117b2017-02-28 15:25:10 -0800372 return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
sergeyv05126d12016-12-15 19:50:15 -0800373 }
374
Mike Reed1103b322014-07-08 12:36:44 -0400375 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyv45082182016-09-29 18:25:40 -0700376 SkBitmap result;
377 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700378
Matt Sarett5320a722017-03-20 13:51:29 -0400379 if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
Chris Craik32054b02014-05-09 13:58:56 -0700380 return NULL;
381 }
sergeyvc1c54062016-10-19 18:47:26 -0700382 auto bitmap = allocator.getStorageObjAndReset();
383 return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700384}
385
sergeyvc1c54062016-10-19 18:47:26 -0700386static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700387 SkBitmap result;
388
389 AshmemPixelAllocator allocator(env);
Matt Sarett5320a722017-03-20 13:51:29 -0400390 if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700391 return NULL;
392 }
sergeyvc1c54062016-10-19 18:47:26 -0700393 auto bitmap = allocator.getStorageObjAndReset();
394 bitmap->setImmutable();
395 return bitmap;
Winsona5fdde92016-04-14 15:27:15 -0700396}
397
398static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
399 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700400 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700401 SkColorType dstCT = src.colorType();
sergeyvc1c54062016-10-19 18:47:26 -0700402 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
403 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Winsona5fdde92016-04-14 15:27:15 -0700404 return ret;
405}
406
407static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
408 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700409 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700410 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyvc1c54062016-10-19 18:47:26 -0700411 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
412 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Riley Andrews721ae5f2015-05-11 16:08:22 -0700413 return ret;
414}
415
sergeyvc1c54062016-10-19 18:47:26 -0700416static void Bitmap_destruct(BitmapWrapper* bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700417 delete bitmap;
Chris Craik32054b02014-05-09 13:58:56 -0700418}
419
Richard Uhler775873a2015-12-29 12:37:39 -0800420static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
421 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
422}
423
Leon Scroggins IIIf8adae12018-05-24 15:25:08 -0400424static void Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700425 LocalScopedBitmap bitmap(bitmapHandle);
426 bitmap->freePixels();
Chris Craik32054b02014-05-09 13:58:56 -0700427}
428
429static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
sergeyv45082182016-09-29 18:25:40 -0700430 jint width, jint height, jint configHandle, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700431 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700432 bitmap->assertValid();
Mike Reed1103b322014-07-08 12:36:44 -0400433 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400434
435 // ARGB_4444 is a deprecated format, convert automatically to 8888
436 if (colorType == kARGB_4444_SkColorType) {
437 colorType = kN32_SkColorType;
438 }
sergeyv45082182016-09-29 18:25:40 -0700439 size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
440 if (requestedSize > bitmap->getAllocationByteCount()) {
Chris Craik32054b02014-05-09 13:58:56 -0700441 // done in native as there's no way to get BytesPerPixel in Java
442 doThrowIAE(env, "Bitmap not large enough to support new configuration");
443 return;
444 }
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400445 SkAlphaType alphaType;
John Reckf29ed282015-04-07 07:32:03 -0700446 if (bitmap->info().colorType() != kRGB_565_SkColorType
447 && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400448 // If the original bitmap was set to opaque, keep that setting, unless it
449 // was 565, which is required to be opaque.
450 alphaType = kOpaque_SkAlphaType;
451 } else {
452 // Otherwise respect the premultiplied request.
453 alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
454 }
sergeyvaed7f582016-10-14 16:30:21 -0700455 bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
sergeyv7d5219f2016-11-03 16:18:16 -0700456 sk_ref_sp(bitmap->info().colorSpace())));
Chris Craik32054b02014-05-09 13:58:56 -0700457}
458
Chris Craik32054b02014-05-09 13:58:56 -0700459static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
460 jint format, jint quality,
461 jobject jstream, jbyteArray jstorage) {
Hal Canary10219fb2016-11-23 20:41:22 -0500462 LocalScopedBitmap bitmap(bitmapHandle);
John Reckf29ed282015-04-07 07:32:03 -0700463 if (!bitmap.valid()) {
464 return JNI_FALSE;
465 }
466
John Reckf29ed282015-04-07 07:32:03 -0700467 std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
468 if (!strm.get()) {
469 return JNI_FALSE;
470 }
Chris Craik32054b02014-05-09 13:58:56 -0700471
Leon Scroggins III9010e8b2019-08-20 11:27:17 -0400472 auto fm = static_cast<Bitmap::JavaCompressFormat>(format);
Leon Scroggins III949c6002020-01-23 16:20:39 -0500473 return bitmap->bitmap().compress(fm, quality, strm.get()) ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700474}
475
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500476static inline void bitmapErase(SkBitmap bitmap, const SkColor4f& color,
477 const sk_sp<SkColorSpace>& colorSpace) {
478 SkPaint p;
479 p.setColor4f(color, colorSpace.get());
480 p.setBlendMode(SkBlendMode::kSrc);
481 SkCanvas canvas(bitmap);
482 canvas.drawPaint(p);
483}
484
Chris Craik32054b02014-05-09 13:58:56 -0700485static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
John Reckf29ed282015-04-07 07:32:03 -0700486 LocalScopedBitmap bitmap(bitmapHandle);
487 SkBitmap skBitmap;
488 bitmap->getSkBitmap(&skBitmap);
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500489 bitmapErase(skBitmap, SkColor4f::FromColor(color), SkColorSpace::MakeSRGB());
490}
491
Leon Scroggins III94ba1002019-01-17 13:34:51 -0500492static void Bitmap_eraseLong(JNIEnv* env, jobject, jlong bitmapHandle,
493 jlong colorSpaceHandle, jlong colorLong) {
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500494 LocalScopedBitmap bitmap(bitmapHandle);
495 SkBitmap skBitmap;
496 bitmap->getSkBitmap(&skBitmap);
Leon Scroggins III0e443d162018-12-19 11:38:35 -0500497
Leon Scroggins III94ba1002019-01-17 13:34:51 -0500498 SkColor4f color = GraphicsJNI::convertColorLong(colorLong);
Leon Scroggins III0e443d162018-12-19 11:38:35 -0500499 sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500500 bitmapErase(skBitmap, color, cs);
Chris Craik32054b02014-05-09 13:58:56 -0700501}
502
503static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700504 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700505 return static_cast<jint>(bitmap->rowBytes());
506}
507
508static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700509 LocalScopedBitmap bitmap(bitmapHandle);
sergeyv15a10852016-12-27 14:32:03 -0800510 if (bitmap->isHardware()) {
sergeyv19b4b012016-12-13 16:06:00 -0800511 return GraphicsJNI::hardwareLegacyBitmapConfig();
512 }
John Reckf29ed282015-04-07 07:32:03 -0700513 return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
Chris Craik32054b02014-05-09 13:58:56 -0700514}
515
516static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700517 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700518 return static_cast<jint>(bitmap->getGenerationID());
Chris Craik32054b02014-05-09 13:58:56 -0700519}
520
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400521static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700522 LocalScopedBitmap bitmap(bitmapHandle);
523 if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400524 return JNI_TRUE;
525 }
526 return JNI_FALSE;
527}
528
Chris Craik32054b02014-05-09 13:58:56 -0700529static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700530 LocalScopedBitmap bitmap(bitmapHandle);
531 return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700532}
533
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400534static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
535 jboolean hasAlpha, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700536 LocalScopedBitmap bitmap(bitmapHandle);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400537 if (hasAlpha) {
John Reck0781a2f2015-05-27 16:29:17 -0700538 bitmap->setAlphaType(
John Reckf29ed282015-04-07 07:32:03 -0700539 requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
Chris Craik32054b02014-05-09 13:58:56 -0700540 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700541 bitmap->setAlphaType(kOpaque_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400542 }
543}
544
545static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
546 jboolean isPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700547 LocalScopedBitmap bitmap(bitmapHandle);
548 if (!bitmap->info().isOpaque()) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400549 if (isPremul) {
John Reck0781a2f2015-05-27 16:29:17 -0700550 bitmap->setAlphaType(kPremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400551 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700552 bitmap->setAlphaType(kUnpremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400553 }
Chris Craik32054b02014-05-09 13:58:56 -0700554 }
555}
556
557static jboolean Bitmap_hasMipMap(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 bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
560}
561
562static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
563 jboolean hasMipMap) {
John Reckf29ed282015-04-07 07:32:03 -0700564 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700565 bitmap->setHasHardwareMipMap(hasMipMap);
566}
567
568///////////////////////////////////////////////////////////////////////////////
569
Derek Sollenberger42c50042020-02-18 14:51:17 -0500570#ifdef __ANDROID__ // Layoutlib does not support parcel
571static struct parcel_offsets_t
572{
573 jclass clazz;
574 jfieldID mNativePtr;
575} gParcelOffsets;
576
577static Parcel* parcelForJavaObject(JNIEnv* env, jobject obj) {
578 if (obj) {
579 Parcel* p = (Parcel*)env->GetLongField(obj, gParcelOffsets.mNativePtr);
580 if (p != NULL) {
581 return p;
582 }
583 jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
584 }
585 return NULL;
586}
587#endif
588
Matt Sarett3ca39752017-05-26 10:55:38 -0400589// This is the maximum possible size because the SkColorSpace must be
590// representable (and therefore serializable) using a matrix and numerical
591// transfer function. If we allow more color space representations in the
592// framework, we may need to update this maximum size.
593static constexpr uint32_t kMaxColorSpaceSerializedBytes = 80;
594
Chris Craik32054b02014-05-09 13:58:56 -0700595static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100596#ifdef __ANDROID__ // Layoutlib does not support parcel
Chris Craik32054b02014-05-09 13:58:56 -0700597 if (parcel == NULL) {
598 SkDebugf("-------- unparcel parcel is NULL\n");
599 return NULL;
600 }
601
Derek Sollenberger42c50042020-02-18 14:51:17 -0500602 android::Parcel* p = parcelForJavaObject(env, parcel);
Chris Craik32054b02014-05-09 13:58:56 -0700603
Mike Reedb9330552014-06-16 17:31:48 -0400604 const SkColorType colorType = (SkColorType)p->readInt32();
605 const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
Romain Guy5acc4762017-03-07 15:29:27 -0800606 const uint32_t colorSpaceSize = p->readUint32();
607 sk_sp<SkColorSpace> colorSpace;
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500608 if (colorSpaceSize > 0) {
Matt Sarett3ca39752017-05-26 10:55:38 -0400609 if (colorSpaceSize > kMaxColorSpaceSerializedBytes) {
610 ALOGD("Bitmap_createFromParcel: Serialized SkColorSpace is larger than expected: "
611 "%d bytes\n", colorSpaceSize);
612 }
613
614 const void* data = p->readInplace(colorSpaceSize);
615 if (data) {
616 colorSpace = SkColorSpace::Deserialize(data, colorSpaceSize);
617 } else {
618 ALOGD("Bitmap_createFromParcel: Unable to read serialized SkColorSpace data\n");
619 }
Romain Guy5acc4762017-03-07 15:29:27 -0800620 }
Mike Reedb9330552014-06-16 17:31:48 -0400621 const int width = p->readInt32();
622 const int height = p->readInt32();
623 const int rowBytes = p->readInt32();
624 const int density = p->readInt32();
Chris Craik32054b02014-05-09 13:58:56 -0700625
Mike Reedb9330552014-06-16 17:31:48 -0400626 if (kN32_SkColorType != colorType &&
Romain Guy9505a652016-12-14 09:43:50 -0800627 kRGBA_F16_SkColorType != colorType &&
Mike Reedb9330552014-06-16 17:31:48 -0400628 kRGB_565_SkColorType != colorType &&
629 kARGB_4444_SkColorType != colorType &&
Mike Reedb9330552014-06-16 17:31:48 -0400630 kAlpha_8_SkColorType != colorType) {
631 SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
Chris Craik32054b02014-05-09 13:58:56 -0700632 return NULL;
633 }
634
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400635 std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
Romain Guy9505a652016-12-14 09:43:50 -0800636 if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
637 rowBytes)) {
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400638 return NULL;
639 }
Chris Craik32054b02014-05-09 13:58:56 -0700640
Jeff Browna316c5d2015-06-05 15:14:06 -0700641 // Read the bitmap blob.
Mike Reed7569de02017-10-06 16:25:49 -0400642 size_t size = bitmap->computeByteSize();
Jeff Browna316c5d2015-06-05 15:14:06 -0700643 android::Parcel::ReadableBlob blob;
644 android::status_t status = p->readBlob(size, &blob);
645 if (status) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700646 doThrowRE(env, "Could not read bitmap blob.");
Chris Craik32054b02014-05-09 13:58:56 -0700647 return NULL;
648 }
649
Jeff Browna316c5d2015-06-05 15:14:06 -0700650 // Map the bitmap in place from the ashmem region if possible otherwise copy.
sergeyvc1c54062016-10-19 18:47:26 -0700651 sk_sp<Bitmap> nativeBitmap;
John Reckefac0522020-01-24 16:04:26 -0800652 if (blob.fd() >= 0 && !blob.isMutable()) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700653#if DEBUG_PARCEL
John Reckefac0522020-01-24 16:04:26 -0800654 ALOGD("Bitmap.createFromParcel: mapped contents of bitmap from %s blob "
Jeff Browna316c5d2015-06-05 15:14:06 -0700655 "(fds %s)",
Jeff Browna316c5d2015-06-05 15:14:06 -0700656 blob.isMutable() ? "mutable" : "immutable",
657 p->allowFds() ? "allowed" : "forbidden");
658#endif
659 // Dup the file descriptor so we can keep a reference to it after the Parcel
660 // is disposed.
Nick Kralevich07f1c1d2019-01-14 13:42:22 -0800661 int dupFd = fcntl(blob.fd(), F_DUPFD_CLOEXEC, 0);
Jeff Browna316c5d2015-06-05 15:14:06 -0700662 if (dupFd < 0) {
Erik Wolsheimer211abad2015-11-13 11:54:47 -0800663 ALOGE("Error allocating dup fd. Error:%d", errno);
Jeff Browna316c5d2015-06-05 15:14:06 -0700664 blob.release();
Jeff Browna316c5d2015-06-05 15:14:06 -0700665 doThrowRE(env, "Could not allocate dup blob fd.");
666 return NULL;
667 }
668
Derek Sollenbergere2169482018-11-20 10:57:20 -0500669 // Map the pixels in place and take ownership of the ashmem region. We must also respect the
670 // rowBytes value already set on the bitmap instead of attempting to compute our own.
671 nativeBitmap = Bitmap::createFrom(bitmap->info(), bitmap->rowBytes(), dupFd,
John Reckefac0522020-01-24 16:04:26 -0800672 const_cast<void*>(blob.data()), size, true);
Jeff Browna316c5d2015-06-05 15:14:06 -0700673 if (!nativeBitmap) {
674 close(dupFd);
675 blob.release();
676 doThrowRE(env, "Could not allocate ashmem pixel ref.");
677 return NULL;
678 }
679
680 // Clear the blob handle, don't release it.
681 blob.clear();
682 } else {
683#if DEBUG_PARCEL
684 if (blob.fd() >= 0) {
685 ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
686 "from immutable blob (fds %s)",
687 p->allowFds() ? "allowed" : "forbidden");
688 } else {
689 ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
690 "(fds %s)",
691 blob.isMutable() ? "mutable" : "immutable",
692 p->allowFds() ? "allowed" : "forbidden");
693 }
694#endif
695
696 // Copy the pixels into a new buffer.
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400697 nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get());
Jeff Browna316c5d2015-06-05 15:14:06 -0700698 if (!nativeBitmap) {
699 blob.release();
700 doThrowRE(env, "Could not allocate java pixel ref.");
701 return NULL;
702 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700703 memcpy(bitmap->getPixels(), blob.data(), size);
Jeff Browna316c5d2015-06-05 15:14:06 -0700704
705 // Release the blob handle.
706 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700707 }
Chris Craik32054b02014-05-09 13:58:56 -0700708
sergeyvc36bd6c2016-10-11 15:49:16 -0700709 return createBitmap(env, nativeBitmap.release(),
John Reckefac0522020-01-24 16:04:26 -0800710 getPremulBitmapCreateFlags(false), NULL, NULL, density);
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100711#else
712 doThrowRE(env, "Cannot use parcels outside of Android");
713 return NULL;
714#endif
Chris Craik32054b02014-05-09 13:58:56 -0700715}
716
717static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
John Reckefac0522020-01-24 16:04:26 -0800718 jlong bitmapHandle, jint density, jobject parcel) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100719#ifdef __ANDROID__ // Layoutlib does not support parcel
Chris Craik32054b02014-05-09 13:58:56 -0700720 if (parcel == NULL) {
721 SkDebugf("------- writeToParcel null parcel\n");
722 return JNI_FALSE;
723 }
724
Derek Sollenberger42c50042020-02-18 14:51:17 -0500725 android::Parcel* p = parcelForJavaObject(env, parcel);
John Reckf29ed282015-04-07 07:32:03 -0700726 SkBitmap bitmap;
Riley Andrews39d7f302014-11-13 17:43:25 -0800727
sergeyvc1c54062016-10-19 18:47:26 -0700728 auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
729 bitmapWrapper->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700730
John Reckf29ed282015-04-07 07:32:03 -0700731 p->writeInt32(bitmap.colorType());
732 p->writeInt32(bitmap.alphaType());
Romain Guy5acc4762017-03-07 15:29:27 -0800733 SkColorSpace* colorSpace = bitmap.colorSpace();
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500734 if (colorSpace != nullptr) {
Romain Guy5acc4762017-03-07 15:29:27 -0800735 sk_sp<SkData> data = colorSpace->serialize();
736 size_t size = data->size();
737 p->writeUint32(size);
738 if (size > 0) {
Matt Sarett3ca39752017-05-26 10:55:38 -0400739 if (size > kMaxColorSpaceSerializedBytes) {
740 ALOGD("Bitmap_writeToParcel: Serialized SkColorSpace is larger than expected: "
741 "%zu bytes\n", size);
742 }
743
Romain Guy5acc4762017-03-07 15:29:27 -0800744 p->write(data->data(), size);
745 }
746 } else {
747 p->writeUint32(0);
748 }
John Reckf29ed282015-04-07 07:32:03 -0700749 p->writeInt32(bitmap.width());
750 p->writeInt32(bitmap.height());
751 p->writeInt32(bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -0700752 p->writeInt32(density);
753
Jeff Browna316c5d2015-06-05 15:14:06 -0700754 // Transfer the underlying ashmem region if we have one and it's immutable.
755 android::status_t status;
sergeyvaed7f582016-10-14 16:30:21 -0700756 int fd = bitmapWrapper->bitmap().getAshmemFd();
John Reckefac0522020-01-24 16:04:26 -0800757 if (fd >= 0 && p->allowFds()) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700758#if DEBUG_PARCEL
759 ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
760 "immutable blob (fds %s)",
761 p->allowFds() ? "allowed" : "forbidden");
762#endif
763
764 status = p->writeDupImmutableBlobFileDescriptor(fd);
765 if (status) {
766 doThrowRE(env, "Could not write bitmap blob file descriptor.");
Riley Andrews39d7f302014-11-13 17:43:25 -0800767 return JNI_FALSE;
768 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700769 return JNI_TRUE;
Riley Andrews39d7f302014-11-13 17:43:25 -0800770 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700771
772 // Copy the bitmap to a new blob.
Jeff Browna316c5d2015-06-05 15:14:06 -0700773#if DEBUG_PARCEL
John Reckefac0522020-01-24 16:04:26 -0800774 ALOGD("Bitmap.writeToParcel: copying bitmap into new blob (fds %s)",
Jeff Browna316c5d2015-06-05 15:14:06 -0700775 p->allowFds() ? "allowed" : "forbidden");
776#endif
777
Mike Reed7569de02017-10-06 16:25:49 -0400778 size_t size = bitmap.computeByteSize();
Jeff Browna316c5d2015-06-05 15:14:06 -0700779 android::Parcel::WritableBlob blob;
John Reckefac0522020-01-24 16:04:26 -0800780 status = p->writeBlob(size, false, &blob);
Jeff Browna316c5d2015-06-05 15:14:06 -0700781 if (status) {
782 doThrowRE(env, "Could not copy bitmap to parcel blob.");
783 return JNI_FALSE;
784 }
785
Jeff Browna316c5d2015-06-05 15:14:06 -0700786 const void* pSrc = bitmap.getPixels();
787 if (pSrc == NULL) {
788 memset(blob.data(), 0, size);
789 } else {
790 memcpy(blob.data(), pSrc, size);
791 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700792
793 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700794 return JNI_TRUE;
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100795#else
796 doThrowRE(env, "Cannot use parcels outside of Android");
797 return JNI_FALSE;
798#endif
Chris Craik32054b02014-05-09 13:58:56 -0700799}
800
801static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
802 jlong srcHandle, jlong paintHandle,
803 jintArray offsetXY) {
John Reckf29ed282015-04-07 07:32:03 -0700804 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700805 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400806 const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700807 SkIPoint offset;
John Reckf29ed282015-04-07 07:32:03 -0700808 SkBitmap dst;
sergeyv45082182016-09-29 18:25:40 -0700809 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700810
John Reckf29ed282015-04-07 07:32:03 -0700811 src.extractAlpha(&dst, paint, &allocator, &offset);
Chris Craik32054b02014-05-09 13:58:56 -0700812 // If Skia can't allocate pixels for destination bitmap, it resets
813 // it, that is set its pixels buffer to NULL, and zero width and height.
John Reckf29ed282015-04-07 07:32:03 -0700814 if (dst.getPixels() == NULL && src.getPixels() != NULL) {
Chris Craik32054b02014-05-09 13:58:56 -0700815 doThrowOOME(env, "failed to allocate pixels for alpha");
816 return NULL;
817 }
818 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
819 int* array = env->GetIntArrayElements(offsetXY, NULL);
820 array[0] = offset.fX;
821 array[1] = offset.fY;
822 env->ReleaseIntArrayElements(offsetXY, array, 0);
823 }
824
sergeyvc69853c2016-10-07 14:14:09 -0700825 return createBitmap(env, allocator.getStorageObjAndReset(),
John Reckf29ed282015-04-07 07:32:03 -0700826 getPremulBitmapCreateFlags(true));
Chris Craik32054b02014-05-09 13:58:56 -0700827}
828
829///////////////////////////////////////////////////////////////////////////////
830
Romain Guyefb4b062017-02-27 11:00:04 -0800831static jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
832 LocalScopedBitmap bitmapHolder(bitmapHandle);
833 if (!bitmapHolder.valid()) return JNI_TRUE;
834
835 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
Brian Osman91c9c282018-08-17 16:57:15 -0400836 return colorSpace == nullptr || colorSpace->isSRGB();
Romain Guyefb4b062017-02-27 11:00:04 -0800837}
838
Leon Scroggins IIIce89a6e2018-03-13 15:39:39 -0400839static jboolean Bitmap_isSRGBLinear(JNIEnv* env, jobject, jlong bitmapHandle) {
840 LocalScopedBitmap bitmapHolder(bitmapHandle);
841 if (!bitmapHolder.valid()) return JNI_FALSE;
842
843 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
844 sk_sp<SkColorSpace> srgbLinear = SkColorSpace::MakeSRGBLinear();
845 return colorSpace == srgbLinear.get() ? JNI_TRUE : JNI_FALSE;
846}
847
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500848static jobject Bitmap_computeColorSpace(JNIEnv* env, jobject, jlong bitmapHandle) {
Romain Guyefb4b062017-02-27 11:00:04 -0800849 LocalScopedBitmap bitmapHolder(bitmapHandle);
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500850 if (!bitmapHolder.valid()) return nullptr;
Romain Guyefb4b062017-02-27 11:00:04 -0800851
852 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500853 if (colorSpace == nullptr) return nullptr;
Romain Guyefb4b062017-02-27 11:00:04 -0800854
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500855 return GraphicsJNI::getColorSpace(env, colorSpace, bitmapHolder->info().colorType());
Romain Guyefb4b062017-02-27 11:00:04 -0800856}
857
Derek Sollenberger202084c2019-01-14 13:55:08 -0500858static void Bitmap_setColorSpace(JNIEnv* env, jobject, jlong bitmapHandle, jlong colorSpacePtr) {
859 LocalScopedBitmap bitmapHolder(bitmapHandle);
860 sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
861 bitmapHolder->setColorSpace(cs);
862}
863
Romain Guyefb4b062017-02-27 11:00:04 -0800864///////////////////////////////////////////////////////////////////////////////
865
Chris Craik32054b02014-05-09 13:58:56 -0700866static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400867 jint x, jint y) {
John Reckf29ed282015-04-07 07:32:03 -0700868 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700869 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700870
Brian Osman91c9c282018-08-17 16:57:15 -0400871 auto sRGB = SkColorSpace::MakeSRGB();
872 SkImageInfo dstInfo = SkImageInfo::Make(
873 1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
Chris Craik32054b02014-05-09 13:58:56 -0700874
Brian Osman91c9c282018-08-17 16:57:15 -0400875 SkColor dst;
876 bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
877 return static_cast<jint>(dst);
Chris Craik32054b02014-05-09 13:58:56 -0700878}
879
Leon Scroggins III870053d2019-01-24 08:37:27 -0500880static jlong Bitmap_getColor(JNIEnv* env, jobject, jlong bitmapHandle,
881 jint x, jint y) {
882 SkBitmap bitmap;
883 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
884
885 SkImageInfo dstInfo = SkImageInfo::Make(
886 1, 1, kRGBA_F16_SkColorType, kUnpremul_SkAlphaType, bitmap.refColorSpace());
887
888 uint64_t dst;
889 bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
890 return static_cast<jlong>(dst);
891}
892
Chris Craik32054b02014-05-09 13:58:56 -0700893static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
894 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400895 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -0700896 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700897 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700898
Brian Osman91c9c282018-08-17 16:57:15 -0400899 auto sRGB = SkColorSpace::MakeSRGB();
900 SkImageInfo dstInfo = SkImageInfo::Make(
901 width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
Chris Craik32054b02014-05-09 13:58:56 -0700902
Chris Craik32054b02014-05-09 13:58:56 -0700903 jint* dst = env->GetIntArrayElements(pixelArray, NULL);
Brian Osman91c9c282018-08-17 16:57:15 -0400904 bitmap.readPixels(dstInfo, dst + offset, stride * 4, x, y);
Chris Craik32054b02014-05-09 13:58:56 -0700905 env->ReleaseIntArrayElements(pixelArray, dst, 0);
906}
907
908///////////////////////////////////////////////////////////////////////////////
909
910static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400911 jint x, jint y, jint colorHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700912 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700913 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700914 SkColor color = static_cast<SkColor>(colorHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700915
Brian Osman91c9c282018-08-17 16:57:15 -0400916 auto sRGB = SkColorSpace::MakeSRGB();
917 SkImageInfo srcInfo = SkImageInfo::Make(
918 1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
919 SkPixmap srcPM(srcInfo, &color, srcInfo.minRowBytes());
Chris Craik32054b02014-05-09 13:58:56 -0700920
Brian Osman91c9c282018-08-17 16:57:15 -0400921 bitmap.writePixels(srcPM, x, y);
Chris Craik32054b02014-05-09 13:58:56 -0700922}
923
924static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
925 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400926 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -0700927 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700928 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700929 GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
Brian Osman91c9c282018-08-17 16:57:15 -0400930 x, y, width, height, &bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700931}
932
933static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
934 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -0700935 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700936 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700937 const void* src = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -0700938
939 if (NULL != src) {
940 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
941
942 // the java side has already checked that buffer is large enough
Mike Reed7569de02017-10-06 16:25:49 -0400943 memcpy(abp.pointer(), src, bitmap.computeByteSize());
Chris Craik32054b02014-05-09 13:58:56 -0700944 }
945}
946
947static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
948 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -0700949 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700950 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700951 void* dst = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -0700952
953 if (NULL != dst) {
954 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
955 // the java side has already checked that buffer is large enough
Mike Reed7569de02017-10-06 16:25:49 -0400956 memcpy(dst, abp.pointer(), bitmap.computeByteSize());
John Reckf29ed282015-04-07 07:32:03 -0700957 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -0700958 }
959}
960
Chris Craik795bd0f2016-12-16 15:22:31 -0800961static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) {
John Reckf29ed282015-04-07 07:32:03 -0700962 SkBitmap bm0;
963 SkBitmap bm1;
sergeyv1eabed32016-12-14 14:19:47 -0800964
965 LocalScopedBitmap bitmap0(bm0Handle);
966 LocalScopedBitmap bitmap1(bm1Handle);
967
968 // Paying the price for making Hardware Bitmap as Config:
969 // later check for colorType will pass successfully,
970 // because Hardware Config internally may be RGBA8888 or smth like that.
sergeyv15a10852016-12-27 14:32:03 -0800971 if (bitmap0->isHardware() != bitmap1->isHardware()) {
sergeyv1eabed32016-12-14 14:19:47 -0800972 return JNI_FALSE;
973 }
974
975 bitmap0->bitmap().getSkBitmap(&bm0);
976 bitmap1->bitmap().getSkBitmap(&bm1);
Chris Craik795bd0f2016-12-16 15:22:31 -0800977 if (bm0.width() != bm1.width()
978 || bm0.height() != bm1.height()
979 || bm0.colorType() != bm1.colorType()
980 || bm0.alphaType() != bm1.alphaType()
981 || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) {
Chris Craik32054b02014-05-09 13:58:56 -0700982 return JNI_FALSE;
983 }
984
Chris Craik32054b02014-05-09 13:58:56 -0700985 // if we can't load the pixels, return false
John Reckf29ed282015-04-07 07:32:03 -0700986 if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -0700987 return JNI_FALSE;
988 }
989
Chris Craik32054b02014-05-09 13:58:56 -0700990 // now compare each scanline. We can't do the entire buffer at once,
991 // since we don't care about the pixel values that might extend beyond
992 // the width (since the scanline might be larger than the logical width)
John Reckf29ed282015-04-07 07:32:03 -0700993 const int h = bm0.height();
994 const size_t size = bm0.width() * bm0.bytesPerPixel();
Chris Craik32054b02014-05-09 13:58:56 -0700995 for (int y = 0; y < h; y++) {
henry.uh_chen53001ca2014-07-03 20:40:22 +0800996 // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
997 // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
998 // and bm1 both have pixel data() (have passed NULL == getPixels() check),
999 // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
1000 // to warn user those 2 unrecognized config bitmaps may be different.
John Reckf29ed282015-04-07 07:32:03 -07001001 void *bm0Addr = bm0.getAddr(0, y);
1002 void *bm1Addr = bm1.getAddr(0, y);
henry.uh_chen53001ca2014-07-03 20:40:22 +08001003
1004 if(bm0Addr == NULL || bm1Addr == NULL) {
1005 return JNI_FALSE;
1006 }
1007
1008 if (memcmp(bm0Addr, bm1Addr, size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -07001009 return JNI_FALSE;
1010 }
1011 }
1012 return JNI_TRUE;
1013}
1014
John Reck43871902016-08-01 14:39:24 -07001015static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001016#ifdef __ANDROID__ // Layoutlib does not support render thread
John Reck43871902016-08-01 14:39:24 -07001017 LocalScopedBitmap bitmapHandle(bitmapPtr);
1018 if (!bitmapHandle.valid()) return;
sergeyvec4a4b12016-10-20 18:39:04 -07001019 android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001020#endif
John Reck43871902016-08-01 14:39:24 -07001021}
1022
sergeyv45082182016-09-29 18:25:40 -07001023static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1024 LocalScopedBitmap bitmapHandle(bitmapPtr);
1025 return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1026}
1027
sergeyv6e3658a2017-01-04 16:57:51 -08001028static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
sergeyv81f97ee2016-12-27 18:08:01 -08001029 LocalScopedBitmap bitmapHandle(bitmapPtr);
1030 LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1031 "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
1032 Bitmap& hwuiBitmap = bitmapHandle->bitmap();
1033 SkBitmap src;
1034 hwuiBitmap.getSkBitmap(&src);
1035
Derek Sollenbergere2169482018-11-20 10:57:20 -05001036 if (src.pixelRef() == nullptr) {
sergeyv81f97ee2016-12-27 18:08:01 -08001037 doThrowRE(env, "Could not copy a hardware bitmap.");
1038 return NULL;
1039 }
Derek Sollenbergere2169482018-11-20 10:57:20 -05001040
1041 sk_sp<Bitmap> bitmap = Bitmap::createFrom(src.info(), *src.pixelRef());
1042 return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
sergeyv81f97ee2016-12-27 18:08:01 -08001043}
1044
Leon Scroggins III898ce752020-02-18 12:22:17 -05001045#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
1046typedef AHardwareBuffer* (*AHB_from_HB)(JNIEnv*, jobject);
1047AHB_from_HB AHardwareBuffer_fromHardwareBuffer;
Leon Scroggins III5a190b12020-02-18 13:52:18 -05001048
1049typedef jobject (*AHB_to_HB)(JNIEnv*, AHardwareBuffer*);
1050AHB_to_HB AHardwareBuffer_toHardwareBuffer;
Leon Scroggins III898ce752020-02-18 12:22:17 -05001051#endif
1052
rennb2e9f522018-09-26 10:49:00 -07001053static jobject Bitmap_wrapHardwareBufferBitmap(JNIEnv* env, jobject, jobject hardwareBuffer,
Leon Scroggins III0e443d162018-12-19 11:38:35 -05001054 jlong colorSpacePtr) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001055#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
Leon Scroggins III898ce752020-02-18 12:22:17 -05001056 AHardwareBuffer* buffer = AHardwareBuffer_fromHardwareBuffer(env, hardwareBuffer);
Derek Sollenbergere78f7c92019-07-31 15:18:47 -04001057 sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer,
1058 GraphicsJNI::getNativeColorSpace(colorSpacePtr));
rennb2e9f522018-09-26 10:49:00 -07001059 if (!bitmap.get()) {
1060 ALOGW("failed to create hardware bitmap from hardware buffer");
1061 return NULL;
1062 }
1063 return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001064#else
1065 return NULL;
1066#endif
rennb2e9f522018-09-26 10:49:00 -07001067}
1068
Leon Scroggins III5a190b12020-02-18 13:52:18 -05001069static jobject Bitmap_getHardwareBuffer(JNIEnv* env, jobject, jlong bitmapPtr) {
1070#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
1071 LocalScopedBitmap bitmapHandle(bitmapPtr);
1072 LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1073 "Hardware config is only supported config in Bitmap_getHardwareBuffer");
1074
1075 Bitmap& bitmap = bitmapHandle->bitmap();
1076 return AHardwareBuffer_toHardwareBuffer(env, bitmap.hardwareBuffer());
1077#else
1078 return NULL;
1079#endif
1080}
1081
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001082static jboolean Bitmap_isImmutable(CRITICAL_JNI_PARAMS_COMMA jlong bitmapHandle) {
Nader Jawade7b51292018-04-12 17:55:31 -07001083 LocalScopedBitmap bitmapHolder(bitmapHandle);
1084 if (!bitmapHolder.valid()) return JNI_FALSE;
1085
1086 return bitmapHolder->bitmap().isImmutable() ? JNI_TRUE : JNI_FALSE;
1087}
1088
1089static void Bitmap_setImmutable(JNIEnv* env, jobject, jlong bitmapHandle) {
1090 LocalScopedBitmap bitmapHolder(bitmapHandle);
1091 if (!bitmapHolder.valid()) return;
1092
1093 return bitmapHolder->bitmap().setImmutable();
1094}
1095
Chris Craik32054b02014-05-09 13:58:56 -07001096///////////////////////////////////////////////////////////////////////////////
1097
Daniel Micay76f6a862015-09-19 17:31:01 -04001098static const JNINativeMethod gBitmapMethods[] = {
Leon Scroggins III0e443d162018-12-19 11:38:35 -05001099 { "nativeCreate", "([IIIIIIZJ)Landroid/graphics/Bitmap;",
Chris Craik32054b02014-05-09 13:58:56 -07001100 (void*)Bitmap_creator },
1101 { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
1102 (void*)Bitmap_copy },
Riley Andrews721ae5f2015-05-11 16:08:22 -07001103 { "nativeCopyAshmem", "(J)Landroid/graphics/Bitmap;",
1104 (void*)Bitmap_copyAshmem },
Winsona5fdde92016-04-14 15:27:15 -07001105 { "nativeCopyAshmemConfig", "(JI)Landroid/graphics/Bitmap;",
1106 (void*)Bitmap_copyAshmemConfig },
Richard Uhler775873a2015-12-29 12:37:39 -08001107 { "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
Leon Scroggins IIIf8adae12018-05-24 15:25:08 -04001108 { "nativeRecycle", "(J)V", (void*)Bitmap_recycle },
sergeyv45082182016-09-29 18:25:40 -07001109 { "nativeReconfigure", "(JIIIZ)V", (void*)Bitmap_reconfigure },
Chris Craik32054b02014-05-09 13:58:56 -07001110 { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
1111 (void*)Bitmap_compress },
1112 { "nativeErase", "(JI)V", (void*)Bitmap_erase },
Leon Scroggins III94ba1002019-01-17 13:34:51 -05001113 { "nativeErase", "(JJJ)V", (void*)Bitmap_eraseLong },
Chris Craik32054b02014-05-09 13:58:56 -07001114 { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
1115 { "nativeConfig", "(J)I", (void*)Bitmap_config },
1116 { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001117 { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},
1118 { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},
1119 { "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied},
Chris Craik32054b02014-05-09 13:58:56 -07001120 { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
1121 { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
1122 { "nativeCreateFromParcel",
1123 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1124 (void*)Bitmap_createFromParcel },
John Reckefac0522020-01-24 16:04:26 -08001125 { "nativeWriteToParcel", "(JILandroid/os/Parcel;)Z",
Chris Craik32054b02014-05-09 13:58:56 -07001126 (void*)Bitmap_writeToParcel },
1127 { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
1128 (void*)Bitmap_extractAlpha },
1129 { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001130 { "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel },
Leon Scroggins III870053d2019-01-24 08:37:27 -05001131 { "nativeGetColor", "(JII)J", (void*)Bitmap_getColor },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001132 { "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1133 { "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel },
1134 { "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels },
Chris Craik32054b02014-05-09 13:58:56 -07001135 { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1136 (void*)Bitmap_copyPixelsToBuffer },
1137 { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1138 (void*)Bitmap_copyPixelsFromBuffer },
1139 { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
John Reck43871902016-08-01 14:39:24 -07001140 { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
sergeyv45082182016-09-29 18:25:40 -07001141 { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
sergeyv81f97ee2016-12-27 18:08:01 -08001142 { "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
sergeyv6e3658a2017-01-04 16:57:51 -08001143 (void*)Bitmap_copyPreserveInternalConfig },
Leon Scroggins III0e443d162018-12-19 11:38:35 -05001144 { "nativeWrapHardwareBufferBitmap", "(Landroid/hardware/HardwareBuffer;J)Landroid/graphics/Bitmap;",
rennb2e9f522018-09-26 10:49:00 -07001145 (void*) Bitmap_wrapHardwareBufferBitmap },
Leon Scroggins III5a190b12020-02-18 13:52:18 -05001146 { "nativeGetHardwareBuffer", "(J)Landroid/hardware/HardwareBuffer;",
1147 (void*) Bitmap_getHardwareBuffer },
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -05001148 { "nativeComputeColorSpace", "(J)Landroid/graphics/ColorSpace;", (void*)Bitmap_computeColorSpace },
Derek Sollenberger202084c2019-01-14 13:55:08 -05001149 { "nativeSetColorSpace", "(JJ)V", (void*)Bitmap_setColorSpace },
Romain Guyefb4b062017-02-27 11:00:04 -08001150 { "nativeIsSRGB", "(J)Z", (void*)Bitmap_isSRGB },
Leon Scroggins IIIce89a6e2018-03-13 15:39:39 -04001151 { "nativeIsSRGBLinear", "(J)Z", (void*)Bitmap_isSRGBLinear},
Nader Jawade7b51292018-04-12 17:55:31 -07001152 { "nativeSetImmutable", "(J)V", (void*)Bitmap_setImmutable},
1153
1154 // ------------ @CriticalNative ----------------
1155 { "nativeIsImmutable", "(J)Z", (void*)Bitmap_isImmutable}
1156
Chris Craik32054b02014-05-09 13:58:56 -07001157};
1158
Derek Sollenberger42c50042020-02-18 14:51:17 -05001159const char* const kParcelPathName = "android/os/Parcel";
1160
Chris Craik32054b02014-05-09 13:58:56 -07001161int register_android_graphics_Bitmap(JNIEnv* env)
1162{
Romain Guy95648b82017-04-13 18:43:42 -07001163 gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap"));
1164 gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J");
Leon Scroggins IIIbbdb7312019-01-31 14:35:54 -05001165 gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
Romain Guy95648b82017-04-13 18:43:42 -07001166 gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V");
Leon Scroggins III898ce752020-02-18 12:22:17 -05001167
Derek Sollenberger42c50042020-02-18 14:51:17 -05001168#ifdef __ANDROID__ // Layoutlib does not support graphic buffer or parcel
Leon Scroggins III898ce752020-02-18 12:22:17 -05001169 void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
1170 AHardwareBuffer_fromHardwareBuffer =
1171 (AHB_from_HB)dlsym(handle_, "AHardwareBuffer_fromHardwareBuffer");
1172 LOG_ALWAYS_FATAL_IF(AHardwareBuffer_fromHardwareBuffer == nullptr,
1173 "Failed to find required symbol AHardwareBuffer_fromHardwareBuffer!");
Leon Scroggins III5a190b12020-02-18 13:52:18 -05001174
1175 AHardwareBuffer_toHardwareBuffer = (AHB_to_HB)dlsym(handle_, "AHardwareBuffer_toHardwareBuffer");
1176 LOG_ALWAYS_FATAL_IF(AHardwareBuffer_toHardwareBuffer == nullptr,
1177 " Failed to find required symbol AHardwareBuffer_toHardwareBuffer!");
Derek Sollenberger42c50042020-02-18 14:51:17 -05001178
1179 gParcelOffsets.clazz = MakeGlobalRefOrDie(env, FindClassOrDie(env, kParcelPathName));
1180 gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, gParcelOffsets.clazz, "mNativePtr", "J");
Leon Scroggins III898ce752020-02-18 12:22:17 -05001181#endif
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001182 return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1183 NELEM(gBitmapMethods));
John Reck9192d5e2016-10-31 10:32:09 -07001184}