Bitmap.cpp revision 95648b8a590995e57948ff2fd57d234bdbf30be0
1#define LOG_TAG "Bitmap"
2#include "Bitmap.h"
3
4#include "GraphicBuffer.h"
5#include "SkBitmap.h"
6#include "SkPixelRef.h"
7#include "SkImageEncoder.h"
8#include "SkImageInfo.h"
9#include "SkColor.h"
10#include "SkColorPriv.h"
11#include "SkColorSpace.h"
12#include "SkColorSpaceXform.h"
13#include "SkHalf.h"
14#include "SkMatrix44.h"
15#include "SkPM4f.h"
16#include "SkPM4fPriv.h"
17#include "GraphicsJNI.h"
18#include "SkDither.h"
19#include "SkUnPreMultiply.h"
20#include "SkStream.h"
21
22#include <binder/Parcel.h>
23#include "android_os_Parcel.h"
24#include "android_util_Binder.h"
25#include "android_nio_utils.h"
26#include "CreateJavaOutputStreamAdaptor.h"
27#include <hwui/Paint.h>
28#include <hwui/Bitmap.h>
29#include <renderthread/RenderProxy.h>
30
31#include "core_jni_helpers.h"
32
33#include <jni.h>
34#include <string.h>
35#include <memory>
36#include <string>
37
38#define DEBUG_PARCEL 0
39#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
40
41static jclass   gBitmap_class;
42static jfieldID gBitmap_nativePtr;
43static jmethodID gBitmap_constructorMethodID;
44static jmethodID gBitmap_reinitMethodID;
45static jmethodID gBitmap_getAllocationByteCountMethodID;
46
47namespace android {
48
49class BitmapWrapper {
50public:
51    BitmapWrapper(Bitmap* bitmap)
52        : mBitmap(bitmap) { }
53
54    void freePixels() {
55        mInfo = mBitmap->info();
56        mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
57        mAllocationSize = mBitmap->getAllocationByteCount();
58        mRowBytes = mBitmap->rowBytes();
59        mGenerationId = mBitmap->getGenerationID();
60        mIsHardware = mBitmap->isHardware();
61        mBitmap.reset();
62    }
63
64    bool valid() {
65        return mBitmap;
66    }
67
68    Bitmap& bitmap() {
69        assertValid();
70        return *mBitmap;
71    }
72
73    void assertValid() {
74        LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
75    }
76
77    void getSkBitmap(SkBitmap* outBitmap) {
78        assertValid();
79        mBitmap->getSkBitmap(outBitmap);
80    }
81
82    bool hasHardwareMipMap() {
83        if (mBitmap) {
84            return mBitmap->hasHardwareMipMap();
85        }
86        return mHasHardwareMipMap;
87    }
88
89    void setHasHardwareMipMap(bool hasMipMap) {
90        assertValid();
91        mBitmap->setHasHardwareMipMap(hasMipMap);
92    }
93
94    void setAlphaType(SkAlphaType alphaType) {
95        assertValid();
96        mBitmap->setAlphaType(alphaType);
97    }
98
99    const SkImageInfo& info() {
100        if (mBitmap) {
101            return mBitmap->info();
102        }
103        return mInfo;
104    }
105
106    size_t getAllocationByteCount() const {
107        if (mBitmap) {
108            return mBitmap->getAllocationByteCount();
109        }
110        return mAllocationSize;
111    }
112
113    size_t rowBytes() const {
114        if (mBitmap) {
115            return mBitmap->rowBytes();
116        }
117        return mRowBytes;
118    }
119
120    uint32_t getGenerationID() const {
121        if (mBitmap) {
122            return mBitmap->getGenerationID();
123        }
124        return mGenerationId;
125    }
126
127    bool isHardware() {
128        if (mBitmap) {
129            return mBitmap->isHardware();
130        }
131        return mIsHardware;
132    }
133
134    ~BitmapWrapper() { }
135
136private:
137    sk_sp<Bitmap> mBitmap;
138    SkImageInfo mInfo;
139    bool mHasHardwareMipMap;
140    size_t mAllocationSize;
141    size_t mRowBytes;
142    uint32_t mGenerationId;
143    bool mIsHardware;
144};
145
146// Convenience class that does not take a global ref on the pixels, relying
147// on the caller already having a local JNI ref
148class LocalScopedBitmap {
149public:
150    explicit LocalScopedBitmap(jlong bitmapHandle)
151            : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
152
153    BitmapWrapper* operator->() {
154        return mBitmapWrapper;
155    }
156
157    void* pixels() {
158        return mBitmapWrapper->bitmap().pixels();
159    }
160
161    bool valid() {
162        return mBitmapWrapper && mBitmapWrapper->valid();
163    }
164
165private:
166    BitmapWrapper* mBitmapWrapper;
167};
168
169namespace bitmap {
170
171// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
172static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
173    // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
174    // irrelevant. This just tests to ensure that the SkAlphaType is not
175    // opposite of isPremultiplied.
176    if (isPremultiplied) {
177        SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
178    } else {
179        SkASSERT(info.alphaType() != kPremul_SkAlphaType);
180    }
181}
182
183void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
184        bool isPremultiplied)
185{
186    // The caller needs to have already set the alpha type properly, so the
187    // native SkBitmap stays in sync with the Java Bitmap.
188    assert_premultiplied(info, isPremultiplied);
189
190    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
191            info.width(), info.height(), isPremultiplied);
192}
193
194int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
195{
196    return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
197}
198
199jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
200        int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
201        int density) {
202    bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
203    bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
204    // The caller needs to have already set the alpha type properly, so the
205    // native SkBitmap stays in sync with the Java Bitmap.
206    assert_premultiplied(bitmap->info(), isPremultiplied);
207    BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
208    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
209            reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
210            isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets);
211
212    if (env->ExceptionCheck() != 0) {
213        ALOGE("*** Uncaught exception returned from Java call!\n");
214        env->ExceptionDescribe();
215    }
216    return obj;
217}
218
219void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
220    LocalScopedBitmap bitmap(bitmapHandle);
221    bitmap->getSkBitmap(outBitmap);
222}
223
224Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
225    SkASSERT(env);
226    SkASSERT(bitmap);
227    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
228    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
229    LocalScopedBitmap localBitmap(bitmapHandle);
230    return localBitmap->bitmap();
231}
232
233Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) {
234    SkASSERT(env);
235    LocalScopedBitmap localBitmap(bitmapHandle);
236    return localBitmap->bitmap();
237}
238
239void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
240    SkASSERT(info);
241    SkASSERT(env);
242    SkASSERT(bitmap);
243    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
244    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
245    LocalScopedBitmap localBitmap(bitmapHandle);
246
247    const SkImageInfo& imageInfo = localBitmap->info();
248    info->width = imageInfo.width();
249    info->height = imageInfo.height();
250    info->stride = localBitmap->rowBytes();
251    info->flags = 0;
252    switch (imageInfo.colorType()) {
253        case kN32_SkColorType:
254            info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
255            break;
256        case kRGB_565_SkColorType:
257            info->format = ANDROID_BITMAP_FORMAT_RGB_565;
258            break;
259        case kARGB_4444_SkColorType:
260            info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
261            break;
262        case kAlpha_8_SkColorType:
263            info->format = ANDROID_BITMAP_FORMAT_A_8;
264            break;
265        default:
266            info->format = ANDROID_BITMAP_FORMAT_NONE;
267            break;
268    }
269}
270
271void* lockPixels(JNIEnv* env, jobject bitmap) {
272    SkASSERT(env);
273    SkASSERT(bitmap);
274    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
275    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
276
277    LocalScopedBitmap localBitmap(bitmapHandle);
278    if (!localBitmap->valid()) return nullptr;
279
280    SkPixelRef& pixelRef = localBitmap->bitmap();
281    pixelRef.lockPixels();
282    if (!pixelRef.pixels()) {
283        pixelRef.unlockPixels();
284        return nullptr;
285    }
286    pixelRef.ref();
287    return pixelRef.pixels();
288}
289
290bool unlockPixels(JNIEnv* env, jobject bitmap) {
291    SkASSERT(env);
292    SkASSERT(bitmap);
293    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
294    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
295
296    LocalScopedBitmap localBitmap(bitmapHandle);
297    if (!localBitmap->valid()) return false;
298
299    SkPixelRef& pixelRef = localBitmap->bitmap();
300    pixelRef.notifyPixelsChanged();
301    pixelRef.unlockPixels();
302    pixelRef.unref();
303    return true;
304}
305
306} // namespace bitmap
307
308} // namespace android
309
310using namespace android;
311using namespace android::bitmap;
312
313///////////////////////////////////////////////////////////////////////////////
314// Conversions to/from SkColor, for get/setPixels, and the create method, which
315// is basically like setPixels
316
317typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
318                              int x, int y);
319
320static void FromColor_F16(void* dst, const SkColor src[], int width,
321                          int, int) {
322    uint64_t* d = (uint64_t*)dst;
323
324    for (int i = 0; i < width; i++) {
325        *d++ = SkColor4f::FromColor(*src++).premul().toF16();
326    }
327}
328
329static void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
330                          int, int) {
331    uint64_t* d = (uint64_t*)dst;
332
333    for (int i = 0; i < width; i++) {
334        const float* color = SkColor4f::FromColor(*src++).vec();
335        uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
336        for (int i = 0; i < 4; ++i) {
337            scratch[i] = SkFloatToHalf(color[i]);
338        }
339    }
340}
341
342static void FromColor_D32(void* dst, const SkColor src[], int width,
343                          int, int) {
344    SkPMColor* d = (SkPMColor*)dst;
345
346    for (int i = 0; i < width; i++) {
347        *d++ = SkPreMultiplyColor(*src++);
348    }
349}
350
351static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
352                          int, int) {
353    // Needed to thwart the unreachable code detection from clang.
354    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
355
356    // SkColor's ordering may be different from SkPMColor
357    if (sk_color_ne_zero) {
358        memcpy(dst, src, width * sizeof(SkColor));
359        return;
360    }
361
362    // order isn't same, repack each pixel manually
363    SkPMColor* d = (SkPMColor*)dst;
364    for (int i = 0; i < width; i++) {
365        SkColor c = *src++;
366        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
367                                   SkColorGetG(c), SkColorGetB(c));
368    }
369}
370
371static void FromColor_D565(void* dst, const SkColor src[], int width,
372                           int x, int y) {
373    uint16_t* d = (uint16_t*)dst;
374
375    DITHER_565_SCAN(y);
376    for (int stop = x + width; x < stop; x++) {
377        SkColor c = *src++;
378        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
379                                DITHER_VALUE(x));
380    }
381}
382
383static void FromColor_D4444(void* dst, const SkColor src[], int width,
384                            int x, int y) {
385    SkPMColor16* d = (SkPMColor16*)dst;
386
387    DITHER_4444_SCAN(y);
388    for (int stop = x + width; x < stop; x++) {
389        SkPMColor pmc = SkPreMultiplyColor(*src++);
390        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
391//        *d++ = SkPixel32ToPixel4444(pmc);
392    }
393}
394
395static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
396                            int x, int y) {
397    SkPMColor16* d = (SkPMColor16*)dst;
398
399    DITHER_4444_SCAN(y);
400    for (int stop = x + width; x < stop; x++) {
401        SkColor c = *src++;
402
403        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
404        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
405                                            SkColorGetG(c), SkColorGetB(c));
406        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
407//        *d++ = SkPixel32ToPixel4444(pmc);
408    }
409}
410
411static void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
412    uint8_t* d = (uint8_t*)dst;
413
414    for (int stop = x + width; x < stop; x++) {
415        *d++ = SkColorGetA(*src++);
416    }
417}
418
419// can return NULL
420static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
421    switch (bitmap.colorType()) {
422        case kN32_SkColorType:
423            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
424        case kARGB_4444_SkColorType:
425            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
426                    FromColor_D4444_Raw;
427        case kRGB_565_SkColorType:
428            return FromColor_D565;
429        case kAlpha_8_SkColorType:
430            return FromColor_DA8;
431        case kRGBA_F16_SkColorType:
432            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
433        default:
434            break;
435    }
436    return NULL;
437}
438
439bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
440        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
441    SkAutoLockPixels alp(dstBitmap);
442    void* dst = dstBitmap.getPixels();
443    FromColorProc proc = ChooseFromColorProc(dstBitmap);
444
445    if (NULL == dst || NULL == proc) {
446        return false;
447    }
448
449    const jint* array = env->GetIntArrayElements(srcColors, NULL);
450    const SkColor* src = (const SkColor*)array + srcOffset;
451
452    // reset to to actual choice from caller
453    dst = dstBitmap.getAddr(x, y);
454
455    SkColorSpace* colorSpace = dstBitmap.colorSpace();
456    if (dstBitmap.colorType() == kRGBA_F16_SkColorType ||
457            GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
458        // now copy/convert each scanline
459        for (int y = 0; y < height; y++) {
460            proc(dst, src, width, x, y);
461            src += srcStride;
462            dst = (char*)dst + dstBitmap.rowBytes();
463        }
464    } else {
465        auto sRGB = SkColorSpace::MakeSRGB();
466        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
467
468        std::unique_ptr<SkColor[]> row(new SkColor[width]);
469
470        // now copy/convert each scanline
471        for (int y = 0; y < height; y++) {
472            memcpy(row.get(), src, sizeof(SkColor) * width);
473            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
474                    SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
475                    SkAlphaType::kUnpremul_SkAlphaType);
476
477            proc(dst, row.get(), width, x, y);
478            src += srcStride;
479            dst = (char*)dst + dstBitmap.rowBytes();
480        }
481    }
482
483    dstBitmap.notifyPixelsChanged();
484
485    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
486    return true;
487}
488
489//////////////////// ToColor procs
490
491typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
492                            SkColorTable*);
493
494static void ToColor_F16_Alpha(SkColor dst[], const void* src, int width,
495                              SkColorTable*) {
496    SkASSERT(width > 0);
497    uint64_t* s = (uint64_t*)src;
498    do {
499        *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
500    } while (--width != 0);
501}
502
503static void ToColor_F16_Raw(SkColor dst[], const void* src, int width,
504                            SkColorTable*) {
505    SkASSERT(width > 0);
506    uint64_t* s = (uint64_t*)src;
507    do {
508        *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
509    } while (--width != 0);
510}
511
512static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
513                              SkColorTable*) {
514    SkASSERT(width > 0);
515    const SkPMColor* s = (const SkPMColor*)src;
516    do {
517        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
518    } while (--width != 0);
519}
520
521static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
522                              SkColorTable*) {
523    SkASSERT(width > 0);
524    const SkPMColor* s = (const SkPMColor*)src;
525    do {
526        SkPMColor c = *s++;
527        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
528                                SkGetPackedG32(c), SkGetPackedB32(c));
529    } while (--width != 0);
530}
531
532static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
533                               SkColorTable*) {
534    SkASSERT(width > 0);
535    const SkPMColor* s = (const SkPMColor*)src;
536    do {
537        SkPMColor c = *s++;
538        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
539                               SkGetPackedB32(c));
540    } while (--width != 0);
541}
542
543static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
544                                SkColorTable*) {
545    SkASSERT(width > 0);
546    const SkPMColor16* s = (const SkPMColor16*)src;
547    do {
548        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
549    } while (--width != 0);
550}
551
552static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
553                                SkColorTable*) {
554    SkASSERT(width > 0);
555    const SkPMColor16* s = (const SkPMColor16*)src;
556    do {
557        SkPMColor c = SkPixel4444ToPixel32(*s++);
558        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
559                                SkGetPackedG32(c), SkGetPackedB32(c));
560    } while (--width != 0);
561}
562
563static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
564                                 SkColorTable*) {
565    SkASSERT(width > 0);
566    const SkPMColor16* s = (const SkPMColor16*)src;
567    do {
568        SkPMColor c = SkPixel4444ToPixel32(*s++);
569        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
570                               SkGetPackedB32(c));
571    } while (--width != 0);
572}
573
574static void ToColor_S565(SkColor dst[], const void* src, int width,
575                         SkColorTable*) {
576    SkASSERT(width > 0);
577    const uint16_t* s = (const uint16_t*)src;
578    do {
579        uint16_t c = *s++;
580        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
581                                SkPacked16ToB32(c));
582    } while (--width != 0);
583}
584
585static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
586                              SkColorTable* ctable) {
587    SkASSERT(width > 0);
588    const uint8_t* s = (const uint8_t*)src;
589    const SkPMColor* colors = ctable->readColors();
590    do {
591        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
592    } while (--width != 0);
593}
594
595static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
596                              SkColorTable* ctable) {
597    SkASSERT(width > 0);
598    const uint8_t* s = (const uint8_t*)src;
599    const SkPMColor* colors = ctable->readColors();
600    do {
601        SkPMColor c = colors[*s++];
602        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
603                                SkGetPackedG32(c), SkGetPackedB32(c));
604    } while (--width != 0);
605}
606
607static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
608                               SkColorTable* ctable) {
609    SkASSERT(width > 0);
610    const uint8_t* s = (const uint8_t*)src;
611    const SkPMColor* colors = ctable->readColors();
612    do {
613        SkPMColor c = colors[*s++];
614        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
615                               SkGetPackedB32(c));
616    } while (--width != 0);
617}
618
619static void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
620    SkASSERT(width > 0);
621    const uint8_t* s = (const uint8_t*)src;
622    do {
623        uint8_t c = *s++;
624        *dst++ = SkColorSetARGB(c, 0, 0, 0);
625    } while (--width != 0);
626}
627
628// can return NULL
629static ToColorProc ChooseToColorProc(const SkBitmap& src) {
630    switch (src.colorType()) {
631        case kN32_SkColorType:
632            switch (src.alphaType()) {
633                case kOpaque_SkAlphaType:
634                    return ToColor_S32_Opaque;
635                case kPremul_SkAlphaType:
636                    return ToColor_S32_Alpha;
637                case kUnpremul_SkAlphaType:
638                    return ToColor_S32_Raw;
639                default:
640                    return NULL;
641            }
642        case kARGB_4444_SkColorType:
643            switch (src.alphaType()) {
644                case kOpaque_SkAlphaType:
645                    return ToColor_S4444_Opaque;
646                case kPremul_SkAlphaType:
647                    return ToColor_S4444_Alpha;
648                case kUnpremul_SkAlphaType:
649                    return ToColor_S4444_Raw;
650                default:
651                    return NULL;
652            }
653        case kRGB_565_SkColorType:
654            return ToColor_S565;
655        case kIndex_8_SkColorType:
656            if (src.getColorTable() == NULL) {
657                return NULL;
658            }
659            switch (src.alphaType()) {
660                case kOpaque_SkAlphaType:
661                    return ToColor_SI8_Opaque;
662                case kPremul_SkAlphaType:
663                    return ToColor_SI8_Alpha;
664                case kUnpremul_SkAlphaType:
665                    return ToColor_SI8_Raw;
666                default:
667                    return NULL;
668            }
669        case kAlpha_8_SkColorType:
670            return ToColor_SA8;
671        case kRGBA_F16_SkColorType:
672            switch (src.alphaType()) {
673                case kOpaque_SkAlphaType:
674                    return ToColor_F16_Raw;
675                case kPremul_SkAlphaType:
676                    return ToColor_F16_Alpha;
677                case kUnpremul_SkAlphaType:
678                    return ToColor_F16_Raw;
679                default:
680                    return NULL;
681            }
682        default:
683            break;
684    }
685    return NULL;
686}
687
688static void ToF16_SA8(void* dst, const void* src, int width) {
689    SkASSERT(width > 0);
690    uint64_t* d = (uint64_t*)dst;
691    const uint8_t* s = (const uint8_t*)src;
692
693    for (int i = 0; i < width; i++) {
694        uint8_t c = *s++;
695        SkPM4f a;
696        a.fVec[SkPM4f::R] = 0.0f;
697        a.fVec[SkPM4f::G] = 0.0f;
698        a.fVec[SkPM4f::B] = 0.0f;
699        a.fVec[SkPM4f::A] = c / 255.0f;
700        *d++ = a.toF16();
701    }
702}
703
704///////////////////////////////////////////////////////////////////////////////
705///////////////////////////////////////////////////////////////////////////////
706
707static int getPremulBitmapCreateFlags(bool isMutable) {
708    int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
709    if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
710    return flags;
711}
712
713static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
714                              jint offset, jint stride, jint width, jint height,
715                              jint configHandle, jboolean isMutable,
716                              jfloatArray xyzD50, jobject transferParameters) {
717    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
718    if (NULL != jColors) {
719        size_t n = env->GetArrayLength(jColors);
720        if (n < SkAbs32(stride) * (size_t)height) {
721            doThrowAIOOBE(env);
722            return NULL;
723        }
724    }
725
726    // ARGB_4444 is a deprecated format, convert automatically to 8888
727    if (colorType == kARGB_4444_SkColorType) {
728        colorType = kN32_SkColorType;
729    }
730
731    SkBitmap bitmap;
732    sk_sp<SkColorSpace> colorSpace;
733
734    if (colorType != kN32_SkColorType || xyzD50 == nullptr || transferParameters == nullptr) {
735        colorSpace = GraphicsJNI::colorSpaceForType(colorType);
736    } else {
737        SkColorSpaceTransferFn p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
738        SkMatrix44 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
739        colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix);
740    }
741
742    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType, colorSpace));
743
744    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
745    if (!nativeBitmap) {
746        return NULL;
747    }
748
749    if (jColors != NULL) {
750        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
751    }
752
753    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
754}
755
756static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
757        SkBitmap::Allocator* alloc) {
758    // Skia does not support copying from kAlpha8 to types that are not alpha only.
759    // We will handle this case here.
760    if (kAlpha_8_SkColorType == src.colorType() && kAlpha_8_SkColorType != dstCT) {
761        SkAutoPixmapUnlock srcUnlocker;
762        if (!src.requestLock(&srcUnlocker)) {
763            return false;
764        }
765        SkPixmap srcPixmap = srcUnlocker.pixmap();
766
767        SkImageInfo dstInfo = src.info().makeColorType(dstCT);
768        if (dstCT == kRGBA_F16_SkColorType) {
769             dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGBLinear());
770        }
771        if (!dst->setInfo(dstInfo)) {
772            return false;
773        }
774        if (!dst->tryAllocPixels(alloc, nullptr)) {
775            return false;
776        }
777
778        switch (dstCT) {
779            case kRGBA_8888_SkColorType:
780            case kBGRA_8888_SkColorType: {
781                for (int y = 0; y < src.height(); y++) {
782                    const uint8_t* srcRow = srcPixmap.addr8(0, y);
783                    uint32_t* dstRow = dst->getAddr32(0, y);
784                    ToColor_SA8(dstRow, srcRow, src.width(), nullptr);
785                }
786                return true;
787            }
788            case kRGB_565_SkColorType: {
789                for (int y = 0; y < src.height(); y++) {
790                    uint16_t* dstRow = dst->getAddr16(0, y);
791                    memset(dstRow, 0, sizeof(uint16_t) * src.width());
792                }
793                return true;
794            }
795            case kRGBA_F16_SkColorType: {
796               for (int y = 0; y < src.height(); y++) {
797                   const uint8_t* srcRow = srcPixmap.addr8(0, y);
798                   void* dstRow = dst->getAddr(0, y);
799                   ToF16_SA8(dstRow, srcRow, src.width());
800               }
801               return true;
802           }
803            default:
804                return false;
805        }
806    }
807
808    return src.copyTo(dst, dstCT, alloc);
809}
810
811static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
812                           jint dstConfigHandle, jboolean isMutable) {
813    SkBitmap src;
814    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
815    if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
816        sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
817        if (!bitmap.get()) {
818            return NULL;
819        }
820        return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
821    }
822
823    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
824    SkBitmap result;
825    HeapAllocator allocator;
826
827    if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
828        return NULL;
829    }
830    auto bitmap = allocator.getStorageObjAndReset();
831    return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
832}
833
834static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
835    SkBitmap result;
836
837    AshmemPixelAllocator allocator(env);
838    if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
839        return NULL;
840    }
841    auto bitmap = allocator.getStorageObjAndReset();
842    bitmap->setImmutable();
843    return bitmap;
844}
845
846static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
847    SkBitmap src;
848    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
849    SkColorType dstCT = src.colorType();
850    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
851    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
852    return ret;
853}
854
855static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
856    SkBitmap src;
857    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
858    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
859    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
860    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
861    return ret;
862}
863
864static void Bitmap_destruct(BitmapWrapper* bitmap) {
865    delete bitmap;
866}
867
868static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
869    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
870}
871
872static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
873    LocalScopedBitmap bitmap(bitmapHandle);
874    bitmap->freePixels();
875    return JNI_TRUE;
876}
877
878static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
879        jint width, jint height, jint configHandle, jboolean requestPremul) {
880    LocalScopedBitmap bitmap(bitmapHandle);
881    bitmap->assertValid();
882    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
883
884    // ARGB_4444 is a deprecated format, convert automatically to 8888
885    if (colorType == kARGB_4444_SkColorType) {
886        colorType = kN32_SkColorType;
887    }
888    size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
889    if (requestedSize > bitmap->getAllocationByteCount()) {
890        // done in native as there's no way to get BytesPerPixel in Java
891        doThrowIAE(env, "Bitmap not large enough to support new configuration");
892        return;
893    }
894    SkAlphaType alphaType;
895    if (bitmap->info().colorType() != kRGB_565_SkColorType
896            && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
897        // If the original bitmap was set to opaque, keep that setting, unless it
898        // was 565, which is required to be opaque.
899        alphaType = kOpaque_SkAlphaType;
900    } else {
901        // Otherwise respect the premultiplied request.
902        alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
903    }
904    bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
905            sk_ref_sp(bitmap->info().colorSpace())));
906}
907
908// These must match the int values in Bitmap.java
909enum JavaEncodeFormat {
910    kJPEG_JavaEncodeFormat = 0,
911    kPNG_JavaEncodeFormat = 1,
912    kWEBP_JavaEncodeFormat = 2
913};
914
915static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
916                                jint format, jint quality,
917                                jobject jstream, jbyteArray jstorage) {
918    SkEncodedImageFormat fm;
919    switch (format) {
920    case kJPEG_JavaEncodeFormat:
921        fm = SkEncodedImageFormat::kJPEG;
922        break;
923    case kPNG_JavaEncodeFormat:
924        fm = SkEncodedImageFormat::kPNG;
925        break;
926    case kWEBP_JavaEncodeFormat:
927        fm = SkEncodedImageFormat::kWEBP;
928        break;
929    default:
930        return JNI_FALSE;
931    }
932
933    LocalScopedBitmap bitmap(bitmapHandle);
934    if (!bitmap.valid()) {
935        return JNI_FALSE;
936    }
937
938    std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
939    if (!strm.get()) {
940        return JNI_FALSE;
941    }
942
943    SkBitmap skbitmap;
944    bitmap->getSkBitmap(&skbitmap);
945    return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
946}
947
948static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
949    LocalScopedBitmap bitmap(bitmapHandle);
950    SkBitmap skBitmap;
951    bitmap->getSkBitmap(&skBitmap);
952    skBitmap.eraseColor(color);
953}
954
955static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
956    LocalScopedBitmap bitmap(bitmapHandle);
957    return static_cast<jint>(bitmap->rowBytes());
958}
959
960static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
961    LocalScopedBitmap bitmap(bitmapHandle);
962    if (bitmap->isHardware()) {
963        return GraphicsJNI::hardwareLegacyBitmapConfig();
964    }
965    return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
966}
967
968static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
969    LocalScopedBitmap bitmap(bitmapHandle);
970    return static_cast<jint>(bitmap->getGenerationID());
971}
972
973static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
974    LocalScopedBitmap bitmap(bitmapHandle);
975    if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
976        return JNI_TRUE;
977    }
978    return JNI_FALSE;
979}
980
981static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
982    LocalScopedBitmap bitmap(bitmapHandle);
983    return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
984}
985
986static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
987        jboolean hasAlpha, jboolean requestPremul) {
988    LocalScopedBitmap bitmap(bitmapHandle);
989    if (hasAlpha) {
990        bitmap->setAlphaType(
991                requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
992    } else {
993        bitmap->setAlphaType(kOpaque_SkAlphaType);
994    }
995}
996
997static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
998        jboolean isPremul) {
999    LocalScopedBitmap bitmap(bitmapHandle);
1000    if (!bitmap->info().isOpaque()) {
1001        if (isPremul) {
1002            bitmap->setAlphaType(kPremul_SkAlphaType);
1003        } else {
1004            bitmap->setAlphaType(kUnpremul_SkAlphaType);
1005        }
1006    }
1007}
1008
1009static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
1010    LocalScopedBitmap bitmap(bitmapHandle);
1011    return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
1012}
1013
1014static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
1015                                jboolean hasMipMap) {
1016    LocalScopedBitmap bitmap(bitmapHandle);
1017    bitmap->setHasHardwareMipMap(hasMipMap);
1018}
1019
1020///////////////////////////////////////////////////////////////////////////////
1021
1022static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
1023    if (parcel == NULL) {
1024        SkDebugf("-------- unparcel parcel is NULL\n");
1025        return NULL;
1026    }
1027
1028    android::Parcel* p = android::parcelForJavaObject(env, parcel);
1029
1030    const bool        isMutable = p->readInt32() != 0;
1031    const SkColorType colorType = (SkColorType)p->readInt32();
1032    const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
1033    const uint32_t    colorSpaceSize = p->readUint32();
1034    sk_sp<SkColorSpace> colorSpace;
1035    if (kRGBA_F16_SkColorType == colorType) {
1036        colorSpace = SkColorSpace::MakeSRGBLinear();
1037    } else if (colorSpaceSize > 0) {
1038        colorSpace = SkColorSpace::Deserialize(p->readInplace(colorSpaceSize), colorSpaceSize);
1039    }
1040    const int         width = p->readInt32();
1041    const int         height = p->readInt32();
1042    const int         rowBytes = p->readInt32();
1043    const int         density = p->readInt32();
1044
1045    if (kN32_SkColorType != colorType &&
1046            kRGBA_F16_SkColorType != colorType &&
1047            kRGB_565_SkColorType != colorType &&
1048            kARGB_4444_SkColorType != colorType &&
1049            kIndex_8_SkColorType != colorType &&
1050            kAlpha_8_SkColorType != colorType) {
1051        SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
1052        return NULL;
1053    }
1054
1055    std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
1056    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
1057            rowBytes)) {
1058        return NULL;
1059    }
1060
1061    SkColorTable* ctable = NULL;
1062    if (colorType == kIndex_8_SkColorType) {
1063        int count = p->readInt32();
1064        if (count < 0 || count > 256) {
1065            // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
1066            // inclusive.
1067            return NULL;
1068        }
1069        if (count > 0) {
1070            size_t size = count * sizeof(SkPMColor);
1071            const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
1072            if (src == NULL) {
1073                return NULL;
1074            }
1075            ctable = new SkColorTable(src, count);
1076        }
1077    }
1078
1079    // Read the bitmap blob.
1080    size_t size = bitmap->getSize();
1081    android::Parcel::ReadableBlob blob;
1082    android::status_t status = p->readBlob(size, &blob);
1083    if (status) {
1084        SkSafeUnref(ctable);
1085        doThrowRE(env, "Could not read bitmap blob.");
1086        return NULL;
1087    }
1088
1089    // Map the bitmap in place from the ashmem region if possible otherwise copy.
1090    sk_sp<Bitmap> nativeBitmap;
1091    if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
1092#if DEBUG_PARCEL
1093        ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
1094                "(fds %s)",
1095                isMutable ? "mutable" : "immutable",
1096                blob.isMutable() ? "mutable" : "immutable",
1097                p->allowFds() ? "allowed" : "forbidden");
1098#endif
1099        // Dup the file descriptor so we can keep a reference to it after the Parcel
1100        // is disposed.
1101        int dupFd = dup(blob.fd());
1102        if (dupFd < 0) {
1103            ALOGE("Error allocating dup fd. Error:%d", errno);
1104            blob.release();
1105            SkSafeUnref(ctable);
1106            doThrowRE(env, "Could not allocate dup blob fd.");
1107            return NULL;
1108        }
1109
1110        // Map the pixels in place and take ownership of the ashmem region.
1111        nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
1112                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
1113        SkSafeUnref(ctable);
1114        if (!nativeBitmap) {
1115            close(dupFd);
1116            blob.release();
1117            doThrowRE(env, "Could not allocate ashmem pixel ref.");
1118            return NULL;
1119        }
1120
1121        // Clear the blob handle, don't release it.
1122        blob.clear();
1123    } else {
1124#if DEBUG_PARCEL
1125        if (blob.fd() >= 0) {
1126            ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
1127                    "from immutable blob (fds %s)",
1128                    p->allowFds() ? "allowed" : "forbidden");
1129        } else {
1130            ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
1131                    "(fds %s)",
1132                    blob.isMutable() ? "mutable" : "immutable",
1133                    p->allowFds() ? "allowed" : "forbidden");
1134        }
1135#endif
1136
1137        // Copy the pixels into a new buffer.
1138        nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
1139        SkSafeUnref(ctable);
1140        if (!nativeBitmap) {
1141            blob.release();
1142            doThrowRE(env, "Could not allocate java pixel ref.");
1143            return NULL;
1144        }
1145        bitmap->lockPixels();
1146        memcpy(bitmap->getPixels(), blob.data(), size);
1147        bitmap->unlockPixels();
1148
1149        // Release the blob handle.
1150        blob.release();
1151    }
1152
1153    return createBitmap(env, nativeBitmap.release(),
1154            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
1155}
1156
1157static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
1158                                     jlong bitmapHandle,
1159                                     jboolean isMutable, jint density,
1160                                     jobject parcel) {
1161    if (parcel == NULL) {
1162        SkDebugf("------- writeToParcel null parcel\n");
1163        return JNI_FALSE;
1164    }
1165
1166    android::Parcel* p = android::parcelForJavaObject(env, parcel);
1167    SkBitmap bitmap;
1168
1169    auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
1170    bitmapWrapper->getSkBitmap(&bitmap);
1171
1172    p->writeInt32(isMutable);
1173    p->writeInt32(bitmap.colorType());
1174    p->writeInt32(bitmap.alphaType());
1175    SkColorSpace* colorSpace = bitmap.colorSpace();
1176    if (colorSpace != nullptr && bitmap.colorType() != kRGBA_F16_SkColorType) {
1177        sk_sp<SkData> data = colorSpace->serialize();
1178        size_t size = data->size();
1179        p->writeUint32(size);
1180        if (size > 0) {
1181            p->write(data->data(), size);
1182        }
1183    } else {
1184        p->writeUint32(0);
1185    }
1186    p->writeInt32(bitmap.width());
1187    p->writeInt32(bitmap.height());
1188    p->writeInt32(bitmap.rowBytes());
1189    p->writeInt32(density);
1190
1191    if (bitmap.colorType() == kIndex_8_SkColorType) {
1192        // The bitmap needs to be locked to access its color table.
1193        SkAutoLockPixels alp(bitmap);
1194        SkColorTable* ctable = bitmap.getColorTable();
1195        if (ctable != NULL) {
1196            int count = ctable->count();
1197            p->writeInt32(count);
1198            memcpy(p->writeInplace(count * sizeof(SkPMColor)),
1199                   ctable->readColors(), count * sizeof(SkPMColor));
1200        } else {
1201            p->writeInt32(0);   // indicate no ctable
1202        }
1203    }
1204
1205    // Transfer the underlying ashmem region if we have one and it's immutable.
1206    android::status_t status;
1207    int fd = bitmapWrapper->bitmap().getAshmemFd();
1208    if (fd >= 0 && !isMutable && p->allowFds()) {
1209#if DEBUG_PARCEL
1210        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
1211                "immutable blob (fds %s)",
1212                p->allowFds() ? "allowed" : "forbidden");
1213#endif
1214
1215        status = p->writeDupImmutableBlobFileDescriptor(fd);
1216        if (status) {
1217            doThrowRE(env, "Could not write bitmap blob file descriptor.");
1218            return JNI_FALSE;
1219        }
1220        return JNI_TRUE;
1221    }
1222
1223    // Copy the bitmap to a new blob.
1224    bool mutableCopy = isMutable;
1225#if DEBUG_PARCEL
1226    ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
1227            isMutable ? "mutable" : "immutable",
1228            mutableCopy ? "mutable" : "immutable",
1229            p->allowFds() ? "allowed" : "forbidden");
1230#endif
1231
1232    size_t size = bitmap.getSize();
1233    android::Parcel::WritableBlob blob;
1234    status = p->writeBlob(size, mutableCopy, &blob);
1235    if (status) {
1236        doThrowRE(env, "Could not copy bitmap to parcel blob.");
1237        return JNI_FALSE;
1238    }
1239
1240    bitmap.lockPixels();
1241    const void* pSrc =  bitmap.getPixels();
1242    if (pSrc == NULL) {
1243        memset(blob.data(), 0, size);
1244    } else {
1245        memcpy(blob.data(), pSrc, size);
1246    }
1247    bitmap.unlockPixels();
1248
1249    blob.release();
1250    return JNI_TRUE;
1251}
1252
1253static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
1254                                   jlong srcHandle, jlong paintHandle,
1255                                   jintArray offsetXY) {
1256    SkBitmap src;
1257    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
1258    const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
1259    SkIPoint  offset;
1260    SkBitmap dst;
1261    HeapAllocator allocator;
1262
1263    src.extractAlpha(&dst, paint, &allocator, &offset);
1264    // If Skia can't allocate pixels for destination bitmap, it resets
1265    // it, that is set its pixels buffer to NULL, and zero width and height.
1266    if (dst.getPixels() == NULL && src.getPixels() != NULL) {
1267        doThrowOOME(env, "failed to allocate pixels for alpha");
1268        return NULL;
1269    }
1270    if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
1271        int* array = env->GetIntArrayElements(offsetXY, NULL);
1272        array[0] = offset.fX;
1273        array[1] = offset.fY;
1274        env->ReleaseIntArrayElements(offsetXY, array, 0);
1275    }
1276
1277    return createBitmap(env, allocator.getStorageObjAndReset(),
1278            getPremulBitmapCreateFlags(true));
1279}
1280
1281///////////////////////////////////////////////////////////////////////////////
1282
1283static jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
1284    LocalScopedBitmap bitmapHolder(bitmapHandle);
1285    if (!bitmapHolder.valid()) return JNI_TRUE;
1286
1287    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
1288    return GraphicsJNI::isColorSpaceSRGB(colorSpace);
1289}
1290
1291static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
1292        jfloatArray xyzArray, jfloatArray paramsArray) {
1293
1294    LocalScopedBitmap bitmapHolder(bitmapHandle);
1295    if (!bitmapHolder.valid()) return JNI_FALSE;
1296
1297    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
1298    if (colorSpace == nullptr) return JNI_FALSE;
1299
1300    SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
1301    if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE;
1302
1303    jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL);
1304    xyz[0] = xyzMatrix.getFloat(0, 0);
1305    xyz[1] = xyzMatrix.getFloat(1, 0);
1306    xyz[2] = xyzMatrix.getFloat(2, 0);
1307    xyz[3] = xyzMatrix.getFloat(0, 1);
1308    xyz[4] = xyzMatrix.getFloat(1, 1);
1309    xyz[5] = xyzMatrix.getFloat(2, 1);
1310    xyz[6] = xyzMatrix.getFloat(0, 2);
1311    xyz[7] = xyzMatrix.getFloat(1, 2);
1312    xyz[8] = xyzMatrix.getFloat(2, 2);
1313    env->ReleaseFloatArrayElements(xyzArray, xyz, 0);
1314
1315    SkColorSpaceTransferFn transferParams;
1316    if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE;
1317
1318    jfloat* params = env->GetFloatArrayElements(paramsArray, NULL);
1319    params[0] = transferParams.fA;
1320    params[1] = transferParams.fB;
1321    params[2] = transferParams.fC;
1322    params[3] = transferParams.fD;
1323    params[4] = transferParams.fE;
1324    params[5] = transferParams.fF;
1325    params[6] = transferParams.fG;
1326    env->ReleaseFloatArrayElements(paramsArray, params, 0);
1327
1328    return JNI_TRUE;
1329}
1330
1331///////////////////////////////////////////////////////////////////////////////
1332
1333static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
1334        jint x, jint y) {
1335    SkBitmap bitmap;
1336    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1337    SkAutoLockPixels alp(bitmap);
1338
1339    ToColorProc proc = ChooseToColorProc(bitmap);
1340    if (NULL == proc) {
1341        return 0;
1342    }
1343    const void* src = bitmap.getAddr(x, y);
1344    if (NULL == src) {
1345        return 0;
1346    }
1347
1348    SkColor dst[1];
1349    proc(dst, src, 1, bitmap.getColorTable());
1350
1351    SkColorSpace* colorSpace = bitmap.colorSpace();
1352    if (bitmap.colorType() != kRGBA_F16_SkColorType &&
1353            !GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1354        auto sRGB = SkColorSpace::MakeSRGB();
1355        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
1356        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
1357                SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
1358                SkAlphaType::kUnpremul_SkAlphaType);
1359    }
1360
1361    return static_cast<jint>(dst[0]);
1362}
1363
1364static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1365        jintArray pixelArray, jint offset, jint stride,
1366        jint x, jint y, jint width, jint height) {
1367    SkBitmap bitmap;
1368    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1369    SkAutoLockPixels alp(bitmap);
1370
1371    ToColorProc proc = ChooseToColorProc(bitmap);
1372    if (NULL == proc) {
1373        return;
1374    }
1375    const void* src = bitmap.getAddr(x, y);
1376    if (NULL == src) {
1377        return;
1378    }
1379
1380    SkColorTable* ctable = bitmap.getColorTable();
1381    jint* dst = env->GetIntArrayElements(pixelArray, NULL);
1382    SkColor* d = (SkColor*)dst + offset;
1383
1384    SkColorSpace* colorSpace = bitmap.colorSpace();
1385    if (bitmap.colorType() == kRGBA_F16_SkColorType ||
1386            GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1387        while (--height >= 0) {
1388            proc(d, src, width, ctable);
1389            d += stride;
1390            src = (void*)((const char*)src + bitmap.rowBytes());
1391        }
1392    } else {
1393        auto sRGB = SkColorSpace::MakeSRGB();
1394        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
1395
1396        while (--height >= 0) {
1397            proc(d, src, width, ctable);
1398
1399            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
1400                    SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
1401                    SkAlphaType::kUnpremul_SkAlphaType);
1402
1403            d += stride;
1404            src = (void*)((const char*)src + bitmap.rowBytes());
1405        }
1406    }
1407
1408    env->ReleaseIntArrayElements(pixelArray, dst, 0);
1409}
1410
1411///////////////////////////////////////////////////////////////////////////////
1412
1413static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
1414        jint x, jint y, jint colorHandle) {
1415    SkBitmap bitmap;
1416    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1417    SkColor color = static_cast<SkColor>(colorHandle);
1418    SkAutoLockPixels alp(bitmap);
1419    if (NULL == bitmap.getPixels()) {
1420        return;
1421    }
1422
1423    FromColorProc proc = ChooseFromColorProc(bitmap);
1424    if (NULL == proc) {
1425        return;
1426    }
1427
1428    SkColorSpace* colorSpace = bitmap.colorSpace();
1429    if (bitmap.colorType() != kRGBA_F16_SkColorType &&
1430            !GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1431        auto sRGB = SkColorSpace::MakeSRGB();
1432        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
1433        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
1434                SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
1435                SkAlphaType::kUnpremul_SkAlphaType);
1436    }
1437
1438    proc(bitmap.getAddr(x, y), &color, 1, x, y);
1439    bitmap.notifyPixelsChanged();
1440}
1441
1442static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1443        jintArray pixelArray, jint offset, jint stride,
1444        jint x, jint y, jint width, jint height) {
1445    SkBitmap bitmap;
1446    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1447    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
1448            x, y, width, height, bitmap);
1449}
1450
1451static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
1452                                      jlong bitmapHandle, jobject jbuffer) {
1453    SkBitmap bitmap;
1454    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1455    SkAutoLockPixels alp(bitmap);
1456    const void* src = bitmap.getPixels();
1457
1458    if (NULL != src) {
1459        android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
1460
1461        // the java side has already checked that buffer is large enough
1462        memcpy(abp.pointer(), src, bitmap.getSize());
1463    }
1464}
1465
1466static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
1467                                        jlong bitmapHandle, jobject jbuffer) {
1468    SkBitmap bitmap;
1469    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1470    SkAutoLockPixels alp(bitmap);
1471    void* dst = bitmap.getPixels();
1472
1473    if (NULL != dst) {
1474        android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
1475        // the java side has already checked that buffer is large enough
1476        memcpy(dst, abp.pointer(), bitmap.getSize());
1477        bitmap.notifyPixelsChanged();
1478    }
1479}
1480
1481static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) {
1482    SkBitmap bm0;
1483    SkBitmap bm1;
1484
1485    LocalScopedBitmap bitmap0(bm0Handle);
1486    LocalScopedBitmap bitmap1(bm1Handle);
1487
1488    // Paying the price for making Hardware Bitmap as Config:
1489    // later check for colorType will pass successfully,
1490    // because Hardware Config internally may be RGBA8888 or smth like that.
1491    if (bitmap0->isHardware() != bitmap1->isHardware()) {
1492        return JNI_FALSE;
1493    }
1494
1495    bitmap0->bitmap().getSkBitmap(&bm0);
1496    bitmap1->bitmap().getSkBitmap(&bm1);
1497    if (bm0.width() != bm1.width()
1498            || bm0.height() != bm1.height()
1499            || bm0.colorType() != bm1.colorType()
1500            || bm0.alphaType() != bm1.alphaType()
1501            || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) {
1502        return JNI_FALSE;
1503    }
1504
1505    SkAutoLockPixels alp0(bm0);
1506    SkAutoLockPixels alp1(bm1);
1507
1508    // if we can't load the pixels, return false
1509    if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
1510        return JNI_FALSE;
1511    }
1512
1513    if (bm0.colorType() == kIndex_8_SkColorType) {
1514        SkColorTable* ct0 = bm0.getColorTable();
1515        SkColorTable* ct1 = bm1.getColorTable();
1516        if (NULL == ct0 || NULL == ct1) {
1517            return JNI_FALSE;
1518        }
1519        if (ct0->count() != ct1->count()) {
1520            return JNI_FALSE;
1521        }
1522
1523        const size_t size = ct0->count() * sizeof(SkPMColor);
1524        if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
1525            return JNI_FALSE;
1526        }
1527    }
1528
1529    // now compare each scanline. We can't do the entire buffer at once,
1530    // since we don't care about the pixel values that might extend beyond
1531    // the width (since the scanline might be larger than the logical width)
1532    const int h = bm0.height();
1533    const size_t size = bm0.width() * bm0.bytesPerPixel();
1534    for (int y = 0; y < h; y++) {
1535        // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
1536        // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
1537        // and bm1 both have pixel data() (have passed NULL == getPixels() check),
1538        // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
1539        // to warn user those 2 unrecognized config bitmaps may be different.
1540        void *bm0Addr = bm0.getAddr(0, y);
1541        void *bm1Addr = bm1.getAddr(0, y);
1542
1543        if(bm0Addr == NULL || bm1Addr == NULL) {
1544            return JNI_FALSE;
1545        }
1546
1547        if (memcmp(bm0Addr, bm1Addr, size) != 0) {
1548            return JNI_FALSE;
1549        }
1550    }
1551    return JNI_TRUE;
1552}
1553
1554static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
1555    LocalScopedBitmap bitmapHandle(bitmapPtr);
1556    if (!bitmapHandle.valid()) return;
1557    android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
1558}
1559
1560static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1561    LocalScopedBitmap bitmapHandle(bitmapPtr);
1562    return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1563}
1564
1565static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
1566    LocalScopedBitmap bitmapHandle(bitmapPtr);
1567    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1568            "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
1569    Bitmap& hwuiBitmap = bitmapHandle->bitmap();
1570    SkBitmap src;
1571    hwuiBitmap.getSkBitmap(&src);
1572
1573    SkBitmap result;
1574    HeapAllocator allocator;
1575    if (!src.copyTo(&result, hwuiBitmap.info().colorType(), &allocator)) {
1576        doThrowRE(env, "Could not copy a hardware bitmap.");
1577        return NULL;
1578    }
1579    return createBitmap(env, allocator.getStorageObjAndReset(), getPremulBitmapCreateFlags(false));
1580}
1581
1582static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
1583    sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
1584    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
1585    if (!bitmap.get()) {
1586        ALOGW("failed to create hardware bitmap from graphic buffer");
1587        return NULL;
1588    }
1589    return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
1590}
1591
1592static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
1593    LocalScopedBitmap bitmapHandle(bitmapPtr);
1594    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1595            "Hardware config is only supported config in Bitmap_getGraphicBuffer");
1596
1597    Bitmap& hwuiBitmap = bitmapHandle->bitmap();
1598    sp<GraphicBuffer> buffer(hwuiBitmap.graphicBuffer());
1599    return createJavaGraphicBuffer(env, buffer);
1600}
1601
1602static void Bitmap_copyColorSpace(JNIEnv* env, jobject, jlong srcBitmapPtr, jlong dstBitmapPtr) {
1603    LocalScopedBitmap srcBitmapHandle(srcBitmapPtr);
1604    LocalScopedBitmap dstBitmapHandle(dstBitmapPtr);
1605
1606    dstBitmapHandle->bitmap().setColorSpace(srcBitmapHandle->bitmap().info().refColorSpace());
1607}
1608
1609///////////////////////////////////////////////////////////////////////////////
1610
1611static const JNINativeMethod gBitmapMethods[] = {
1612    {   "nativeCreate",             "([IIIIIIZ[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/Bitmap;",
1613        (void*)Bitmap_creator },
1614    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
1615        (void*)Bitmap_copy },
1616    {   "nativeCopyAshmem",         "(J)Landroid/graphics/Bitmap;",
1617        (void*)Bitmap_copyAshmem },
1618    {   "nativeCopyAshmemConfig",   "(JI)Landroid/graphics/Bitmap;",
1619        (void*)Bitmap_copyAshmemConfig },
1620    {   "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
1621    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
1622    {   "nativeReconfigure",        "(JIIIZ)V", (void*)Bitmap_reconfigure },
1623    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
1624        (void*)Bitmap_compress },
1625    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
1626    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
1627    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
1628    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
1629    {   "nativeIsPremultiplied",    "(J)Z", (void*)Bitmap_isPremultiplied},
1630    {   "nativeSetHasAlpha",        "(JZZ)V", (void*)Bitmap_setHasAlpha},
1631    {   "nativeSetPremultiplied",   "(JZ)V", (void*)Bitmap_setPremultiplied},
1632    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },
1633    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },
1634    {   "nativeCreateFromParcel",
1635        "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1636        (void*)Bitmap_createFromParcel },
1637    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",
1638        (void*)Bitmap_writeToParcel },
1639    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
1640        (void*)Bitmap_extractAlpha },
1641    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },
1642    {   "nativeGetPixel",           "(JII)I", (void*)Bitmap_getPixel },
1643    {   "nativeGetPixels",          "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1644    {   "nativeSetPixel",           "(JIII)V", (void*)Bitmap_setPixel },
1645    {   "nativeSetPixels",          "(J[IIIIIII)V", (void*)Bitmap_setPixels },
1646    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1647                                            (void*)Bitmap_copyPixelsToBuffer },
1648    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1649                                            (void*)Bitmap_copyPixelsFromBuffer },
1650    {   "nativeSameAs",             "(JJ)Z", (void*)Bitmap_sameAs },
1651    {   "nativePrepareToDraw",      "(J)V", (void*)Bitmap_prepareToDraw },
1652    {   "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
1653    {   "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
1654        (void*)Bitmap_copyPreserveInternalConfig },
1655    {   "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;",
1656        (void*) Bitmap_createHardwareBitmap },
1657    {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
1658        (void*) Bitmap_createGraphicBufferHandle },
1659    {   "nativeGetColorSpace",      "(J[F[F)Z", (void*)Bitmap_getColorSpace },
1660    {   "nativeIsSRGB",             "(J)Z", (void*)Bitmap_isSRGB },
1661    {   "nativeCopyColorSpace",     "(JJ)V",
1662        (void*)Bitmap_copyColorSpace },
1663};
1664
1665int register_android_graphics_Bitmap(JNIEnv* env)
1666{
1667    gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap"));
1668    gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J");
1669    gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1670    gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V");
1671    gBitmap_getAllocationByteCountMethodID = GetMethodIDOrDie(env, gBitmap_class, "getAllocationByteCount", "()I");
1672    return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1673                                         NELEM(gBitmapMethods));
1674}
1675