blob: b656bb08cba91c2e977c25bef296400d08f03936 [file] [log] [blame]
John Reckf29ed282015-04-07 07:32:03 -07001#define LOG_TAG "Bitmap"
John Reckf29ed282015-04-07 07:32:03 -07002#include "Bitmap.h"
3
Chris Craik32054b02014-05-09 13:58:56 -07004#include "SkBitmap.h"
5#include "SkPixelRef.h"
6#include "SkImageEncoder.h"
Leon Scroggins III57ee6202014-06-04 18:51:07 -04007#include "SkImageInfo.h"
Romain Guy9505a652016-12-14 09:43:50 -08008#include "SkColor.h"
Chris Craik32054b02014-05-09 13:58:56 -07009#include "SkColorPriv.h"
Romain Guy9505a652016-12-14 09:43:50 -080010#include "SkHalf.h"
11#include "SkPM4f.h"
12#include "SkPM4fPriv.h"
Chris Craik32054b02014-05-09 13:58:56 -070013#include "GraphicsJNI.h"
14#include "SkDither.h"
15#include "SkUnPreMultiply.h"
16#include "SkStream.h"
17
18#include <binder/Parcel.h>
19#include "android_os_Parcel.h"
20#include "android_util_Binder.h"
21#include "android_nio_utils.h"
22#include "CreateJavaOutputStreamAdaptor.h"
sergeyvdccca442016-03-21 15:38:21 -070023#include <hwui/Paint.h>
sergeyvc1c54062016-10-19 18:47:26 -070024#include <hwui/Bitmap.h>
John Reck43871902016-08-01 14:39:24 -070025#include <renderthread/RenderProxy.h>
Chris Craik32054b02014-05-09 13:58:56 -070026
Andreas Gampeed6b9df2014-11-20 22:02:20 -080027#include "core_jni_helpers.h"
28
Chris Craik32054b02014-05-09 13:58:56 -070029#include <jni.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
Riley Andrews8cee7c12015-11-01 23:36:04 -080034#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
Jeff Browna316c5d2015-06-05 15:14:06 -070035
sergeyvc69853c2016-10-07 14:14:09 -070036static jclass gBitmap_class;
37static jfieldID gBitmap_nativePtr;
38static jmethodID gBitmap_constructorMethodID;
39static jmethodID gBitmap_reinitMethodID;
40static jmethodID gBitmap_getAllocationByteCountMethodID;
41
John Reckf29ed282015-04-07 07:32:03 -070042namespace android {
43
sergeyvc1c54062016-10-19 18:47:26 -070044class BitmapWrapper {
John Reckf29ed282015-04-07 07:32:03 -070045public:
sergeyvc1c54062016-10-19 18:47:26 -070046 BitmapWrapper(Bitmap* bitmap)
47 : mBitmap(bitmap) { }
sergeyvc69853c2016-10-07 14:14:09 -070048
49 void freePixels() {
sergeyvc1c54062016-10-19 18:47:26 -070050 mInfo = mBitmap->info();
51 mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
52 mAllocationSize = mBitmap->getAllocationByteCount();
53 mRowBytes = mBitmap->rowBytes();
54 mGenerationId = mBitmap->getGenerationID();
55 mBitmap.reset();
John Reckf29ed282015-04-07 07:32:03 -070056 }
57
sergeyvc69853c2016-10-07 14:14:09 -070058 bool valid() {
sergeyvfc9999502016-10-17 13:07:38 -070059 return mBitmap;
John Reckf29ed282015-04-07 07:32:03 -070060 }
61
sergeyvaed7f582016-10-14 16:30:21 -070062 Bitmap& bitmap() {
63 assertValid();
64 return *mBitmap;
65 }
sergeyvc69853c2016-10-07 14:14:09 -070066
67 void assertValid() {
68 LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
69 }
70
71 void getSkBitmap(SkBitmap* outBitmap) {
72 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070073 mBitmap->getSkBitmap(outBitmap);
sergeyvc69853c2016-10-07 14:14:09 -070074 }
75
76 bool hasHardwareMipMap() {
sergeyvc1c54062016-10-19 18:47:26 -070077 if (mBitmap) {
78 return mBitmap->hasHardwareMipMap();
John Reckf29ed282015-04-07 07:32:03 -070079 }
John Reckf29ed282015-04-07 07:32:03 -070080 return mHasHardwareMipMap;
81 }
82
83 void setHasHardwareMipMap(bool hasMipMap) {
sergeyvc69853c2016-10-07 14:14:09 -070084 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070085 mBitmap->setHasHardwareMipMap(hasMipMap);
John Reckf29ed282015-04-07 07:32:03 -070086 }
87
sergeyvc69853c2016-10-07 14:14:09 -070088 void setAlphaType(SkAlphaType alphaType) {
89 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070090 mBitmap->setAlphaType(alphaType);
John Reckf29ed282015-04-07 07:32:03 -070091 }
92
sergeyvc69853c2016-10-07 14:14:09 -070093 const SkImageInfo& info() {
sergeyvc1c54062016-10-19 18:47:26 -070094 if (mBitmap) {
95 return mBitmap->info();
sergeyvc69853c2016-10-07 14:14:09 -070096 }
97 return mInfo;
John Reckf29ed282015-04-07 07:32:03 -070098 }
99
sergeyvc69853c2016-10-07 14:14:09 -0700100 size_t getAllocationByteCount() const {
sergeyvc1c54062016-10-19 18:47:26 -0700101 if (mBitmap) {
102 return mBitmap->getAllocationByteCount();
sergeyvc69853c2016-10-07 14:14:09 -0700103 }
104 return mAllocationSize;
John Reckf29ed282015-04-07 07:32:03 -0700105 }
106
sergeyvc69853c2016-10-07 14:14:09 -0700107 size_t rowBytes() const {
sergeyvc1c54062016-10-19 18:47:26 -0700108 if (mBitmap) {
109 return mBitmap->rowBytes();
sergeyvc69853c2016-10-07 14:14:09 -0700110 }
111 return mRowBytes;
112 }
113
114 uint32_t getGenerationID() const {
sergeyvc1c54062016-10-19 18:47:26 -0700115 if (mBitmap) {
116 return mBitmap->getGenerationID();
sergeyvc69853c2016-10-07 14:14:09 -0700117 }
118 return mGenerationId;
119 }
120
sergeyvc1c54062016-10-19 18:47:26 -0700121 ~BitmapWrapper() { }
sergeyvc69853c2016-10-07 14:14:09 -0700122
John Reckf29ed282015-04-07 07:32:03 -0700123private:
sergeyvc1c54062016-10-19 18:47:26 -0700124 sk_sp<Bitmap> mBitmap;
sergeyvc69853c2016-10-07 14:14:09 -0700125 SkImageInfo mInfo;
126 bool mHasHardwareMipMap;
127 size_t mAllocationSize;
128 size_t mRowBytes;
129 uint32_t mGenerationId;
John Reckf29ed282015-04-07 07:32:03 -0700130};
131
John Reckf29ed282015-04-07 07:32:03 -0700132// Convenience class that does not take a global ref on the pixels, relying
133// on the caller already having a local JNI ref
134class LocalScopedBitmap {
135public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -0700136 explicit LocalScopedBitmap(jlong bitmapHandle)
sergeyvc1c54062016-10-19 18:47:26 -0700137 : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
John Reckf29ed282015-04-07 07:32:03 -0700138
sergeyvc1c54062016-10-19 18:47:26 -0700139 BitmapWrapper* operator->() {
140 return mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700141 }
142
143 void* pixels() {
sergeyvaed7f582016-10-14 16:30:21 -0700144 return mBitmapWrapper->bitmap().pixels();
John Reckf29ed282015-04-07 07:32:03 -0700145 }
146
147 bool valid() {
sergeyvc1c54062016-10-19 18:47:26 -0700148 return mBitmapWrapper && mBitmapWrapper->valid();
John Reckf29ed282015-04-07 07:32:03 -0700149 }
150
151private:
sergeyvc1c54062016-10-19 18:47:26 -0700152 BitmapWrapper* mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700153};
154
sergeyvc69853c2016-10-07 14:14:09 -0700155namespace bitmap {
156
157// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
158static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
159 // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
160 // irrelevant. This just tests to ensure that the SkAlphaType is not
161 // opposite of isPremultiplied.
162 if (isPremultiplied) {
163 SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
164 } else {
165 SkASSERT(info.alphaType() != kPremul_SkAlphaType);
166 }
167}
168
169void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
170 bool isPremultiplied)
171{
172 // The caller needs to have already set the alpha type properly, so the
173 // native SkBitmap stays in sync with the Java Bitmap.
174 assert_premultiplied(info, isPremultiplied);
175
176 env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
177 info.width(), info.height(), isPremultiplied);
178}
179
180int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
181{
182 return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
183}
184
sergeyvc1c54062016-10-19 18:47:26 -0700185jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
sergeyvc69853c2016-10-07 14:14:09 -0700186 int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
187 int density) {
188 bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
189 bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
190 // The caller needs to have already set the alpha type properly, so the
191 // native SkBitmap stays in sync with the Java Bitmap.
sergeyvc1c54062016-10-19 18:47:26 -0700192 assert_premultiplied(bitmap->info(), isPremultiplied);
193 BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
sergeyvc69853c2016-10-07 14:14:09 -0700194 jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
sergeyvc1c54062016-10-19 18:47:26 -0700195 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
196 isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets);
sergeyvc69853c2016-10-07 14:14:09 -0700197
198 if (env->ExceptionCheck() != 0) {
199 ALOGE("*** Uncaught exception returned from Java call!\n");
200 env->ExceptionDescribe();
201 }
202 return obj;
203}
204
205void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
206 LocalScopedBitmap bitmap(bitmapHandle);
207 bitmap->getSkBitmap(outBitmap);
208}
209
sergeyvaed7f582016-10-14 16:30:21 -0700210Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700211 SkASSERT(env);
212 SkASSERT(bitmap);
213 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
214 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
215 LocalScopedBitmap localBitmap(bitmapHandle);
sergeyvc1c54062016-10-19 18:47:26 -0700216 return localBitmap->bitmap();
sergeyvc69853c2016-10-07 14:14:09 -0700217}
218
sergeyv5fd2a1c2016-10-20 15:04:28 -0700219Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) {
220 SkASSERT(env);
221 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
Chris Craik32054b02014-05-09 13:58:56 -0700232///////////////////////////////////////////////////////////////////////////////
233// Conversions to/from SkColor, for get/setPixels, and the create method, which
234// is basically like setPixels
235
236typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
237 int x, int y);
238
Romain Guy9505a652016-12-14 09:43:50 -0800239static void FromColor_F16(void* dst, const SkColor src[], int width,
240 int, int) {
241 uint64_t* d = (uint64_t*)dst;
242
243 for (int i = 0; i < width; i++) {
244 *d++ = SkColor4f::FromColor(*src++).premul().toF16();
245 }
246}
247
248static void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
249 int, int) {
250 uint64_t* d = (uint64_t*)dst;
251
252 for (int i = 0; i < width; i++) {
253 const float* color = SkColor4f::FromColor(*src++).vec();
254 uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
255 for (int i = 0; i < 4; ++i) {
256 scratch[i] = SkFloatToHalf(color[i]);
257 }
258 }
259}
260
Chris Craik32054b02014-05-09 13:58:56 -0700261static void FromColor_D32(void* dst, const SkColor src[], int width,
262 int, int) {
263 SkPMColor* d = (SkPMColor*)dst;
264
265 for (int i = 0; i < width; i++) {
266 *d++ = SkPreMultiplyColor(*src++);
267 }
268}
269
270static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
271 int, int) {
Dan Albert46d84442014-11-18 16:07:51 -0800272 // Needed to thwart the unreachable code detection from clang.
273 static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
274
Chris Craik32054b02014-05-09 13:58:56 -0700275 // SkColor's ordering may be different from SkPMColor
Dan Albert46d84442014-11-18 16:07:51 -0800276 if (sk_color_ne_zero) {
Chris Craik32054b02014-05-09 13:58:56 -0700277 memcpy(dst, src, width * sizeof(SkColor));
278 return;
279 }
280
281 // order isn't same, repack each pixel manually
282 SkPMColor* d = (SkPMColor*)dst;
283 for (int i = 0; i < width; i++) {
284 SkColor c = *src++;
285 *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
286 SkColorGetG(c), SkColorGetB(c));
287 }
288}
289
290static void FromColor_D565(void* dst, const SkColor src[], int width,
291 int x, int y) {
292 uint16_t* d = (uint16_t*)dst;
293
294 DITHER_565_SCAN(y);
295 for (int stop = x + width; x < stop; x++) {
296 SkColor c = *src++;
297 *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
298 DITHER_VALUE(x));
299 }
300}
301
302static void FromColor_D4444(void* dst, const SkColor src[], int width,
303 int x, int y) {
304 SkPMColor16* d = (SkPMColor16*)dst;
305
306 DITHER_4444_SCAN(y);
307 for (int stop = x + width; x < stop; x++) {
308 SkPMColor pmc = SkPreMultiplyColor(*src++);
309 *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
310// *d++ = SkPixel32ToPixel4444(pmc);
311 }
312}
313
314static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
315 int x, int y) {
316 SkPMColor16* d = (SkPMColor16*)dst;
317
318 DITHER_4444_SCAN(y);
319 for (int stop = x + width; x < stop; x++) {
320 SkColor c = *src++;
321
322 // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
323 SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
324 SkColorGetG(c), SkColorGetB(c));
325 *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
326// *d++ = SkPixel32ToPixel4444(pmc);
327 }
328}
329
Chris Craik6260b222015-07-24 15:17:29 -0700330static void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
331 uint8_t* d = (uint8_t*)dst;
332
333 for (int stop = x + width; x < stop; x++) {
334 *d++ = SkColorGetA(*src++);
335 }
336}
337
Chris Craik32054b02014-05-09 13:58:56 -0700338// can return NULL
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400339static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
340 switch (bitmap.colorType()) {
341 case kN32_SkColorType:
342 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
343 case kARGB_4444_SkColorType:
344 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
345 FromColor_D4444_Raw;
346 case kRGB_565_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700347 return FromColor_D565;
Chris Craik6260b222015-07-24 15:17:29 -0700348 case kAlpha_8_SkColorType:
349 return FromColor_DA8;
Romain Guy9505a652016-12-14 09:43:50 -0800350 case kRGBA_F16_SkColorType:
351 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
Chris Craik32054b02014-05-09 13:58:56 -0700352 default:
353 break;
354 }
355 return NULL;
356}
357
358bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400359 int x, int y, int width, int height, const SkBitmap& dstBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700360 SkAutoLockPixels alp(dstBitmap);
361 void* dst = dstBitmap.getPixels();
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400362 FromColorProc proc = ChooseFromColorProc(dstBitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700363
364 if (NULL == dst || NULL == proc) {
365 return false;
366 }
367
368 const jint* array = env->GetIntArrayElements(srcColors, NULL);
369 const SkColor* src = (const SkColor*)array + srcOffset;
370
371 // reset to to actual choice from caller
372 dst = dstBitmap.getAddr(x, y);
373 // now copy/convert each scanline
374 for (int y = 0; y < height; y++) {
375 proc(dst, src, width, x, y);
376 src += srcStride;
377 dst = (char*)dst + dstBitmap.rowBytes();
378 }
379
380 dstBitmap.notifyPixelsChanged();
381
Romain Guy9505a652016-12-14 09:43:50 -0800382 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
Chris Craik32054b02014-05-09 13:58:56 -0700383 return true;
384}
385
386//////////////////// ToColor procs
387
388typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
389 SkColorTable*);
390
Romain Guy9505a652016-12-14 09:43:50 -0800391static void ToColor_F16_Alpha(SkColor dst[], const void* src, int width,
392 SkColorTable*) {
393 SkASSERT(width > 0);
394 uint64_t* s = (uint64_t*)src;
395 do {
396 *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
397 } while (--width != 0);
398}
399
400static void ToColor_F16_Raw(SkColor dst[], const void* src, int width,
401 SkColorTable*) {
402 SkASSERT(width > 0);
403 uint64_t* s = (uint64_t*)src;
404 do {
405 *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
406 } while (--width != 0);
407}
408
Chris Craik32054b02014-05-09 13:58:56 -0700409static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
410 SkColorTable*) {
411 SkASSERT(width > 0);
412 const SkPMColor* s = (const SkPMColor*)src;
413 do {
414 *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
415 } while (--width != 0);
416}
417
418static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
419 SkColorTable*) {
420 SkASSERT(width > 0);
421 const SkPMColor* s = (const SkPMColor*)src;
422 do {
423 SkPMColor c = *s++;
424 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
425 SkGetPackedG32(c), SkGetPackedB32(c));
426 } while (--width != 0);
427}
428
429static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
430 SkColorTable*) {
431 SkASSERT(width > 0);
432 const SkPMColor* s = (const SkPMColor*)src;
433 do {
434 SkPMColor c = *s++;
435 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
436 SkGetPackedB32(c));
437 } while (--width != 0);
438}
439
440static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
441 SkColorTable*) {
442 SkASSERT(width > 0);
443 const SkPMColor16* s = (const SkPMColor16*)src;
444 do {
445 *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
446 } while (--width != 0);
447}
448
449static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
450 SkColorTable*) {
451 SkASSERT(width > 0);
452 const SkPMColor16* s = (const SkPMColor16*)src;
453 do {
454 SkPMColor c = SkPixel4444ToPixel32(*s++);
455 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
456 SkGetPackedG32(c), SkGetPackedB32(c));
457 } while (--width != 0);
458}
459
460static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
461 SkColorTable*) {
462 SkASSERT(width > 0);
463 const SkPMColor16* s = (const SkPMColor16*)src;
464 do {
465 SkPMColor c = SkPixel4444ToPixel32(*s++);
466 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
467 SkGetPackedB32(c));
468 } while (--width != 0);
469}
470
471static void ToColor_S565(SkColor dst[], const void* src, int width,
472 SkColorTable*) {
473 SkASSERT(width > 0);
474 const uint16_t* s = (const uint16_t*)src;
475 do {
476 uint16_t c = *s++;
477 *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
478 SkPacked16ToB32(c));
479 } while (--width != 0);
480}
481
482static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
483 SkColorTable* ctable) {
484 SkASSERT(width > 0);
485 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500486 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700487 do {
488 *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
489 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700490}
491
492static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
493 SkColorTable* ctable) {
494 SkASSERT(width > 0);
495 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500496 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700497 do {
498 SkPMColor c = colors[*s++];
499 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
500 SkGetPackedG32(c), SkGetPackedB32(c));
501 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700502}
503
504static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
505 SkColorTable* ctable) {
506 SkASSERT(width > 0);
507 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500508 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700509 do {
510 SkPMColor c = colors[*s++];
511 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
512 SkGetPackedB32(c));
513 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700514}
515
Chris Craik6260b222015-07-24 15:17:29 -0700516static void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
517 SkASSERT(width > 0);
518 const uint8_t* s = (const uint8_t*)src;
519 do {
520 uint8_t c = *s++;
521 *dst++ = SkColorSetARGB(c, c, c, c);
522 } while (--width != 0);
523}
524
Chris Craik32054b02014-05-09 13:58:56 -0700525// can return NULL
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400526static ToColorProc ChooseToColorProc(const SkBitmap& src) {
Mike Reedb9330552014-06-16 17:31:48 -0400527 switch (src.colorType()) {
528 case kN32_SkColorType:
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400529 switch (src.alphaType()) {
530 case kOpaque_SkAlphaType:
531 return ToColor_S32_Opaque;
532 case kPremul_SkAlphaType:
533 return ToColor_S32_Alpha;
534 case kUnpremul_SkAlphaType:
535 return ToColor_S32_Raw;
536 default:
537 return NULL;
538 }
Mike Reedb9330552014-06-16 17:31:48 -0400539 case kARGB_4444_SkColorType:
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400540 switch (src.alphaType()) {
541 case kOpaque_SkAlphaType:
542 return ToColor_S4444_Opaque;
543 case kPremul_SkAlphaType:
544 return ToColor_S4444_Alpha;
545 case kUnpremul_SkAlphaType:
546 return ToColor_S4444_Raw;
547 default:
548 return NULL;
549 }
Mike Reedb9330552014-06-16 17:31:48 -0400550 case kRGB_565_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700551 return ToColor_S565;
Mike Reedb9330552014-06-16 17:31:48 -0400552 case kIndex_8_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700553 if (src.getColorTable() == NULL) {
554 return NULL;
555 }
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400556 switch (src.alphaType()) {
557 case kOpaque_SkAlphaType:
558 return ToColor_SI8_Opaque;
559 case kPremul_SkAlphaType:
560 return ToColor_SI8_Alpha;
561 case kUnpremul_SkAlphaType:
562 return ToColor_SI8_Raw;
563 default:
564 return NULL;
565 }
Chris Craik6260b222015-07-24 15:17:29 -0700566 case kAlpha_8_SkColorType:
567 return ToColor_SA8;
Romain Guy9505a652016-12-14 09:43:50 -0800568 case kRGBA_F16_SkColorType:
569 switch (src.alphaType()) {
570 case kOpaque_SkAlphaType:
571 return ToColor_F16_Raw;
572 case kPremul_SkAlphaType:
573 return ToColor_F16_Alpha;
574 case kUnpremul_SkAlphaType:
575 return ToColor_F16_Raw;
576 default:
577 return NULL;
578 }
Chris Craik32054b02014-05-09 13:58:56 -0700579 default:
580 break;
581 }
582 return NULL;
583}
584
585///////////////////////////////////////////////////////////////////////////////
586///////////////////////////////////////////////////////////////////////////////
587
588static int getPremulBitmapCreateFlags(bool isMutable) {
sergeyvc69853c2016-10-07 14:14:09 -0700589 int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
590 if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
Chris Craik32054b02014-05-09 13:58:56 -0700591 return flags;
592}
593
594static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
595 jint offset, jint stride, jint width, jint height,
596 jint configHandle, jboolean isMutable) {
Mike Reed1103b322014-07-08 12:36:44 -0400597 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700598 if (NULL != jColors) {
599 size_t n = env->GetArrayLength(jColors);
600 if (n < SkAbs32(stride) * (size_t)height) {
601 doThrowAIOOBE(env);
602 return NULL;
603 }
604 }
605
606 // ARGB_4444 is a deprecated format, convert automatically to 8888
Mike Reedb9330552014-06-16 17:31:48 -0400607 if (colorType == kARGB_4444_SkColorType) {
608 colorType = kN32_SkColorType;
Chris Craik32054b02014-05-09 13:58:56 -0700609 }
610
611 SkBitmap bitmap;
Romain Guy253f2c22016-09-28 17:34:42 -0700612 bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
Romain Guy9505a652016-12-14 09:43:50 -0800613 GraphicsJNI::colorSpaceForType(colorType)));
Chris Craik32054b02014-05-09 13:58:56 -0700614
sergeyvc1c54062016-10-19 18:47:26 -0700615 sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
John Reckf29ed282015-04-07 07:32:03 -0700616 if (!nativeBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700617 return NULL;
618 }
619
620 if (jColors != NULL) {
Romain Guy9505a652016-12-14 09:43:50 -0800621 GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700622 }
623
sergeyvc36bd6c2016-10-11 15:49:16 -0700624 return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700625}
626
627static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
628 jint dstConfigHandle, jboolean isMutable) {
John Reckf29ed282015-04-07 07:32:03 -0700629 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700630 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Mike Reed1103b322014-07-08 12:36:44 -0400631 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyv45082182016-09-29 18:25:40 -0700632 SkBitmap result;
633 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700634
John Reckf29ed282015-04-07 07:32:03 -0700635 if (!src.copyTo(&result, dstCT, &allocator)) {
Chris Craik32054b02014-05-09 13:58:56 -0700636 return NULL;
637 }
sergeyvc1c54062016-10-19 18:47:26 -0700638 auto bitmap = allocator.getStorageObjAndReset();
639 return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700640}
641
sergeyvc1c54062016-10-19 18:47:26 -0700642static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700643 SkBitmap result;
644
645 AshmemPixelAllocator allocator(env);
Winsona5fdde92016-04-14 15:27:15 -0700646 if (!src.copyTo(&result, dstCT, &allocator)) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700647 return NULL;
648 }
sergeyvc1c54062016-10-19 18:47:26 -0700649 auto bitmap = allocator.getStorageObjAndReset();
650 bitmap->setImmutable();
651 return bitmap;
Winsona5fdde92016-04-14 15:27:15 -0700652}
653
654static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
655 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700656 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700657 SkColorType dstCT = src.colorType();
sergeyvc1c54062016-10-19 18:47:26 -0700658 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
659 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Winsona5fdde92016-04-14 15:27:15 -0700660 return ret;
661}
662
663static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
664 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700665 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700666 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyvc1c54062016-10-19 18:47:26 -0700667 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
668 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Riley Andrews721ae5f2015-05-11 16:08:22 -0700669 return ret;
670}
671
sergeyvc1c54062016-10-19 18:47:26 -0700672static void Bitmap_destruct(BitmapWrapper* bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700673 delete bitmap;
Chris Craik32054b02014-05-09 13:58:56 -0700674}
675
Richard Uhler775873a2015-12-29 12:37:39 -0800676static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
677 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
678}
679
Chris Craik32054b02014-05-09 13:58:56 -0700680static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700681 LocalScopedBitmap bitmap(bitmapHandle);
682 bitmap->freePixels();
Chris Craik32054b02014-05-09 13:58:56 -0700683 return JNI_TRUE;
684}
685
686static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
sergeyv45082182016-09-29 18:25:40 -0700687 jint width, jint height, jint configHandle, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700688 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700689 bitmap->assertValid();
Mike Reed1103b322014-07-08 12:36:44 -0400690 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400691
692 // ARGB_4444 is a deprecated format, convert automatically to 8888
693 if (colorType == kARGB_4444_SkColorType) {
694 colorType = kN32_SkColorType;
695 }
sergeyv45082182016-09-29 18:25:40 -0700696 size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
697 if (requestedSize > bitmap->getAllocationByteCount()) {
Chris Craik32054b02014-05-09 13:58:56 -0700698 // done in native as there's no way to get BytesPerPixel in Java
699 doThrowIAE(env, "Bitmap not large enough to support new configuration");
700 return;
701 }
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400702 SkAlphaType alphaType;
John Reckf29ed282015-04-07 07:32:03 -0700703 if (bitmap->info().colorType() != kRGB_565_SkColorType
704 && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400705 // If the original bitmap was set to opaque, keep that setting, unless it
706 // was 565, which is required to be opaque.
707 alphaType = kOpaque_SkAlphaType;
708 } else {
709 // Otherwise respect the premultiplied request.
710 alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
711 }
sergeyvaed7f582016-10-14 16:30:21 -0700712 bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
sergeyv7d5219f2016-11-03 16:18:16 -0700713 sk_ref_sp(bitmap->info().colorSpace())));
Chris Craik32054b02014-05-09 13:58:56 -0700714}
715
716// These must match the int values in Bitmap.java
717enum JavaEncodeFormat {
718 kJPEG_JavaEncodeFormat = 0,
719 kPNG_JavaEncodeFormat = 1,
720 kWEBP_JavaEncodeFormat = 2
721};
722
723static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
724 jint format, jint quality,
725 jobject jstream, jbyteArray jstorage) {
Hal Canary10219fb2016-11-23 20:41:22 -0500726 SkEncodedImageFormat fm;
Chris Craik32054b02014-05-09 13:58:56 -0700727 switch (format) {
728 case kJPEG_JavaEncodeFormat:
Hal Canary10219fb2016-11-23 20:41:22 -0500729 fm = SkEncodedImageFormat::kJPEG;
Chris Craik32054b02014-05-09 13:58:56 -0700730 break;
731 case kPNG_JavaEncodeFormat:
Hal Canary10219fb2016-11-23 20:41:22 -0500732 fm = SkEncodedImageFormat::kPNG;
Chris Craik32054b02014-05-09 13:58:56 -0700733 break;
734 case kWEBP_JavaEncodeFormat:
Hal Canary10219fb2016-11-23 20:41:22 -0500735 fm = SkEncodedImageFormat::kWEBP;
Chris Craik32054b02014-05-09 13:58:56 -0700736 break;
737 default:
738 return JNI_FALSE;
739 }
740
Hal Canary10219fb2016-11-23 20:41:22 -0500741 LocalScopedBitmap bitmap(bitmapHandle);
John Reckf29ed282015-04-07 07:32:03 -0700742 if (!bitmap.valid()) {
743 return JNI_FALSE;
744 }
745
John Reckf29ed282015-04-07 07:32:03 -0700746 std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
747 if (!strm.get()) {
748 return JNI_FALSE;
749 }
Chris Craik32054b02014-05-09 13:58:56 -0700750
Hal Canary10219fb2016-11-23 20:41:22 -0500751 SkBitmap skbitmap;
752 bitmap->getSkBitmap(&skbitmap);
753 return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700754}
755
756static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
John Reckf29ed282015-04-07 07:32:03 -0700757 LocalScopedBitmap bitmap(bitmapHandle);
758 SkBitmap skBitmap;
759 bitmap->getSkBitmap(&skBitmap);
760 skBitmap.eraseColor(color);
Chris Craik32054b02014-05-09 13:58:56 -0700761}
762
763static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700764 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700765 return static_cast<jint>(bitmap->rowBytes());
766}
767
768static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700769 LocalScopedBitmap bitmap(bitmapHandle);
sergeyv19b4b012016-12-13 16:06:00 -0800770 if (bitmap->bitmap().isHardware()) {
771 return GraphicsJNI::hardwareLegacyBitmapConfig();
772 }
John Reckf29ed282015-04-07 07:32:03 -0700773 return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
Chris Craik32054b02014-05-09 13:58:56 -0700774}
775
776static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700777 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700778 return static_cast<jint>(bitmap->getGenerationID());
Chris Craik32054b02014-05-09 13:58:56 -0700779}
780
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400781static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700782 LocalScopedBitmap bitmap(bitmapHandle);
783 if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400784 return JNI_TRUE;
785 }
786 return JNI_FALSE;
787}
788
Chris Craik32054b02014-05-09 13:58:56 -0700789static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700790 LocalScopedBitmap bitmap(bitmapHandle);
791 return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700792}
793
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400794static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
795 jboolean hasAlpha, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700796 LocalScopedBitmap bitmap(bitmapHandle);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400797 if (hasAlpha) {
John Reck0781a2f2015-05-27 16:29:17 -0700798 bitmap->setAlphaType(
John Reckf29ed282015-04-07 07:32:03 -0700799 requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
Chris Craik32054b02014-05-09 13:58:56 -0700800 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700801 bitmap->setAlphaType(kOpaque_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400802 }
803}
804
805static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
806 jboolean isPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700807 LocalScopedBitmap bitmap(bitmapHandle);
808 if (!bitmap->info().isOpaque()) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400809 if (isPremul) {
John Reck0781a2f2015-05-27 16:29:17 -0700810 bitmap->setAlphaType(kPremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400811 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700812 bitmap->setAlphaType(kUnpremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400813 }
Chris Craik32054b02014-05-09 13:58:56 -0700814 }
815}
816
817static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700818 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700819 return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
820}
821
822static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
823 jboolean hasMipMap) {
John Reckf29ed282015-04-07 07:32:03 -0700824 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700825 bitmap->setHasHardwareMipMap(hasMipMap);
826}
827
828///////////////////////////////////////////////////////////////////////////////
829
830static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
831 if (parcel == NULL) {
832 SkDebugf("-------- unparcel parcel is NULL\n");
833 return NULL;
834 }
835
836 android::Parcel* p = android::parcelForJavaObject(env, parcel);
837
Mike Reedb9330552014-06-16 17:31:48 -0400838 const bool isMutable = p->readInt32() != 0;
839 const SkColorType colorType = (SkColorType)p->readInt32();
840 const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
Romain Guy253f2c22016-09-28 17:34:42 -0700841 const bool isSRGB = p->readInt32() != 0;
Mike Reedb9330552014-06-16 17:31:48 -0400842 const int width = p->readInt32();
843 const int height = p->readInt32();
844 const int rowBytes = p->readInt32();
845 const int density = p->readInt32();
Chris Craik32054b02014-05-09 13:58:56 -0700846
Mike Reedb9330552014-06-16 17:31:48 -0400847 if (kN32_SkColorType != colorType &&
Romain Guy9505a652016-12-14 09:43:50 -0800848 kRGBA_F16_SkColorType != colorType &&
Mike Reedb9330552014-06-16 17:31:48 -0400849 kRGB_565_SkColorType != colorType &&
850 kARGB_4444_SkColorType != colorType &&
851 kIndex_8_SkColorType != colorType &&
852 kAlpha_8_SkColorType != colorType) {
853 SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
Chris Craik32054b02014-05-09 13:58:56 -0700854 return NULL;
855 }
856
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400857 std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700858
Romain Guy9505a652016-12-14 09:43:50 -0800859 sk_sp<SkColorSpace> colorSpace;
860 if (kRGBA_F16_SkColorType == colorType) {
861 colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named);
862 } else {
863 colorSpace = isSRGB ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : nullptr;
864 }
865
866 if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
867 rowBytes)) {
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400868 return NULL;
869 }
Chris Craik32054b02014-05-09 13:58:56 -0700870
871 SkColorTable* ctable = NULL;
Mike Reedb9330552014-06-16 17:31:48 -0400872 if (colorType == kIndex_8_SkColorType) {
Chris Craik32054b02014-05-09 13:58:56 -0700873 int count = p->readInt32();
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400874 if (count < 0 || count > 256) {
875 // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
876 // inclusive.
877 return NULL;
878 }
Chris Craik32054b02014-05-09 13:58:56 -0700879 if (count > 0) {
880 size_t size = count * sizeof(SkPMColor);
881 const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400882 if (src == NULL) {
883 return NULL;
884 }
Chris Craik32054b02014-05-09 13:58:56 -0700885 ctable = new SkColorTable(src, count);
886 }
887 }
888
Jeff Browna316c5d2015-06-05 15:14:06 -0700889 // Read the bitmap blob.
890 size_t size = bitmap->getSize();
891 android::Parcel::ReadableBlob blob;
892 android::status_t status = p->readBlob(size, &blob);
893 if (status) {
Chris Craik32054b02014-05-09 13:58:56 -0700894 SkSafeUnref(ctable);
Jeff Browna316c5d2015-06-05 15:14:06 -0700895 doThrowRE(env, "Could not read bitmap blob.");
Chris Craik32054b02014-05-09 13:58:56 -0700896 return NULL;
897 }
898
Jeff Browna316c5d2015-06-05 15:14:06 -0700899 // Map the bitmap in place from the ashmem region if possible otherwise copy.
sergeyvc1c54062016-10-19 18:47:26 -0700900 sk_sp<Bitmap> nativeBitmap;
Riley Andrews8cee7c12015-11-01 23:36:04 -0800901 if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700902#if DEBUG_PARCEL
903 ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
904 "(fds %s)",
905 isMutable ? "mutable" : "immutable",
906 blob.isMutable() ? "mutable" : "immutable",
907 p->allowFds() ? "allowed" : "forbidden");
908#endif
909 // Dup the file descriptor so we can keep a reference to it after the Parcel
910 // is disposed.
911 int dupFd = dup(blob.fd());
912 if (dupFd < 0) {
Erik Wolsheimer211abad2015-11-13 11:54:47 -0800913 ALOGE("Error allocating dup fd. Error:%d", errno);
Jeff Browna316c5d2015-06-05 15:14:06 -0700914 blob.release();
915 SkSafeUnref(ctable);
916 doThrowRE(env, "Could not allocate dup blob fd.");
917 return NULL;
918 }
919
920 // Map the pixels in place and take ownership of the ashmem region.
sergeyvc1c54062016-10-19 18:47:26 -0700921 nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
sergeyvc36bd6c2016-10-11 15:49:16 -0700922 ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
Jeff Browna316c5d2015-06-05 15:14:06 -0700923 SkSafeUnref(ctable);
924 if (!nativeBitmap) {
925 close(dupFd);
926 blob.release();
927 doThrowRE(env, "Could not allocate ashmem pixel ref.");
928 return NULL;
929 }
930
931 // Clear the blob handle, don't release it.
932 blob.clear();
933 } else {
934#if DEBUG_PARCEL
935 if (blob.fd() >= 0) {
936 ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
937 "from immutable blob (fds %s)",
938 p->allowFds() ? "allowed" : "forbidden");
939 } else {
940 ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
941 "(fds %s)",
942 blob.isMutable() ? "mutable" : "immutable",
943 p->allowFds() ? "allowed" : "forbidden");
944 }
945#endif
946
947 // Copy the pixels into a new buffer.
sergeyvc1c54062016-10-19 18:47:26 -0700948 nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
Jeff Browna316c5d2015-06-05 15:14:06 -0700949 SkSafeUnref(ctable);
950 if (!nativeBitmap) {
951 blob.release();
952 doThrowRE(env, "Could not allocate java pixel ref.");
953 return NULL;
954 }
955 bitmap->lockPixels();
956 memcpy(bitmap->getPixels(), blob.data(), size);
957 bitmap->unlockPixels();
958
959 // Release the blob handle.
960 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700961 }
Chris Craik32054b02014-05-09 13:58:56 -0700962
sergeyvc36bd6c2016-10-11 15:49:16 -0700963 return createBitmap(env, nativeBitmap.release(),
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400964 getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
Chris Craik32054b02014-05-09 13:58:56 -0700965}
966
967static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
968 jlong bitmapHandle,
969 jboolean isMutable, jint density,
970 jobject parcel) {
Chris Craik32054b02014-05-09 13:58:56 -0700971 if (parcel == NULL) {
972 SkDebugf("------- writeToParcel null parcel\n");
973 return JNI_FALSE;
974 }
975
976 android::Parcel* p = android::parcelForJavaObject(env, parcel);
John Reckf29ed282015-04-07 07:32:03 -0700977 SkBitmap bitmap;
Riley Andrews39d7f302014-11-13 17:43:25 -0800978
sergeyvc1c54062016-10-19 18:47:26 -0700979 auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
980 bitmapWrapper->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700981
Mike Reedab12c1f2016-11-03 12:54:10 -0400982 sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
Romain Guy253f2c22016-09-28 17:34:42 -0700983 bool isSRGB = bitmap.colorSpace() == sRGB.get();
984
Chris Craik32054b02014-05-09 13:58:56 -0700985 p->writeInt32(isMutable);
John Reckf29ed282015-04-07 07:32:03 -0700986 p->writeInt32(bitmap.colorType());
987 p->writeInt32(bitmap.alphaType());
Romain Guy253f2c22016-09-28 17:34:42 -0700988 p->writeInt32(isSRGB); // TODO: We should write the color space (b/32072280)
John Reckf29ed282015-04-07 07:32:03 -0700989 p->writeInt32(bitmap.width());
990 p->writeInt32(bitmap.height());
991 p->writeInt32(bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -0700992 p->writeInt32(density);
993
John Reckf29ed282015-04-07 07:32:03 -0700994 if (bitmap.colorType() == kIndex_8_SkColorType) {
Leon Scroggins III66ce1c32016-02-02 11:11:55 -0500995 // The bitmap needs to be locked to access its color table.
996 SkAutoLockPixels alp(bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700997 SkColorTable* ctable = bitmap.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -0700998 if (ctable != NULL) {
999 int count = ctable->count();
1000 p->writeInt32(count);
1001 memcpy(p->writeInplace(count * sizeof(SkPMColor)),
Mike Reed71487eb2014-11-19 16:13:20 -05001002 ctable->readColors(), count * sizeof(SkPMColor));
Chris Craik32054b02014-05-09 13:58:56 -07001003 } else {
1004 p->writeInt32(0); // indicate no ctable
1005 }
1006 }
1007
Jeff Browna316c5d2015-06-05 15:14:06 -07001008 // Transfer the underlying ashmem region if we have one and it's immutable.
1009 android::status_t status;
sergeyvaed7f582016-10-14 16:30:21 -07001010 int fd = bitmapWrapper->bitmap().getAshmemFd();
Jeff Browna316c5d2015-06-05 15:14:06 -07001011 if (fd >= 0 && !isMutable && p->allowFds()) {
1012#if DEBUG_PARCEL
1013 ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
1014 "immutable blob (fds %s)",
1015 p->allowFds() ? "allowed" : "forbidden");
1016#endif
1017
1018 status = p->writeDupImmutableBlobFileDescriptor(fd);
1019 if (status) {
1020 doThrowRE(env, "Could not write bitmap blob file descriptor.");
Riley Andrews39d7f302014-11-13 17:43:25 -08001021 return JNI_FALSE;
1022 }
Jeff Browna316c5d2015-06-05 15:14:06 -07001023 return JNI_TRUE;
Riley Andrews39d7f302014-11-13 17:43:25 -08001024 }
Jeff Browna316c5d2015-06-05 15:14:06 -07001025
1026 // Copy the bitmap to a new blob.
1027 bool mutableCopy = isMutable;
1028#if DEBUG_PARCEL
1029 ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
1030 isMutable ? "mutable" : "immutable",
1031 mutableCopy ? "mutable" : "immutable",
1032 p->allowFds() ? "allowed" : "forbidden");
1033#endif
1034
1035 size_t size = bitmap.getSize();
1036 android::Parcel::WritableBlob blob;
1037 status = p->writeBlob(size, mutableCopy, &blob);
1038 if (status) {
1039 doThrowRE(env, "Could not copy bitmap to parcel blob.");
1040 return JNI_FALSE;
1041 }
1042
1043 bitmap.lockPixels();
1044 const void* pSrc = bitmap.getPixels();
1045 if (pSrc == NULL) {
1046 memset(blob.data(), 0, size);
1047 } else {
1048 memcpy(blob.data(), pSrc, size);
1049 }
1050 bitmap.unlockPixels();
1051
1052 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -07001053 return JNI_TRUE;
1054}
1055
1056static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
1057 jlong srcHandle, jlong paintHandle,
1058 jintArray offsetXY) {
John Reckf29ed282015-04-07 07:32:03 -07001059 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -07001060 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -04001061 const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
Chris Craik32054b02014-05-09 13:58:56 -07001062 SkIPoint offset;
John Reckf29ed282015-04-07 07:32:03 -07001063 SkBitmap dst;
sergeyv45082182016-09-29 18:25:40 -07001064 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -07001065
John Reckf29ed282015-04-07 07:32:03 -07001066 src.extractAlpha(&dst, paint, &allocator, &offset);
Chris Craik32054b02014-05-09 13:58:56 -07001067 // If Skia can't allocate pixels for destination bitmap, it resets
1068 // it, that is set its pixels buffer to NULL, and zero width and height.
John Reckf29ed282015-04-07 07:32:03 -07001069 if (dst.getPixels() == NULL && src.getPixels() != NULL) {
Chris Craik32054b02014-05-09 13:58:56 -07001070 doThrowOOME(env, "failed to allocate pixels for alpha");
1071 return NULL;
1072 }
1073 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
1074 int* array = env->GetIntArrayElements(offsetXY, NULL);
1075 array[0] = offset.fX;
1076 array[1] = offset.fY;
1077 env->ReleaseIntArrayElements(offsetXY, array, 0);
1078 }
1079
sergeyvc69853c2016-10-07 14:14:09 -07001080 return createBitmap(env, allocator.getStorageObjAndReset(),
John Reckf29ed282015-04-07 07:32:03 -07001081 getPremulBitmapCreateFlags(true));
Chris Craik32054b02014-05-09 13:58:56 -07001082}
1083
1084///////////////////////////////////////////////////////////////////////////////
1085
1086static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001087 jint x, jint y) {
John Reckf29ed282015-04-07 07:32:03 -07001088 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001089 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001090 SkAutoLockPixels alp(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001091
John Reckf29ed282015-04-07 07:32:03 -07001092 ToColorProc proc = ChooseToColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001093 if (NULL == proc) {
1094 return 0;
1095 }
John Reckf29ed282015-04-07 07:32:03 -07001096 const void* src = bitmap.getAddr(x, y);
Chris Craik32054b02014-05-09 13:58:56 -07001097 if (NULL == src) {
1098 return 0;
1099 }
1100
1101 SkColor dst[1];
John Reckf29ed282015-04-07 07:32:03 -07001102 proc(dst, src, 1, bitmap.getColorTable());
Chris Craik32054b02014-05-09 13:58:56 -07001103 return static_cast<jint>(dst[0]);
1104}
1105
1106static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1107 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001108 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -07001109 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001110 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001111 SkAutoLockPixels alp(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001112
John Reckf29ed282015-04-07 07:32:03 -07001113 ToColorProc proc = ChooseToColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001114 if (NULL == proc) {
1115 return;
1116 }
John Reckf29ed282015-04-07 07:32:03 -07001117 const void* src = bitmap.getAddr(x, y);
Chris Craik32054b02014-05-09 13:58:56 -07001118 if (NULL == src) {
1119 return;
1120 }
1121
John Reckf29ed282015-04-07 07:32:03 -07001122 SkColorTable* ctable = bitmap.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -07001123 jint* dst = env->GetIntArrayElements(pixelArray, NULL);
1124 SkColor* d = (SkColor*)dst + offset;
1125 while (--height >= 0) {
1126 proc(d, src, width, ctable);
1127 d += stride;
John Reckf29ed282015-04-07 07:32:03 -07001128 src = (void*)((const char*)src + bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -07001129 }
1130 env->ReleaseIntArrayElements(pixelArray, dst, 0);
1131}
1132
1133///////////////////////////////////////////////////////////////////////////////
1134
1135static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001136 jint x, jint y, jint colorHandle) {
John Reckf29ed282015-04-07 07:32:03 -07001137 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001138 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001139 SkColor color = static_cast<SkColor>(colorHandle);
John Reckf29ed282015-04-07 07:32:03 -07001140 SkAutoLockPixels alp(bitmap);
1141 if (NULL == bitmap.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -07001142 return;
1143 }
1144
John Reckf29ed282015-04-07 07:32:03 -07001145 FromColorProc proc = ChooseFromColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001146 if (NULL == proc) {
1147 return;
1148 }
1149
John Reckf29ed282015-04-07 07:32:03 -07001150 proc(bitmap.getAddr(x, y), &color, 1, x, y);
1151 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -07001152}
1153
1154static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1155 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001156 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -07001157 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001158 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001159 GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
John Reckf29ed282015-04-07 07:32:03 -07001160 x, y, width, height, bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001161}
1162
1163static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
1164 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -07001165 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001166 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001167 SkAutoLockPixels alp(bitmap);
1168 const void* src = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -07001169
1170 if (NULL != src) {
1171 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
1172
1173 // the java side has already checked that buffer is large enough
John Reckf29ed282015-04-07 07:32:03 -07001174 memcpy(abp.pointer(), src, bitmap.getSize());
Chris Craik32054b02014-05-09 13:58:56 -07001175 }
1176}
1177
1178static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
1179 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -07001180 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001181 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001182 SkAutoLockPixels alp(bitmap);
1183 void* dst = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -07001184
1185 if (NULL != dst) {
1186 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
1187 // the java side has already checked that buffer is large enough
John Reckf29ed282015-04-07 07:32:03 -07001188 memcpy(dst, abp.pointer(), bitmap.getSize());
1189 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -07001190 }
1191}
1192
1193static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
1194 jlong bm1Handle) {
John Reckf29ed282015-04-07 07:32:03 -07001195 SkBitmap bm0;
1196 SkBitmap bm1;
sergeyv1eabed32016-12-14 14:19:47 -08001197
1198 LocalScopedBitmap bitmap0(bm0Handle);
1199 LocalScopedBitmap bitmap1(bm1Handle);
1200
1201 // Paying the price for making Hardware Bitmap as Config:
1202 // later check for colorType will pass successfully,
1203 // because Hardware Config internally may be RGBA8888 or smth like that.
1204 if (bitmap0->bitmap().isHardware() != bitmap1->bitmap().isHardware()) {
1205 return JNI_FALSE;
1206 }
1207
1208 bitmap0->bitmap().getSkBitmap(&bm0);
1209 bitmap1->bitmap().getSkBitmap(&bm1);
John Reckf29ed282015-04-07 07:32:03 -07001210 if (bm0.width() != bm1.width() ||
1211 bm0.height() != bm1.height() ||
Romain Guy253f2c22016-09-28 17:34:42 -07001212 bm0.colorType() != bm1.colorType() ||
1213 bm0.alphaType() != bm1.alphaType() ||
1214 bm0.colorSpace() != bm1.colorSpace()) {
Chris Craik32054b02014-05-09 13:58:56 -07001215 return JNI_FALSE;
1216 }
1217
John Reckf29ed282015-04-07 07:32:03 -07001218 SkAutoLockPixels alp0(bm0);
1219 SkAutoLockPixels alp1(bm1);
Chris Craik32054b02014-05-09 13:58:56 -07001220
1221 // if we can't load the pixels, return false
John Reckf29ed282015-04-07 07:32:03 -07001222 if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -07001223 return JNI_FALSE;
1224 }
1225
John Reckf29ed282015-04-07 07:32:03 -07001226 if (bm0.colorType() == kIndex_8_SkColorType) {
1227 SkColorTable* ct0 = bm0.getColorTable();
1228 SkColorTable* ct1 = bm1.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -07001229 if (NULL == ct0 || NULL == ct1) {
1230 return JNI_FALSE;
1231 }
1232 if (ct0->count() != ct1->count()) {
1233 return JNI_FALSE;
1234 }
1235
Chris Craik32054b02014-05-09 13:58:56 -07001236 const size_t size = ct0->count() * sizeof(SkPMColor);
Mike Reed71487eb2014-11-19 16:13:20 -05001237 if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -07001238 return JNI_FALSE;
1239 }
1240 }
1241
1242 // now compare each scanline. We can't do the entire buffer at once,
1243 // since we don't care about the pixel values that might extend beyond
1244 // the width (since the scanline might be larger than the logical width)
John Reckf29ed282015-04-07 07:32:03 -07001245 const int h = bm0.height();
1246 const size_t size = bm0.width() * bm0.bytesPerPixel();
Chris Craik32054b02014-05-09 13:58:56 -07001247 for (int y = 0; y < h; y++) {
henry.uh_chen53001ca2014-07-03 20:40:22 +08001248 // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
1249 // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
1250 // and bm1 both have pixel data() (have passed NULL == getPixels() check),
1251 // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
1252 // to warn user those 2 unrecognized config bitmaps may be different.
John Reckf29ed282015-04-07 07:32:03 -07001253 void *bm0Addr = bm0.getAddr(0, y);
1254 void *bm1Addr = bm1.getAddr(0, y);
henry.uh_chen53001ca2014-07-03 20:40:22 +08001255
1256 if(bm0Addr == NULL || bm1Addr == NULL) {
1257 return JNI_FALSE;
1258 }
1259
1260 if (memcmp(bm0Addr, bm1Addr, size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -07001261 return JNI_FALSE;
1262 }
1263 }
1264 return JNI_TRUE;
1265}
1266
John Reck43871902016-08-01 14:39:24 -07001267static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
1268 LocalScopedBitmap bitmapHandle(bitmapPtr);
1269 if (!bitmapHandle.valid()) return;
sergeyvec4a4b12016-10-20 18:39:04 -07001270 android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
John Reck43871902016-08-01 14:39:24 -07001271}
1272
sergeyv45082182016-09-29 18:25:40 -07001273static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1274 LocalScopedBitmap bitmapHandle(bitmapPtr);
1275 return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1276}
1277
Chris Craik32054b02014-05-09 13:58:56 -07001278///////////////////////////////////////////////////////////////////////////////
sergeyvc69853c2016-10-07 14:14:09 -07001279static jclass make_globalref(JNIEnv* env, const char classname[])
1280{
1281 jclass c = env->FindClass(classname);
1282 SkASSERT(c);
1283 return (jclass) env->NewGlobalRef(c);
1284}
1285
1286static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1287 const char fieldname[], const char type[])
1288{
1289 jfieldID id = env->GetFieldID(clazz, fieldname, type);
1290 SkASSERT(id);
1291 return id;
1292}
Chris Craik32054b02014-05-09 13:58:56 -07001293
Daniel Micay76f6a862015-09-19 17:31:01 -04001294static const JNINativeMethod gBitmapMethods[] = {
Chris Craik32054b02014-05-09 13:58:56 -07001295 { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
1296 (void*)Bitmap_creator },
1297 { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
1298 (void*)Bitmap_copy },
Riley Andrews721ae5f2015-05-11 16:08:22 -07001299 { "nativeCopyAshmem", "(J)Landroid/graphics/Bitmap;",
1300 (void*)Bitmap_copyAshmem },
Winsona5fdde92016-04-14 15:27:15 -07001301 { "nativeCopyAshmemConfig", "(JI)Landroid/graphics/Bitmap;",
1302 (void*)Bitmap_copyAshmemConfig },
Richard Uhler775873a2015-12-29 12:37:39 -08001303 { "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
Chris Craik32054b02014-05-09 13:58:56 -07001304 { "nativeRecycle", "(J)Z", (void*)Bitmap_recycle },
sergeyv45082182016-09-29 18:25:40 -07001305 { "nativeReconfigure", "(JIIIZ)V", (void*)Bitmap_reconfigure },
Chris Craik32054b02014-05-09 13:58:56 -07001306 { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
1307 (void*)Bitmap_compress },
1308 { "nativeErase", "(JI)V", (void*)Bitmap_erase },
1309 { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
1310 { "nativeConfig", "(J)I", (void*)Bitmap_config },
1311 { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001312 { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},
1313 { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},
1314 { "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied},
Chris Craik32054b02014-05-09 13:58:56 -07001315 { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
1316 { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
1317 { "nativeCreateFromParcel",
1318 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1319 (void*)Bitmap_createFromParcel },
1320 { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",
1321 (void*)Bitmap_writeToParcel },
1322 { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
1323 (void*)Bitmap_extractAlpha },
1324 { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001325 { "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel },
1326 { "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1327 { "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel },
1328 { "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels },
Chris Craik32054b02014-05-09 13:58:56 -07001329 { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1330 (void*)Bitmap_copyPixelsToBuffer },
1331 { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1332 (void*)Bitmap_copyPixelsFromBuffer },
1333 { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
John Reck43871902016-08-01 14:39:24 -07001334 { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
sergeyv45082182016-09-29 18:25:40 -07001335 { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
Chris Craik32054b02014-05-09 13:58:56 -07001336};
1337
Chris Craik32054b02014-05-09 13:58:56 -07001338int register_android_graphics_Bitmap(JNIEnv* env)
1339{
sergeyvc69853c2016-10-07 14:14:09 -07001340 gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1341 gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1342 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1343 gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1344 gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001345 return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1346 NELEM(gBitmapMethods));
John Reck9192d5e2016-10-31 10:32:09 -07001347}