blob: b1b2959ee9457277cd6e267f83524f20516a18b6 [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"
Chris Craik32054b02014-05-09 13:58:56 -07008#include "SkColorPriv.h"
9#include "GraphicsJNI.h"
10#include "SkDither.h"
11#include "SkUnPreMultiply.h"
12#include "SkStream.h"
13
14#include <binder/Parcel.h>
15#include "android_os_Parcel.h"
16#include "android_util_Binder.h"
17#include "android_nio_utils.h"
18#include "CreateJavaOutputStreamAdaptor.h"
sergeyvdccca442016-03-21 15:38:21 -070019#include <hwui/Paint.h>
sergeyvc1c54062016-10-19 18:47:26 -070020#include <hwui/Bitmap.h>
John Reck43871902016-08-01 14:39:24 -070021#include <renderthread/RenderProxy.h>
Chris Craik32054b02014-05-09 13:58:56 -070022
Andreas Gampeed6b9df2014-11-20 22:02:20 -080023#include "core_jni_helpers.h"
24
Chris Craik32054b02014-05-09 13:58:56 -070025#include <jni.h>
Riley Andrews39d7f302014-11-13 17:43:25 -080026#include <memory>
27#include <string>
Chris Craik32054b02014-05-09 13:58:56 -070028
Jeff Browna316c5d2015-06-05 15:14:06 -070029#define DEBUG_PARCEL 0
Riley Andrews8cee7c12015-11-01 23:36:04 -080030#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
Jeff Browna316c5d2015-06-05 15:14:06 -070031
sergeyvc69853c2016-10-07 14:14:09 -070032static jclass gBitmap_class;
33static jfieldID gBitmap_nativePtr;
34static jmethodID gBitmap_constructorMethodID;
35static jmethodID gBitmap_reinitMethodID;
36static jmethodID gBitmap_getAllocationByteCountMethodID;
37
John Reckf29ed282015-04-07 07:32:03 -070038namespace android {
39
sergeyvc1c54062016-10-19 18:47:26 -070040class BitmapWrapper {
John Reckf29ed282015-04-07 07:32:03 -070041public:
sergeyvc1c54062016-10-19 18:47:26 -070042 BitmapWrapper(Bitmap* bitmap)
43 : mBitmap(bitmap) { }
sergeyvc69853c2016-10-07 14:14:09 -070044
45 void freePixels() {
sergeyvc1c54062016-10-19 18:47:26 -070046 mInfo = mBitmap->info();
47 mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
48 mAllocationSize = mBitmap->getAllocationByteCount();
49 mRowBytes = mBitmap->rowBytes();
50 mGenerationId = mBitmap->getGenerationID();
51 mBitmap.reset();
John Reckf29ed282015-04-07 07:32:03 -070052 }
53
sergeyvc69853c2016-10-07 14:14:09 -070054 bool valid() {
sergeyvfc9999502016-10-17 13:07:38 -070055 return mBitmap;
John Reckf29ed282015-04-07 07:32:03 -070056 }
57
sergeyvaed7f582016-10-14 16:30:21 -070058 Bitmap& bitmap() {
59 assertValid();
60 return *mBitmap;
61 }
sergeyvc69853c2016-10-07 14:14:09 -070062
63 void assertValid() {
64 LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
65 }
66
67 void getSkBitmap(SkBitmap* outBitmap) {
68 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070069 mBitmap->getSkBitmap(outBitmap);
sergeyvc69853c2016-10-07 14:14:09 -070070 }
71
72 bool hasHardwareMipMap() {
sergeyvc1c54062016-10-19 18:47:26 -070073 if (mBitmap) {
74 return mBitmap->hasHardwareMipMap();
John Reckf29ed282015-04-07 07:32:03 -070075 }
John Reckf29ed282015-04-07 07:32:03 -070076 return mHasHardwareMipMap;
77 }
78
79 void setHasHardwareMipMap(bool hasMipMap) {
sergeyvc69853c2016-10-07 14:14:09 -070080 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070081 mBitmap->setHasHardwareMipMap(hasMipMap);
John Reckf29ed282015-04-07 07:32:03 -070082 }
83
sergeyvc69853c2016-10-07 14:14:09 -070084 void setAlphaType(SkAlphaType alphaType) {
85 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070086 mBitmap->setAlphaType(alphaType);
John Reckf29ed282015-04-07 07:32:03 -070087 }
88
sergeyvc69853c2016-10-07 14:14:09 -070089 const SkImageInfo& info() {
sergeyvc1c54062016-10-19 18:47:26 -070090 if (mBitmap) {
91 return mBitmap->info();
sergeyvc69853c2016-10-07 14:14:09 -070092 }
93 return mInfo;
John Reckf29ed282015-04-07 07:32:03 -070094 }
95
sergeyvc69853c2016-10-07 14:14:09 -070096 size_t getAllocationByteCount() const {
sergeyvc1c54062016-10-19 18:47:26 -070097 if (mBitmap) {
98 return mBitmap->getAllocationByteCount();
sergeyvc69853c2016-10-07 14:14:09 -070099 }
100 return mAllocationSize;
John Reckf29ed282015-04-07 07:32:03 -0700101 }
102
sergeyvc69853c2016-10-07 14:14:09 -0700103 size_t rowBytes() const {
sergeyvc1c54062016-10-19 18:47:26 -0700104 if (mBitmap) {
105 return mBitmap->rowBytes();
sergeyvc69853c2016-10-07 14:14:09 -0700106 }
107 return mRowBytes;
108 }
109
110 uint32_t getGenerationID() const {
sergeyvc1c54062016-10-19 18:47:26 -0700111 if (mBitmap) {
112 return mBitmap->getGenerationID();
sergeyvc69853c2016-10-07 14:14:09 -0700113 }
114 return mGenerationId;
115 }
116
sergeyvc1c54062016-10-19 18:47:26 -0700117 ~BitmapWrapper() { }
sergeyvc69853c2016-10-07 14:14:09 -0700118
John Reckf29ed282015-04-07 07:32:03 -0700119private:
sergeyvc1c54062016-10-19 18:47:26 -0700120 sk_sp<Bitmap> mBitmap;
sergeyvc69853c2016-10-07 14:14:09 -0700121 SkImageInfo mInfo;
122 bool mHasHardwareMipMap;
123 size_t mAllocationSize;
124 size_t mRowBytes;
125 uint32_t mGenerationId;
John Reckf29ed282015-04-07 07:32:03 -0700126};
127
John Reckf29ed282015-04-07 07:32:03 -0700128// Convenience class that does not take a global ref on the pixels, relying
129// on the caller already having a local JNI ref
130class LocalScopedBitmap {
131public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -0700132 explicit LocalScopedBitmap(jlong bitmapHandle)
sergeyvc1c54062016-10-19 18:47:26 -0700133 : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
John Reckf29ed282015-04-07 07:32:03 -0700134
sergeyvc1c54062016-10-19 18:47:26 -0700135 BitmapWrapper* operator->() {
136 return mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700137 }
138
139 void* pixels() {
sergeyvaed7f582016-10-14 16:30:21 -0700140 return mBitmapWrapper->bitmap().pixels();
John Reckf29ed282015-04-07 07:32:03 -0700141 }
142
143 bool valid() {
sergeyvc1c54062016-10-19 18:47:26 -0700144 return mBitmapWrapper && mBitmapWrapper->valid();
John Reckf29ed282015-04-07 07:32:03 -0700145 }
146
147private:
sergeyvc1c54062016-10-19 18:47:26 -0700148 BitmapWrapper* mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700149};
150
sergeyvc69853c2016-10-07 14:14:09 -0700151namespace bitmap {
152
153// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
154static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
155 // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
156 // irrelevant. This just tests to ensure that the SkAlphaType is not
157 // opposite of isPremultiplied.
158 if (isPremultiplied) {
159 SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
160 } else {
161 SkASSERT(info.alphaType() != kPremul_SkAlphaType);
162 }
163}
164
165void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
166 bool isPremultiplied)
167{
168 // The caller needs to have already set the alpha type properly, so the
169 // native SkBitmap stays in sync with the Java Bitmap.
170 assert_premultiplied(info, isPremultiplied);
171
172 env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
173 info.width(), info.height(), isPremultiplied);
174}
175
176int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
177{
178 return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
179}
180
sergeyvc1c54062016-10-19 18:47:26 -0700181jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
sergeyvc69853c2016-10-07 14:14:09 -0700182 int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
183 int density) {
184 bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
185 bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
186 // The caller needs to have already set the alpha type properly, so the
187 // native SkBitmap stays in sync with the Java Bitmap.
sergeyvc1c54062016-10-19 18:47:26 -0700188 assert_premultiplied(bitmap->info(), isPremultiplied);
189 BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
sergeyvc69853c2016-10-07 14:14:09 -0700190 jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
sergeyvc1c54062016-10-19 18:47:26 -0700191 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
192 isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets);
sergeyvc69853c2016-10-07 14:14:09 -0700193
194 if (env->ExceptionCheck() != 0) {
195 ALOGE("*** Uncaught exception returned from Java call!\n");
196 env->ExceptionDescribe();
197 }
198 return obj;
199}
200
201void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
202 LocalScopedBitmap bitmap(bitmapHandle);
203 bitmap->getSkBitmap(outBitmap);
204}
205
sergeyvaed7f582016-10-14 16:30:21 -0700206Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700207 SkASSERT(env);
208 SkASSERT(bitmap);
209 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
210 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
211 LocalScopedBitmap localBitmap(bitmapHandle);
sergeyvc1c54062016-10-19 18:47:26 -0700212 return localBitmap->bitmap();
sergeyvc69853c2016-10-07 14:14:09 -0700213}
214
sergeyv5fd2a1c2016-10-20 15:04:28 -0700215Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) {
216 SkASSERT(env);
217 LocalScopedBitmap localBitmap(bitmapHandle);
218 return localBitmap->bitmap();
219}
220
sergeyvc69853c2016-10-07 14:14:09 -0700221} // namespace bitmap
222
223} // namespace android
224
225using namespace android;
226using namespace android::bitmap;
227
Chris Craik32054b02014-05-09 13:58:56 -0700228///////////////////////////////////////////////////////////////////////////////
229// Conversions to/from SkColor, for get/setPixels, and the create method, which
230// is basically like setPixels
231
232typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
233 int x, int y);
234
235static void FromColor_D32(void* dst, const SkColor src[], int width,
236 int, int) {
237 SkPMColor* d = (SkPMColor*)dst;
238
239 for (int i = 0; i < width; i++) {
240 *d++ = SkPreMultiplyColor(*src++);
241 }
242}
243
244static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
245 int, int) {
Dan Albert46d84442014-11-18 16:07:51 -0800246 // Needed to thwart the unreachable code detection from clang.
247 static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
248
Chris Craik32054b02014-05-09 13:58:56 -0700249 // SkColor's ordering may be different from SkPMColor
Dan Albert46d84442014-11-18 16:07:51 -0800250 if (sk_color_ne_zero) {
Chris Craik32054b02014-05-09 13:58:56 -0700251 memcpy(dst, src, width * sizeof(SkColor));
252 return;
253 }
254
255 // order isn't same, repack each pixel manually
256 SkPMColor* d = (SkPMColor*)dst;
257 for (int i = 0; i < width; i++) {
258 SkColor c = *src++;
259 *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
260 SkColorGetG(c), SkColorGetB(c));
261 }
262}
263
264static void FromColor_D565(void* dst, const SkColor src[], int width,
265 int x, int y) {
266 uint16_t* d = (uint16_t*)dst;
267
268 DITHER_565_SCAN(y);
269 for (int stop = x + width; x < stop; x++) {
270 SkColor c = *src++;
271 *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
272 DITHER_VALUE(x));
273 }
274}
275
276static void FromColor_D4444(void* dst, const SkColor src[], int width,
277 int x, int y) {
278 SkPMColor16* d = (SkPMColor16*)dst;
279
280 DITHER_4444_SCAN(y);
281 for (int stop = x + width; x < stop; x++) {
282 SkPMColor pmc = SkPreMultiplyColor(*src++);
283 *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
284// *d++ = SkPixel32ToPixel4444(pmc);
285 }
286}
287
288static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
289 int x, int y) {
290 SkPMColor16* d = (SkPMColor16*)dst;
291
292 DITHER_4444_SCAN(y);
293 for (int stop = x + width; x < stop; x++) {
294 SkColor c = *src++;
295
296 // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
297 SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
298 SkColorGetG(c), SkColorGetB(c));
299 *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
300// *d++ = SkPixel32ToPixel4444(pmc);
301 }
302}
303
Chris Craik6260b222015-07-24 15:17:29 -0700304static void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
305 uint8_t* d = (uint8_t*)dst;
306
307 for (int stop = x + width; x < stop; x++) {
308 *d++ = SkColorGetA(*src++);
309 }
310}
311
Chris Craik32054b02014-05-09 13:58:56 -0700312// can return NULL
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400313static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
314 switch (bitmap.colorType()) {
315 case kN32_SkColorType:
316 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
317 case kARGB_4444_SkColorType:
318 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
319 FromColor_D4444_Raw;
320 case kRGB_565_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700321 return FromColor_D565;
Chris Craik6260b222015-07-24 15:17:29 -0700322 case kAlpha_8_SkColorType:
323 return FromColor_DA8;
Chris Craik32054b02014-05-09 13:58:56 -0700324 default:
325 break;
326 }
327 return NULL;
328}
329
330bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400331 int x, int y, int width, int height, const SkBitmap& dstBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700332 SkAutoLockPixels alp(dstBitmap);
333 void* dst = dstBitmap.getPixels();
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400334 FromColorProc proc = ChooseFromColorProc(dstBitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700335
336 if (NULL == dst || NULL == proc) {
337 return false;
338 }
339
340 const jint* array = env->GetIntArrayElements(srcColors, NULL);
341 const SkColor* src = (const SkColor*)array + srcOffset;
342
343 // reset to to actual choice from caller
344 dst = dstBitmap.getAddr(x, y);
345 // now copy/convert each scanline
346 for (int y = 0; y < height; y++) {
347 proc(dst, src, width, x, y);
348 src += srcStride;
349 dst = (char*)dst + dstBitmap.rowBytes();
350 }
351
352 dstBitmap.notifyPixelsChanged();
353
354 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
355 JNI_ABORT);
356 return true;
357}
358
359//////////////////// ToColor procs
360
361typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
362 SkColorTable*);
363
364static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
365 SkColorTable*) {
366 SkASSERT(width > 0);
367 const SkPMColor* s = (const SkPMColor*)src;
368 do {
369 *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
370 } while (--width != 0);
371}
372
373static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
374 SkColorTable*) {
375 SkASSERT(width > 0);
376 const SkPMColor* s = (const SkPMColor*)src;
377 do {
378 SkPMColor c = *s++;
379 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
380 SkGetPackedG32(c), SkGetPackedB32(c));
381 } while (--width != 0);
382}
383
384static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
385 SkColorTable*) {
386 SkASSERT(width > 0);
387 const SkPMColor* s = (const SkPMColor*)src;
388 do {
389 SkPMColor c = *s++;
390 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
391 SkGetPackedB32(c));
392 } while (--width != 0);
393}
394
395static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
396 SkColorTable*) {
397 SkASSERT(width > 0);
398 const SkPMColor16* s = (const SkPMColor16*)src;
399 do {
400 *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
401 } while (--width != 0);
402}
403
404static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
405 SkColorTable*) {
406 SkASSERT(width > 0);
407 const SkPMColor16* s = (const SkPMColor16*)src;
408 do {
409 SkPMColor c = SkPixel4444ToPixel32(*s++);
410 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
411 SkGetPackedG32(c), SkGetPackedB32(c));
412 } while (--width != 0);
413}
414
415static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
416 SkColorTable*) {
417 SkASSERT(width > 0);
418 const SkPMColor16* s = (const SkPMColor16*)src;
419 do {
420 SkPMColor c = SkPixel4444ToPixel32(*s++);
421 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
422 SkGetPackedB32(c));
423 } while (--width != 0);
424}
425
426static void ToColor_S565(SkColor dst[], const void* src, int width,
427 SkColorTable*) {
428 SkASSERT(width > 0);
429 const uint16_t* s = (const uint16_t*)src;
430 do {
431 uint16_t c = *s++;
432 *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
433 SkPacked16ToB32(c));
434 } while (--width != 0);
435}
436
437static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
438 SkColorTable* ctable) {
439 SkASSERT(width > 0);
440 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500441 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700442 do {
443 *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
444 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700445}
446
447static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
448 SkColorTable* ctable) {
449 SkASSERT(width > 0);
450 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500451 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700452 do {
453 SkPMColor c = colors[*s++];
454 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
455 SkGetPackedG32(c), SkGetPackedB32(c));
456 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700457}
458
459static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
460 SkColorTable* ctable) {
461 SkASSERT(width > 0);
462 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500463 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700464 do {
465 SkPMColor c = colors[*s++];
466 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
467 SkGetPackedB32(c));
468 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700469}
470
Chris Craik6260b222015-07-24 15:17:29 -0700471static void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
472 SkASSERT(width > 0);
473 const uint8_t* s = (const uint8_t*)src;
474 do {
475 uint8_t c = *s++;
476 *dst++ = SkColorSetARGB(c, c, c, c);
477 } while (--width != 0);
478}
479
Chris Craik32054b02014-05-09 13:58:56 -0700480// can return NULL
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400481static ToColorProc ChooseToColorProc(const SkBitmap& src) {
Mike Reedb9330552014-06-16 17:31:48 -0400482 switch (src.colorType()) {
483 case kN32_SkColorType:
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400484 switch (src.alphaType()) {
485 case kOpaque_SkAlphaType:
486 return ToColor_S32_Opaque;
487 case kPremul_SkAlphaType:
488 return ToColor_S32_Alpha;
489 case kUnpremul_SkAlphaType:
490 return ToColor_S32_Raw;
491 default:
492 return NULL;
493 }
Mike Reedb9330552014-06-16 17:31:48 -0400494 case kARGB_4444_SkColorType:
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400495 switch (src.alphaType()) {
496 case kOpaque_SkAlphaType:
497 return ToColor_S4444_Opaque;
498 case kPremul_SkAlphaType:
499 return ToColor_S4444_Alpha;
500 case kUnpremul_SkAlphaType:
501 return ToColor_S4444_Raw;
502 default:
503 return NULL;
504 }
Mike Reedb9330552014-06-16 17:31:48 -0400505 case kRGB_565_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700506 return ToColor_S565;
Mike Reedb9330552014-06-16 17:31:48 -0400507 case kIndex_8_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700508 if (src.getColorTable() == NULL) {
509 return NULL;
510 }
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400511 switch (src.alphaType()) {
512 case kOpaque_SkAlphaType:
513 return ToColor_SI8_Opaque;
514 case kPremul_SkAlphaType:
515 return ToColor_SI8_Alpha;
516 case kUnpremul_SkAlphaType:
517 return ToColor_SI8_Raw;
518 default:
519 return NULL;
520 }
Chris Craik6260b222015-07-24 15:17:29 -0700521 case kAlpha_8_SkColorType:
522 return ToColor_SA8;
Chris Craik32054b02014-05-09 13:58:56 -0700523 default:
524 break;
525 }
526 return NULL;
527}
528
529///////////////////////////////////////////////////////////////////////////////
530///////////////////////////////////////////////////////////////////////////////
531
532static int getPremulBitmapCreateFlags(bool isMutable) {
sergeyvc69853c2016-10-07 14:14:09 -0700533 int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
534 if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
Chris Craik32054b02014-05-09 13:58:56 -0700535 return flags;
536}
537
538static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
539 jint offset, jint stride, jint width, jint height,
540 jint configHandle, jboolean isMutable) {
Mike Reed1103b322014-07-08 12:36:44 -0400541 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700542 if (NULL != jColors) {
543 size_t n = env->GetArrayLength(jColors);
544 if (n < SkAbs32(stride) * (size_t)height) {
545 doThrowAIOOBE(env);
546 return NULL;
547 }
548 }
549
550 // ARGB_4444 is a deprecated format, convert automatically to 8888
Mike Reedb9330552014-06-16 17:31:48 -0400551 if (colorType == kARGB_4444_SkColorType) {
552 colorType = kN32_SkColorType;
Chris Craik32054b02014-05-09 13:58:56 -0700553 }
554
555 SkBitmap bitmap;
Romain Guy253f2c22016-09-28 17:34:42 -0700556 bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
557 GraphicsJNI::defaultColorSpace()));
Chris Craik32054b02014-05-09 13:58:56 -0700558
sergeyvc1c54062016-10-19 18:47:26 -0700559 sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
John Reckf29ed282015-04-07 07:32:03 -0700560 if (!nativeBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700561 return NULL;
562 }
563
564 if (jColors != NULL) {
565 GraphicsJNI::SetPixels(env, jColors, offset, stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400566 0, 0, width, height, bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700567 }
568
sergeyvc36bd6c2016-10-11 15:49:16 -0700569 return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700570}
571
572static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
573 jint dstConfigHandle, jboolean isMutable) {
John Reckf29ed282015-04-07 07:32:03 -0700574 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700575 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
sergeyv05126d12016-12-15 19:50:15 -0800576 if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
577 sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
578 if (!bitmap.get()) {
579 return NULL;
580 }
581 return createBitmap(env, bitmap.release(), kBitmapCreateFlag_None);
582 }
583
Mike Reed1103b322014-07-08 12:36:44 -0400584 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyv45082182016-09-29 18:25:40 -0700585 SkBitmap result;
586 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700587
John Reckf29ed282015-04-07 07:32:03 -0700588 if (!src.copyTo(&result, dstCT, &allocator)) {
Chris Craik32054b02014-05-09 13:58:56 -0700589 return NULL;
590 }
sergeyvc1c54062016-10-19 18:47:26 -0700591 auto bitmap = allocator.getStorageObjAndReset();
592 return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700593}
594
sergeyvc1c54062016-10-19 18:47:26 -0700595static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700596 SkBitmap result;
597
598 AshmemPixelAllocator allocator(env);
Winsona5fdde92016-04-14 15:27:15 -0700599 if (!src.copyTo(&result, dstCT, &allocator)) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700600 return NULL;
601 }
sergeyvc1c54062016-10-19 18:47:26 -0700602 auto bitmap = allocator.getStorageObjAndReset();
603 bitmap->setImmutable();
604 return bitmap;
Winsona5fdde92016-04-14 15:27:15 -0700605}
606
607static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
608 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700609 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700610 SkColorType dstCT = src.colorType();
sergeyvc1c54062016-10-19 18:47:26 -0700611 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
612 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Winsona5fdde92016-04-14 15:27:15 -0700613 return ret;
614}
615
616static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
617 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700618 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700619 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyvc1c54062016-10-19 18:47:26 -0700620 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
621 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Riley Andrews721ae5f2015-05-11 16:08:22 -0700622 return ret;
623}
624
sergeyvc1c54062016-10-19 18:47:26 -0700625static void Bitmap_destruct(BitmapWrapper* bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700626 delete bitmap;
Chris Craik32054b02014-05-09 13:58:56 -0700627}
628
Richard Uhler775873a2015-12-29 12:37:39 -0800629static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
630 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
631}
632
Chris Craik32054b02014-05-09 13:58:56 -0700633static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700634 LocalScopedBitmap bitmap(bitmapHandle);
635 bitmap->freePixels();
Chris Craik32054b02014-05-09 13:58:56 -0700636 return JNI_TRUE;
637}
638
639static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
sergeyv45082182016-09-29 18:25:40 -0700640 jint width, jint height, jint configHandle, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700641 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700642 bitmap->assertValid();
Mike Reed1103b322014-07-08 12:36:44 -0400643 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400644
645 // ARGB_4444 is a deprecated format, convert automatically to 8888
646 if (colorType == kARGB_4444_SkColorType) {
647 colorType = kN32_SkColorType;
648 }
sergeyv45082182016-09-29 18:25:40 -0700649 size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
650 if (requestedSize > bitmap->getAllocationByteCount()) {
Chris Craik32054b02014-05-09 13:58:56 -0700651 // done in native as there's no way to get BytesPerPixel in Java
652 doThrowIAE(env, "Bitmap not large enough to support new configuration");
653 return;
654 }
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400655 SkAlphaType alphaType;
John Reckf29ed282015-04-07 07:32:03 -0700656 if (bitmap->info().colorType() != kRGB_565_SkColorType
657 && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400658 // If the original bitmap was set to opaque, keep that setting, unless it
659 // was 565, which is required to be opaque.
660 alphaType = kOpaque_SkAlphaType;
661 } else {
662 // Otherwise respect the premultiplied request.
663 alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
664 }
sergeyvaed7f582016-10-14 16:30:21 -0700665 bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
sergeyv7d5219f2016-11-03 16:18:16 -0700666 sk_ref_sp(bitmap->info().colorSpace())));
Chris Craik32054b02014-05-09 13:58:56 -0700667}
668
669// These must match the int values in Bitmap.java
670enum JavaEncodeFormat {
671 kJPEG_JavaEncodeFormat = 0,
672 kPNG_JavaEncodeFormat = 1,
673 kWEBP_JavaEncodeFormat = 2
674};
675
676static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
677 jint format, jint quality,
678 jobject jstream, jbyteArray jstorage) {
Hal Canary10219fb2016-11-23 20:41:22 -0500679 SkEncodedImageFormat fm;
Chris Craik32054b02014-05-09 13:58:56 -0700680 switch (format) {
681 case kJPEG_JavaEncodeFormat:
Hal Canary10219fb2016-11-23 20:41:22 -0500682 fm = SkEncodedImageFormat::kJPEG;
Chris Craik32054b02014-05-09 13:58:56 -0700683 break;
684 case kPNG_JavaEncodeFormat:
Hal Canary10219fb2016-11-23 20:41:22 -0500685 fm = SkEncodedImageFormat::kPNG;
Chris Craik32054b02014-05-09 13:58:56 -0700686 break;
687 case kWEBP_JavaEncodeFormat:
Hal Canary10219fb2016-11-23 20:41:22 -0500688 fm = SkEncodedImageFormat::kWEBP;
Chris Craik32054b02014-05-09 13:58:56 -0700689 break;
690 default:
691 return JNI_FALSE;
692 }
693
Hal Canary10219fb2016-11-23 20:41:22 -0500694 LocalScopedBitmap bitmap(bitmapHandle);
John Reckf29ed282015-04-07 07:32:03 -0700695 if (!bitmap.valid()) {
696 return JNI_FALSE;
697 }
698
John Reckf29ed282015-04-07 07:32:03 -0700699 std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
700 if (!strm.get()) {
701 return JNI_FALSE;
702 }
Chris Craik32054b02014-05-09 13:58:56 -0700703
Hal Canary10219fb2016-11-23 20:41:22 -0500704 SkBitmap skbitmap;
705 bitmap->getSkBitmap(&skbitmap);
706 return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700707}
708
709static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
John Reckf29ed282015-04-07 07:32:03 -0700710 LocalScopedBitmap bitmap(bitmapHandle);
711 SkBitmap skBitmap;
712 bitmap->getSkBitmap(&skBitmap);
713 skBitmap.eraseColor(color);
Chris Craik32054b02014-05-09 13:58:56 -0700714}
715
716static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700717 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700718 return static_cast<jint>(bitmap->rowBytes());
719}
720
721static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700722 LocalScopedBitmap bitmap(bitmapHandle);
sergeyv19b4b012016-12-13 16:06:00 -0800723 if (bitmap->bitmap().isHardware()) {
724 return GraphicsJNI::hardwareLegacyBitmapConfig();
725 }
John Reckf29ed282015-04-07 07:32:03 -0700726 return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
Chris Craik32054b02014-05-09 13:58:56 -0700727}
728
729static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700730 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700731 return static_cast<jint>(bitmap->getGenerationID());
Chris Craik32054b02014-05-09 13:58:56 -0700732}
733
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400734static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700735 LocalScopedBitmap bitmap(bitmapHandle);
736 if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400737 return JNI_TRUE;
738 }
739 return JNI_FALSE;
740}
741
Chris Craik32054b02014-05-09 13:58:56 -0700742static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700743 LocalScopedBitmap bitmap(bitmapHandle);
744 return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700745}
746
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400747static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
748 jboolean hasAlpha, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700749 LocalScopedBitmap bitmap(bitmapHandle);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400750 if (hasAlpha) {
John Reck0781a2f2015-05-27 16:29:17 -0700751 bitmap->setAlphaType(
John Reckf29ed282015-04-07 07:32:03 -0700752 requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
Chris Craik32054b02014-05-09 13:58:56 -0700753 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700754 bitmap->setAlphaType(kOpaque_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400755 }
756}
757
758static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
759 jboolean isPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700760 LocalScopedBitmap bitmap(bitmapHandle);
761 if (!bitmap->info().isOpaque()) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400762 if (isPremul) {
John Reck0781a2f2015-05-27 16:29:17 -0700763 bitmap->setAlphaType(kPremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400764 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700765 bitmap->setAlphaType(kUnpremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400766 }
Chris Craik32054b02014-05-09 13:58:56 -0700767 }
768}
769
770static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700771 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700772 return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
773}
774
775static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
776 jboolean hasMipMap) {
John Reckf29ed282015-04-07 07:32:03 -0700777 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700778 bitmap->setHasHardwareMipMap(hasMipMap);
779}
780
781///////////////////////////////////////////////////////////////////////////////
782
783static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
784 if (parcel == NULL) {
785 SkDebugf("-------- unparcel parcel is NULL\n");
786 return NULL;
787 }
788
789 android::Parcel* p = android::parcelForJavaObject(env, parcel);
790
Mike Reedb9330552014-06-16 17:31:48 -0400791 const bool isMutable = p->readInt32() != 0;
792 const SkColorType colorType = (SkColorType)p->readInt32();
793 const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
Romain Guy253f2c22016-09-28 17:34:42 -0700794 const bool isSRGB = p->readInt32() != 0;
Mike Reedb9330552014-06-16 17:31:48 -0400795 const int width = p->readInt32();
796 const int height = p->readInt32();
797 const int rowBytes = p->readInt32();
798 const int density = p->readInt32();
Chris Craik32054b02014-05-09 13:58:56 -0700799
Mike Reedb9330552014-06-16 17:31:48 -0400800 if (kN32_SkColorType != colorType &&
801 kRGB_565_SkColorType != colorType &&
802 kARGB_4444_SkColorType != colorType &&
803 kIndex_8_SkColorType != colorType &&
804 kAlpha_8_SkColorType != colorType) {
805 SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
Chris Craik32054b02014-05-09 13:58:56 -0700806 return NULL;
807 }
808
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400809 std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700810
Romain Guy253f2c22016-09-28 17:34:42 -0700811 if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType,
Mike Reedab12c1f2016-11-03 12:54:10 -0400812 isSRGB ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : nullptr), rowBytes)) {
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400813 return NULL;
814 }
Chris Craik32054b02014-05-09 13:58:56 -0700815
816 SkColorTable* ctable = NULL;
Mike Reedb9330552014-06-16 17:31:48 -0400817 if (colorType == kIndex_8_SkColorType) {
Chris Craik32054b02014-05-09 13:58:56 -0700818 int count = p->readInt32();
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400819 if (count < 0 || count > 256) {
820 // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
821 // inclusive.
822 return NULL;
823 }
Chris Craik32054b02014-05-09 13:58:56 -0700824 if (count > 0) {
825 size_t size = count * sizeof(SkPMColor);
826 const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400827 if (src == NULL) {
828 return NULL;
829 }
Chris Craik32054b02014-05-09 13:58:56 -0700830 ctable = new SkColorTable(src, count);
831 }
832 }
833
Jeff Browna316c5d2015-06-05 15:14:06 -0700834 // Read the bitmap blob.
835 size_t size = bitmap->getSize();
836 android::Parcel::ReadableBlob blob;
837 android::status_t status = p->readBlob(size, &blob);
838 if (status) {
Chris Craik32054b02014-05-09 13:58:56 -0700839 SkSafeUnref(ctable);
Jeff Browna316c5d2015-06-05 15:14:06 -0700840 doThrowRE(env, "Could not read bitmap blob.");
Chris Craik32054b02014-05-09 13:58:56 -0700841 return NULL;
842 }
843
Jeff Browna316c5d2015-06-05 15:14:06 -0700844 // Map the bitmap in place from the ashmem region if possible otherwise copy.
sergeyvc1c54062016-10-19 18:47:26 -0700845 sk_sp<Bitmap> nativeBitmap;
Riley Andrews8cee7c12015-11-01 23:36:04 -0800846 if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700847#if DEBUG_PARCEL
848 ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
849 "(fds %s)",
850 isMutable ? "mutable" : "immutable",
851 blob.isMutable() ? "mutable" : "immutable",
852 p->allowFds() ? "allowed" : "forbidden");
853#endif
854 // Dup the file descriptor so we can keep a reference to it after the Parcel
855 // is disposed.
856 int dupFd = dup(blob.fd());
857 if (dupFd < 0) {
Erik Wolsheimer211abad2015-11-13 11:54:47 -0800858 ALOGE("Error allocating dup fd. Error:%d", errno);
Jeff Browna316c5d2015-06-05 15:14:06 -0700859 blob.release();
860 SkSafeUnref(ctable);
861 doThrowRE(env, "Could not allocate dup blob fd.");
862 return NULL;
863 }
864
865 // Map the pixels in place and take ownership of the ashmem region.
sergeyvc1c54062016-10-19 18:47:26 -0700866 nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
sergeyvc36bd6c2016-10-11 15:49:16 -0700867 ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
Jeff Browna316c5d2015-06-05 15:14:06 -0700868 SkSafeUnref(ctable);
869 if (!nativeBitmap) {
870 close(dupFd);
871 blob.release();
872 doThrowRE(env, "Could not allocate ashmem pixel ref.");
873 return NULL;
874 }
875
876 // Clear the blob handle, don't release it.
877 blob.clear();
878 } else {
879#if DEBUG_PARCEL
880 if (blob.fd() >= 0) {
881 ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
882 "from immutable blob (fds %s)",
883 p->allowFds() ? "allowed" : "forbidden");
884 } else {
885 ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
886 "(fds %s)",
887 blob.isMutable() ? "mutable" : "immutable",
888 p->allowFds() ? "allowed" : "forbidden");
889 }
890#endif
891
892 // Copy the pixels into a new buffer.
sergeyvc1c54062016-10-19 18:47:26 -0700893 nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
Jeff Browna316c5d2015-06-05 15:14:06 -0700894 SkSafeUnref(ctable);
895 if (!nativeBitmap) {
896 blob.release();
897 doThrowRE(env, "Could not allocate java pixel ref.");
898 return NULL;
899 }
900 bitmap->lockPixels();
901 memcpy(bitmap->getPixels(), blob.data(), size);
902 bitmap->unlockPixels();
903
904 // Release the blob handle.
905 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700906 }
Chris Craik32054b02014-05-09 13:58:56 -0700907
sergeyvc36bd6c2016-10-11 15:49:16 -0700908 return createBitmap(env, nativeBitmap.release(),
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400909 getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
Chris Craik32054b02014-05-09 13:58:56 -0700910}
911
912static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
913 jlong bitmapHandle,
914 jboolean isMutable, jint density,
915 jobject parcel) {
Chris Craik32054b02014-05-09 13:58:56 -0700916 if (parcel == NULL) {
917 SkDebugf("------- writeToParcel null parcel\n");
918 return JNI_FALSE;
919 }
920
921 android::Parcel* p = android::parcelForJavaObject(env, parcel);
John Reckf29ed282015-04-07 07:32:03 -0700922 SkBitmap bitmap;
Riley Andrews39d7f302014-11-13 17:43:25 -0800923
sergeyvc1c54062016-10-19 18:47:26 -0700924 auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
925 bitmapWrapper->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700926
Mike Reedab12c1f2016-11-03 12:54:10 -0400927 sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
Romain Guy253f2c22016-09-28 17:34:42 -0700928 bool isSRGB = bitmap.colorSpace() == sRGB.get();
929
Chris Craik32054b02014-05-09 13:58:56 -0700930 p->writeInt32(isMutable);
John Reckf29ed282015-04-07 07:32:03 -0700931 p->writeInt32(bitmap.colorType());
932 p->writeInt32(bitmap.alphaType());
Romain Guy253f2c22016-09-28 17:34:42 -0700933 p->writeInt32(isSRGB); // TODO: We should write the color space (b/32072280)
John Reckf29ed282015-04-07 07:32:03 -0700934 p->writeInt32(bitmap.width());
935 p->writeInt32(bitmap.height());
936 p->writeInt32(bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -0700937 p->writeInt32(density);
938
John Reckf29ed282015-04-07 07:32:03 -0700939 if (bitmap.colorType() == kIndex_8_SkColorType) {
Leon Scroggins III66ce1c32016-02-02 11:11:55 -0500940 // The bitmap needs to be locked to access its color table.
941 SkAutoLockPixels alp(bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700942 SkColorTable* ctable = bitmap.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -0700943 if (ctable != NULL) {
944 int count = ctable->count();
945 p->writeInt32(count);
946 memcpy(p->writeInplace(count * sizeof(SkPMColor)),
Mike Reed71487eb2014-11-19 16:13:20 -0500947 ctable->readColors(), count * sizeof(SkPMColor));
Chris Craik32054b02014-05-09 13:58:56 -0700948 } else {
949 p->writeInt32(0); // indicate no ctable
950 }
951 }
952
Jeff Browna316c5d2015-06-05 15:14:06 -0700953 // Transfer the underlying ashmem region if we have one and it's immutable.
954 android::status_t status;
sergeyvaed7f582016-10-14 16:30:21 -0700955 int fd = bitmapWrapper->bitmap().getAshmemFd();
Jeff Browna316c5d2015-06-05 15:14:06 -0700956 if (fd >= 0 && !isMutable && p->allowFds()) {
957#if DEBUG_PARCEL
958 ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
959 "immutable blob (fds %s)",
960 p->allowFds() ? "allowed" : "forbidden");
961#endif
962
963 status = p->writeDupImmutableBlobFileDescriptor(fd);
964 if (status) {
965 doThrowRE(env, "Could not write bitmap blob file descriptor.");
Riley Andrews39d7f302014-11-13 17:43:25 -0800966 return JNI_FALSE;
967 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700968 return JNI_TRUE;
Riley Andrews39d7f302014-11-13 17:43:25 -0800969 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700970
971 // Copy the bitmap to a new blob.
972 bool mutableCopy = isMutable;
973#if DEBUG_PARCEL
974 ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
975 isMutable ? "mutable" : "immutable",
976 mutableCopy ? "mutable" : "immutable",
977 p->allowFds() ? "allowed" : "forbidden");
978#endif
979
980 size_t size = bitmap.getSize();
981 android::Parcel::WritableBlob blob;
982 status = p->writeBlob(size, mutableCopy, &blob);
983 if (status) {
984 doThrowRE(env, "Could not copy bitmap to parcel blob.");
985 return JNI_FALSE;
986 }
987
988 bitmap.lockPixels();
989 const void* pSrc = bitmap.getPixels();
990 if (pSrc == NULL) {
991 memset(blob.data(), 0, size);
992 } else {
993 memcpy(blob.data(), pSrc, size);
994 }
995 bitmap.unlockPixels();
996
997 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700998 return JNI_TRUE;
999}
1000
1001static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
1002 jlong srcHandle, jlong paintHandle,
1003 jintArray offsetXY) {
John Reckf29ed282015-04-07 07:32:03 -07001004 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -07001005 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -04001006 const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
Chris Craik32054b02014-05-09 13:58:56 -07001007 SkIPoint offset;
John Reckf29ed282015-04-07 07:32:03 -07001008 SkBitmap dst;
sergeyv45082182016-09-29 18:25:40 -07001009 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -07001010
John Reckf29ed282015-04-07 07:32:03 -07001011 src.extractAlpha(&dst, paint, &allocator, &offset);
Chris Craik32054b02014-05-09 13:58:56 -07001012 // If Skia can't allocate pixels for destination bitmap, it resets
1013 // it, that is set its pixels buffer to NULL, and zero width and height.
John Reckf29ed282015-04-07 07:32:03 -07001014 if (dst.getPixels() == NULL && src.getPixels() != NULL) {
Chris Craik32054b02014-05-09 13:58:56 -07001015 doThrowOOME(env, "failed to allocate pixels for alpha");
1016 return NULL;
1017 }
1018 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
1019 int* array = env->GetIntArrayElements(offsetXY, NULL);
1020 array[0] = offset.fX;
1021 array[1] = offset.fY;
1022 env->ReleaseIntArrayElements(offsetXY, array, 0);
1023 }
1024
sergeyvc69853c2016-10-07 14:14:09 -07001025 return createBitmap(env, allocator.getStorageObjAndReset(),
John Reckf29ed282015-04-07 07:32:03 -07001026 getPremulBitmapCreateFlags(true));
Chris Craik32054b02014-05-09 13:58:56 -07001027}
1028
1029///////////////////////////////////////////////////////////////////////////////
1030
1031static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001032 jint x, jint y) {
John Reckf29ed282015-04-07 07:32:03 -07001033 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001034 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001035 SkAutoLockPixels alp(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001036
John Reckf29ed282015-04-07 07:32:03 -07001037 ToColorProc proc = ChooseToColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001038 if (NULL == proc) {
1039 return 0;
1040 }
John Reckf29ed282015-04-07 07:32:03 -07001041 const void* src = bitmap.getAddr(x, y);
Chris Craik32054b02014-05-09 13:58:56 -07001042 if (NULL == src) {
1043 return 0;
1044 }
1045
1046 SkColor dst[1];
John Reckf29ed282015-04-07 07:32:03 -07001047 proc(dst, src, 1, bitmap.getColorTable());
Chris Craik32054b02014-05-09 13:58:56 -07001048 return static_cast<jint>(dst[0]);
1049}
1050
1051static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1052 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001053 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -07001054 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001055 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001056 SkAutoLockPixels alp(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001057
John Reckf29ed282015-04-07 07:32:03 -07001058 ToColorProc proc = ChooseToColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001059 if (NULL == proc) {
1060 return;
1061 }
John Reckf29ed282015-04-07 07:32:03 -07001062 const void* src = bitmap.getAddr(x, y);
Chris Craik32054b02014-05-09 13:58:56 -07001063 if (NULL == src) {
1064 return;
1065 }
1066
John Reckf29ed282015-04-07 07:32:03 -07001067 SkColorTable* ctable = bitmap.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -07001068 jint* dst = env->GetIntArrayElements(pixelArray, NULL);
1069 SkColor* d = (SkColor*)dst + offset;
1070 while (--height >= 0) {
1071 proc(d, src, width, ctable);
1072 d += stride;
John Reckf29ed282015-04-07 07:32:03 -07001073 src = (void*)((const char*)src + bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -07001074 }
1075 env->ReleaseIntArrayElements(pixelArray, dst, 0);
1076}
1077
1078///////////////////////////////////////////////////////////////////////////////
1079
1080static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001081 jint x, jint y, jint colorHandle) {
John Reckf29ed282015-04-07 07:32:03 -07001082 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001083 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001084 SkColor color = static_cast<SkColor>(colorHandle);
John Reckf29ed282015-04-07 07:32:03 -07001085 SkAutoLockPixels alp(bitmap);
1086 if (NULL == bitmap.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -07001087 return;
1088 }
1089
John Reckf29ed282015-04-07 07:32:03 -07001090 FromColorProc proc = ChooseFromColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001091 if (NULL == proc) {
1092 return;
1093 }
1094
John Reckf29ed282015-04-07 07:32:03 -07001095 proc(bitmap.getAddr(x, y), &color, 1, x, y);
1096 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -07001097}
1098
1099static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1100 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001101 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -07001102 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001103 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001104 GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
John Reckf29ed282015-04-07 07:32:03 -07001105 x, y, width, height, bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001106}
1107
1108static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
1109 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -07001110 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001111 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001112 SkAutoLockPixels alp(bitmap);
1113 const void* src = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -07001114
1115 if (NULL != src) {
1116 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
1117
1118 // the java side has already checked that buffer is large enough
John Reckf29ed282015-04-07 07:32:03 -07001119 memcpy(abp.pointer(), src, bitmap.getSize());
Chris Craik32054b02014-05-09 13:58:56 -07001120 }
1121}
1122
1123static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
1124 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -07001125 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001126 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001127 SkAutoLockPixels alp(bitmap);
1128 void* dst = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -07001129
1130 if (NULL != dst) {
1131 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
1132 // the java side has already checked that buffer is large enough
John Reckf29ed282015-04-07 07:32:03 -07001133 memcpy(dst, abp.pointer(), bitmap.getSize());
1134 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -07001135 }
1136}
1137
1138static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
1139 jlong bm1Handle) {
John Reckf29ed282015-04-07 07:32:03 -07001140 SkBitmap bm0;
1141 SkBitmap bm1;
sergeyvc1c54062016-10-19 18:47:26 -07001142 reinterpret_cast<BitmapWrapper*>(bm0Handle)->getSkBitmap(&bm0);
1143 reinterpret_cast<BitmapWrapper*>(bm1Handle)->getSkBitmap(&bm1);
John Reckf29ed282015-04-07 07:32:03 -07001144 if (bm0.width() != bm1.width() ||
1145 bm0.height() != bm1.height() ||
Romain Guy253f2c22016-09-28 17:34:42 -07001146 bm0.colorType() != bm1.colorType() ||
1147 bm0.alphaType() != bm1.alphaType() ||
1148 bm0.colorSpace() != bm1.colorSpace()) {
Chris Craik32054b02014-05-09 13:58:56 -07001149 return JNI_FALSE;
1150 }
1151
John Reckf29ed282015-04-07 07:32:03 -07001152 SkAutoLockPixels alp0(bm0);
1153 SkAutoLockPixels alp1(bm1);
Chris Craik32054b02014-05-09 13:58:56 -07001154
1155 // if we can't load the pixels, return false
John Reckf29ed282015-04-07 07:32:03 -07001156 if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -07001157 return JNI_FALSE;
1158 }
1159
John Reckf29ed282015-04-07 07:32:03 -07001160 if (bm0.colorType() == kIndex_8_SkColorType) {
1161 SkColorTable* ct0 = bm0.getColorTable();
1162 SkColorTable* ct1 = bm1.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -07001163 if (NULL == ct0 || NULL == ct1) {
1164 return JNI_FALSE;
1165 }
1166 if (ct0->count() != ct1->count()) {
1167 return JNI_FALSE;
1168 }
1169
Chris Craik32054b02014-05-09 13:58:56 -07001170 const size_t size = ct0->count() * sizeof(SkPMColor);
Mike Reed71487eb2014-11-19 16:13:20 -05001171 if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -07001172 return JNI_FALSE;
1173 }
1174 }
1175
1176 // now compare each scanline. We can't do the entire buffer at once,
1177 // since we don't care about the pixel values that might extend beyond
1178 // the width (since the scanline might be larger than the logical width)
John Reckf29ed282015-04-07 07:32:03 -07001179 const int h = bm0.height();
1180 const size_t size = bm0.width() * bm0.bytesPerPixel();
Chris Craik32054b02014-05-09 13:58:56 -07001181 for (int y = 0; y < h; y++) {
henry.uh_chen53001ca2014-07-03 20:40:22 +08001182 // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
1183 // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
1184 // and bm1 both have pixel data() (have passed NULL == getPixels() check),
1185 // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
1186 // to warn user those 2 unrecognized config bitmaps may be different.
John Reckf29ed282015-04-07 07:32:03 -07001187 void *bm0Addr = bm0.getAddr(0, y);
1188 void *bm1Addr = bm1.getAddr(0, y);
henry.uh_chen53001ca2014-07-03 20:40:22 +08001189
1190 if(bm0Addr == NULL || bm1Addr == NULL) {
1191 return JNI_FALSE;
1192 }
1193
1194 if (memcmp(bm0Addr, bm1Addr, size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -07001195 return JNI_FALSE;
1196 }
1197 }
1198 return JNI_TRUE;
1199}
1200
John Reck43871902016-08-01 14:39:24 -07001201static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
1202 LocalScopedBitmap bitmapHandle(bitmapPtr);
1203 if (!bitmapHandle.valid()) return;
sergeyvec4a4b12016-10-20 18:39:04 -07001204 android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
John Reck43871902016-08-01 14:39:24 -07001205}
1206
sergeyv45082182016-09-29 18:25:40 -07001207static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1208 LocalScopedBitmap bitmapHandle(bitmapPtr);
1209 return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1210}
1211
Chris Craik32054b02014-05-09 13:58:56 -07001212///////////////////////////////////////////////////////////////////////////////
sergeyvc69853c2016-10-07 14:14:09 -07001213static jclass make_globalref(JNIEnv* env, const char classname[])
1214{
1215 jclass c = env->FindClass(classname);
1216 SkASSERT(c);
1217 return (jclass) env->NewGlobalRef(c);
1218}
1219
1220static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1221 const char fieldname[], const char type[])
1222{
1223 jfieldID id = env->GetFieldID(clazz, fieldname, type);
1224 SkASSERT(id);
1225 return id;
1226}
Chris Craik32054b02014-05-09 13:58:56 -07001227
Daniel Micay76f6a862015-09-19 17:31:01 -04001228static const JNINativeMethod gBitmapMethods[] = {
Chris Craik32054b02014-05-09 13:58:56 -07001229 { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
1230 (void*)Bitmap_creator },
1231 { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
1232 (void*)Bitmap_copy },
Riley Andrews721ae5f2015-05-11 16:08:22 -07001233 { "nativeCopyAshmem", "(J)Landroid/graphics/Bitmap;",
1234 (void*)Bitmap_copyAshmem },
Winsona5fdde92016-04-14 15:27:15 -07001235 { "nativeCopyAshmemConfig", "(JI)Landroid/graphics/Bitmap;",
1236 (void*)Bitmap_copyAshmemConfig },
Richard Uhler775873a2015-12-29 12:37:39 -08001237 { "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
Chris Craik32054b02014-05-09 13:58:56 -07001238 { "nativeRecycle", "(J)Z", (void*)Bitmap_recycle },
sergeyv45082182016-09-29 18:25:40 -07001239 { "nativeReconfigure", "(JIIIZ)V", (void*)Bitmap_reconfigure },
Chris Craik32054b02014-05-09 13:58:56 -07001240 { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
1241 (void*)Bitmap_compress },
1242 { "nativeErase", "(JI)V", (void*)Bitmap_erase },
1243 { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
1244 { "nativeConfig", "(J)I", (void*)Bitmap_config },
1245 { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001246 { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},
1247 { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},
1248 { "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied},
Chris Craik32054b02014-05-09 13:58:56 -07001249 { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
1250 { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
1251 { "nativeCreateFromParcel",
1252 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1253 (void*)Bitmap_createFromParcel },
1254 { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",
1255 (void*)Bitmap_writeToParcel },
1256 { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
1257 (void*)Bitmap_extractAlpha },
1258 { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001259 { "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel },
1260 { "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1261 { "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel },
1262 { "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels },
Chris Craik32054b02014-05-09 13:58:56 -07001263 { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1264 (void*)Bitmap_copyPixelsToBuffer },
1265 { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1266 (void*)Bitmap_copyPixelsFromBuffer },
1267 { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
John Reck43871902016-08-01 14:39:24 -07001268 { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
sergeyv45082182016-09-29 18:25:40 -07001269 { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
Chris Craik32054b02014-05-09 13:58:56 -07001270};
1271
Chris Craik32054b02014-05-09 13:58:56 -07001272int register_android_graphics_Bitmap(JNIEnv* env)
1273{
sergeyvc69853c2016-10-07 14:14:09 -07001274 gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1275 gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1276 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1277 gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1278 gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001279 return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1280 NELEM(gBitmapMethods));
John Reck9192d5e2016-10-31 10:32:09 -07001281}