Merge changes from topics 'hw_prohibit_copy_buffer', 'hw_create_immutable_bitmap', 'recycled_getConfig'
* changes:
Prohibit copyPixelsToBuffer & copyPixelsFromBuffer
HardwareBitmaps: support createBitmap methods that return immutable bitmap
Fix getConfig on recycled bitmap
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 8f74bf8..59cbc93 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -52,6 +52,7 @@
mAllocationSize = mBitmap->getAllocationByteCount();
mRowBytes = mBitmap->rowBytes();
mGenerationId = mBitmap->getGenerationID();
+ mIsHardware = mBitmap->isHardware();
mBitmap.reset();
}
@@ -118,6 +119,13 @@
return mGenerationId;
}
+ bool isHardware() {
+ if (mBitmap) {
+ return mBitmap->isHardware();
+ }
+ return mIsHardware;
+ }
+
~BitmapWrapper() { }
private:
@@ -127,6 +135,7 @@
size_t mAllocationSize;
size_t mRowBytes;
uint32_t mGenerationId;
+ bool mIsHardware;
};
// Convenience class that does not take a global ref on the pixels, relying
@@ -775,7 +784,7 @@
static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
LocalScopedBitmap bitmap(bitmapHandle);
- if (bitmap->bitmap().isHardware()) {
+ if (bitmap->isHardware()) {
return GraphicsJNI::hardwareLegacyBitmapConfig();
}
return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
@@ -1208,7 +1217,7 @@
// Paying the price for making Hardware Bitmap as Config:
// later check for colorType will pass successfully,
// because Hardware Config internally may be RGBA8888 or smth like that.
- if (bitmap0->bitmap().isHardware() != bitmap1->bitmap().isHardware()) {
+ if (bitmap0->isHardware() != bitmap1->isHardware()) {
return JNI_FALSE;
}
@@ -1282,6 +1291,23 @@
return static_cast<jint>(bitmapHandle->getAllocationByteCount());
}
+static jobject Bitmap_nativeCopyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
+ LocalScopedBitmap bitmapHandle(bitmapPtr);
+ LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
+ "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
+ Bitmap& hwuiBitmap = bitmapHandle->bitmap();
+ SkBitmap src;
+ hwuiBitmap.getSkBitmap(&src);
+
+ SkBitmap result;
+ HeapAllocator allocator;
+ if (!src.copyTo(&result, hwuiBitmap.info().colorType(), &allocator)) {
+ doThrowRE(env, "Could not copy a hardware bitmap.");
+ return NULL;
+ }
+ return createBitmap(env, allocator.getStorageObjAndReset(), kBitmapCreateFlag_None);
+}
+
///////////////////////////////////////////////////////////////////////////////
static jclass make_globalref(JNIEnv* env, const char classname[])
{
@@ -1340,6 +1366,8 @@
{ "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
{ "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
{ "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
+ { "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
+ (void*)Bitmap_nativeCopyPreserveInternalConfig },
};
int register_android_graphics_Bitmap(JNIEnv* env)
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index b6db327..a259937 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -372,6 +372,16 @@
}
/**
+ * This is called by methods that want to throw an exception if the bitmap
+ * is {@link Config#HARDWARE}.
+ */
+ private void checkHardware(String errorMessage) {
+ if (getConfig() == Config.HARDWARE) {
+ throw new IllegalStateException(errorMessage);
+ }
+ }
+
+ /**
* Common code for checking that x and y are >= 0
*
* @param x x coordinate to ensure is >= 0
@@ -512,8 +522,11 @@
* <p>After this method returns, the current position of the buffer is
* updated: the position is incremented by the number of elements written
* in the buffer.</p>
+ * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
*/
public void copyPixelsToBuffer(Buffer dst) {
+ checkHardware("unable to copyPixelsToBuffer, "
+ + "pixel access is not supported on Config#HARDWARE bitmaps");
int elements = dst.remaining();
int shift;
if (dst instanceof ByteBuffer) {
@@ -550,9 +563,11 @@
* updated: the position is incremented by the number of elements read from
* the buffer. If you need to read the bitmap from the buffer again you must
* first rewind the buffer.</p>
+ * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
*/
public void copyPixelsFromBuffer(Buffer src) {
checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
+ checkHardware("unable to copyPixelsFromBuffer, Config#HARDWARE bitmaps are immutable");
int elements = src.remaining();
int shift;
@@ -753,6 +768,11 @@
return source;
}
+ boolean isHardware = source.getConfig() == Config.HARDWARE;
+ if (isHardware) {
+ source = nativeCopyPreserveInternalConfig(source.mNativePtr);
+ }
+
int neww = width;
int newh = height;
Canvas canvas = new Canvas();
@@ -824,7 +844,9 @@
canvas.setBitmap(bitmap);
canvas.drawBitmap(source, srcR, dstR, paint);
canvas.setBitmap(null);
-
+ if (isHardware) {
+ return bitmap.copy(Config.HARDWARE, false);
+ }
return bitmap;
}
@@ -1428,9 +1450,8 @@
@ColorInt
public int getPixel(int x, int y) {
checkRecycled("Can't call getPixel() on a recycled bitmap");
- if (getConfig() == Config.HARDWARE) {
- throw new IllegalStateException("Can't access pixels in hardware Bitmaps");
- }
+ checkHardware("unable to getPixel(), "
+ + "pixel access is not supported on Config#HARDWARE bitmaps");
checkPixelAccess(x, y);
return nativeGetPixel(mNativePtr, x, y);
}
@@ -1462,9 +1483,8 @@
public void getPixels(@ColorInt int[] pixels, int offset, int stride,
int x, int y, int width, int height) {
checkRecycled("Can't call getPixels() on a recycled bitmap");
- if (getConfig() == Config.HARDWARE) {
- throw new IllegalStateException("Can't access pixels in hardware Bitmaps");
- }
+ checkHardware("unable to getPixels(), "
+ + "pixel access is not supported on Config#HARDWARE bitmaps");
if (width == 0 || height == 0) {
return; // nothing to do
}
@@ -1773,4 +1793,5 @@
private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);
private static native void nativePrepareToDraw(long nativeBitmap);
private static native int nativeGetAllocationByteCount(long nativeBitmap);
+ private static native Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap);
}