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

Commit dbf22ccd authored by Derek Sollenberger's avatar Derek Sollenberger Committed by Android (Google) Code Review
Browse files

Merge "Update HWUI to store its own SkBitmap objects"

parents b2b98a00 3d4eed7f
Loading
Loading
Loading
Loading
+1 −12
Original line number Diff line number Diff line
@@ -19,8 +19,6 @@

#include <jni.h>

#include <ResourceCache.h>

///////////////////////////////////////////////////////////////////////////////
// Conversions to/from SkColor, for get/setPixels, and the create method, which
// is basically like setPixels
@@ -360,20 +358,11 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,

static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {
    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
    if (android::uirenderer::ResourceCache::hasInstance()) {
        android::uirenderer::ResourceCache::getInstance().destructor(bitmap);
    } else {
    delete bitmap;
}
}

static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
    if (android::uirenderer::ResourceCache::hasInstance()) {
        bool result;
        result = android::uirenderer::ResourceCache::getInstance().recycle(bitmap);
        return result ? JNI_TRUE : JNI_FALSE;
    }
    bitmap->setPixels(NULL, NULL);
    return JNI_TRUE;
}
+77 −3
Original line number Diff line number Diff line
@@ -11,6 +11,9 @@
#include "SkRegion.h"
#include <android_runtime/AndroidRuntime.h>

#include <Caches.h>
#include <TextureCache.h>

void doThrowNPE(JNIEnv* env) {
    jniThrowNullPointerException(env, NULL);
}
@@ -500,10 +503,28 @@ AndroidPixelRef::~AndroidPixelRef() {
        JNIEnv* env = vm2env(fVM);
        env->DeleteGlobalRef(fStorageObj);
    }

    if (android::uirenderer::Caches::hasInstance()) {
        android::uirenderer::Caches::getInstance().textureCache.releaseTexture(getStableID());
    }
}

///////////////////////////////////////////////////////////////////////////////

static bool computeAllocationSize(const SkImageInfo& info, size_t* size, size_t* rowBytes) {
        int32_t rowBytes32 = SkToS32(info.minRowBytes());
        int64_t bigSize = (int64_t)info.height() * rowBytes32;
        if (rowBytes32 < 0 || !sk_64_isS32(bigSize)) {
            return false; // allocation will be too large
        }

        *size = sk_64_asS32(bigSize);
        *rowBytes = rowBytes32;

        SkASSERT(*size >= info.getSafeSize(*rowBytes));
        return true;
}

jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
                                             SkColorTable* ctable) {
    const SkImageInfo& info = bitmap->info();
@@ -512,7 +533,11 @@ jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
        return NULL;
    }

    const size_t size = bitmap->getSize();
    size_t size, rowBytes;
    if (!computeAllocationSize(info, &size, &rowBytes)) {
        return NULL;
    }

    jbyteArray arrayObj = (jbyteArray) env->CallObjectMethod(gVMRuntime,
                                                             gVMRuntime_newNonMovableArray,
                                                             gByte_class, size);
@@ -525,8 +550,7 @@ jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
        return NULL;
    }
    SkASSERT(addr);
    SkPixelRef* pr = new AndroidPixelRef(env, info, (void*) addr,
            bitmap->rowBytes(), arrayObj, ctable);
    SkPixelRef* pr = new AndroidPixelRef(env, info, (void*) addr, rowBytes, arrayObj, ctable);
    bitmap->setPixelRef(pr)->unref();
    // since we're already allocated, we lockPixels right away
    // HeapAllocator behaves this way too
@@ -535,6 +559,56 @@ jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
    return arrayObj;
}

struct AndroidPixelRefContext {
    int32_t stableID;
};

static void allocatePixelsReleaseProc(void* ptr, void* ctx) {
    AndroidPixelRefContext* context = (AndroidPixelRefContext*)ctx;
    if (android::uirenderer::Caches::hasInstance()) {
         android::uirenderer::Caches::getInstance().textureCache.releaseTexture(context->stableID);
    }

    sk_free(ptr);
    delete context;
}

bool GraphicsJNI::allocatePixels(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable) {
    const SkImageInfo& info = bitmap->info();
    if (info.fColorType == kUnknown_SkColorType) {
        doThrowIAE(env, "unknown bitmap configuration");
        return NULL;
    }

    size_t size, rowBytes;
    if (!computeAllocationSize(info, &size, &rowBytes)) {
        return false;
    }

    void* addr = sk_malloc_flags(size, 0);
    if (NULL == addr) {
        return false;
    }

    AndroidPixelRefContext* context = new AndroidPixelRefContext;
    SkMallocPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rowBytes, ctable, addr,
                                                         &allocatePixelsReleaseProc, context);
    if (!pr) {
        delete context;
        return false;
    }

    // set the stableID in the context so that it can be used later in
    // allocatePixelsReleaseProc to remove the texture from the cache.
    context->stableID = pr->getStableID();

    bitmap->setPixelRef(pr)->unref();
    // since we're already allocated, we can lockPixels right away
    bitmap->lockPixels();

    return true;
}

///////////////////////////////////////////////////////////////////////////////

JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env)
+8 −0
Original line number Diff line number Diff line
@@ -95,6 +95,14 @@ public:
    static jbyteArray allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
            SkColorTable* ctable);

    /**
     * Given a bitmap we natively allocate a memory block to store the contents
     * of that bitmap.  The memory is then attached to the bitmap via an
     * SkPixelRef, which ensures that upon deletion the appropriate caches
     * are notified.
     */
    static bool allocatePixels(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable);

    /** Copy the colors in colors[] to the bitmap, convert to the correct
        format along the way.
        Whether to use premultiplied pixels is determined by dstBitmap's alphaType.
+2 −1
Original line number Diff line number Diff line
@@ -383,7 +383,8 @@ static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
                           hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
                           kPremul_SkAlphaType);
    SkBitmap bitmap;
    if (!bitmap.tryAllocPixels(info)) {
    bitmap.setInfo(info);
    if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) {
        return;
    }

+0 −7
Original line number Diff line number Diff line
@@ -46,12 +46,6 @@ void DisplayListData::cleanupResources() {
        resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i));
    }

    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
        const SkBitmap* bitmap = ownedBitmapResources.itemAt(i);
        resourceCache.decrementRefcountLocked(bitmap);
        resourceCache.destructorLocked(bitmap);
    }

    for (size_t i = 0; i < patchResources.size(); i++) {
        resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
    }
@@ -63,7 +57,6 @@ void DisplayListData::cleanupResources() {
    resourceCache.unlock();

    bitmapResources.clear();
    ownedBitmapResources.clear();
    patchResources.clear();
    sourcePaths.clear();
    paints.clear();
Loading