Merge "Create a pixelref wrapper for reused bitmaps" into klp-dev

This commit is contained in:
Chris Craik
2013-09-09 23:00:48 +00:00
committed by Android (Google) Code Review
3 changed files with 55 additions and 7 deletions

View File

@@ -189,7 +189,13 @@ public:
mSize, bitmap->getSize()); mSize, bitmap->getSize());
return false; 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(); bitmap->lockPixels();
return true; return true;
} }

View File

@@ -414,7 +414,8 @@ static JNIEnv* vm2env(JavaVM* vm)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
AndroidPixelRef::AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj, 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(storage);
SkASSERT(env); 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() { AndroidPixelRef::~AndroidPixelRef() {
if (fOnJavaHeap) { if (fWrappedPixelRef) {
SkSafeUnref(fWrappedPixelRef);
} else if (fOnJavaHeap) {
JNIEnv* env = vm2env(fVM); JNIEnv* env = vm2env(fVM);
if (fStorageObj && fHasGlobalRef) { if (fStorageObj && fHasGlobalRef) {
@@ -441,15 +459,27 @@ AndroidPixelRef::~AndroidPixelRef() {
fStorageObj = NULL; fStorageObj = NULL;
} }
} }
jbyteArray AndroidPixelRef::getStorageObj() {
if (fWrappedPixelRef) {
return fWrappedPixelRef->fStorageObj;
}
return fStorageObj;
}
void AndroidPixelRef::setLocalJNIRef(jbyteArray arr) { 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; fStorageObj = arr;
} }
} }
void AndroidPixelRef::globalRef(void* localref) { 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); JNIEnv *env = vm2env(fVM);
// If JNI ref was passed, it is always used // If JNI ref was passed, it is always used
@@ -473,7 +503,10 @@ void AndroidPixelRef::globalRef(void* localref) {
} }
void AndroidPixelRef::globalUnref() { 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); JNIEnv *env = vm2env(fVM);
if (!fHasGlobalRef) { if (!fHasGlobalRef) {
SkDebugf("We don't have a global ref!"); SkDebugf("We don't have a global ref!");

View File

@@ -91,9 +91,16 @@ public:
AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj, AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
SkColorTable* ctable); 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(); virtual ~AndroidPixelRef();
jbyteArray getStorageObj() { return fStorageObj; } jbyteArray getStorageObj();
void setLocalJNIRef(jbyteArray arr); void setLocalJNIRef(jbyteArray arr);
@@ -110,6 +117,8 @@ public:
virtual void globalUnref(); virtual void globalUnref();
private: private:
AndroidPixelRef* const fWrappedPixelRef; // if set, delegate memory management calls to this
JavaVM* fVM; JavaVM* fVM;
bool fOnJavaHeap; // If true, the memory was allocated on the Java heap bool fOnJavaHeap; // If true, the memory was allocated on the Java heap