From e4ac2d6b5723c95e648c489b187ddde449452c13 Mon Sep 17 00:00:00 2001 From: Patrick Dubroy Date: Wed, 1 Dec 2010 11:23:13 -0800 Subject: Allocate bitmap backing buffers in the Java heap. Change-Id: I60f6ccff13357c1c518e9d56b02fe0171637edd1 --- graphics/java/android/graphics/Bitmap.java | 52 +++++++++++++++++------------- graphics/java/android/graphics/Canvas.java | 33 +++++++++++-------- 2 files changed, 49 insertions(+), 36 deletions(-) (limited to 'graphics') diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index d283dea..a8efd00 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -19,18 +19,15 @@ package android.graphics; import android.os.Parcel; import android.os.Parcelable; import android.util.DisplayMetrics; -import android.util.Finalizers; import java.io.OutputStream; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; public final class Bitmap implements Parcelable { + /** * Indicates that the bitmap was created for an unknown pixel density. * @@ -47,6 +44,17 @@ public final class Bitmap implements Parcelable { */ public final int mNativeBitmap; + /** + * Backing buffer for the Bitmap. + * Made public for quick access from drawing methods -- do NOT modify + * from outside this class. + * + * @hide + */ + public byte[] mBuffer; + + private final BitmapFinalizer mFinalizer; + private final boolean mIsMutable; private byte[] mNinePatchChunk; // may be null private int mWidth = -1; @@ -85,25 +93,22 @@ public final class Bitmap implements Parcelable { This can be called from JNI code. */ - private Bitmap(int nativeBitmap, boolean isMutable, byte[] ninePatchChunk, int density) { + private Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk, + int density) { if (nativeBitmap == 0) { throw new RuntimeException("internal error: native bitmap is 0"); } + mBuffer = buffer; // we delete this in our finalizer mNativeBitmap = nativeBitmap; + mFinalizer = new BitmapFinalizer(nativeBitmap); + mIsMutable = isMutable; mNinePatchChunk = ninePatchChunk; if (density >= 0) { mDensity = density; } - - // If the finalizers queue is null, we are running in zygote and the - // bitmap will never be reclaimed, so we don't need to run our native - // destructor - if (Finalizers.getQueue() != null) { - new BitmapFinalizer(this); - } } /** @@ -169,6 +174,7 @@ public final class Bitmap implements Parcelable { */ public void recycle() { if (!mRecycled) { + mBuffer = null; nativeRecycle(mNativeBitmap); mNinePatchChunk = null; mRecycled = true; @@ -520,6 +526,9 @@ public final class Bitmap implements Parcelable { * @throws IllegalArgumentException if the width or height are <= 0 */ private static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) { + if (width <= 0 || height <= 0) { + throw new IllegalArgumentException("width and height must be > 0"); + } Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true); if (config == Config.ARGB_8888 && !hasAlpha) { bm.eraseColor(0xff000000); @@ -561,6 +570,9 @@ public final class Bitmap implements Parcelable { (lastScanline + width > length)) { throw new ArrayIndexOutOfBoundsException(); } + if (width <= 0 || height <= 0) { + throw new IllegalArgumentException("width and height must be > 0"); + } return nativeCreate(colors, offset, stride, width, height, config.nativeInt, false); } @@ -1059,22 +1071,16 @@ public final class Bitmap implements Parcelable { nativePrepareToDraw(mNativeBitmap); } - private static class BitmapFinalizer extends Finalizers.ReclaimableReference { - private static final Set sFinalizers = Collections.synchronizedSet( - new HashSet()); - - private int mNativeBitmap; + private static class BitmapFinalizer { + private final int mNativeBitmap; - BitmapFinalizer(Bitmap b) { - super(b, Finalizers.getQueue()); - mNativeBitmap = b.mNativeBitmap; - sFinalizers.add(this); + BitmapFinalizer(int nativeBitmap) { + mNativeBitmap = nativeBitmap; } @Override - public void reclaim() { + public void finalize() { nativeDestructor(mNativeBitmap); - sFinalizers.remove(this); } } diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 07fe66c..66c6d81 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -74,6 +74,23 @@ public class Canvas { */ public static final int DIRECTION_RTL = 1; + private final CanvasFinalizer mFinalizer; + + private static class CanvasFinalizer { + private final int mNativeCanvas; + + public CanvasFinalizer(int nativeCanvas) { + mNativeCanvas = nativeCanvas; + } + + @Override + protected void finalize() throws Throwable { + if (mNativeCanvas != 0) { + finalizer(mNativeCanvas); + } + } + } + /** * Construct an empty raster canvas. Use setBitmap() to specify a bitmap to * draw into. The initial target density is {@link Bitmap#DENSITY_NONE}; @@ -83,6 +100,7 @@ public class Canvas { public Canvas() { // 0 means no native bitmap mNativeCanvas = initRaster(0); + mFinalizer = new CanvasFinalizer(0); } /** @@ -101,6 +119,7 @@ public class Canvas { } throwIfRecycled(bitmap); mNativeCanvas = initRaster(bitmap.ni()); + mFinalizer = new CanvasFinalizer(mNativeCanvas); mBitmap = bitmap; mDensity = bitmap.mDensity; } @@ -110,6 +129,7 @@ public class Canvas { throw new IllegalStateException(); } mNativeCanvas = nativeCanvas; + mFinalizer = new CanvasFinalizer(nativeCanvas); mDensity = Bitmap.getDefaultDensity(); } @@ -1607,19 +1627,6 @@ public class Canvas { public void releaseContext() { } - @Override - protected void finalize() throws Throwable { - try { - super.finalize(); - } finally { - // If the constructor threw an exception before setting mNativeCanvas, - // the native finalizer must not be invoked. - if (mNativeCanvas != 0) { - finalizer(mNativeCanvas); - } - } - } - /** * Free up as much memory as possible from private caches (e.g. fonts, images) * -- cgit v1.1