Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd0ba71a authored by Chris Craik's avatar Chris Craik
Browse files

Create a pixelref wrapper for reused bitmaps

Reused bitmaps may gain a color table when reused, so we wrap a new
AndroidPixelRef that holds the color table around the old.

bug:10608305
Change-Id: I35288edf3158cfda21c500360ad1abdf5654af8d
parent b8b017cb
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -189,7 +189,13 @@ public:
                    mSize, bitmap->getSize());
            return false;
        }
        bitmap->setPixelRef(mPixelRef);

        // Create a new pixelref with the new ctable that wraps the previous pixelref
        SkPixelRef* pr = new AndroidPixelRef(*static_cast<AndroidPixelRef*>(mPixelRef), ctable);

        bitmap->setPixelRef(pr)->unref();
        // since we're already allocated, we lockPixels right away
        // HeapAllocator/JavaPixelAllocator behaves this way too
        bitmap->lockPixels();
        return true;
    }
+38 −5
Original line number Diff line number Diff line
@@ -414,7 +414,8 @@ static JNIEnv* vm2env(JavaVM* vm)
///////////////////////////////////////////////////////////////////////////////

AndroidPixelRef::AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
        SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable, (storageObj == NULL)) {
        SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable, (storageObj == NULL)),
        fWrappedPixelRef(NULL) {
    SkASSERT(storage);
    SkASSERT(env);

@@ -431,8 +432,25 @@ AndroidPixelRef::AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteA

}

AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, SkColorTable* ctable) :
        SkMallocPixelRef(wrappedPixelRef.getAddr(), wrappedPixelRef.getSize(), ctable, false),
        fWrappedPixelRef(wrappedPixelRef.fWrappedPixelRef ?
            wrappedPixelRef.fWrappedPixelRef : &wrappedPixelRef)
{
    SkASSERT(fWrappedPixelRef);
    SkSafeRef(fWrappedPixelRef);

    // don't need to initialize these, as all the relevant logic delegates to the wrapped ref
    fStorageObj = NULL;
    fHasGlobalRef = false;
    fGlobalRefCnt = 0;
    fOnJavaHeap = false;
}

AndroidPixelRef::~AndroidPixelRef() {
    if (fOnJavaHeap) {
    if (fWrappedPixelRef) {
        SkSafeUnref(fWrappedPixelRef);
    } else if (fOnJavaHeap) {
        JNIEnv* env = vm2env(fVM);

        if (fStorageObj && fHasGlobalRef) {
@@ -441,15 +459,27 @@ AndroidPixelRef::~AndroidPixelRef() {
        fStorageObj = NULL;
    }
}
jbyteArray AndroidPixelRef::getStorageObj() {
    if (fWrappedPixelRef) {
        return fWrappedPixelRef->fStorageObj;
    }
    return fStorageObj;
}

void AndroidPixelRef::setLocalJNIRef(jbyteArray arr) {
    if (!fHasGlobalRef) {
    if (fWrappedPixelRef) {
        // delegate java obj management to the wrapped ref
        fWrappedPixelRef->setLocalJNIRef(arr);
    } else if (!fHasGlobalRef) {
        fStorageObj = arr;
    }
}

void AndroidPixelRef::globalRef(void* localref) {
    if (fOnJavaHeap && sk_atomic_inc(&fGlobalRefCnt) == 0) {
    if (fWrappedPixelRef) {
        // delegate java obj management to the wrapped ref
        fWrappedPixelRef->globalRef(localref);
    } else if (fOnJavaHeap && sk_atomic_inc(&fGlobalRefCnt) == 0) {
        JNIEnv *env = vm2env(fVM);

        // If JNI ref was passed, it is always used
@@ -473,7 +503,10 @@ void AndroidPixelRef::globalRef(void* localref) {
}

void AndroidPixelRef::globalUnref() {
    if (fOnJavaHeap && sk_atomic_dec(&fGlobalRefCnt) == 1) {
    if (fWrappedPixelRef) {
        // delegate java obj management to the wrapped ref
        fWrappedPixelRef->globalUnref();
    } else if (fOnJavaHeap && sk_atomic_dec(&fGlobalRefCnt) == 1) {
        JNIEnv *env = vm2env(fVM);
        if (!fHasGlobalRef) {
            SkDebugf("We don't have a global ref!");
+10 −1
Original line number Diff line number Diff line
@@ -91,9 +91,16 @@ public:
    AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
                    SkColorTable* ctable);

    /**
     * Creates an AndroidPixelRef that wraps (and refs) another to reuse/share
     * the same storage and java byte array refcounting, yet have a different
     * color table.
     */
    AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, SkColorTable* ctable);

    virtual ~AndroidPixelRef();

    jbyteArray getStorageObj() { return fStorageObj; }
    jbyteArray getStorageObj();

    void setLocalJNIRef(jbyteArray arr);

@@ -110,6 +117,8 @@ public:
    virtual void globalUnref();

private:
    AndroidPixelRef* const fWrappedPixelRef; // if set, delegate memory management calls to this

    JavaVM* fVM;
    bool fOnJavaHeap; // If true, the memory was allocated on the Java heap