1f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#define LOG_TAG "Bitmap"
2f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#include "Bitmap.h"
3f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkBitmap.h"
532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkPixelRef.h"
632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkImageEncoder.h"
757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III#include "SkImageInfo.h"
832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkColorPriv.h"
932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "GraphicsJNI.h"
1032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkDither.h"
1132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkUnPreMultiply.h"
1232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkStream.h"
1332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <binder/Parcel.h>
1532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_os_Parcel.h"
1632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_util_Binder.h"
1732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_nio_utils.h"
1832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "CreateJavaOutputStreamAdaptor.h"
19f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#include <Caches.h>
20dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h>
2132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
22ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
23ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
2432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <jni.h>
2539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <memory>
2639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <string>
2739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <sys/mman.h>
2839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <cutils/ashmem.h>
2932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
30a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#define DEBUG_PARCEL 0
318cee7c17119b204be88860feb812f2374d0de732Riley Andrews#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
32a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
33f29ed28c7b878ef28058bc730715d0d32445bc57John Recknamespace android {
34f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
35f29ed28c7b878ef28058bc730715d0d32445bc57John Reckclass WrappedPixelRef : public SkPixelRef {
36f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
37f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    WrappedPixelRef(Bitmap* wrapper, void* storage,
38f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
39f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            : SkPixelRef(info)
40f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            , mBitmap(*wrapper)
41f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            , mStorage(storage) {
42f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        reconfigure(info, rowBytes, ctable);
43f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
44f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
45f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ~WrappedPixelRef() {
46f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // Tell SkRefCnt that everything is as it expects by forcing
47f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // the refcnt to 1
48f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        internal_dispose_restore_refcnt_to_1();
49f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkSafeUnref(mColorTable);
50f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
51f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
520781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck    void reconfigure(const SkImageInfo& newInfo, size_t rowBytes, SkColorTable* ctable) {
530781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        if (kIndex_8_SkColorType != newInfo.colorType()) {
54f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            ctable = nullptr;
55f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        }
56f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        mRowBytes = rowBytes;
57f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        if (mColorTable != ctable) {
58f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            SkSafeUnref(mColorTable);
59f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            mColorTable = ctable;
60f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            SkSafeRef(mColorTable);
61f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        }
620781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck
630781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        // Need to validate the alpha type to filter against the color type
640781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        // to prevent things like a non-opaque RGB565 bitmap
650781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        SkAlphaType alphaType;
660781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        LOG_ALWAYS_FATAL_IF(!SkColorTypeValidateAlphaType(
670781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck                newInfo.colorType(), newInfo.alphaType(), &alphaType),
680781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck                "Failed to validate alpha type!");
690781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck
70f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // Dirty hack is dirty
71f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // TODO: Figure something out here, Skia's current design makes this
72f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // really hard to work with. Skia really, really wants immutable objects,
73f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // but with the nested-ref-count hackery going on that's just not
74f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // feasible without going insane trying to figure it out
75f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkImageInfo* myInfo = const_cast<SkImageInfo*>(&this->info());
760781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        *myInfo = newInfo;
770781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        changeAlphaType(alphaType);
78f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
79f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // Docs say to only call this in the ctor, but we're going to call
80f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // it anyway even if this isn't always the ctor.
81f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // TODO: Fix this too as part of the above TODO
82f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        setPreLocked(mStorage, mRowBytes, mColorTable);
83f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
84f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
85f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // Can't mark as override since SkPixelRef::rowBytes isn't virtual
86f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // but that's OK since we just want BitmapWrapper to be able to rely
87f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // on calling rowBytes() on an unlocked pixelref, which it will be
88f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // doing on a WrappedPixelRef type, not a SkPixelRef, so static
89f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // dispatching will do what we want.
90f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    size_t rowBytes() const { return mRowBytes; }
91f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkColorTable* colorTable() const { return mColorTable; }
92f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
93f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool hasHardwareMipMap() const {
94f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return mHasHardwareMipMap;
95f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
96f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
97f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void setHasHardwareMipMap(bool hasMipMap) {
98f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        mHasHardwareMipMap = hasMipMap;
99f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
100f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
101f29ed28c7b878ef28058bc730715d0d32445bc57John Reckprotected:
102f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    virtual bool onNewLockPixels(LockRec* rec) override {
103f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        rec->fPixels = mStorage;
104f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        rec->fRowBytes = mRowBytes;
105f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        rec->fColorTable = mColorTable;
106f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return true;
107f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
108f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
109f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    virtual void onUnlockPixels() override {
110f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // nothing
111f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
112f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
113f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    virtual size_t getAllocatedSizeInBytes() const override {
114f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return info().getSafeSize(mRowBytes);
115f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
116f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
117f29ed28c7b878ef28058bc730715d0d32445bc57John Reckprivate:
118f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    Bitmap& mBitmap;
119f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* mStorage;
120f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    size_t mRowBytes = 0;
121f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkColorTable* mColorTable = nullptr;
122f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool mHasHardwareMipMap = false;
123f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
124f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    virtual void internal_dispose() const override {
125f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        mBitmap.onStrongRefDestroyed();
126f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
127f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
128f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
129f29ed28c7b878ef28058bc730715d0d32445bc57John ReckBitmap::Bitmap(JNIEnv* env, jbyteArray storageObj, void* address,
130f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
131f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        : mPixelStorageType(PixelStorageType::Java) {
132f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    env->GetJavaVM(&mPixelStorage.java.jvm);
133f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelStorage.java.jweakRef = env->NewWeakGlobalRef(storageObj);
134f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelStorage.java.jstrongRef = nullptr;
135f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable));
136f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // Note: this will trigger a call to onStrongRefDestroyed(), but
137f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // we want the pixel ref to have a ref count of 0 at this point
138f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelRef->unref();
139f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
140f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
141f29ed28c7b878ef28058bc730715d0d32445bc57John ReckBitmap::Bitmap(void* address, void* context, FreeFunc freeFunc,
142f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
143f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        : mPixelStorageType(PixelStorageType::External) {
144f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelStorage.external.address = address;
145f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelStorage.external.context = context;
146f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelStorage.external.freeFunc = freeFunc;
147f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable));
148f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // Note: this will trigger a call to onStrongRefDestroyed(), but
149f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // we want the pixel ref to have a ref count of 0 at this point
150f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelRef->unref();
151f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
152f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
15339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley AndrewsBitmap::Bitmap(void* address, int fd,
15439d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
15539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        : mPixelStorageType(PixelStorageType::Ashmem) {
15639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    mPixelStorage.ashmem.address = address;
15739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    mPixelStorage.ashmem.fd = fd;
15839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    mPixelStorage.ashmem.size = ashmem_get_size_region(fd);
15939d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable));
16039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    // Note: this will trigger a call to onStrongRefDestroyed(), but
16139d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    // we want the pixel ref to have a ref count of 0 at this point
16239d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    mPixelRef->unref();
16339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews}
164f29ed28c7b878ef28058bc730715d0d32445bc57John ReckBitmap::~Bitmap() {
165f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    doFreePixels();
166f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
167f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
168f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::freePixels() {
169f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    AutoMutex _lock(mLock);
170f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (mPinnedRefCount == 0) {
171f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        doFreePixels();
172f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        mPixelStorageType = PixelStorageType::Invalid;
173f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
174f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
175f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
176f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::doFreePixels() {
177f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    switch (mPixelStorageType) {
178f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    case PixelStorageType::Invalid:
179f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // already free'd, nothing to do
180f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
181f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    case PixelStorageType::External:
182f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        mPixelStorage.external.freeFunc(mPixelStorage.external.address,
183f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                mPixelStorage.external.context);
184f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
18539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    case PixelStorageType::Ashmem:
18639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        munmap(mPixelStorage.ashmem.address, mPixelStorage.ashmem.size);
18739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        close(mPixelStorage.ashmem.fd);
18839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        break;
189f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    case PixelStorageType::Java:
190f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        JNIEnv* env = jniEnv();
191f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        LOG_ALWAYS_FATAL_IF(mPixelStorage.java.jstrongRef,
192f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                "Deleting a bitmap wrapper while there are outstanding strong "
193f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                "references! mPinnedRefCount = %d", mPinnedRefCount);
194f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        env->DeleteWeakGlobalRef(mPixelStorage.java.jweakRef);
195f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
196f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
197f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
198f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (android::uirenderer::Caches::hasInstance()) {
199f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        android::uirenderer::Caches::getInstance().textureCache.releaseTexture(
200f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                mPixelRef->getStableID());
201f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
202f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
203f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
204f29ed28c7b878ef28058bc730715d0d32445bc57John Reckbool Bitmap::hasHardwareMipMap() {
205f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return mPixelRef->hasHardwareMipMap();
206f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
207f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
208f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::setHasHardwareMipMap(bool hasMipMap) {
209f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelRef->setHasHardwareMipMap(hasMipMap);
210f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
211f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
21239d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrewsint Bitmap::getAshmemFd() const {
21339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    switch (mPixelStorageType) {
21439d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    case PixelStorageType::Ashmem:
21539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        return mPixelStorage.ashmem.fd;
21639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    default:
21739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        return -1;
21839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
21939d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews}
22039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
221f29ed28c7b878ef28058bc730715d0d32445bc57John Reckconst SkImageInfo& Bitmap::info() const {
222f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return mPixelRef->info();
223f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
224f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
225f29ed28c7b878ef28058bc730715d0d32445bc57John Recksize_t Bitmap::rowBytes() const {
226f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return mPixelRef->rowBytes();
227f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
228f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
229ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn ReckSkPixelRef* Bitmap::peekAtPixelRef() const {
230f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    assertValid();
231f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return mPixelRef.get();
232f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
233f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
234ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn ReckSkPixelRef* Bitmap::refPixelRef() {
235ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    assertValid();
236ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    android::AutoMutex _lock(mLock);
237ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    return refPixelRefLocked();
238ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck}
239ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck
240ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn ReckSkPixelRef* Bitmap::refPixelRefLocked() {
241ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    mPixelRef->ref();
242ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    if (mPixelRef->unique()) {
243ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck        // We just restored this from 0, pin the pixels and inc the strong count
244ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck        // Note that there *might be* an incoming onStrongRefDestroyed from whatever
245ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck        // last unref'd
246ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck        pinPixelsLocked();
247ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck        mPinnedRefCount++;
248ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    }
249ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    return mPixelRef.get();
250ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck}
251ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck
252f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::reconfigure(const SkImageInfo& info, size_t rowBytes,
253f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ctable) {
254f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelRef->reconfigure(info, rowBytes, ctable);
255f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
256f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
257f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::reconfigure(const SkImageInfo& info) {
2582a94a10bec186d832c2b95675cb6dc27b012c2d0Derek Sollenberger    reconfigure(info, info.minRowBytes(), nullptr);
259f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
260f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
2610781a2f116be045ff1a3aca721c47f9fef980beaJohn Reckvoid Bitmap::setAlphaType(SkAlphaType alphaType) {
2620781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck    if (!SkColorTypeValidateAlphaType(info().colorType(), alphaType, &alphaType)) {
2630781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        return;
2640781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck    }
2650781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck
2660781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck    mPixelRef->changeAlphaType(alphaType);
2670781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck}
2680781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck
269f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::detachFromJava() {
270f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool disposeSelf;
271f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    {
272f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        android::AutoMutex _lock(mLock);
273f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        mAttachedToJava = false;
274f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        disposeSelf = shouldDisposeSelfLocked();
275f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
276f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (disposeSelf) {
277f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        delete this;
278f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
279f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
280f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
281f29ed28c7b878ef28058bc730715d0d32445bc57John Reckbool Bitmap::shouldDisposeSelfLocked() {
282f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return mPinnedRefCount == 0 && !mAttachedToJava;
283f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
284f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
285f29ed28c7b878ef28058bc730715d0d32445bc57John ReckJNIEnv* Bitmap::jniEnv() {
286f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    JNIEnv* env;
287f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    auto success = mPixelStorage.java.jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
288f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LOG_ALWAYS_FATAL_IF(success != JNI_OK,
289f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        "Failed to get JNIEnv* from JVM: %p", mPixelStorage.java.jvm);
290f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return env;
291f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
292f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
293f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::onStrongRefDestroyed() {
294f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool disposeSelf = false;
295f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    {
296f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        android::AutoMutex _lock(mLock);
297f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        if (mPinnedRefCount > 0) {
298f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            mPinnedRefCount--;
299f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            if (mPinnedRefCount == 0) {
300f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                unpinPixelsLocked();
301f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                disposeSelf = shouldDisposeSelfLocked();
302f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            }
303f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        }
304f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
305f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (disposeSelf) {
306f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        delete this;
307f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
308f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
309f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
310f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::pinPixelsLocked() {
311f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    switch (mPixelStorageType) {
312f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    case PixelStorageType::Invalid:
313f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        LOG_ALWAYS_FATAL("Cannot pin invalid pixels!");
314f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
315f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    case PixelStorageType::External:
31639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    case PixelStorageType::Ashmem:
317f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // Nothing to do
318f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
319f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    case PixelStorageType::Java: {
320f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        JNIEnv* env = jniEnv();
321f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        if (!mPixelStorage.java.jstrongRef) {
322f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            mPixelStorage.java.jstrongRef = reinterpret_cast<jbyteArray>(
323f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                    env->NewGlobalRef(mPixelStorage.java.jweakRef));
324f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            if (!mPixelStorage.java.jstrongRef) {
325f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                LOG_ALWAYS_FATAL("Failed to acquire strong reference to pixels");
326f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            }
327f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        }
328f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
329f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
330f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
331f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
332f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
333f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::unpinPixelsLocked() {
334f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    switch (mPixelStorageType) {
335f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    case PixelStorageType::Invalid:
336f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        LOG_ALWAYS_FATAL("Cannot unpin invalid pixels!");
337f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
338f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    case PixelStorageType::External:
33939d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    case PixelStorageType::Ashmem:
340f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        // Don't need to do anything
341f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
342f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    case PixelStorageType::Java: {
343f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        JNIEnv* env = jniEnv();
344f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        if (mPixelStorage.java.jstrongRef) {
345f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            env->DeleteGlobalRef(mPixelStorage.java.jstrongRef);
346f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            mPixelStorage.java.jstrongRef = nullptr;
347f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        }
348f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
349f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
350f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
351f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
352f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
353f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::getSkBitmap(SkBitmap* outBitmap) {
354f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    assertValid();
355f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    android::AutoMutex _lock(mLock);
356f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // Safe because mPixelRef is a WrappedPixelRef type, otherwise rowBytes()
357f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    // would require locking the pixels first.
358f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    outBitmap->setInfo(mPixelRef->info(), mPixelRef->rowBytes());
359ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    outBitmap->setPixelRef(refPixelRefLocked())->unref();
360f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    outBitmap->setHasHardwareMipMap(hasHardwareMipMap());
361f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
362f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
363f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid Bitmap::assertValid() const {
364f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LOG_ALWAYS_FATAL_IF(mPixelStorageType == PixelStorageType::Invalid,
365f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            "Error, cannot access an invalid/free'd bitmap here!");
366f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
367f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
368f29ed28c7b878ef28058bc730715d0d32445bc57John Reck} // namespace android
369f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
370f29ed28c7b878ef28058bc730715d0d32445bc57John Reckusing namespace android;
371f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
372f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// Convenience class that does not take a global ref on the pixels, relying
373f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// on the caller already having a local JNI ref
374f29ed28c7b878ef28058bc730715d0d32445bc57John Reckclass LocalScopedBitmap {
375f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
376f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap(jlong bitmapHandle)
377f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            : mBitmap(reinterpret_cast<Bitmap*>(bitmapHandle)) {}
378f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
379f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    Bitmap* operator->() {
380f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return mBitmap;
381f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
382f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
383f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* pixels() {
384ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck        return mBitmap->peekAtPixelRef()->pixels();
385f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
386f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
387f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool valid() {
388f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return mBitmap && mBitmap->valid();
389f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
390f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
391f29ed28c7b878ef28058bc730715d0d32445bc57John Reckprivate:
392f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    Bitmap* mBitmap;
393f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
394f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
39532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
39632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// Conversions to/from SkColor, for get/setPixels, and the create method, which
39732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// is basically like setPixels
39832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
39932054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
40032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              int x, int y);
40132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
40232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32(void* dst, const SkColor src[], int width,
40332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
40432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
40532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
40632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
40732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPreMultiplyColor(*src++);
40832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
40932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
41032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
41132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
41232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
41346d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    // Needed to thwart the unreachable code detection from clang.
41446d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
41546d8444631b4b1253a76bfcc78a29d26014d022fDan Albert
41632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // SkColor's ordering may be different from SkPMColor
41746d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    if (sk_color_ne_zero) {
41832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        memcpy(dst, src, width * sizeof(SkColor));
41932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
42032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
42132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
42232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // order isn't same, repack each pixel manually
42332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
42432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
42532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
42632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
42732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   SkColorGetG(c), SkColorGetB(c));
42832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
42932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
43032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
43132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D565(void* dst, const SkColor src[], int width,
43232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           int x, int y) {
43332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    uint16_t* d = (uint16_t*)dst;
43432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
43532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_565_SCAN(y);
43632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
43732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
43832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
43932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                DITHER_VALUE(x));
44032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
44132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
44232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
44332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444(void* dst, const SkColor src[], int width,
44432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
44532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
44632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
44732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
44832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
44932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPreMultiplyColor(*src++);
45032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
45132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
45232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
45332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
45432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
45532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
45632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
45732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
45832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
45932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
46032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
46132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
46232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
46332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
46432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
46532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            SkColorGetG(c), SkColorGetB(c));
46632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
46732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
46832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
46932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
47032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
4716260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
4726260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    uint8_t* d = (uint8_t*)dst;
4736260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
4746260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    for (int stop = x + width; x < stop; x++) {
4756260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *d++ = SkColorGetA(*src++);
4766260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    }
4776260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
4786260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
47932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
48057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
48157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    switch (bitmap.colorType()) {
48257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kN32_SkColorType:
48357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
48457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kARGB_4444_SkColorType:
48557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
48657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    FromColor_D4444_Raw;
48757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kRGB_565_SkColorType:
48832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return FromColor_D565;
4896260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
4906260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return FromColor_DA8;
49132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
49232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
49332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
49432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
49532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
49632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
49732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikbool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
49857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
49932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkAutoLockPixels alp(dstBitmap);
50032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    void* dst = dstBitmap.getPixels();
50157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    FromColorProc proc = ChooseFromColorProc(dstBitmap);
50232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
50332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == dst || NULL == proc) {
50432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return false;
50532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
50632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
50732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const jint* array = env->GetIntArrayElements(srcColors, NULL);
50832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkColor* src = (const SkColor*)array + srcOffset;
50932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
51032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // reset to to actual choice from caller
51132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dst = dstBitmap.getAddr(x, y);
51232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // now copy/convert each scanline
51332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int y = 0; y < height; y++) {
51432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        proc(dst, src, width, x, y);
51532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        src += srcStride;
51632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        dst = (char*)dst + dstBitmap.rowBytes();
51732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
51832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
51932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dstBitmap.notifyPixelsChanged();
52032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
52132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
52232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                 JNI_ABORT);
52332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return true;
52432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
52532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
52632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//////////////////// ToColor procs
52732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
52832054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
52932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            SkColorTable*);
53032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
53132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
53232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
53332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
53432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
53532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
53632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
53732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
53832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
53932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
54032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
54132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
54232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
54332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
54432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
54532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
54632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
54732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
54832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
54932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
55032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
55132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
55232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable*) {
55332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
55432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
55532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
55632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
55732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
55832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
55932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
56032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
56132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
56232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
56332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
56432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
56532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
56632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
56732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
56832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
56932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
57032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
57132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
57232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
57332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
57432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
57532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
57632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
57732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
57832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
57932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
58032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
58132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
58232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
58332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                 SkColorTable*) {
58432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
58532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
58632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
58732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
58832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
58932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
59032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
59132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
59232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
59332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S565(SkColor dst[], const void* src, int width,
59432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                         SkColorTable*) {
59532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
59632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint16_t* s = (const uint16_t*)src;
59732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
59832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        uint16_t c = *s++;
59932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
60032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkPacked16ToB32(c));
60132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
60232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
60332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
60432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
60532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
60632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
60732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
60871487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
60932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
61032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
61132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
61232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
61332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
61432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
61532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
61632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
61732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
61871487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
61932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
62032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
62132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
62232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
62332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
62432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
62532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
62632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
62732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable* ctable) {
62832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
62932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
63071487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
63132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
63232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
63332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
63432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
63532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
63632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
63732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
6386260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
6396260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    SkASSERT(width > 0);
6406260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    const uint8_t* s = (const uint8_t*)src;
6416260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    do {
6426260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        uint8_t c = *s++;
6436260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *dst++ = SkColorSetARGB(c, c, c, c);
6446260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    } while (--width != 0);
6456260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
6466260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
64732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
64857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic ToColorProc ChooseToColorProc(const SkBitmap& src) {
649b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    switch (src.colorType()) {
650b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kN32_SkColorType:
65157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
65257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
65357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Opaque;
65457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
65557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Alpha;
65657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
65757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Raw;
65857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
65957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
66057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
661b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kARGB_4444_SkColorType:
66257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
66357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
66457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Opaque;
66557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
66657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Alpha;
66757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
66857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Raw;
66957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
67057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
67157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
672b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kRGB_565_SkColorType:
67332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return ToColor_S565;
674b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kIndex_8_SkColorType:
67532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            if (src.getColorTable() == NULL) {
67632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                return NULL;
67732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            }
67857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
67957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
68057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Opaque;
68157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
68257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Alpha;
68357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
68457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Raw;
68557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
68657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
68757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
6886260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
6896260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return ToColor_SA8;
69032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
69132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
69232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
69332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
69432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
69532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
69632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
69732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
69832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
69932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic int getPremulBitmapCreateFlags(bool isMutable) {
70032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    int flags = GraphicsJNI::kBitmapCreateFlag_Premultiplied;
70132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (isMutable) flags |= GraphicsJNI::kBitmapCreateFlag_Mutable;
70232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return flags;
70332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
70432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
70532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
70632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint offset, jint stride, jint width, jint height,
70732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint configHandle, jboolean isMutable) {
7081103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
70932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != jColors) {
71032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        size_t n = env->GetArrayLength(jColors);
71132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (n < SkAbs32(stride) * (size_t)height) {
71232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            doThrowAIOOBE(env);
71332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return NULL;
71432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
71532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
71632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
71732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // ARGB_4444 is a deprecated format, convert automatically to 8888
718b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kARGB_4444_SkColorType) {
719b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        colorType = kN32_SkColorType;
72032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
72132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
72232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkBitmap bitmap;
723b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType));
72432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
725f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    Bitmap* nativeBitmap = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
726f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!nativeBitmap) {
72732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
72832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
72932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
73032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (jColors != NULL) {
73132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        GraphicsJNI::SetPixels(env, jColors, offset, stride,
73257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                0, 0, width, height, bitmap);
73332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
73432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
735f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return GraphicsJNI::createBitmap(env, nativeBitmap,
736f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            getPremulBitmapCreateFlags(isMutable));
73732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
73832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
73932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
74032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           jint dstConfigHandle, jboolean isMutable) {
741f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
742f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
7431103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
74432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkBitmap            result;
74532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    JavaPixelAllocator  allocator(env);
74632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
747f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!src.copyTo(&result, dstCT, &allocator)) {
74832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
74932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
750f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    Bitmap* bitmap = allocator.getStorageObjAndReset();
751f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return GraphicsJNI::createBitmap(env, bitmap,
752f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            getPremulBitmapCreateFlags(isMutable));
75332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
75432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
755a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
756721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    SkBitmap result;
757721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
758721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    AshmemPixelAllocator allocator(env);
759a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    if (!src.copyTo(&result, dstCT, &allocator)) {
760721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        return NULL;
761721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    }
762721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    Bitmap* bitmap = allocator.getStorageObjAndReset();
763721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    bitmap->peekAtPixelRef()->setImmutable();
764a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    return bitmap;
765a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
766a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
767a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
768a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
769a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
770a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = src.colorType();
771a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    Bitmap* bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
772a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    jobject ret = GraphicsJNI::createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
773a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    return ret;
774a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
775a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
776a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
777a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
778a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
779a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
780a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    Bitmap* bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
781721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    jobject ret = GraphicsJNI::createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
782721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    return ret;
783721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews}
784721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
785775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhlerstatic void Bitmap_destruct(Bitmap* bitmap) {
786f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->detachFromJava();
78732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
78832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
789775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhlerstatic jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
790775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
791775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler}
792775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler
79332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
794f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
795f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->freePixels();
79632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
79732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
79832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
79932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
80017a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        jint width, jint height, jint configHandle, jint allocSize,
80117a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        jboolean requestPremul) {
802f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
8031103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
80417a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III
80517a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    // ARGB_4444 is a deprecated format, convert automatically to 8888
80617a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    if (colorType == kARGB_4444_SkColorType) {
80717a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        colorType = kN32_SkColorType;
80817a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
80917a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III
81017a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    if (width * height * SkColorTypeBytesPerPixel(colorType) > allocSize) {
81132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // done in native as there's no way to get BytesPerPixel in Java
81232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowIAE(env, "Bitmap not large enough to support new configuration");
81332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
81432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
81517a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    SkAlphaType alphaType;
816f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().colorType() != kRGB_565_SkColorType
817f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
81817a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // If the original bitmap was set to opaque, keep that setting, unless it
81917a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // was 565, which is required to be opaque.
82017a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = kOpaque_SkAlphaType;
82117a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    } else {
82217a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // Otherwise respect the premultiplied request.
82317a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
82417a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
825f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->reconfigure(SkImageInfo::Make(width, height, colorType, alphaType));
82632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
82732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
82832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// These must match the int values in Bitmap.java
82932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikenum JavaEncodeFormat {
83032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kJPEG_JavaEncodeFormat = 0,
83132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kPNG_JavaEncodeFormat = 1,
83232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kWEBP_JavaEncodeFormat = 2
83332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
83432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
83532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
83632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jint format, jint quality,
83732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jobject jstream, jbyteArray jstorage) {
838f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
839f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
84032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkImageEncoder::Type fm;
84132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
84232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    switch (format) {
84332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kJPEG_JavaEncodeFormat:
84432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        fm = SkImageEncoder::kJPEG_Type;
84532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
84632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kPNG_JavaEncodeFormat:
84732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        fm = SkImageEncoder::kPNG_Type;
84832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
84932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kWEBP_JavaEncodeFormat:
85032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        fm = SkImageEncoder::kWEBP_Type;
85132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
85232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    default:
85332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
85432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
85532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
856f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap.valid()) {
857f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
858f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
85932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
860f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool success = false;
86132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
862f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
863f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!strm.get()) {