blob: 9981e89ab561684f8e5eba52c46bfb6d7cdc23a5 [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_os_Parcel.h"
Chris Craik32054b02014-05-09 13:58:56 -070016#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
Derek Sollenbergere78f7c92019-07-31 15:18:47 -040023#include <android_runtime/android_graphics_GraphicBuffer.h>
Leon Scroggins III5a190b12020-02-18 13:52:18 -050024#include <binder/Parcel.h>
Leon Scroggins III898ce752020-02-18 12:22:17 -050025#include <dlfcn.h>
Leon Scroggins III5a190b12020-02-18 13:52:18 -050026#include <renderthread/RenderProxy.h>
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010027#endif
rennb2e9f522018-09-26 10:49:00 -070028
Romain Guyce217fa2017-03-08 15:58:06 -080029#include <string.h>
Riley Andrews39d7f302014-11-13 17:43:25 -080030#include <memory>
31#include <string>
Chris Craik32054b02014-05-09 13:58:56 -070032
Jeff Browna316c5d2015-06-05 15:14:06 -070033#define DEBUG_PARCEL 0
34
sergeyvc69853c2016-10-07 14:14:09 -070035static jclass gBitmap_class;
36static jfieldID gBitmap_nativePtr;
37static jmethodID gBitmap_constructorMethodID;
38static jmethodID gBitmap_reinitMethodID;
sergeyvc69853c2016-10-07 14:14:09 -070039
John Reckf29ed282015-04-07 07:32:03 -070040namespace android {
41
sergeyvc1c54062016-10-19 18:47:26 -070042class BitmapWrapper {
John Reckf29ed282015-04-07 07:32:03 -070043public:
Chih-Hung Hsieh0727be12018-12-20 13:43:46 -080044 explicit BitmapWrapper(Bitmap* bitmap)
sergeyvc1c54062016-10-19 18:47:26 -070045 : mBitmap(bitmap) { }
sergeyvc69853c2016-10-07 14:14:09 -070046
47 void freePixels() {
sergeyvc1c54062016-10-19 18:47:26 -070048 mInfo = mBitmap->info();
49 mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
50 mAllocationSize = mBitmap->getAllocationByteCount();
51 mRowBytes = mBitmap->rowBytes();
52 mGenerationId = mBitmap->getGenerationID();
sergeyv15a10852016-12-27 14:32:03 -080053 mIsHardware = mBitmap->isHardware();
sergeyvc1c54062016-10-19 18:47:26 -070054 mBitmap.reset();
John Reckf29ed282015-04-07 07:32:03 -070055 }
56
sergeyvc69853c2016-10-07 14:14:09 -070057 bool valid() {
Ben Wagner6b62ac02018-05-29 14:16:02 -040058 return mBitmap != nullptr;
John Reckf29ed282015-04-07 07:32:03 -070059 }
60
sergeyvaed7f582016-10-14 16:30:21 -070061 Bitmap& bitmap() {
62 assertValid();
63 return *mBitmap;
64 }
sergeyvc69853c2016-10-07 14:14:09 -070065
66 void assertValid() {
67 LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
68 }
69
70 void getSkBitmap(SkBitmap* outBitmap) {
71 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070072 mBitmap->getSkBitmap(outBitmap);
sergeyvc69853c2016-10-07 14:14:09 -070073 }
74
75 bool hasHardwareMipMap() {
sergeyvc1c54062016-10-19 18:47:26 -070076 if (mBitmap) {
77 return mBitmap->hasHardwareMipMap();
John Reckf29ed282015-04-07 07:32:03 -070078 }
John Reckf29ed282015-04-07 07:32:03 -070079 return mHasHardwareMipMap;
80 }
81
82 void setHasHardwareMipMap(bool hasMipMap) {
sergeyvc69853c2016-10-07 14:14:09 -070083 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070084 mBitmap->setHasHardwareMipMap(hasMipMap);
John Reckf29ed282015-04-07 07:32:03 -070085 }
86
sergeyvc69853c2016-10-07 14:14:09 -070087 void setAlphaType(SkAlphaType alphaType) {
88 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070089 mBitmap->setAlphaType(alphaType);
John Reckf29ed282015-04-07 07:32:03 -070090 }
91
Derek Sollenberger202084c2019-01-14 13:55:08 -050092 void setColorSpace(sk_sp<SkColorSpace> colorSpace) {
93 assertValid();
94 mBitmap->setColorSpace(colorSpace);
95 }
96
sergeyvc69853c2016-10-07 14:14:09 -070097 const SkImageInfo& info() {
sergeyvc1c54062016-10-19 18:47:26 -070098 if (mBitmap) {
99 return mBitmap->info();
sergeyvc69853c2016-10-07 14:14:09 -0700100 }
101 return mInfo;
John Reckf29ed282015-04-07 07:32:03 -0700102 }
103
sergeyvc69853c2016-10-07 14:14:09 -0700104 size_t getAllocationByteCount() const {
sergeyvc1c54062016-10-19 18:47:26 -0700105 if (mBitmap) {
106 return mBitmap->getAllocationByteCount();
sergeyvc69853c2016-10-07 14:14:09 -0700107 }
108 return mAllocationSize;
John Reckf29ed282015-04-07 07:32:03 -0700109 }
110
sergeyvc69853c2016-10-07 14:14:09 -0700111 size_t rowBytes() const {
sergeyvc1c54062016-10-19 18:47:26 -0700112 if (mBitmap) {
113 return mBitmap->rowBytes();
sergeyvc69853c2016-10-07 14:14:09 -0700114 }
115 return mRowBytes;
116 }
117
118 uint32_t getGenerationID() const {
sergeyvc1c54062016-10-19 18:47:26 -0700119 if (mBitmap) {
120 return mBitmap->getGenerationID();
sergeyvc69853c2016-10-07 14:14:09 -0700121 }
122 return mGenerationId;
123 }
124
sergeyv15a10852016-12-27 14:32:03 -0800125 bool isHardware() {
126 if (mBitmap) {
127 return mBitmap->isHardware();
128 }
129 return mIsHardware;
130 }
131
sergeyvc1c54062016-10-19 18:47:26 -0700132 ~BitmapWrapper() { }
sergeyvc69853c2016-10-07 14:14:09 -0700133
John Reckf29ed282015-04-07 07:32:03 -0700134private:
sergeyvc1c54062016-10-19 18:47:26 -0700135 sk_sp<Bitmap> mBitmap;
sergeyvc69853c2016-10-07 14:14:09 -0700136 SkImageInfo mInfo;
137 bool mHasHardwareMipMap;
138 size_t mAllocationSize;
139 size_t mRowBytes;
140 uint32_t mGenerationId;
sergeyv15a10852016-12-27 14:32:03 -0800141 bool mIsHardware;
John Reckf29ed282015-04-07 07:32:03 -0700142};
143
John Reckf29ed282015-04-07 07:32:03 -0700144// Convenience class that does not take a global ref on the pixels, relying
145// on the caller already having a local JNI ref
146class LocalScopedBitmap {
147public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -0700148 explicit LocalScopedBitmap(jlong bitmapHandle)
sergeyvc1c54062016-10-19 18:47:26 -0700149 : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
John Reckf29ed282015-04-07 07:32:03 -0700150
sergeyvc1c54062016-10-19 18:47:26 -0700151 BitmapWrapper* operator->() {
152 return mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700153 }
154
155 void* pixels() {
sergeyvaed7f582016-10-14 16:30:21 -0700156 return mBitmapWrapper->bitmap().pixels();
John Reckf29ed282015-04-07 07:32:03 -0700157 }
158
159 bool valid() {
sergeyvc1c54062016-10-19 18:47:26 -0700160 return mBitmapWrapper && mBitmapWrapper->valid();
John Reckf29ed282015-04-07 07:32:03 -0700161 }
162
163private:
sergeyvc1c54062016-10-19 18:47:26 -0700164 BitmapWrapper* mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700165};
166
sergeyvc69853c2016-10-07 14:14:09 -0700167namespace bitmap {
168
169// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
170static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
171 // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
172 // irrelevant. This just tests to ensure that the SkAlphaType is not
173 // opposite of isPremultiplied.
174 if (isPremultiplied) {
175 SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
176 } else {
177 SkASSERT(info.alphaType() != kPremul_SkAlphaType);
178 }
179}
180
181void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
182 bool isPremultiplied)
183{
184 // The caller needs to have already set the alpha type properly, so the
185 // native SkBitmap stays in sync with the Java Bitmap.
186 assert_premultiplied(info, isPremultiplied);
187
188 env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
189 info.width(), info.height(), isPremultiplied);
190}
191
sergeyvc1c54062016-10-19 18:47:26 -0700192jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
sergeyvc69853c2016-10-07 14:14:09 -0700193 int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
194 int density) {
195 bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
196 bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
197 // The caller needs to have already set the alpha type properly, so the
198 // native SkBitmap stays in sync with the Java Bitmap.
sergeyvc1c54062016-10-19 18:47:26 -0700199 assert_premultiplied(bitmap->info(), isPremultiplied);
Leon Scroggins IIIbbdb7312019-01-31 14:35:54 -0500200 bool fromMalloc = bitmap->pixelStorageType() == PixelStorageType::Heap;
sergeyvc1c54062016-10-19 18:47:26 -0700201 BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
Nader Jawade7b51292018-04-12 17:55:31 -0700202 if (!isMutable) {
203 bitmapWrapper->bitmap().setImmutable();
204 }
sergeyvc69853c2016-10-07 14:14:09 -0700205 jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
sergeyvc1c54062016-10-19 18:47:26 -0700206 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
Leon Scroggins IIIbbdb7312019-01-31 14:35:54 -0500207 isPremultiplied, ninePatchChunk, ninePatchInsets, fromMalloc);
sergeyvc69853c2016-10-07 14:14:09 -0700208
209 if (env->ExceptionCheck() != 0) {
210 ALOGE("*** Uncaught exception returned from Java call!\n");
211 env->ExceptionDescribe();
212 }
213 return obj;
214}
215
216void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
217 LocalScopedBitmap bitmap(bitmapHandle);
218 bitmap->getSkBitmap(outBitmap);
219}
220
Leon Scroggins III71fae622019-03-26 16:28:41 -0400221Bitmap& toBitmap(jlong bitmapHandle) {
sergeyv5fd2a1c2016-10-20 15:04:28 -0700222 LocalScopedBitmap localBitmap(bitmapHandle);
223 return localBitmap->bitmap();
224}
225
sergeyvc69853c2016-10-07 14:14:09 -0700226} // namespace bitmap
227
228} // namespace android
229
230using namespace android;
231using namespace android::bitmap;
232
Derek Sollenberger6c41ab12019-11-08 08:50:58 -0500233Bitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
234 SkASSERT(env);
235 SkASSERT(bitmap);
236 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
237 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
238 LocalScopedBitmap localBitmap(bitmapHandle);
239 return localBitmap.valid() ? &localBitmap->bitmap() : nullptr;
240}
241
Leon Scroggins III84a2afc2020-01-19 19:27:16 -0500242SkImageInfo GraphicsJNI::getBitmapInfo(JNIEnv* env, jobject bitmap, uint32_t* outRowBytes,
243 bool* isHardware) {
Derek Sollenberger6c41ab12019-11-08 08:50:58 -0500244 SkASSERT(env);
245 SkASSERT(bitmap);
246 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
247 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
248 LocalScopedBitmap localBitmap(bitmapHandle);
249 if (outRowBytes) {
250 *outRowBytes = localBitmap->rowBytes();
251 }
Leon Scroggins III84a2afc2020-01-19 19:27:16 -0500252 if (isHardware) {
253 *isHardware = localBitmap->isHardware();
254 }
Derek Sollenberger6c41ab12019-11-08 08:50:58 -0500255 return localBitmap->info();
256}
257
Chris Craik32054b02014-05-09 13:58:56 -0700258bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
Brian Osman91c9c282018-08-17 16:57:15 -0400259 int x, int y, int width, int height, SkBitmap* dstBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700260 const jint* array = env->GetIntArrayElements(srcColors, NULL);
261 const SkColor* src = (const SkColor*)array + srcOffset;
262
Brian Osman91c9c282018-08-17 16:57:15 -0400263 auto sRGB = SkColorSpace::MakeSRGB();
264 SkImageInfo srcInfo = SkImageInfo::Make(
265 width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
266 SkPixmap srcPM(srcInfo, src, srcStride * 4);
Romain Guyce217fa2017-03-08 15:58:06 -0800267
Brian Osman91c9c282018-08-17 16:57:15 -0400268 dstBitmap->writePixels(srcPM, x, y);
Chris Craik32054b02014-05-09 13:58:56 -0700269
Romain Guy9505a652016-12-14 09:43:50 -0800270 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
Chris Craik32054b02014-05-09 13:58:56 -0700271 return true;
272}
273
Chris Craik32054b02014-05-09 13:58:56 -0700274///////////////////////////////////////////////////////////////////////////////
275///////////////////////////////////////////////////////////////////////////////
276
277static int getPremulBitmapCreateFlags(bool isMutable) {
sergeyvc69853c2016-10-07 14:14:09 -0700278 int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
279 if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
Chris Craik32054b02014-05-09 13:58:56 -0700280 return flags;
281}
282
283static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
284 jint offset, jint stride, jint width, jint height,
Romain Guy82426562017-04-04 19:38:50 -0700285 jint configHandle, jboolean isMutable,
Leon Scroggins III0e443d162018-12-19 11:38:35 -0500286 jlong colorSpacePtr) {
Mike Reed1103b322014-07-08 12:36:44 -0400287 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700288 if (NULL != jColors) {
289 size_t n = env->GetArrayLength(jColors);
290 if (n < SkAbs32(stride) * (size_t)height) {
291 doThrowAIOOBE(env);
292 return NULL;
293 }
294 }
295
296 // ARGB_4444 is a deprecated format, convert automatically to 8888
Mike Reedb9330552014-06-16 17:31:48 -0400297 if (colorType == kARGB_4444_SkColorType) {
298 colorType = kN32_SkColorType;
Chris Craik32054b02014-05-09 13:58:56 -0700299 }
300
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500301 sk_sp<SkColorSpace> colorSpace;
302 if (colorType == kAlpha_8_SkColorType) {
303 colorSpace = nullptr;
304 } else {
305 colorSpace = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
306 }
307
Chris Craik32054b02014-05-09 13:58:56 -0700308 SkBitmap bitmap;
Leon Scroggins III0e443d162018-12-19 11:38:35 -0500309 bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500310 colorSpace));
Chris Craik32054b02014-05-09 13:58:56 -0700311
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400312 sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700313 if (!nativeBitmap) {
Leon Scroggins IIIf3a02992017-10-03 14:00:20 -0400314 ALOGE("OOM allocating Bitmap with dimensions %i x %i", width, height);
315 doThrowOOME(env);
Chris Craik32054b02014-05-09 13:58:56 -0700316 return NULL;
317 }
318
319 if (jColors != NULL) {
Brian Osman91c9c282018-08-17 16:57:15 -0400320 GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, &bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700321 }
322
sergeyvc36bd6c2016-10-11 15:49:16 -0700323 return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700324}
325
Matt Sarett5320a722017-03-20 13:51:29 -0400326static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
327 SkBitmap::Allocator* alloc) {
Matt Sarette9834402017-04-25 13:49:42 -0400328 SkPixmap srcPM;
329 if (!src.peekPixels(&srcPM)) {
330 return false;
331 }
332
333 SkImageInfo dstInfo = srcPM.info().makeColorType(dstCT);
334 switch (dstCT) {
335 case kRGB_565_SkColorType:
Brian Osmanbaf13e82018-09-21 11:21:30 -0400336 dstInfo = dstInfo.makeAlphaType(kOpaque_SkAlphaType);
Matt Sarette9834402017-04-25 13:49:42 -0400337 break;
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500338 case kAlpha_8_SkColorType:
339 dstInfo = dstInfo.makeColorSpace(nullptr);
Matt Sarette9834402017-04-25 13:49:42 -0400340 break;
341 default:
342 break;
343 }
344
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500345 if (!dstInfo.colorSpace() && dstCT != kAlpha_8_SkColorType) {
346 dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGB());
347 }
348
Matt Sarette9834402017-04-25 13:49:42 -0400349 if (!dst->setInfo(dstInfo)) {
350 return false;
351 }
Mike Reed81397c42017-07-18 17:04:16 -0400352 if (!dst->tryAllocPixels(alloc)) {
Matt Sarette9834402017-04-25 13:49:42 -0400353 return false;
354 }
355
Matt Sarette9834402017-04-25 13:49:42 -0400356 SkPixmap dstPM;
357 if (!dst->peekPixels(&dstPM)) {
358 return false;
359 }
360
Matt Sarette9834402017-04-25 13:49:42 -0400361 return srcPM.readPixels(dstPM);
Matt Sarett5320a722017-03-20 13:51:29 -0400362}
363
Chris Craik32054b02014-05-09 13:58:56 -0700364static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
365 jint dstConfigHandle, jboolean isMutable) {
John Reckf29ed282015-04-07 07:32:03 -0700366 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700367 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
sergeyv05126d12016-12-15 19:50:15 -0800368 if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
369 sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
370 if (!bitmap.get()) {
371 return NULL;
372 }
sergeyv656117b2017-02-28 15:25:10 -0800373 return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
sergeyv05126d12016-12-15 19:50:15 -0800374 }
375
Mike Reed1103b322014-07-08 12:36:44 -0400376 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyv45082182016-09-29 18:25:40 -0700377 SkBitmap result;
378 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700379
Matt Sarett5320a722017-03-20 13:51:29 -0400380 if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
Chris Craik32054b02014-05-09 13:58:56 -0700381 return NULL;
382 }
sergeyvc1c54062016-10-19 18:47:26 -0700383 auto bitmap = allocator.getStorageObjAndReset();
384 return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700385}
386
sergeyvc1c54062016-10-19 18:47:26 -0700387static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700388 SkBitmap result;
389
390 AshmemPixelAllocator allocator(env);
Matt Sarett5320a722017-03-20 13:51:29 -0400391 if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700392 return NULL;
393 }
sergeyvc1c54062016-10-19 18:47:26 -0700394 auto bitmap = allocator.getStorageObjAndReset();
395 bitmap->setImmutable();
396 return bitmap;
Winsona5fdde92016-04-14 15:27:15 -0700397}
398
399static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
400 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700401 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700402 SkColorType dstCT = src.colorType();
sergeyvc1c54062016-10-19 18:47:26 -0700403 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
404 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Winsona5fdde92016-04-14 15:27:15 -0700405 return ret;
406}
407
408static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
409 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700410 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700411 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyvc1c54062016-10-19 18:47:26 -0700412 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
413 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Riley Andrews721ae5f2015-05-11 16:08:22 -0700414 return ret;
415}
416
sergeyvc1c54062016-10-19 18:47:26 -0700417static void Bitmap_destruct(BitmapWrapper* bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700418 delete bitmap;
Chris Craik32054b02014-05-09 13:58:56 -0700419}
420
Richard Uhler775873a2015-12-29 12:37:39 -0800421static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
422 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
423}
424
Leon Scroggins IIIf8adae12018-05-24 15:25:08 -0400425static void Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700426 LocalScopedBitmap bitmap(bitmapHandle);
427 bitmap->freePixels();
Chris Craik32054b02014-05-09 13:58:56 -0700428}
429
430static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
sergeyv45082182016-09-29 18:25:40 -0700431 jint width, jint height, jint configHandle, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700432 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700433 bitmap->assertValid();
Mike Reed1103b322014-07-08 12:36:44 -0400434 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400435
436 // ARGB_4444 is a deprecated format, convert automatically to 8888
437 if (colorType == kARGB_4444_SkColorType) {
438 colorType = kN32_SkColorType;
439 }
sergeyv45082182016-09-29 18:25:40 -0700440 size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
441 if (requestedSize > bitmap->getAllocationByteCount()) {
Chris Craik32054b02014-05-09 13:58:56 -0700442 // done in native as there's no way to get BytesPerPixel in Java
443 doThrowIAE(env, "Bitmap not large enough to support new configuration");
444 return;
445 }
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400446 SkAlphaType alphaType;
John Reckf29ed282015-04-07 07:32:03 -0700447 if (bitmap->info().colorType() != kRGB_565_SkColorType
448 && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400449 // If the original bitmap was set to opaque, keep that setting, unless it
450 // was 565, which is required to be opaque.
451 alphaType = kOpaque_SkAlphaType;
452 } else {
453 // Otherwise respect the premultiplied request.
454 alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
455 }
sergeyvaed7f582016-10-14 16:30:21 -0700456 bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
sergeyv7d5219f2016-11-03 16:18:16 -0700457 sk_ref_sp(bitmap->info().colorSpace())));
Chris Craik32054b02014-05-09 13:58:56 -0700458}
459
Chris Craik32054b02014-05-09 13:58:56 -0700460static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
461 jint format, jint quality,
462 jobject jstream, jbyteArray jstorage) {
Hal Canary10219fb2016-11-23 20:41:22 -0500463 LocalScopedBitmap bitmap(bitmapHandle);
John Reckf29ed282015-04-07 07:32:03 -0700464 if (!bitmap.valid()) {
465 return JNI_FALSE;
466 }
467
John Reckf29ed282015-04-07 07:32:03 -0700468 std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
469 if (!strm.get()) {
470 return JNI_FALSE;
471 }
Chris Craik32054b02014-05-09 13:58:56 -0700472
Leon Scroggins III9010e8b2019-08-20 11:27:17 -0400473 auto fm = static_cast<Bitmap::JavaCompressFormat>(format);
Leon Scroggins III949c6002020-01-23 16:20:39 -0500474 return bitmap->bitmap().compress(fm, quality, strm.get()) ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700475}
476
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500477static inline void bitmapErase(SkBitmap bitmap, const SkColor4f& color,
478 const sk_sp<SkColorSpace>& colorSpace) {
479 SkPaint p;
480 p.setColor4f(color, colorSpace.get());
481 p.setBlendMode(SkBlendMode::kSrc);
482 SkCanvas canvas(bitmap);
483 canvas.drawPaint(p);
484}
485
Chris Craik32054b02014-05-09 13:58:56 -0700486static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
John Reckf29ed282015-04-07 07:32:03 -0700487 LocalScopedBitmap bitmap(bitmapHandle);
488 SkBitmap skBitmap;
489 bitmap->getSkBitmap(&skBitmap);
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500490 bitmapErase(skBitmap, SkColor4f::FromColor(color), SkColorSpace::MakeSRGB());
491}
492
Leon Scroggins III94ba1002019-01-17 13:34:51 -0500493static void Bitmap_eraseLong(JNIEnv* env, jobject, jlong bitmapHandle,
494 jlong colorSpaceHandle, jlong colorLong) {
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500495 LocalScopedBitmap bitmap(bitmapHandle);
496 SkBitmap skBitmap;
497 bitmap->getSkBitmap(&skBitmap);
Leon Scroggins III0e443d162018-12-19 11:38:35 -0500498
Leon Scroggins III94ba1002019-01-17 13:34:51 -0500499 SkColor4f color = GraphicsJNI::convertColorLong(colorLong);
Leon Scroggins III0e443d162018-12-19 11:38:35 -0500500 sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
Leon Scroggins III4c4259b2018-12-17 10:40:07 -0500501 bitmapErase(skBitmap, color, cs);
Chris Craik32054b02014-05-09 13:58:56 -0700502}
503
504static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700505 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700506 return static_cast<jint>(bitmap->rowBytes());
507}
508
509static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700510 LocalScopedBitmap bitmap(bitmapHandle);
sergeyv15a10852016-12-27 14:32:03 -0800511 if (bitmap->isHardware()) {
sergeyv19b4b012016-12-13 16:06:00 -0800512 return GraphicsJNI::hardwareLegacyBitmapConfig();
513 }
John Reckf29ed282015-04-07 07:32:03 -0700514 return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
Chris Craik32054b02014-05-09 13:58:56 -0700515}
516
517static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700518 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700519 return static_cast<jint>(bitmap->getGenerationID());
Chris Craik32054b02014-05-09 13:58:56 -0700520}
521
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400522static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700523 LocalScopedBitmap bitmap(bitmapHandle);
524 if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400525 return JNI_TRUE;
526 }
527 return JNI_FALSE;
528}
529
Chris Craik32054b02014-05-09 13:58:56 -0700530static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700531 LocalScopedBitmap bitmap(bitmapHandle);
532 return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700533}
534
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400535static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
536 jboolean hasAlpha, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700537 LocalScopedBitmap bitmap(bitmapHandle);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400538 if (hasAlpha) {
John Reck0781a2f2015-05-27 16:29:17 -0700539 bitmap->setAlphaType(
John Reckf29ed282015-04-07 07:32:03 -0700540 requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
Chris Craik32054b02014-05-09 13:58:56 -0700541 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700542 bitmap->setAlphaType(kOpaque_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400543 }
544}
545
546static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
547 jboolean isPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700548 LocalScopedBitmap bitmap(bitmapHandle);
549 if (!bitmap->info().isOpaque()) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400550 if (isPremul) {
John Reck0781a2f2015-05-27 16:29:17 -0700551 bitmap->setAlphaType(kPremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400552 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700553 bitmap->setAlphaType(kUnpremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400554 }
Chris Craik32054b02014-05-09 13:58:56 -0700555 }
556}
557
558static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700559 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700560 return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
561}
562
563static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
564 jboolean hasMipMap) {
John Reckf29ed282015-04-07 07:32:03 -0700565 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700566 bitmap->setHasHardwareMipMap(hasMipMap);
567}
568
569///////////////////////////////////////////////////////////////////////////////
570
Matt Sarett3ca39752017-05-26 10:55:38 -0400571// This is the maximum possible size because the SkColorSpace must be
572// representable (and therefore serializable) using a matrix and numerical
573// transfer function. If we allow more color space representations in the
574// framework, we may need to update this maximum size.
575static constexpr uint32_t kMaxColorSpaceSerializedBytes = 80;
576
Chris Craik32054b02014-05-09 13:58:56 -0700577static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100578#ifdef __ANDROID__ // Layoutlib does not support parcel
Chris Craik32054b02014-05-09 13:58:56 -0700579 if (parcel == NULL) {
580 SkDebugf("-------- unparcel parcel is NULL\n");
581 return NULL;
582 }
583
584 android::Parcel* p = android::parcelForJavaObject(env, parcel);
585
Mike Reedb9330552014-06-16 17:31:48 -0400586 const SkColorType colorType = (SkColorType)p->readInt32();
587 const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
Romain Guy5acc4762017-03-07 15:29:27 -0800588 const uint32_t colorSpaceSize = p->readUint32();
589 sk_sp<SkColorSpace> colorSpace;
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500590 if (colorSpaceSize > 0) {
Matt Sarett3ca39752017-05-26 10:55:38 -0400591 if (colorSpaceSize > kMaxColorSpaceSerializedBytes) {
592 ALOGD("Bitmap_createFromParcel: Serialized SkColorSpace is larger than expected: "
593 "%d bytes\n", colorSpaceSize);
594 }
595
596 const void* data = p->readInplace(colorSpaceSize);
597 if (data) {
598 colorSpace = SkColorSpace::Deserialize(data, colorSpaceSize);
599 } else {
600 ALOGD("Bitmap_createFromParcel: Unable to read serialized SkColorSpace data\n");
601 }
Romain Guy5acc4762017-03-07 15:29:27 -0800602 }
Mike Reedb9330552014-06-16 17:31:48 -0400603 const int width = p->readInt32();
604 const int height = p->readInt32();
605 const int rowBytes = p->readInt32();
606 const int density = p->readInt32();
Chris Craik32054b02014-05-09 13:58:56 -0700607
Mike Reedb9330552014-06-16 17:31:48 -0400608 if (kN32_SkColorType != colorType &&
Romain Guy9505a652016-12-14 09:43:50 -0800609 kRGBA_F16_SkColorType != colorType &&
Mike Reedb9330552014-06-16 17:31:48 -0400610 kRGB_565_SkColorType != colorType &&
611 kARGB_4444_SkColorType != colorType &&
Mike Reedb9330552014-06-16 17:31:48 -0400612 kAlpha_8_SkColorType != colorType) {
613 SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
Chris Craik32054b02014-05-09 13:58:56 -0700614 return NULL;
615 }
616
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400617 std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
Romain Guy9505a652016-12-14 09:43:50 -0800618 if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
619 rowBytes)) {
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400620 return NULL;
621 }
Chris Craik32054b02014-05-09 13:58:56 -0700622
Jeff Browna316c5d2015-06-05 15:14:06 -0700623 // Read the bitmap blob.
Mike Reed7569de02017-10-06 16:25:49 -0400624 size_t size = bitmap->computeByteSize();
Jeff Browna316c5d2015-06-05 15:14:06 -0700625 android::Parcel::ReadableBlob blob;
626 android::status_t status = p->readBlob(size, &blob);
627 if (status) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700628 doThrowRE(env, "Could not read bitmap blob.");
Chris Craik32054b02014-05-09 13:58:56 -0700629 return NULL;
630 }
631
Jeff Browna316c5d2015-06-05 15:14:06 -0700632 // Map the bitmap in place from the ashmem region if possible otherwise copy.
sergeyvc1c54062016-10-19 18:47:26 -0700633 sk_sp<Bitmap> nativeBitmap;
John Reckefac0522020-01-24 16:04:26 -0800634 if (blob.fd() >= 0 && !blob.isMutable()) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700635#if DEBUG_PARCEL
John Reckefac0522020-01-24 16:04:26 -0800636 ALOGD("Bitmap.createFromParcel: mapped contents of bitmap from %s blob "
Jeff Browna316c5d2015-06-05 15:14:06 -0700637 "(fds %s)",
Jeff Browna316c5d2015-06-05 15:14:06 -0700638 blob.isMutable() ? "mutable" : "immutable",
639 p->allowFds() ? "allowed" : "forbidden");
640#endif
641 // Dup the file descriptor so we can keep a reference to it after the Parcel
642 // is disposed.
Nick Kralevich07f1c1d2019-01-14 13:42:22 -0800643 int dupFd = fcntl(blob.fd(), F_DUPFD_CLOEXEC, 0);
Jeff Browna316c5d2015-06-05 15:14:06 -0700644 if (dupFd < 0) {
Erik Wolsheimer211abad2015-11-13 11:54:47 -0800645 ALOGE("Error allocating dup fd. Error:%d", errno);
Jeff Browna316c5d2015-06-05 15:14:06 -0700646 blob.release();
Jeff Browna316c5d2015-06-05 15:14:06 -0700647 doThrowRE(env, "Could not allocate dup blob fd.");
648 return NULL;
649 }
650
Derek Sollenbergere2169482018-11-20 10:57:20 -0500651 // Map the pixels in place and take ownership of the ashmem region. We must also respect the
652 // rowBytes value already set on the bitmap instead of attempting to compute our own.
653 nativeBitmap = Bitmap::createFrom(bitmap->info(), bitmap->rowBytes(), dupFd,
John Reckefac0522020-01-24 16:04:26 -0800654 const_cast<void*>(blob.data()), size, true);
Jeff Browna316c5d2015-06-05 15:14:06 -0700655 if (!nativeBitmap) {
656 close(dupFd);
657 blob.release();
658 doThrowRE(env, "Could not allocate ashmem pixel ref.");
659 return NULL;
660 }
661
662 // Clear the blob handle, don't release it.
663 blob.clear();
664 } else {
665#if DEBUG_PARCEL
666 if (blob.fd() >= 0) {
667 ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
668 "from immutable blob (fds %s)",
669 p->allowFds() ? "allowed" : "forbidden");
670 } else {
671 ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
672 "(fds %s)",
673 blob.isMutable() ? "mutable" : "immutable",
674 p->allowFds() ? "allowed" : "forbidden");
675 }
676#endif
677
678 // Copy the pixels into a new buffer.
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400679 nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get());
Jeff Browna316c5d2015-06-05 15:14:06 -0700680 if (!nativeBitmap) {
681 blob.release();
682 doThrowRE(env, "Could not allocate java pixel ref.");
683 return NULL;
684 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700685 memcpy(bitmap->getPixels(), blob.data(), size);
Jeff Browna316c5d2015-06-05 15:14:06 -0700686
687 // Release the blob handle.
688 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700689 }
Chris Craik32054b02014-05-09 13:58:56 -0700690
sergeyvc36bd6c2016-10-11 15:49:16 -0700691 return createBitmap(env, nativeBitmap.release(),
John Reckefac0522020-01-24 16:04:26 -0800692 getPremulBitmapCreateFlags(false), NULL, NULL, density);
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100693#else
694 doThrowRE(env, "Cannot use parcels outside of Android");
695 return NULL;
696#endif
Chris Craik32054b02014-05-09 13:58:56 -0700697}
698
699static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
John Reckefac0522020-01-24 16:04:26 -0800700 jlong bitmapHandle, jint density, jobject parcel) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100701#ifdef __ANDROID__ // Layoutlib does not support parcel
Chris Craik32054b02014-05-09 13:58:56 -0700702 if (parcel == NULL) {
703 SkDebugf("------- writeToParcel null parcel\n");
704 return JNI_FALSE;
705 }
706
707 android::Parcel* p = android::parcelForJavaObject(env, parcel);
John Reckf29ed282015-04-07 07:32:03 -0700708 SkBitmap bitmap;
Riley Andrews39d7f302014-11-13 17:43:25 -0800709
sergeyvc1c54062016-10-19 18:47:26 -0700710 auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
711 bitmapWrapper->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700712
John Reckf29ed282015-04-07 07:32:03 -0700713 p->writeInt32(bitmap.colorType());
714 p->writeInt32(bitmap.alphaType());
Romain Guy5acc4762017-03-07 15:29:27 -0800715 SkColorSpace* colorSpace = bitmap.colorSpace();
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500716 if (colorSpace != nullptr) {
Romain Guy5acc4762017-03-07 15:29:27 -0800717 sk_sp<SkData> data = colorSpace->serialize();
718 size_t size = data->size();
719 p->writeUint32(size);
720 if (size > 0) {
Matt Sarett3ca39752017-05-26 10:55:38 -0400721 if (size > kMaxColorSpaceSerializedBytes) {
722 ALOGD("Bitmap_writeToParcel: Serialized SkColorSpace is larger than expected: "
723 "%zu bytes\n", size);
724 }
725
Romain Guy5acc4762017-03-07 15:29:27 -0800726 p->write(data->data(), size);
727 }
728 } else {
729 p->writeUint32(0);
730 }
John Reckf29ed282015-04-07 07:32:03 -0700731 p->writeInt32(bitmap.width());
732 p->writeInt32(bitmap.height());
733 p->writeInt32(bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -0700734 p->writeInt32(density);
735
Jeff Browna316c5d2015-06-05 15:14:06 -0700736 // Transfer the underlying ashmem region if we have one and it's immutable.
737 android::status_t status;
sergeyvaed7f582016-10-14 16:30:21 -0700738 int fd = bitmapWrapper->bitmap().getAshmemFd();
John Reckefac0522020-01-24 16:04:26 -0800739 if (fd >= 0 && p->allowFds()) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700740#if DEBUG_PARCEL
741 ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
742 "immutable blob (fds %s)",
743 p->allowFds() ? "allowed" : "forbidden");
744#endif
745
746 status = p->writeDupImmutableBlobFileDescriptor(fd);
747 if (status) {
748 doThrowRE(env, "Could not write bitmap blob file descriptor.");
Riley Andrews39d7f302014-11-13 17:43:25 -0800749 return JNI_FALSE;
750 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700751 return JNI_TRUE;
Riley Andrews39d7f302014-11-13 17:43:25 -0800752 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700753
754 // Copy the bitmap to a new blob.
Jeff Browna316c5d2015-06-05 15:14:06 -0700755#if DEBUG_PARCEL
John Reckefac0522020-01-24 16:04:26 -0800756 ALOGD("Bitmap.writeToParcel: copying bitmap into new blob (fds %s)",
Jeff Browna316c5d2015-06-05 15:14:06 -0700757 p->allowFds() ? "allowed" : "forbidden");
758#endif
759
Mike Reed7569de02017-10-06 16:25:49 -0400760 size_t size = bitmap.computeByteSize();
Jeff Browna316c5d2015-06-05 15:14:06 -0700761 android::Parcel::WritableBlob blob;
John Reckefac0522020-01-24 16:04:26 -0800762 status = p->writeBlob(size, false, &blob);
Jeff Browna316c5d2015-06-05 15:14:06 -0700763 if (status) {
764 doThrowRE(env, "Could not copy bitmap to parcel blob.");
765 return JNI_FALSE;
766 }
767
Jeff Browna316c5d2015-06-05 15:14:06 -0700768 const void* pSrc = bitmap.getPixels();
769 if (pSrc == NULL) {
770 memset(blob.data(), 0, size);
771 } else {
772 memcpy(blob.data(), pSrc, size);
773 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700774
775 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700776 return JNI_TRUE;
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100777#else
778 doThrowRE(env, "Cannot use parcels outside of Android");
779 return JNI_FALSE;
780#endif
Chris Craik32054b02014-05-09 13:58:56 -0700781}
782
783static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
784 jlong srcHandle, jlong paintHandle,
785 jintArray offsetXY) {
John Reckf29ed282015-04-07 07:32:03 -0700786 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700787 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400788 const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700789 SkIPoint offset;
John Reckf29ed282015-04-07 07:32:03 -0700790 SkBitmap dst;
sergeyv45082182016-09-29 18:25:40 -0700791 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700792
John Reckf29ed282015-04-07 07:32:03 -0700793 src.extractAlpha(&dst, paint, &allocator, &offset);
Chris Craik32054b02014-05-09 13:58:56 -0700794 // If Skia can't allocate pixels for destination bitmap, it resets
795 // it, that is set its pixels buffer to NULL, and zero width and height.
John Reckf29ed282015-04-07 07:32:03 -0700796 if (dst.getPixels() == NULL && src.getPixels() != NULL) {
Chris Craik32054b02014-05-09 13:58:56 -0700797 doThrowOOME(env, "failed to allocate pixels for alpha");
798 return NULL;
799 }
800 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
801 int* array = env->GetIntArrayElements(offsetXY, NULL);
802 array[0] = offset.fX;
803 array[1] = offset.fY;
804 env->ReleaseIntArrayElements(offsetXY, array, 0);
805 }
806
sergeyvc69853c2016-10-07 14:14:09 -0700807 return createBitmap(env, allocator.getStorageObjAndReset(),
John Reckf29ed282015-04-07 07:32:03 -0700808 getPremulBitmapCreateFlags(true));
Chris Craik32054b02014-05-09 13:58:56 -0700809}
810
811///////////////////////////////////////////////////////////////////////////////
812
Romain Guyefb4b062017-02-27 11:00:04 -0800813static jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
814 LocalScopedBitmap bitmapHolder(bitmapHandle);
815 if (!bitmapHolder.valid()) return JNI_TRUE;
816
817 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
Brian Osman91c9c282018-08-17 16:57:15 -0400818 return colorSpace == nullptr || colorSpace->isSRGB();
Romain Guyefb4b062017-02-27 11:00:04 -0800819}
820
Leon Scroggins IIIce89a6e2018-03-13 15:39:39 -0400821static jboolean Bitmap_isSRGBLinear(JNIEnv* env, jobject, jlong bitmapHandle) {
822 LocalScopedBitmap bitmapHolder(bitmapHandle);
823 if (!bitmapHolder.valid()) return JNI_FALSE;
824
825 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
826 sk_sp<SkColorSpace> srgbLinear = SkColorSpace::MakeSRGBLinear();
827 return colorSpace == srgbLinear.get() ? JNI_TRUE : JNI_FALSE;
828}
829
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500830static jobject Bitmap_computeColorSpace(JNIEnv* env, jobject, jlong bitmapHandle) {
Romain Guyefb4b062017-02-27 11:00:04 -0800831 LocalScopedBitmap bitmapHolder(bitmapHandle);
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500832 if (!bitmapHolder.valid()) return nullptr;
Romain Guyefb4b062017-02-27 11:00:04 -0800833
834 SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500835 if (colorSpace == nullptr) return nullptr;
Romain Guyefb4b062017-02-27 11:00:04 -0800836
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500837 return GraphicsJNI::getColorSpace(env, colorSpace, bitmapHolder->info().colorType());
Romain Guyefb4b062017-02-27 11:00:04 -0800838}
839
Derek Sollenberger202084c2019-01-14 13:55:08 -0500840static void Bitmap_setColorSpace(JNIEnv* env, jobject, jlong bitmapHandle, jlong colorSpacePtr) {
841 LocalScopedBitmap bitmapHolder(bitmapHandle);
842 sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
843 bitmapHolder->setColorSpace(cs);
844}
845
Romain Guyefb4b062017-02-27 11:00:04 -0800846///////////////////////////////////////////////////////////////////////////////
847
Chris Craik32054b02014-05-09 13:58:56 -0700848static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400849 jint x, jint y) {
John Reckf29ed282015-04-07 07:32:03 -0700850 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700851 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700852
Brian Osman91c9c282018-08-17 16:57:15 -0400853 auto sRGB = SkColorSpace::MakeSRGB();
854 SkImageInfo dstInfo = SkImageInfo::Make(
855 1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
Chris Craik32054b02014-05-09 13:58:56 -0700856
Brian Osman91c9c282018-08-17 16:57:15 -0400857 SkColor dst;
858 bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
859 return static_cast<jint>(dst);
Chris Craik32054b02014-05-09 13:58:56 -0700860}
861
Leon Scroggins III870053d2019-01-24 08:37:27 -0500862static jlong Bitmap_getColor(JNIEnv* env, jobject, jlong bitmapHandle,
863 jint x, jint y) {
864 SkBitmap bitmap;
865 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
866
867 SkImageInfo dstInfo = SkImageInfo::Make(
868 1, 1, kRGBA_F16_SkColorType, kUnpremul_SkAlphaType, bitmap.refColorSpace());
869
870 uint64_t dst;
871 bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
872 return static_cast<jlong>(dst);
873}
874
Chris Craik32054b02014-05-09 13:58:56 -0700875static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
876 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400877 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -0700878 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700879 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700880
Brian Osman91c9c282018-08-17 16:57:15 -0400881 auto sRGB = SkColorSpace::MakeSRGB();
882 SkImageInfo dstInfo = SkImageInfo::Make(
883 width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
Chris Craik32054b02014-05-09 13:58:56 -0700884
Chris Craik32054b02014-05-09 13:58:56 -0700885 jint* dst = env->GetIntArrayElements(pixelArray, NULL);
Brian Osman91c9c282018-08-17 16:57:15 -0400886 bitmap.readPixels(dstInfo, dst + offset, stride * 4, x, y);
Chris Craik32054b02014-05-09 13:58:56 -0700887 env->ReleaseIntArrayElements(pixelArray, dst, 0);
888}
889
890///////////////////////////////////////////////////////////////////////////////
891
892static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400893 jint x, jint y, jint colorHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700894 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700895 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700896 SkColor color = static_cast<SkColor>(colorHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700897
Brian Osman91c9c282018-08-17 16:57:15 -0400898 auto sRGB = SkColorSpace::MakeSRGB();
899 SkImageInfo srcInfo = SkImageInfo::Make(
900 1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
901 SkPixmap srcPM(srcInfo, &color, srcInfo.minRowBytes());
Chris Craik32054b02014-05-09 13:58:56 -0700902
Brian Osman91c9c282018-08-17 16:57:15 -0400903 bitmap.writePixels(srcPM, x, y);
Chris Craik32054b02014-05-09 13:58:56 -0700904}
905
906static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
907 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400908 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -0700909 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700910 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700911 GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
Brian Osman91c9c282018-08-17 16:57:15 -0400912 x, y, width, height, &bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700913}
914
915static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
916 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -0700917 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700918 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700919 const void* src = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -0700920
921 if (NULL != src) {
922 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
923
924 // the java side has already checked that buffer is large enough
Mike Reed7569de02017-10-06 16:25:49 -0400925 memcpy(abp.pointer(), src, bitmap.computeByteSize());
Chris Craik32054b02014-05-09 13:58:56 -0700926 }
927}
928
929static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
930 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -0700931 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -0700932 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700933 void* dst = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -0700934
935 if (NULL != dst) {
936 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
937 // the java side has already checked that buffer is large enough
Mike Reed7569de02017-10-06 16:25:49 -0400938 memcpy(dst, abp.pointer(), bitmap.computeByteSize());
John Reckf29ed282015-04-07 07:32:03 -0700939 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -0700940 }
941}
942
Chris Craik795bd0f2016-12-16 15:22:31 -0800943static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) {
John Reckf29ed282015-04-07 07:32:03 -0700944 SkBitmap bm0;
945 SkBitmap bm1;
sergeyv1eabed32016-12-14 14:19:47 -0800946
947 LocalScopedBitmap bitmap0(bm0Handle);
948 LocalScopedBitmap bitmap1(bm1Handle);
949
950 // Paying the price for making Hardware Bitmap as Config:
951 // later check for colorType will pass successfully,
952 // because Hardware Config internally may be RGBA8888 or smth like that.
sergeyv15a10852016-12-27 14:32:03 -0800953 if (bitmap0->isHardware() != bitmap1->isHardware()) {
sergeyv1eabed32016-12-14 14:19:47 -0800954 return JNI_FALSE;
955 }
956
957 bitmap0->bitmap().getSkBitmap(&bm0);
958 bitmap1->bitmap().getSkBitmap(&bm1);
Chris Craik795bd0f2016-12-16 15:22:31 -0800959 if (bm0.width() != bm1.width()
960 || bm0.height() != bm1.height()
961 || bm0.colorType() != bm1.colorType()
962 || bm0.alphaType() != bm1.alphaType()
963 || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) {
Chris Craik32054b02014-05-09 13:58:56 -0700964 return JNI_FALSE;
965 }
966
Chris Craik32054b02014-05-09 13:58:56 -0700967 // if we can't load the pixels, return false
John Reckf29ed282015-04-07 07:32:03 -0700968 if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -0700969 return JNI_FALSE;
970 }
971
Chris Craik32054b02014-05-09 13:58:56 -0700972 // now compare each scanline. We can't do the entire buffer at once,
973 // since we don't care about the pixel values that might extend beyond
974 // the width (since the scanline might be larger than the logical width)
John Reckf29ed282015-04-07 07:32:03 -0700975 const int h = bm0.height();
976 const size_t size = bm0.width() * bm0.bytesPerPixel();
Chris Craik32054b02014-05-09 13:58:56 -0700977 for (int y = 0; y < h; y++) {
henry.uh_chen53001ca2014-07-03 20:40:22 +0800978 // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
979 // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
980 // and bm1 both have pixel data() (have passed NULL == getPixels() check),
981 // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
982 // to warn user those 2 unrecognized config bitmaps may be different.
John Reckf29ed282015-04-07 07:32:03 -0700983 void *bm0Addr = bm0.getAddr(0, y);
984 void *bm1Addr = bm1.getAddr(0, y);
henry.uh_chen53001ca2014-07-03 20:40:22 +0800985
986 if(bm0Addr == NULL || bm1Addr == NULL) {
987 return JNI_FALSE;
988 }
989
990 if (memcmp(bm0Addr, bm1Addr, size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -0700991 return JNI_FALSE;
992 }
993 }
994 return JNI_TRUE;
995}
996
John Reck43871902016-08-01 14:39:24 -0700997static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100998#ifdef __ANDROID__ // Layoutlib does not support render thread
John Reck43871902016-08-01 14:39:24 -0700999 LocalScopedBitmap bitmapHandle(bitmapPtr);
1000 if (!bitmapHandle.valid()) return;
sergeyvec4a4b12016-10-20 18:39:04 -07001001 android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001002#endif
John Reck43871902016-08-01 14:39:24 -07001003}
1004
sergeyv45082182016-09-29 18:25:40 -07001005static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1006 LocalScopedBitmap bitmapHandle(bitmapPtr);
1007 return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1008}
1009
sergeyv6e3658a2017-01-04 16:57:51 -08001010static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
sergeyv81f97ee2016-12-27 18:08:01 -08001011 LocalScopedBitmap bitmapHandle(bitmapPtr);
1012 LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1013 "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
1014 Bitmap& hwuiBitmap = bitmapHandle->bitmap();
1015 SkBitmap src;
1016 hwuiBitmap.getSkBitmap(&src);
1017
Derek Sollenbergere2169482018-11-20 10:57:20 -05001018 if (src.pixelRef() == nullptr) {
sergeyv81f97ee2016-12-27 18:08:01 -08001019 doThrowRE(env, "Could not copy a hardware bitmap.");
1020 return NULL;
1021 }
Derek Sollenbergere2169482018-11-20 10:57:20 -05001022
1023 sk_sp<Bitmap> bitmap = Bitmap::createFrom(src.info(), *src.pixelRef());
1024 return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
sergeyv81f97ee2016-12-27 18:08:01 -08001025}
1026
Leon Scroggins III898ce752020-02-18 12:22:17 -05001027#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
1028typedef AHardwareBuffer* (*AHB_from_HB)(JNIEnv*, jobject);
1029AHB_from_HB AHardwareBuffer_fromHardwareBuffer;
Leon Scroggins III5a190b12020-02-18 13:52:18 -05001030
1031typedef jobject (*AHB_to_HB)(JNIEnv*, AHardwareBuffer*);
1032AHB_to_HB AHardwareBuffer_toHardwareBuffer;
Leon Scroggins III898ce752020-02-18 12:22:17 -05001033#endif
1034
rennb2e9f522018-09-26 10:49:00 -07001035static jobject Bitmap_wrapHardwareBufferBitmap(JNIEnv* env, jobject, jobject hardwareBuffer,
Leon Scroggins III0e443d162018-12-19 11:38:35 -05001036 jlong colorSpacePtr) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001037#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
Leon Scroggins III898ce752020-02-18 12:22:17 -05001038 AHardwareBuffer* buffer = AHardwareBuffer_fromHardwareBuffer(env, hardwareBuffer);
Derek Sollenbergere78f7c92019-07-31 15:18:47 -04001039 sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer,
1040 GraphicsJNI::getNativeColorSpace(colorSpacePtr));
rennb2e9f522018-09-26 10:49:00 -07001041 if (!bitmap.get()) {
1042 ALOGW("failed to create hardware bitmap from hardware buffer");
1043 return NULL;
1044 }
1045 return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001046#else
1047 return NULL;
1048#endif
rennb2e9f522018-09-26 10:49:00 -07001049}
1050
sergeyv6e3658a2017-01-04 16:57:51 -08001051static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001052#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
sergeyv6e3658a2017-01-04 16:57:51 -08001053 LocalScopedBitmap bitmapHandle(bitmapPtr);
1054 LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1055 "Hardware config is only supported config in Bitmap_getGraphicBuffer");
1056
Derek Sollenbergere78f7c92019-07-31 15:18:47 -04001057 Bitmap& bitmap = bitmapHandle->bitmap();
1058 return android_graphics_GraphicBuffer_createFromAHardwareBuffer(env, bitmap.hardwareBuffer());
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001059#else
1060 return NULL;
1061#endif
sergeyv6e3658a2017-01-04 16:57:51 -08001062}
1063
Leon Scroggins III5a190b12020-02-18 13:52:18 -05001064static jobject Bitmap_getHardwareBuffer(JNIEnv* env, jobject, jlong bitmapPtr) {
1065#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
1066 LocalScopedBitmap bitmapHandle(bitmapPtr);
1067 LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1068 "Hardware config is only supported config in Bitmap_getHardwareBuffer");
1069
1070 Bitmap& bitmap = bitmapHandle->bitmap();
1071 return AHardwareBuffer_toHardwareBuffer(env, bitmap.hardwareBuffer());
1072#else
1073 return NULL;
1074#endif
1075}
1076
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +01001077static jboolean Bitmap_isImmutable(CRITICAL_JNI_PARAMS_COMMA jlong bitmapHandle) {
Nader Jawade7b51292018-04-12 17:55:31 -07001078 LocalScopedBitmap bitmapHolder(bitmapHandle);
1079 if (!bitmapHolder.valid()) return JNI_FALSE;
1080
1081 return bitmapHolder->bitmap().isImmutable() ? JNI_TRUE : JNI_FALSE;
1082}
1083
1084static void Bitmap_setImmutable(JNIEnv* env, jobject, jlong bitmapHandle) {
1085 LocalScopedBitmap bitmapHolder(bitmapHandle);
1086 if (!bitmapHolder.valid()) return;
1087
1088 return bitmapHolder->bitmap().setImmutable();
1089}
1090
Chris Craik32054b02014-05-09 13:58:56 -07001091///////////////////////////////////////////////////////////////////////////////
1092
Daniel Micay76f6a862015-09-19 17:31:01 -04001093static const JNINativeMethod gBitmapMethods[] = {
Leon Scroggins III0e443d162018-12-19 11:38:35 -05001094 { "nativeCreate", "([IIIIIIZJ)Landroid/graphics/Bitmap;",
Chris Craik32054b02014-05-09 13:58:56 -07001095 (void*)Bitmap_creator },
1096 { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
1097 (void*)Bitmap_copy },
Riley Andrews721ae5f2015-05-11 16:08:22 -07001098 { "nativeCopyAshmem", "(J)Landroid/graphics/Bitmap;",
1099 (void*)Bitmap_copyAshmem },
Winsona5fdde92016-04-14 15:27:15 -07001100 { "nativeCopyAshmemConfig", "(JI)Landroid/graphics/Bitmap;",
1101 (void*)Bitmap_copyAshmemConfig },
Richard Uhler775873a2015-12-29 12:37:39 -08001102 { "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
Leon Scroggins IIIf8adae12018-05-24 15:25:08 -04001103 { "nativeRecycle", "(J)V", (void*)Bitmap_recycle },
sergeyv45082182016-09-29 18:25:40 -07001104 { "nativeReconfigure", "(JIIIZ)V", (void*)Bitmap_reconfigure },
Chris Craik32054b02014-05-09 13:58:56 -07001105 { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
1106 (void*)Bitmap_compress },
1107 { "nativeErase", "(JI)V", (void*)Bitmap_erase },
Leon Scroggins III94ba1002019-01-17 13:34:51 -05001108 { "nativeErase", "(JJJ)V", (void*)Bitmap_eraseLong },
Chris Craik32054b02014-05-09 13:58:56 -07001109 { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
1110 { "nativeConfig", "(J)I", (void*)Bitmap_config },
1111 { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001112 { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},
1113 { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},
1114 { "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied},
Chris Craik32054b02014-05-09 13:58:56 -07001115 { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
1116 { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
1117 { "nativeCreateFromParcel",
1118 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1119 (void*)Bitmap_createFromParcel },
John Reckefac0522020-01-24 16:04:26 -08001120 { "nativeWriteToParcel", "(JILandroid/os/Parcel;)Z",
Chris Craik32054b02014-05-09 13:58:56 -07001121 (void*)Bitmap_writeToParcel },
1122 { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
1123 (void*)Bitmap_extractAlpha },
1124 { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001125 { "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel },
Leon Scroggins III870053d2019-01-24 08:37:27 -05001126 { "nativeGetColor", "(JII)J", (void*)Bitmap_getColor },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001127 { "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1128 { "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel },
1129 { "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels },
Chris Craik32054b02014-05-09 13:58:56 -07001130 { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1131 (void*)Bitmap_copyPixelsToBuffer },
1132 { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1133 (void*)Bitmap_copyPixelsFromBuffer },
1134 { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
John Reck43871902016-08-01 14:39:24 -07001135 { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
sergeyv45082182016-09-29 18:25:40 -07001136 { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
sergeyv81f97ee2016-12-27 18:08:01 -08001137 { "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
sergeyv6e3658a2017-01-04 16:57:51 -08001138 (void*)Bitmap_copyPreserveInternalConfig },
Leon Scroggins III0e443d162018-12-19 11:38:35 -05001139 { "nativeWrapHardwareBufferBitmap", "(Landroid/hardware/HardwareBuffer;J)Landroid/graphics/Bitmap;",
rennb2e9f522018-09-26 10:49:00 -07001140 (void*) Bitmap_wrapHardwareBufferBitmap },
sergeyv6e3658a2017-01-04 16:57:51 -08001141 { "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
Romain Guyefb4b062017-02-27 11:00:04 -08001142 (void*) Bitmap_createGraphicBufferHandle },
Leon Scroggins III5a190b12020-02-18 13:52:18 -05001143 { "nativeGetHardwareBuffer", "(J)Landroid/hardware/HardwareBuffer;",
1144 (void*) Bitmap_getHardwareBuffer },
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -05001145 { "nativeComputeColorSpace", "(J)Landroid/graphics/ColorSpace;", (void*)Bitmap_computeColorSpace },
Derek Sollenberger202084c2019-01-14 13:55:08 -05001146 { "nativeSetColorSpace", "(JJ)V", (void*)Bitmap_setColorSpace },
Romain Guyefb4b062017-02-27 11:00:04 -08001147 { "nativeIsSRGB", "(J)Z", (void*)Bitmap_isSRGB },
Leon Scroggins IIIce89a6e2018-03-13 15:39:39 -04001148 { "nativeIsSRGBLinear", "(J)Z", (void*)Bitmap_isSRGBLinear},
Nader Jawade7b51292018-04-12 17:55:31 -07001149 { "nativeSetImmutable", "(J)V", (void*)Bitmap_setImmutable},
1150
1151 // ------------ @CriticalNative ----------------
1152 { "nativeIsImmutable", "(J)Z", (void*)Bitmap_isImmutable}
1153
Chris Craik32054b02014-05-09 13:58:56 -07001154};
1155
Chris Craik32054b02014-05-09 13:58:56 -07001156int register_android_graphics_Bitmap(JNIEnv* env)
1157{
Romain Guy95648b82017-04-13 18:43:42 -07001158 gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap"));
1159 gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J");
Leon Scroggins IIIbbdb7312019-01-31 14:35:54 -05001160 gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
Romain Guy95648b82017-04-13 18:43:42 -07001161 gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V");
Leon Scroggins III898ce752020-02-18 12:22:17 -05001162
1163#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
1164 void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
1165 AHardwareBuffer_fromHardwareBuffer =
1166 (AHB_from_HB)dlsym(handle_, "AHardwareBuffer_fromHardwareBuffer");
1167 LOG_ALWAYS_FATAL_IF(AHardwareBuffer_fromHardwareBuffer == nullptr,
1168 "Failed to find required symbol AHardwareBuffer_fromHardwareBuffer!");
Leon Scroggins III5a190b12020-02-18 13:52:18 -05001169
1170 AHardwareBuffer_toHardwareBuffer = (AHB_to_HB)dlsym(handle_, "AHardwareBuffer_toHardwareBuffer");
1171 LOG_ALWAYS_FATAL_IF(AHardwareBuffer_toHardwareBuffer == nullptr,
1172 " Failed to find required symbol AHardwareBuffer_toHardwareBuffer!");
Leon Scroggins III898ce752020-02-18 12:22:17 -05001173#endif
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001174 return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1175 NELEM(gBitmapMethods));
John Reck9192d5e2016-10-31 10:32:09 -07001176}