Bitmap.cpp revision ce217faddb4b40c1b3e698944da1951027080427
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 (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
457        // now copy/convert each scanline
458        for (int y = 0; y < height; y++) {
459            proc(dst, src, width, x, y);
460            src += srcStride;
461            dst = (char*)dst + dstBitmap.rowBytes();
462        }
463    } else {
464        auto sRGB = SkColorSpace::MakeSRGB();
465        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
466
467        std::unique_ptr<SkColor[]> row(new SkColor[width]);
468
469        // now copy/convert each scanline
470        for (int y = 0; y < height; y++) {
471            memcpy(row.get(), src, sizeof(SkColor) * width);
472            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
473                    SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
474                    SkAlphaType::kUnpremul_SkAlphaType);
475
476            proc(dst, row.get(), width, x, y);
477            src += srcStride;
478            dst = (char*)dst + dstBitmap.rowBytes();
479        }
480    }
481
482    dstBitmap.notifyPixelsChanged();
483
484    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
485    return true;
486}
487
488//////////////////// ToColor procs
489
490typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
491                            SkColorTable*);
492
493static void ToColor_F16_Alpha(SkColor dst[], const void* src, int width,
494                              SkColorTable*) {
495    SkASSERT(width > 0);
496    uint64_t* s = (uint64_t*)src;
497    do {
498        *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
499    } while (--width != 0);
500}
501
502static void ToColor_F16_Raw(SkColor dst[], const void* src, int width,
503                            SkColorTable*) {
504    SkASSERT(width > 0);
505    uint64_t* s = (uint64_t*)src;
506    do {
507        *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
508    } while (--width != 0);
509}
510
511static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
512                              SkColorTable*) {
513    SkASSERT(width > 0);
514    const SkPMColor* s = (const SkPMColor*)src;
515    do {
516        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
517    } while (--width != 0);
518}
519
520static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
521                              SkColorTable*) {
522    SkASSERT(width > 0);
523    const SkPMColor* s = (const SkPMColor*)src;
524    do {
525        SkPMColor c = *s++;
526        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
527                                SkGetPackedG32(c), SkGetPackedB32(c));
528    } while (--width != 0);
529}
530
531static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
532                               SkColorTable*) {
533    SkASSERT(width > 0);
534    const SkPMColor* s = (const SkPMColor*)src;
535    do {
536        SkPMColor c = *s++;
537        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
538                               SkGetPackedB32(c));
539    } while (--width != 0);
540}
541
542static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
543                                SkColorTable*) {
544    SkASSERT(width > 0);
545    const SkPMColor16* s = (const SkPMColor16*)src;
546    do {
547        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
548    } while (--width != 0);
549}
550
551static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
552                                SkColorTable*) {
553    SkASSERT(width > 0);
554    const SkPMColor16* s = (const SkPMColor16*)src;
555    do {
556        SkPMColor c = SkPixel4444ToPixel32(*s++);
557        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
558                                SkGetPackedG32(c), SkGetPackedB32(c));
559    } while (--width != 0);
560}
561
562static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
563                                 SkColorTable*) {
564    SkASSERT(width > 0);
565    const SkPMColor16* s = (const SkPMColor16*)src;
566    do {
567        SkPMColor c = SkPixel4444ToPixel32(*s++);
568        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
569                               SkGetPackedB32(c));
570    } while (--width != 0);
571}
572
573static void ToColor_S565(SkColor dst[], const void* src, int width,
574                         SkColorTable*) {
575    SkASSERT(width > 0);
576    const uint16_t* s = (const uint16_t*)src;
577    do {
578        uint16_t c = *s++;
579        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
580                                SkPacked16ToB32(c));
581    } while (--width != 0);
582}
583
584static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
585                              SkColorTable* ctable) {
586    SkASSERT(width > 0);
587    const uint8_t* s = (const uint8_t*)src;
588    const SkPMColor* colors = ctable->readColors();
589    do {
590        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
591    } while (--width != 0);
592}
593
594static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
595                              SkColorTable* ctable) {
596    SkASSERT(width > 0);
597    const uint8_t* s = (const uint8_t*)src;
598    const SkPMColor* colors = ctable->readColors();
599    do {
600        SkPMColor c = colors[*s++];
601        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
602                                SkGetPackedG32(c), SkGetPackedB32(c));
603    } while (--width != 0);
604}
605
606static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
607                               SkColorTable* ctable) {
608    SkASSERT(width > 0);
609    const uint8_t* s = (const uint8_t*)src;
610    const SkPMColor* colors = ctable->readColors();
611    do {
612        SkPMColor c = colors[*s++];
613        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
614                               SkGetPackedB32(c));
615    } while (--width != 0);
616}
617
618static void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
619    SkASSERT(width > 0);
620    const uint8_t* s = (const uint8_t*)src;
621    do {
622        uint8_t c = *s++;
623        *dst++ = SkColorSetARGB(c, c, c, c);
624    } while (--width != 0);
625}
626
627// can return NULL
628static ToColorProc ChooseToColorProc(const SkBitmap& src) {
629    switch (src.colorType()) {
630        case kN32_SkColorType:
631            switch (src.alphaType()) {
632                case kOpaque_SkAlphaType:
633                    return ToColor_S32_Opaque;
634                case kPremul_SkAlphaType:
635                    return ToColor_S32_Alpha;
636                case kUnpremul_SkAlphaType:
637                    return ToColor_S32_Raw;
638                default:
639                    return NULL;
640            }
641        case kARGB_4444_SkColorType:
642            switch (src.alphaType()) {
643                case kOpaque_SkAlphaType:
644                    return ToColor_S4444_Opaque;
645                case kPremul_SkAlphaType:
646                    return ToColor_S4444_Alpha;
647                case kUnpremul_SkAlphaType:
648                    return ToColor_S4444_Raw;
649                default:
650                    return NULL;
651            }
652        case kRGB_565_SkColorType:
653            return ToColor_S565;
654        case kIndex_8_SkColorType:
655            if (src.getColorTable() == NULL) {
656                return NULL;
657            }
658            switch (src.alphaType()) {
659                case kOpaque_SkAlphaType:
660                    return ToColor_SI8_Opaque;
661                case kPremul_SkAlphaType:
662                    return ToColor_SI8_Alpha;
663                case kUnpremul_SkAlphaType:
664                    return ToColor_SI8_Raw;
665                default:
666                    return NULL;
667            }
668        case kAlpha_8_SkColorType:
669            return ToColor_SA8;
670        case kRGBA_F16_SkColorType:
671            switch (src.alphaType()) {
672                case kOpaque_SkAlphaType:
673                    return ToColor_F16_Raw;
674                case kPremul_SkAlphaType:
675                    return ToColor_F16_Alpha;
676                case kUnpremul_SkAlphaType:
677                    return ToColor_F16_Raw;
678                default:
679                    return NULL;
680            }
681        default:
682            break;
683    }
684    return NULL;
685}
686
687///////////////////////////////////////////////////////////////////////////////
688///////////////////////////////////////////////////////////////////////////////
689
690static int getPremulBitmapCreateFlags(bool isMutable) {
691    int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
692    if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
693    return flags;
694}
695
696static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
697                              jint offset, jint stride, jint width, jint height,
698                              jint configHandle, jboolean isMutable) {
699    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
700    if (NULL != jColors) {
701        size_t n = env->GetArrayLength(jColors);
702        if (n < SkAbs32(stride) * (size_t)height) {
703            doThrowAIOOBE(env);
704            return NULL;
705        }
706    }
707
708    // ARGB_4444 is a deprecated format, convert automatically to 8888
709    if (colorType == kARGB_4444_SkColorType) {
710        colorType = kN32_SkColorType;
711    }
712
713    SkBitmap bitmap;
714    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
715            GraphicsJNI::colorSpaceForType(colorType)));
716
717    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
718    if (!nativeBitmap) {
719        return NULL;
720    }
721
722    if (jColors != NULL) {
723        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
724    }
725
726    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
727}
728
729static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
730                           jint dstConfigHandle, jboolean isMutable) {
731    SkBitmap src;
732    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
733    if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
734        sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
735        if (!bitmap.get()) {
736            return NULL;
737        }
738        return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
739    }
740
741    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
742    SkBitmap result;
743    HeapAllocator allocator;
744
745    if (!src.copyTo(&result, dstCT, &allocator)) {
746        return NULL;
747    }
748    auto bitmap = allocator.getStorageObjAndReset();
749    return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
750}
751
752static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
753    SkBitmap result;
754
755    AshmemPixelAllocator allocator(env);
756    if (!src.copyTo(&result, dstCT, &allocator)) {
757        return NULL;
758    }
759    auto bitmap = allocator.getStorageObjAndReset();
760    bitmap->setImmutable();
761    return bitmap;
762}
763
764static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
765    SkBitmap src;
766    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
767    SkColorType dstCT = src.colorType();
768    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
769    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
770    return ret;
771}
772
773static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
774    SkBitmap src;
775    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
776    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
777    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
778    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
779    return ret;
780}
781
782static void Bitmap_destruct(BitmapWrapper* bitmap) {
783    delete bitmap;
784}
785
786static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
787    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
788}
789
790static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
791    LocalScopedBitmap bitmap(bitmapHandle);
792    bitmap->freePixels();
793    return JNI_TRUE;
794}
795
796static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
797        jint width, jint height, jint configHandle, jboolean requestPremul) {
798    LocalScopedBitmap bitmap(bitmapHandle);
799    bitmap->assertValid();
800    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
801
802    // ARGB_4444 is a deprecated format, convert automatically to 8888
803    if (colorType == kARGB_4444_SkColorType) {
804        colorType = kN32_SkColorType;
805    }
806    size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
807    if (requestedSize > bitmap->getAllocationByteCount()) {
808        // done in native as there's no way to get BytesPerPixel in Java
809        doThrowIAE(env, "Bitmap not large enough to support new configuration");
810        return;
811    }
812    SkAlphaType alphaType;
813    if (bitmap->info().colorType() != kRGB_565_SkColorType
814            && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
815        // If the original bitmap was set to opaque, keep that setting, unless it
816        // was 565, which is required to be opaque.
817        alphaType = kOpaque_SkAlphaType;
818    } else {
819        // Otherwise respect the premultiplied request.
820        alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
821    }
822    bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
823            sk_ref_sp(bitmap->info().colorSpace())));
824}
825
826// These must match the int values in Bitmap.java
827enum JavaEncodeFormat {
828    kJPEG_JavaEncodeFormat = 0,
829    kPNG_JavaEncodeFormat = 1,
830    kWEBP_JavaEncodeFormat = 2
831};
832
833static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
834                                jint format, jint quality,
835                                jobject jstream, jbyteArray jstorage) {
836    SkEncodedImageFormat fm;
837    switch (format) {
838    case kJPEG_JavaEncodeFormat:
839        fm = SkEncodedImageFormat::kJPEG;
840        break;
841    case kPNG_JavaEncodeFormat:
842        fm = SkEncodedImageFormat::kPNG;
843        break;
844    case kWEBP_JavaEncodeFormat:
845        fm = SkEncodedImageFormat::kWEBP;
846        break;
847    default:
848        return JNI_FALSE;
849    }
850
851    LocalScopedBitmap bitmap(bitmapHandle);
852    if (!bitmap.valid()) {
853        return JNI_FALSE;
854    }
855
856    std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
857    if (!strm.get()) {
858        return JNI_FALSE;
859    }
860
861    SkBitmap skbitmap;
862    bitmap->getSkBitmap(&skbitmap);
863    return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
864}
865
866static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
867    LocalScopedBitmap bitmap(bitmapHandle);
868    SkBitmap skBitmap;
869    bitmap->getSkBitmap(&skBitmap);
870    skBitmap.eraseColor(color);
871}
872
873static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
874    LocalScopedBitmap bitmap(bitmapHandle);
875    return static_cast<jint>(bitmap->rowBytes());
876}
877
878static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
879    LocalScopedBitmap bitmap(bitmapHandle);
880    if (bitmap->isHardware()) {
881        return GraphicsJNI::hardwareLegacyBitmapConfig();
882    }
883    return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
884}
885
886static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
887    LocalScopedBitmap bitmap(bitmapHandle);
888    return static_cast<jint>(bitmap->getGenerationID());
889}
890
891static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
892    LocalScopedBitmap bitmap(bitmapHandle);
893    if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
894        return JNI_TRUE;
895    }
896    return JNI_FALSE;
897}
898
899static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
900    LocalScopedBitmap bitmap(bitmapHandle);
901    return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
902}
903
904static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
905        jboolean hasAlpha, jboolean requestPremul) {
906    LocalScopedBitmap bitmap(bitmapHandle);
907    if (hasAlpha) {
908        bitmap->setAlphaType(
909                requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
910    } else {
911        bitmap->setAlphaType(kOpaque_SkAlphaType);
912    }
913}
914
915static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
916        jboolean isPremul) {
917    LocalScopedBitmap bitmap(bitmapHandle);
918    if (!bitmap->info().isOpaque()) {
919        if (isPremul) {
920            bitmap->setAlphaType(kPremul_SkAlphaType);
921        } else {
922            bitmap->setAlphaType(kUnpremul_SkAlphaType);
923        }
924    }
925}
926
927static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
928    LocalScopedBitmap bitmap(bitmapHandle);
929    return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
930}
931
932static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
933                                jboolean hasMipMap) {
934    LocalScopedBitmap bitmap(bitmapHandle);
935    bitmap->setHasHardwareMipMap(hasMipMap);
936}
937
938///////////////////////////////////////////////////////////////////////////////
939
940static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
941    if (parcel == NULL) {
942        SkDebugf("-------- unparcel parcel is NULL\n");
943        return NULL;
944    }
945
946    android::Parcel* p = android::parcelForJavaObject(env, parcel);
947
948    const bool        isMutable = p->readInt32() != 0;
949    const SkColorType colorType = (SkColorType)p->readInt32();
950    const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
951    const uint32_t    colorSpaceSize = p->readUint32();
952    sk_sp<SkColorSpace> colorSpace;
953    if (kRGBA_F16_SkColorType == colorType) {
954        colorSpace = SkColorSpace::MakeSRGBLinear();
955    } else if (colorSpaceSize > 0) {
956        colorSpace = SkColorSpace::Deserialize(p->readInplace(colorSpaceSize), colorSpaceSize);
957    }
958    const int         width = p->readInt32();
959    const int         height = p->readInt32();
960    const int         rowBytes = p->readInt32();
961    const int         density = p->readInt32();
962
963    if (kN32_SkColorType != colorType &&
964            kRGBA_F16_SkColorType != colorType &&
965            kRGB_565_SkColorType != colorType &&
966            kARGB_4444_SkColorType != colorType &&
967            kIndex_8_SkColorType != colorType &&
968            kAlpha_8_SkColorType != colorType) {
969        SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
970        return NULL;
971    }
972
973    std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
974    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
975            rowBytes)) {
976        return NULL;
977    }
978
979    SkColorTable* ctable = NULL;
980    if (colorType == kIndex_8_SkColorType) {
981        int count = p->readInt32();
982        if (count < 0 || count > 256) {
983            // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
984            // inclusive.
985            return NULL;
986        }
987        if (count > 0) {
988            size_t size = count * sizeof(SkPMColor);
989            const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
990            if (src == NULL) {
991                return NULL;
992            }
993            ctable = new SkColorTable(src, count);
994        }
995    }
996
997    // Read the bitmap blob.
998    size_t size = bitmap->getSize();
999    android::Parcel::ReadableBlob blob;
1000    android::status_t status = p->readBlob(size, &blob);
1001    if (status) {
1002        SkSafeUnref(ctable);
1003        doThrowRE(env, "Could not read bitmap blob.");
1004        return NULL;
1005    }
1006
1007    // Map the bitmap in place from the ashmem region if possible otherwise copy.
1008    sk_sp<Bitmap> nativeBitmap;
1009    if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
1010#if DEBUG_PARCEL
1011        ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
1012                "(fds %s)",
1013                isMutable ? "mutable" : "immutable",
1014                blob.isMutable() ? "mutable" : "immutable",
1015                p->allowFds() ? "allowed" : "forbidden");
1016#endif
1017        // Dup the file descriptor so we can keep a reference to it after the Parcel
1018        // is disposed.
1019        int dupFd = dup(blob.fd());
1020        if (dupFd < 0) {
1021            ALOGE("Error allocating dup fd. Error:%d", errno);
1022            blob.release();
1023            SkSafeUnref(ctable);
1024            doThrowRE(env, "Could not allocate dup blob fd.");
1025            return NULL;
1026        }
1027
1028        // Map the pixels in place and take ownership of the ashmem region.
1029        nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
1030                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
1031        SkSafeUnref(ctable);
1032        if (!nativeBitmap) {
1033            close(dupFd);
1034            blob.release();
1035            doThrowRE(env, "Could not allocate ashmem pixel ref.");
1036            return NULL;
1037        }
1038
1039        // Clear the blob handle, don't release it.
1040        blob.clear();
1041    } else {
1042#if DEBUG_PARCEL
1043        if (blob.fd() >= 0) {
1044            ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
1045                    "from immutable blob (fds %s)",
1046                    p->allowFds() ? "allowed" : "forbidden");
1047        } else {
1048            ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
1049                    "(fds %s)",
1050                    blob.isMutable() ? "mutable" : "immutable",
1051                    p->allowFds() ? "allowed" : "forbidden");
1052        }
1053#endif
1054
1055        // Copy the pixels into a new buffer.
1056        nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
1057        SkSafeUnref(ctable);
1058        if (!nativeBitmap) {
1059            blob.release();
1060            doThrowRE(env, "Could not allocate java pixel ref.");
1061            return NULL;
1062        }
1063        bitmap->lockPixels();
1064        memcpy(bitmap->getPixels(), blob.data(), size);
1065        bitmap->unlockPixels();
1066
1067        // Release the blob handle.
1068        blob.release();
1069    }
1070
1071    return createBitmap(env, nativeBitmap.release(),
1072            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
1073}
1074
1075static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
1076                                     jlong bitmapHandle,
1077                                     jboolean isMutable, jint density,
1078                                     jobject parcel) {
1079    if (parcel == NULL) {
1080        SkDebugf("------- writeToParcel null parcel\n");
1081        return JNI_FALSE;
1082    }
1083
1084    android::Parcel* p = android::parcelForJavaObject(env, parcel);
1085    SkBitmap bitmap;
1086
1087    auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
1088    bitmapWrapper->getSkBitmap(&bitmap);
1089
1090    p->writeInt32(isMutable);
1091    p->writeInt32(bitmap.colorType());
1092    p->writeInt32(bitmap.alphaType());
1093    SkColorSpace* colorSpace = bitmap.colorSpace();
1094    if (colorSpace != nullptr && bitmap.colorType() != kRGBA_F16_SkColorType) {
1095        sk_sp<SkData> data = colorSpace->serialize();
1096        size_t size = data->size();
1097        p->writeUint32(size);
1098        if (size > 0) {
1099            p->write(data->data(), size);
1100        }
1101    } else {
1102        p->writeUint32(0);
1103    }
1104    p->writeInt32(bitmap.width());
1105    p->writeInt32(bitmap.height());
1106    p->writeInt32(bitmap.rowBytes());
1107    p->writeInt32(density);
1108
1109    if (bitmap.colorType() == kIndex_8_SkColorType) {
1110        // The bitmap needs to be locked to access its color table.
1111        SkAutoLockPixels alp(bitmap);
1112        SkColorTable* ctable = bitmap.getColorTable();
1113        if (ctable != NULL) {
1114            int count = ctable->count();
1115            p->writeInt32(count);
1116            memcpy(p->writeInplace(count * sizeof(SkPMColor)),
1117                   ctable->readColors(), count * sizeof(SkPMColor));
1118        } else {
1119            p->writeInt32(0);   // indicate no ctable
1120        }
1121    }
1122
1123    // Transfer the underlying ashmem region if we have one and it's immutable.
1124    android::status_t status;
1125    int fd = bitmapWrapper->bitmap().getAshmemFd();
1126    if (fd >= 0 && !isMutable && p->allowFds()) {
1127#if DEBUG_PARCEL
1128        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
1129                "immutable blob (fds %s)",
1130                p->allowFds() ? "allowed" : "forbidden");
1131#endif
1132
1133        status = p->writeDupImmutableBlobFileDescriptor(fd);
1134        if (status) {
1135            doThrowRE(env, "Could not write bitmap blob file descriptor.");
1136            return JNI_FALSE;
1137        }
1138        return JNI_TRUE;
1139    }
1140
1141    // Copy the bitmap to a new blob.
1142    bool mutableCopy = isMutable;
1143#if DEBUG_PARCEL
1144    ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
1145            isMutable ? "mutable" : "immutable",
1146            mutableCopy ? "mutable" : "immutable",
1147            p->allowFds() ? "allowed" : "forbidden");
1148#endif
1149
1150    size_t size = bitmap.getSize();
1151    android::Parcel::WritableBlob blob;
1152    status = p->writeBlob(size, mutableCopy, &blob);
1153    if (status) {
1154        doThrowRE(env, "Could not copy bitmap to parcel blob.");
1155        return JNI_FALSE;
1156    }
1157
1158    bitmap.lockPixels();
1159    const void* pSrc =  bitmap.getPixels();
1160    if (pSrc == NULL) {
1161        memset(blob.data(), 0, size);
1162    } else {
1163        memcpy(blob.data(), pSrc, size);
1164    }
1165    bitmap.unlockPixels();
1166
1167    blob.release();
1168    return JNI_TRUE;
1169}
1170
1171static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
1172                                   jlong srcHandle, jlong paintHandle,
1173                                   jintArray offsetXY) {
1174    SkBitmap src;
1175    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
1176    const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
1177    SkIPoint  offset;
1178    SkBitmap dst;
1179    HeapAllocator allocator;
1180
1181    src.extractAlpha(&dst, paint, &allocator, &offset);
1182    // If Skia can't allocate pixels for destination bitmap, it resets
1183    // it, that is set its pixels buffer to NULL, and zero width and height.
1184    if (dst.getPixels() == NULL && src.getPixels() != NULL) {
1185        doThrowOOME(env, "failed to allocate pixels for alpha");
1186        return NULL;
1187    }
1188    if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
1189        int* array = env->GetIntArrayElements(offsetXY, NULL);
1190        array[0] = offset.fX;
1191        array[1] = offset.fY;
1192        env->ReleaseIntArrayElements(offsetXY, array, 0);
1193    }
1194
1195    return createBitmap(env, allocator.getStorageObjAndReset(),
1196            getPremulBitmapCreateFlags(true));
1197}
1198
1199///////////////////////////////////////////////////////////////////////////////
1200
1201static jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
1202    LocalScopedBitmap bitmapHolder(bitmapHandle);
1203    if (!bitmapHolder.valid()) return JNI_TRUE;
1204
1205    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
1206    return GraphicsJNI::isColorSpaceSRGB(colorSpace);
1207}
1208
1209static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
1210        jfloatArray xyzArray, jfloatArray paramsArray) {
1211
1212    LocalScopedBitmap bitmapHolder(bitmapHandle);
1213    if (!bitmapHolder.valid()) return JNI_FALSE;
1214
1215    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
1216    if (colorSpace == nullptr) return JNI_FALSE;
1217
1218    SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
1219    if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE;
1220
1221    jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL);
1222    xyz[0] = xyzMatrix.getFloat(0, 0);
1223    xyz[1] = xyzMatrix.getFloat(1, 0);
1224    xyz[2] = xyzMatrix.getFloat(2, 0);
1225    xyz[3] = xyzMatrix.getFloat(0, 1);
1226    xyz[4] = xyzMatrix.getFloat(1, 1);
1227    xyz[5] = xyzMatrix.getFloat(2, 1);
1228    xyz[6] = xyzMatrix.getFloat(0, 2);
1229    xyz[7] = xyzMatrix.getFloat(1, 2);
1230    xyz[8] = xyzMatrix.getFloat(2, 2);
1231    env->ReleaseFloatArrayElements(xyzArray, xyz, 0);
1232
1233    SkColorSpaceTransferFn transferParams;
1234    if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE;
1235
1236    jfloat* params = env->GetFloatArrayElements(paramsArray, NULL);
1237    params[0] = transferParams.fA;
1238    params[1] = transferParams.fB;
1239    params[2] = transferParams.fC;
1240    params[3] = transferParams.fD;
1241    params[4] = transferParams.fE;
1242    params[5] = transferParams.fF;
1243    params[6] = transferParams.fG;
1244    env->ReleaseFloatArrayElements(paramsArray, params, 0);
1245
1246    return JNI_TRUE;
1247}
1248
1249///////////////////////////////////////////////////////////////////////////////
1250
1251static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
1252        jint x, jint y) {
1253    SkBitmap bitmap;
1254    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1255    SkAutoLockPixels alp(bitmap);
1256
1257    ToColorProc proc = ChooseToColorProc(bitmap);
1258    if (NULL == proc) {
1259        return 0;
1260    }
1261    const void* src = bitmap.getAddr(x, y);
1262    if (NULL == src) {
1263        return 0;
1264    }
1265
1266    SkColor dst[1];
1267    proc(dst, src, 1, bitmap.getColorTable());
1268
1269    SkColorSpace* colorSpace = bitmap.colorSpace();
1270    if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1271        auto sRGB = SkColorSpace::MakeSRGB();
1272        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
1273        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
1274                SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
1275                SkAlphaType::kUnpremul_SkAlphaType);
1276    }
1277
1278    return static_cast<jint>(dst[0]);
1279}
1280
1281static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1282        jintArray pixelArray, jint offset, jint stride,
1283        jint x, jint y, jint width, jint height) {
1284    SkBitmap bitmap;
1285    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1286    SkAutoLockPixels alp(bitmap);
1287
1288    ToColorProc proc = ChooseToColorProc(bitmap);
1289    if (NULL == proc) {
1290        return;
1291    }
1292    const void* src = bitmap.getAddr(x, y);
1293    if (NULL == src) {
1294        return;
1295    }
1296
1297    SkColorTable* ctable = bitmap.getColorTable();
1298    jint* dst = env->GetIntArrayElements(pixelArray, NULL);
1299    SkColor* d = (SkColor*)dst + offset;
1300
1301    SkColorSpace* colorSpace = bitmap.colorSpace();
1302    if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1303        while (--height >= 0) {
1304            proc(d, src, width, ctable);
1305            d += stride;
1306            src = (void*)((const char*)src + bitmap.rowBytes());
1307        }
1308    } else {
1309        auto sRGB = SkColorSpace::MakeSRGB();
1310        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
1311
1312        while (--height >= 0) {
1313            proc(d, src, width, ctable);
1314
1315            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
1316                    SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
1317                    SkAlphaType::kUnpremul_SkAlphaType);
1318
1319            d += stride;
1320            src = (void*)((const char*)src + bitmap.rowBytes());
1321        }
1322    }
1323
1324    env->ReleaseIntArrayElements(pixelArray, dst, 0);
1325}
1326
1327///////////////////////////////////////////////////////////////////////////////
1328
1329static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
1330        jint x, jint y, jint colorHandle) {
1331    SkBitmap bitmap;
1332    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1333    SkColor color = static_cast<SkColor>(colorHandle);
1334    SkAutoLockPixels alp(bitmap);
1335    if (NULL == bitmap.getPixels()) {
1336        return;
1337    }
1338
1339    FromColorProc proc = ChooseFromColorProc(bitmap);
1340    if (NULL == proc) {
1341        return;
1342    }
1343
1344    SkColorSpace* colorSpace = bitmap.colorSpace();
1345    if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1346        auto sRGB = SkColorSpace::MakeSRGB();
1347        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
1348        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
1349                SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
1350                SkAlphaType::kUnpremul_SkAlphaType);
1351    }
1352
1353    proc(bitmap.getAddr(x, y), &color, 1, x, y);
1354    bitmap.notifyPixelsChanged();
1355}
1356
1357static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1358        jintArray pixelArray, jint offset, jint stride,
1359        jint x, jint y, jint width, jint height) {
1360    SkBitmap bitmap;
1361    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1362    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
1363            x, y, width, height, bitmap);
1364}
1365
1366static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
1367                                      jlong bitmapHandle, jobject jbuffer) {
1368    SkBitmap bitmap;
1369    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1370    SkAutoLockPixels alp(bitmap);
1371    const void* src = bitmap.getPixels();
1372
1373    if (NULL != src) {
1374        android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
1375
1376        // the java side has already checked that buffer is large enough
1377        memcpy(abp.pointer(), src, bitmap.getSize());
1378    }
1379}
1380
1381static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
1382                                        jlong bitmapHandle, jobject jbuffer) {
1383    SkBitmap bitmap;
1384    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1385    SkAutoLockPixels alp(bitmap);
1386    void* dst = bitmap.getPixels();
1387
1388    if (NULL != dst) {
1389        android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
1390        // the java side has already checked that buffer is large enough
1391        memcpy(dst, abp.pointer(), bitmap.getSize());
1392        bitmap.notifyPixelsChanged();
1393    }
1394}
1395
1396static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) {
1397    SkBitmap bm0;
1398    SkBitmap bm1;
1399
1400    LocalScopedBitmap bitmap0(bm0Handle);
1401    LocalScopedBitmap bitmap1(bm1Handle);
1402
1403    // Paying the price for making Hardware Bitmap as Config:
1404    // later check for colorType will pass successfully,
1405    // because Hardware Config internally may be RGBA8888 or smth like that.
1406    if (bitmap0->isHardware() != bitmap1->isHardware()) {
1407        return JNI_FALSE;
1408    }
1409
1410    bitmap0->bitmap().getSkBitmap(&bm0);
1411    bitmap1->bitmap().getSkBitmap(&bm1);
1412    if (bm0.width() != bm1.width()
1413            || bm0.height() != bm1.height()
1414            || bm0.colorType() != bm1.colorType()
1415            || bm0.alphaType() != bm1.alphaType()
1416            || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) {
1417        return JNI_FALSE;
1418    }
1419
1420    SkAutoLockPixels alp0(bm0);
1421    SkAutoLockPixels alp1(bm1);
1422
1423    // if we can't load the pixels, return false
1424    if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
1425        return JNI_FALSE;
1426    }
1427
1428    if (bm0.colorType() == kIndex_8_SkColorType) {
1429        SkColorTable* ct0 = bm0.getColorTable();
1430        SkColorTable* ct1 = bm1.getColorTable();
1431        if (NULL == ct0 || NULL == ct1) {
1432            return JNI_FALSE;
1433        }
1434        if (ct0->count() != ct1->count()) {
1435            return JNI_FALSE;
1436        }
1437
1438        const size_t size = ct0->count() * sizeof(SkPMColor);
1439        if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
1440            return JNI_FALSE;
1441        }
1442    }
1443
1444    // now compare each scanline. We can't do the entire buffer at once,
1445    // since we don't care about the pixel values that might extend beyond
1446    // the width (since the scanline might be larger than the logical width)
1447    const int h = bm0.height();
1448    const size_t size = bm0.width() * bm0.bytesPerPixel();
1449    for (int y = 0; y < h; y++) {
1450        // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
1451        // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
1452        // and bm1 both have pixel data() (have passed NULL == getPixels() check),
1453        // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
1454        // to warn user those 2 unrecognized config bitmaps may be different.
1455        void *bm0Addr = bm0.getAddr(0, y);
1456        void *bm1Addr = bm1.getAddr(0, y);
1457
1458        if(bm0Addr == NULL || bm1Addr == NULL) {
1459            return JNI_FALSE;
1460        }
1461
1462        if (memcmp(bm0Addr, bm1Addr, size) != 0) {
1463            return JNI_FALSE;
1464        }
1465    }
1466    return JNI_TRUE;
1467}
1468
1469static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
1470    LocalScopedBitmap bitmapHandle(bitmapPtr);
1471    if (!bitmapHandle.valid()) return;
1472    android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
1473}
1474
1475static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1476    LocalScopedBitmap bitmapHandle(bitmapPtr);
1477    return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1478}
1479
1480static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
1481    LocalScopedBitmap bitmapHandle(bitmapPtr);
1482    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1483            "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
1484    Bitmap& hwuiBitmap = bitmapHandle->bitmap();
1485    SkBitmap src;
1486    hwuiBitmap.getSkBitmap(&src);
1487
1488    SkBitmap result;
1489    HeapAllocator allocator;
1490    if (!src.copyTo(&result, hwuiBitmap.info().colorType(), &allocator)) {
1491        doThrowRE(env, "Could not copy a hardware bitmap.");
1492        return NULL;
1493    }
1494    return createBitmap(env, allocator.getStorageObjAndReset(), getPremulBitmapCreateFlags(false));
1495}
1496
1497static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
1498    sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
1499    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
1500    if (!bitmap.get()) {
1501        ALOGW("failed to create hardware bitmap from graphic buffer");
1502        return NULL;
1503    }
1504    return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
1505}
1506
1507static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
1508    LocalScopedBitmap bitmapHandle(bitmapPtr);
1509    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1510            "Hardware config is only supported config in Bitmap_getGraphicBuffer");
1511
1512    Bitmap& hwuiBitmap = bitmapHandle->bitmap();
1513    sp<GraphicBuffer> buffer(hwuiBitmap.graphicBuffer());
1514    return createJavaGraphicBuffer(env, buffer);
1515}
1516
1517///////////////////////////////////////////////////////////////////////////////
1518static jclass make_globalref(JNIEnv* env, const char classname[])
1519{
1520    jclass c = env->FindClass(classname);
1521    SkASSERT(c);
1522    return (jclass) env->NewGlobalRef(c);
1523}
1524
1525static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1526                                const char fieldname[], const char type[])
1527{
1528    jfieldID id = env->GetFieldID(clazz, fieldname, type);
1529    SkASSERT(id);
1530    return id;
1531}
1532
1533static const JNINativeMethod gBitmapMethods[] = {
1534    {   "nativeCreate",             "([IIIIIIZ)Landroid/graphics/Bitmap;",
1535        (void*)Bitmap_creator },
1536    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
1537        (void*)Bitmap_copy },
1538    {   "nativeCopyAshmem",         "(J)Landroid/graphics/Bitmap;",
1539        (void*)Bitmap_copyAshmem },
1540    {   "nativeCopyAshmemConfig",   "(JI)Landroid/graphics/Bitmap;",
1541        (void*)Bitmap_copyAshmemConfig },
1542    {   "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
1543    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
1544    {   "nativeReconfigure",        "(JIIIZ)V", (void*)Bitmap_reconfigure },
1545    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
1546        (void*)Bitmap_compress },
1547    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
1548    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
1549    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
1550    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
1551    {   "nativeIsPremultiplied",    "(J)Z", (void*)Bitmap_isPremultiplied},
1552    {   "nativeSetHasAlpha",        "(JZZ)V", (void*)Bitmap_setHasAlpha},
1553    {   "nativeSetPremultiplied",   "(JZ)V", (void*)Bitmap_setPremultiplied},
1554    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },
1555    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },
1556    {   "nativeCreateFromParcel",
1557        "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1558        (void*)Bitmap_createFromParcel },
1559    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",
1560        (void*)Bitmap_writeToParcel },
1561    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
1562        (void*)Bitmap_extractAlpha },
1563    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },
1564    {   "nativeGetPixel",           "(JII)I", (void*)Bitmap_getPixel },
1565    {   "nativeGetPixels",          "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1566    {   "nativeSetPixel",           "(JIII)V", (void*)Bitmap_setPixel },
1567    {   "nativeSetPixels",          "(J[IIIIIII)V", (void*)Bitmap_setPixels },
1568    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1569                                            (void*)Bitmap_copyPixelsToBuffer },
1570    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1571                                            (void*)Bitmap_copyPixelsFromBuffer },
1572    {   "nativeSameAs",             "(JJ)Z", (void*)Bitmap_sameAs },
1573    {   "nativePrepareToDraw",      "(J)V", (void*)Bitmap_prepareToDraw },
1574    {   "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
1575    {   "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
1576        (void*)Bitmap_copyPreserveInternalConfig },
1577    {   "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;",
1578        (void*) Bitmap_createHardwareBitmap },
1579    {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
1580        (void*) Bitmap_createGraphicBufferHandle },
1581    {   "nativeGetColorSpace",      "(J[F[F)Z", (void*)Bitmap_getColorSpace },
1582    {   "nativeIsSRGB",             "(J)Z", (void*)Bitmap_isSRGB },
1583};
1584
1585int register_android_graphics_Bitmap(JNIEnv* env)
1586{
1587    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1588    gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1589    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1590    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1591    gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
1592    return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1593                                         NELEM(gBitmapMethods));
1594}
1595