diff options
Diffstat (limited to 'core/jni/android/graphics/Graphics.cpp')
-rw-r--r-- | core/jni/android/graphics/Graphics.cpp | 80 |
1 files changed, 77 insertions, 3 deletions
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 8e1e8d3..9996ce1 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -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) |