diff options
author | Derek Sollenberger <djsollen@google.com> | 2014-12-04 21:46:39 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-12-04 21:46:39 +0000 |
commit | 203c8171806a15b83efa9ad56be048281a40693b (patch) | |
tree | 6f0192f56d548718f231c275c6d2aa6a5ee64929 /core | |
parent | 51347595a3ea7749b2c771ac1e8f8f729a55e1a9 (diff) | |
parent | c1a2f38ce0447b005d0cde6836857f451af84dc6 (diff) | |
download | frameworks_base-203c8171806a15b83efa9ad56be048281a40693b.zip frameworks_base-203c8171806a15b83efa9ad56be048281a40693b.tar.gz frameworks_base-203c8171806a15b83efa9ad56be048281a40693b.tar.bz2 |
am c1a2f38c: am 4d9da135: Merge "Update AndroidPixelRef to prevent VM from cleaning up memory prematurely." into lmp-mr1-dev
* commit 'c1a2f38ce0447b005d0cde6836857f451af84dc6':
Update AndroidPixelRef to prevent VM from cleaning up memory prematurely.
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 27 | ||||
-rw-r--r-- | core/jni/android/graphics/Graphics.cpp | 106 | ||||
-rw-r--r-- | core/jni/android/graphics/GraphicsJNI.h | 41 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 35 |
4 files changed, 29 insertions, 180 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 9061679..60a489b 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -558,7 +558,7 @@ class GLES20Canvas extends HardwareCanvas { Bitmap bitmap = patch.getBitmap(); throwIfCannotDraw(bitmap); final long nativePaint = paint == null ? 0 : paint.mNativePaint; - nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk, + nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk, dst.left, dst.top, dst.right, dst.bottom, nativePaint); } @@ -567,32 +567,31 @@ class GLES20Canvas extends HardwareCanvas { Bitmap bitmap = patch.getBitmap(); throwIfCannotDraw(bitmap); final long nativePaint = paint == null ? 0 : paint.mNativePaint; - nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk, + nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk, dst.left, dst.top, dst.right, dst.bottom, nativePaint); } - private static native void nDrawPatch(long renderer, long bitmap, byte[] buffer, long chunk, + private static native void nDrawPatch(long renderer, long bitmap, long chunk, float left, float top, float right, float bottom, long paint); @Override public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { throwIfCannotDraw(bitmap); final long nativePaint = paint == null ? 0 : paint.mNativePaint; - nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint); + nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, nativePaint); } - private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer, - float left, float top, long paint); + private static native void nDrawBitmap(long renderer, long bitmap, float left, + float top, long paint); @Override public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { throwIfCannotDraw(bitmap); final long nativePaint = paint == null ? 0 : paint.mNativePaint; - nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, - matrix.native_instance, nativePaint); + nDrawBitmap(mRenderer, bitmap.mNativeBitmap, matrix.native_instance, nativePaint); } - private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer, + private static native void nDrawBitmap(long renderer, long bitmap, long matrix, long paint); @Override @@ -612,7 +611,7 @@ class GLES20Canvas extends HardwareCanvas { bottom = src.bottom; } - nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom, + nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint); } @@ -633,11 +632,11 @@ class GLES20Canvas extends HardwareCanvas { bottom = src.bottom; } - nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom, + nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint); } - private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer, + private static native void nDrawBitmap(long renderer, long bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float left, float top, float right, float bottom, long paint); @@ -698,11 +697,11 @@ class GLES20Canvas extends HardwareCanvas { } final long nativePaint = paint == null ? 0 : paint.mNativePaint; - nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight, + nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, nativePaint); } - private static native void nDrawBitmapMesh(long renderer, long bitmap, byte[] buffer, + private static native void nDrawBitmapMesh(long renderer, long bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, long paint); diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 2eccfbd..a51af40 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -492,19 +492,15 @@ AndroidPixelRef::AndroidPixelRef(JNIEnv* env, const SkImageInfo& info, void* sto SkMallocPixelRef(info, storage, rowBytes, ctable, (storageObj == NULL)), fWrappedPixelRef(NULL) { SkASSERT(storage); + SkASSERT(storageObj); SkASSERT(env); if (env->GetJavaVM(&fVM) != JNI_OK) { SkDebugf("------ [%p] env->GetJavaVM failed\n", env); sk_throw(); } - fStorageObj = storageObj; - fHasGlobalRef = false; - fGlobalRefCnt = 0; - - // If storageObj is NULL, the memory was NOT allocated on the Java heap - fOnJavaHeap = (storageObj != NULL); + fStorageObj = (jbyteArray) env->NewGlobalRef(storageObj); } AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, const SkImageInfo& info, @@ -516,91 +512,18 @@ AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, const SkImage SkASSERT(fWrappedPixelRef); SkSafeRef(fWrappedPixelRef); - // don't need to initialize these, as all the relevant logic delegates to the wrapped ref + // don't need to initialize this, as all the relevant logic delegates to the wrapped ref fStorageObj = NULL; - fHasGlobalRef = false; - fGlobalRefCnt = 0; - fOnJavaHeap = false; } AndroidPixelRef::~AndroidPixelRef() { if (fWrappedPixelRef) { SkSafeUnref(fWrappedPixelRef); - } else if (fOnJavaHeap) { + } else { + SkASSERT(fStorageObj); JNIEnv* env = vm2env(fVM); - - if (fStorageObj && fHasGlobalRef) { - env->DeleteGlobalRef(fStorageObj); - } - fStorageObj = NULL; - } -} -jbyteArray AndroidPixelRef::getStorageObj() { - if (fWrappedPixelRef) { - return fWrappedPixelRef->fStorageObj; - } - return fStorageObj; -} - -void AndroidPixelRef::setLocalJNIRef(jbyteArray arr) { - if (fWrappedPixelRef) { - // delegate java obj management to the wrapped ref - fWrappedPixelRef->setLocalJNIRef(arr); - } else if (!fHasGlobalRef) { - fStorageObj = arr; - } -} - -void AndroidPixelRef::globalRef(void* localref) { - if (fWrappedPixelRef) { - // delegate java obj management to the wrapped ref - fWrappedPixelRef->globalRef(localref); - - // Note: we only ref and unref the wrapped AndroidPixelRef so that - // bitmap->pixelRef()->globalRef() and globalUnref() can be used in a pair, even if - // the bitmap has its underlying AndroidPixelRef swapped out/wrapped - return; - } - if (fOnJavaHeap && sk_atomic_inc(&fGlobalRefCnt) == 0) { - JNIEnv *env = vm2env(fVM); - - // If JNI ref was passed, it is always used - if (localref) fStorageObj = (jbyteArray) localref; - - if (fStorageObj == NULL) { - SkDebugf("No valid local ref to create a JNI global ref\n"); - sk_throw(); - } - if (fHasGlobalRef) { - // This should never happen - SkDebugf("Already holding a JNI global ref"); - sk_throw(); - } - - fStorageObj = (jbyteArray) env->NewGlobalRef(fStorageObj); - // TODO: Check for failure here - fHasGlobalRef = true; - } - ref(); -} - -void AndroidPixelRef::globalUnref() { - if (fWrappedPixelRef) { - // delegate java obj management to the wrapped ref - fWrappedPixelRef->globalUnref(); - return; - } - if (fOnJavaHeap && sk_atomic_dec(&fGlobalRefCnt) == 1) { - JNIEnv *env = vm2env(fVM); - if (!fHasGlobalRef) { - SkDebugf("We don't have a global ref!"); - sk_throw(); - } env->DeleteGlobalRef(fStorageObj); - fStorageObj = NULL; - fHasGlobalRef = false; } - unref(); } /////////////////////////////////////////////////////////////////////////////// @@ -657,25 +580,6 @@ bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) { //////////////////////////////////////////////////////////////////////////////// -JavaHeapBitmapRef::JavaHeapBitmapRef(JNIEnv* env, SkBitmap* nativeBitmap, jbyteArray buffer) { - fEnv = env; - fNativeBitmap = nativeBitmap; - fBuffer = buffer; - - // If the buffer is NULL, the backing memory wasn't allocated on the Java heap - if (fBuffer) { - ((AndroidPixelRef*) fNativeBitmap->pixelRef())->setLocalJNIRef(fBuffer); - } -} - -JavaHeapBitmapRef::~JavaHeapBitmapRef() { - if (fBuffer) { - ((AndroidPixelRef*) fNativeBitmap->pixelRef())->setLocalJNIRef(NULL); - } -} - -//////////////////////////////////////////////////////////////////////////////// - static jclass make_globalref(JNIEnv* env, const char classname[]) { jclass c = env->FindClass(classname); diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index 0ce6e49..a48b764 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -123,52 +123,11 @@ public: virtual ~AndroidPixelRef(); - jbyteArray getStorageObj(); - - void setLocalJNIRef(jbyteArray arr); - - /** Used to hold a ref to the pixels when the Java bitmap may be collected. - * If specified, 'localref' is a valid JNI local reference to the byte array - * containing the pixel data. - * - * 'localref' may only be NULL if setLocalJNIRef() was already called with - * a JNI local ref that is still valid. - */ - virtual void globalRef(void* localref=NULL); - - /** Release a ref that was acquired using globalRef(). */ - virtual void globalUnref(); - private: AndroidPixelRef* const fWrappedPixelRef; // if set, delegate memory management calls to this JavaVM* fVM; - bool fOnJavaHeap; // If true, the memory was allocated on the Java heap - jbyteArray fStorageObj; // The Java byte[] object used as the bitmap backing store - bool fHasGlobalRef; // If true, fStorageObj holds a JNI global ref - - mutable int32_t fGlobalRefCnt; -}; - -/** A helper class for accessing Java-heap-allocated bitmaps. - * This should be used when calling into a JNI method that retains a - * reference to the bitmap longer than the lifetime of the Java Bitmap. - * - * After creating an instance of this class, a call to - * AndroidPixelRef::globalRef() will allocate a JNI global reference - * to the backing buffer object. - */ -class JavaHeapBitmapRef { -public: - - JavaHeapBitmapRef(JNIEnv *env, SkBitmap* nativeBitmap, jbyteArray buffer); - ~JavaHeapBitmapRef(); - -private: - JNIEnv* fEnv; - SkBitmap* fNativeBitmap; - jbyteArray fBuffer; }; /** Allocator which allocates the backing buffer in the Java heap. diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 7a9da7e..da8a9ed 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -341,11 +341,8 @@ static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz, // ---------------------------------------------------------------------------- static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz, - jlong rendererPtr, jlong bitmapPtr, jbyteArray buffer, - jfloat left, jfloat top, jlong paintPtr) { + jlong rendererPtr, jlong bitmapPtr, jfloat left, jfloat top, jlong paintPtr) { SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr); - // This object allows the renderer to allocate a global JNI ref to the buffer object. - JavaHeapBitmapRef bitmapRef(env, bitmap, buffer); DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); Paint* paint = reinterpret_cast<Paint*>(paintPtr); @@ -358,12 +355,10 @@ static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz, } static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz, - jlong rendererPtr, jlong bitmapPtr, jbyteArray buffer, + jlong rendererPtr, jlong bitmapPtr, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, jlong paintPtr) { SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr); - // This object allows the renderer to allocate a global JNI ref to the buffer object. - JavaHeapBitmapRef bitmapRef(env, bitmap, buffer); DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); Paint* paint = reinterpret_cast<Paint*>(paintPtr); @@ -372,11 +367,8 @@ static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz, } static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject clazz, - jlong rendererPtr, jlong bitmapPtr, jbyteArray buffer, - jlong matrixPtr, jlong paintPtr) { + jlong rendererPtr, jlong bitmapPtr, jlong matrixPtr, jlong paintPtr) { SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr); - // This object allows the renderer to allocate a global JNI ref to the buffer object. - JavaHeapBitmapRef bitmapRef(env, bitmap, buffer); DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr); @@ -421,12 +413,9 @@ static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz, } static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz, - jlong rendererPtr, jlong bitmapPtr, jbyteArray buffer, - jint meshWidth, jint meshHeight, jfloatArray vertices, jint offset, jintArray colors, - jint colorOffset, jlong paintPtr) { + jlong rendererPtr, jlong bitmapPtr, jint meshWidth, jint meshHeight, + jfloatArray vertices, jint offset, jintArray colors, jint colorOffset, jlong paintPtr) { SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr); - // This object allows the renderer to allocate a global JNI ref to the buffer object. - JavaHeapBitmapRef bitmapRef(env, bitmap, buffer); jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL; jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL; @@ -440,11 +429,9 @@ static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz, } static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz, - jlong rendererPtr, jlong bitmapPtr, jbyteArray buffer, jlong patchPtr, + jlong rendererPtr, jlong bitmapPtr, jlong patchPtr, float left, float top, float right, float bottom, jlong paintPtr) { SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr); - // This object allows the renderer to allocate a global JNI ref to the buffer object. - JavaHeapBitmapRef bitmapRef(env, bitmap, buffer); DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr); @@ -914,14 +901,14 @@ static JNINativeMethod gMethods[] = { { "nGetMatrix", "(JJ)V", (void*) android_view_GLES20Canvas_getMatrix }, { "nConcatMatrix", "(JJ)V", (void*) android_view_GLES20Canvas_concatMatrix }, - { "nDrawBitmap", "(JJ[BFFJ)V", (void*) android_view_GLES20Canvas_drawBitmap }, - { "nDrawBitmap", "(JJ[BFFFFFFFFJ)V",(void*) android_view_GLES20Canvas_drawBitmapRect }, - { "nDrawBitmap", "(JJ[BJJ)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix }, + { "nDrawBitmap", "(JJFFJ)V", (void*) android_view_GLES20Canvas_drawBitmap }, + { "nDrawBitmap", "(JJFFFFFFFFJ)V",(void*) android_view_GLES20Canvas_drawBitmapRect }, + { "nDrawBitmap", "(JJJJ)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix }, { "nDrawBitmap", "(J[IIIFFIIZJ)V", (void*) android_view_GLES20Canvas_drawBitmapData }, - { "nDrawBitmapMesh", "(JJ[BII[FI[IIJ)V",(void*) android_view_GLES20Canvas_drawBitmapMesh }, + { "nDrawBitmapMesh", "(JJII[FI[IIJ)V",(void*) android_view_GLES20Canvas_drawBitmapMesh }, - { "nDrawPatch", "(JJ[BJFFFFJ)V", (void*) android_view_GLES20Canvas_drawPatch }, + { "nDrawPatch", "(JJJFFFFJ)V", (void*) android_view_GLES20Canvas_drawPatch }, { "nDrawColor", "(JII)V", (void*) android_view_GLES20Canvas_drawColor }, { "nDrawRect", "(JFFFFJ)V", (void*) android_view_GLES20Canvas_drawRect }, |