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

Commit c36bd6c1 authored by sergeyv's avatar sergeyv
Browse files

Move allocatePixelRef methods to hwui.

This patch also makes tests to use SkBitmap backed by hwui/PixelRef,
Test: refactoring cl.
bug:27762775

Change-Id: Ib936e81877790849118420f5e565fc8f4466c1be
parent 01421d76
Loading
Loading
Loading
Loading
+7 −8
Original line number Diff line number Diff line
@@ -548,7 +548,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
            GraphicsJNI::defaultColorSpace()));

    PixelRef* nativeBitmap = GraphicsJNI::allocateHeapPixelRef(&bitmap, NULL);
    sk_sp<PixelRef> nativeBitmap = PixelRef::allocateHeapPixelRef(&bitmap, NULL);
    if (!nativeBitmap) {
        return NULL;
    }
@@ -558,8 +558,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
                0, 0, width, height, bitmap);
    }

    return createBitmap(env, nativeBitmap,
            getPremulBitmapCreateFlags(isMutable));
    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
}

static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
@@ -832,7 +831,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
    }

    // Map the bitmap in place from the ashmem region if possible otherwise copy.
    PixelRef* nativeBitmap;
    sk_sp<PixelRef> nativeBitmap;
    if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
#if DEBUG_PARCEL
        ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
@@ -853,8 +852,8 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
        }

        // Map the pixels in place and take ownership of the ashmem region.
        nativeBitmap = GraphicsJNI::mapAshmemPixelRef(env, bitmap.get(),
                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable);
        nativeBitmap = sk_sp<PixelRef>(GraphicsJNI::mapAshmemPixelRef(env, bitmap.get(),
                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
        SkSafeUnref(ctable);
        if (!nativeBitmap) {
            close(dupFd);
@@ -880,7 +879,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
#endif

        // Copy the pixels into a new buffer.
        nativeBitmap = GraphicsJNI::allocateHeapPixelRef(bitmap.get(), ctable);
        nativeBitmap = PixelRef::allocateHeapPixelRef(bitmap.get(), ctable);
        SkSafeUnref(ctable);
        if (!nativeBitmap) {
            blob.release();
@@ -895,7 +894,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
        blob.release();
    }

    return createBitmap(env, nativeBitmap,
    return createBitmap(env, nativeBitmap.release(),
            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
}

+2 −155
Original line number Diff line number Diff line
@@ -399,160 +399,8 @@ jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region)
    return obj;
}

static JNIEnv* vm2env(JavaVM* vm)
{
    JNIEnv* env = NULL;
    if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK || NULL == env)
    {
        SkDebugf("------- [%p] vm->GetEnv() failed\n", vm);
        sk_throw();
    }
    return env;
}

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

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

    *size = sk_64_asS32(bigSize);
    return true;
}

android::PixelRef* GraphicsJNI::allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
    const SkImageInfo& info = bitmap->info();
    if (info.colorType() == kUnknown_SkColorType) {
        LOG_ALWAYS_FATAL("unknown bitmap configuration");
        return nullptr;
    }

    size_t size;
    if (!computeAllocationSize(*bitmap, &size)) {
        return nullptr;
    }

    // we must respect the rowBytes value already set on the bitmap instead of
    // attempting to compute our own.
    const size_t rowBytes = bitmap->rowBytes();

    void* addr = calloc(size, 1);
    if (!addr) {
        return nullptr;
    }

    auto wrapper = new android::PixelRef(addr, size, info, rowBytes, ctable);
    wrapper->getSkBitmap(bitmap);
    // since we're already allocated, we lockPixels right away
    // HeapAllocator behaves this way too
    bitmap->lockPixels();

    return wrapper;
}

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.colorType() == kUnknown_SkColorType) {
        doThrowIAE(env, "unknown bitmap configuration");
        return NULL;
    }

    size_t size;
    if (!computeAllocationSize(*bitmap, &size)) {
        return false;
    }

    // we must respect the rowBytes value already set on the bitmap instead of
    // attempting to compute our own.
    const size_t rowBytes = bitmap->rowBytes();

    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;
}

android::PixelRef* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
                                                     SkColorTable* ctable) {
    int fd;

    const SkImageInfo& info = bitmap->info();
    if (info.colorType() == kUnknown_SkColorType) {
        doThrowIAE(env, "unknown bitmap configuration");
        return nullptr;
    }

    size_t size;
    if (!computeAllocationSize(*bitmap, &size)) {
        return nullptr;
    }

    // we must respect the rowBytes value already set on the bitmap instead of
    // attempting to compute our own.
    const size_t rowBytes = bitmap->rowBytes();

    // Create new ashmem region with read/write priv
    fd = ashmem_create_region("bitmap", size);
    if (fd < 0) {
        return nullptr;
    }

    void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED) {
        close(fd);
        return nullptr;
    }

    if (ashmem_set_prot_region(fd, PROT_READ) < 0) {
        munmap(addr, size);
        close(fd);
        return nullptr;
    }

    auto wrapper = new android::PixelRef(addr, fd, size, info, rowBytes, ctable);
    wrapper->getSkBitmap(bitmap);
    // since we're already allocated, we lockPixels right away
    // HeapAllocator behaves this way too
    bitmap->lockPixels();

    return wrapper;
}

