bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable, bool reportSizeToVM) { Sk64 size64 = bitmap->getSize64(); if (size64.isNeg() || !size64.is32()) { doThrow(env, "java/lang/IllegalArgumentException", "bitmap size exceeds 32bits"); return false; } size_t size = size64.get32(); jlong jsize = size; // the VM wants longs for the size if (reportSizeToVM) { // SkDebugf("-------------- inform VM we've allocated %d bytes\n", size); bool r = env->CallBooleanMethod(gVMRuntime_singleton, gVMRuntime_trackExternalAllocationMethodID, jsize); if (GraphicsJNI::hasException(env)) { return false; } if (!r) { LOGE("VM won't let us allocate %zd bytes\n", size); doThrowOOME(env, "bitmap size exceeds VM budget"); return false; } } // call the version of malloc that returns null on failure void* addr = sk_malloc_flags(size, 0); if (NULL == addr) { if (reportSizeToVM) { // SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size); // we didn't actually allocate it, so inform the VM env->CallVoidMethod(gVMRuntime_singleton, gVMRuntime_trackExternalFreeMethodID, jsize); if (!GraphicsJNI::hasException(env)) { doThrowOOME(env, "bitmap size too large for malloc"); } } return false; } SkPixelRef* pr = reportSizeToVM ? new AndroidPixelRef(env, addr, size, ctable) : new SkMallocPixelRef(addr, size, ctable); bitmap->setPixelRef(pr)->unref(); // since we're already allocated, we lockPixels right away // HeapAllocator behaves this way too bitmap->lockPixels(); return true; }
static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz, jlong srcHandle, jlong paintHandle, jintArray offsetXY) { const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle); const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle); SkIPoint offset; SkBitmap* dst = new SkBitmap; JavaPixelAllocator allocator(env); src->extractAlpha(dst, paint, &allocator, &offset); // If Skia can't allocate pixels for destination bitmap, it resets // it, that is set its pixels buffer to NULL, and zero width and height. if (dst->getPixels() == NULL && src->getPixels() != NULL) { delete dst; doThrowOOME(env, "failed to allocate pixels for alpha"); return NULL; } if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) { int* array = env->GetIntArrayElements(offsetXY, NULL); array[0] = offset.fX; array[1] = offset.fY; env->ReleaseIntArrayElements(offsetXY, array, 0); } return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(), getPremulBitmapCreateFlags(true), NULL, NULL); }
bool JavaMemoryUsageReporter::reportMemory(size_t memorySize) { jlong jsize = memorySize; // the VM wants longs for the size JNIEnv* env = vm2env(fVM); bool r = env->CallBooleanMethod(gVMRuntime_singleton, gVMRuntime_trackExternalAllocationMethodID, jsize); if (GraphicsJNI::hasException(env)) { return false; } if (!r) { LOGE("VM won't let us allocate %zd bytes\n", memorySize); doThrowOOME(env, "bitmap size exceeds VM budget"); return false; } fTotalSize += memorySize; return true; }