android::PixelRef* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
        SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly) {
    const SkImageInfo& info = bitmap->info();
@@ -597,7 +445,7 @@ sk_sp<SkColorSpace> GraphicsJNI::defaultColorSpace() {

///////////////////////////////////////////////////////////////////////////////
bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
    mStorage.reset(GraphicsJNI::allocateHeapPixelRef(bitmap, ctable));
    mStorage = android::PixelRef::allocateHeapPixelRef(bitmap, ctable);
    return !!mStorage;
}

@@ -702,8 +550,7 @@ AshmemPixelAllocator::AshmemPixelAllocator(JNIEnv *env) {
}

bool AshmemPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
    JNIEnv* env = vm2env(mJavaVM);
    mStorage.reset(GraphicsJNI::allocateAshmemPixelRef(env, bitmap, ctable));
    mStorage = android::PixelRef::allocateAshmemPixelRef(bitmap, ctable);
    return !!mStorage;
}

+0 −5
Original line number Diff line number Diff line
@@ -72,11 +72,6 @@ public:

    static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap);

    static android::PixelRef* allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable);

    static android::PixelRef* allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
            SkColorTable* ctable);

    static android::PixelRef* mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
            SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly);

+2 −1
Original line number Diff line number Diff line
@@ -446,7 +446,8 @@ static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
            GraphicsJNI::defaultColorSpace());
    SkBitmap bitmap;
    bitmap.setInfo(info);
    if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) {
    sk_sp<PixelRef> pixelRef = PixelRef::allocateHeapPixelRef(&bitmap, NULL);
    if (!pixelRef) {
        return;
    }

+78 −0
Original line number Diff line number Diff line
@@ -23,6 +23,84 @@

namespace android {

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

    *size = sk_64_asS32(bigSize);
    return true;
}

typedef sk_sp<PixelRef> (*AllocPixeRef)(size_t allocSize, const SkImageInfo& info, size_t rowBytes,
        SkColorTable* ctable);

static sk_sp<PixelRef> allocatePixelRef(SkBitmap* bitmap, SkColorTable* ctable, AllocPixeRef alloc) {
    const SkImageInfo& info = bitmap->info();
    if (info.colorType() == kUnknown_SkColorType) {
        LOG_ALWAYS_FATAL("unknown bitmap configuration");
        return nullptr;
    }

    size_t size;
    if (!computeAllocationSize(*bitmap, &size)) {
        return nullptr;
    }

    // we must respect the rowBytes value already set on the bitmap instead of
    // attempting to compute our own.
    const size_t rowBytes = bitmap->rowBytes();
    auto wrapper = alloc(size, info, rowBytes, ctable);
    if (wrapper) {
        wrapper->getSkBitmap(bitmap);
        // since we're already allocated, we lockPixels right away
        // HeapAllocator behaves this way too
        bitmap->lockPixels();
    }
    return wrapper;
}

sk_sp<PixelRef> PixelRef::allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
   return allocatePixelRef(bitmap, ctable, &PixelRef::allocateHeapPixelRef);
}

sk_sp<PixelRef> PixelRef::allocateAshmemPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
   return allocatePixelRef(bitmap, ctable, &PixelRef::allocateAshmemPixelRef);
}

sk_sp<PixelRef> PixelRef::allocateHeapPixelRef(size_t size, const SkImageInfo& info, size_t rowBytes,
        SkColorTable* ctable) {
    void* addr = calloc(size, 1);
    if (!addr) {
        return nullptr;
    }
    return sk_sp<PixelRef>(new PixelRef(addr, size, info, rowBytes, ctable));
}

sk_sp<PixelRef> PixelRef::allocateAshmemPixelRef(size_t size, const SkImageInfo& info,
        size_t rowBytes, SkColorTable* ctable) {
    // Create new ashmem region with read/write priv
    int fd = ashmem_create_region("bitmap", size);
    if (fd < 0) {
        return nullptr;
    }

    void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED) {
        close(fd);
        return nullptr;
    }

    if (ashmem_set_prot_region(fd, PROT_READ) < 0) {
        munmap(addr, size);
        close(fd);
        return nullptr;
    }
    return sk_sp<PixelRef>(new PixelRef(addr, fd, size, info, rowBytes, ctable));
}

void PixelRef::reconfigure(const SkImageInfo& newInfo, size_t rowBytes, SkColorTable* ctable) {
    if (kIndex_8_SkColorType != newInfo.colorType()) {
        ctable = nullptr;
Loading