From 17a8bfc38a565ae96f43d36b223779be840bb50c Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Tue, 3 Jun 2014 16:15:15 -0400 Subject: [PATCH] In Bitmap.reconfigure, update the pixelref's info. This fixes CTS tests which are crashing on an SkASSERT due to a mismatch of SkImageInfo between the SkPixelRef and SkBitmap. Also directly call ref() and unref() instead of SkSafeRef/SkSafeUnref, since we would already crash if the SkPixelRef in question was NULL. Also if the user attempts to reconfigure to 4444, use 8888 instead. Change-Id: I473ef225c6cd1c92d67ae103c53c6cff0dad92de --- core/jni/android/graphics/Bitmap.cpp | 40 ++++++++++++++++++---- graphics/java/android/graphics/Bitmap.java | 11 ++++-- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 032851749c409..9998995eb319e 100644 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -361,24 +361,50 @@ static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) { } static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle, - jint width, jint height, jint configHandle, jint allocSize) { + jint width, jint height, jint configHandle, jint allocSize, + jboolean requestPremul) { SkBitmap* bitmap = reinterpret_cast(bitmapHandle); SkBitmap::Config config = static_cast(configHandle); - if (width * height * SkBitmap::ComputeBytesPerPixel(config) > allocSize) { + SkColorType colorType = SkBitmapConfigToColorType(config); + + // ARGB_4444 is a deprecated format, convert automatically to 8888 + if (colorType == kARGB_4444_SkColorType) { + colorType = kN32_SkColorType; + } + + if (width * height * SkColorTypeBytesPerPixel(colorType) > allocSize) { // done in native as there's no way to get BytesPerPixel in Java doThrowIAE(env, "Bitmap not large enough to support new configuration"); return; } SkPixelRef* ref = bitmap->pixelRef(); - SkSafeRef(ref); - bitmap->setConfig(config, width, height); + ref->ref(); + SkAlphaType alphaType; + if (bitmap->colorType() != kRGB_565_SkColorType + && bitmap->alphaType() == kOpaque_SkAlphaType) { + // If the original bitmap was set to opaque, keep that setting, unless it + // was 565, which is required to be opaque. + alphaType = kOpaque_SkAlphaType; + } else { + // Otherwise respect the premultiplied request. + alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType; + } + bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType)); + // FIXME: Skia thinks of an SkPixelRef as having a constant SkImageInfo (except for + // its alphatype), so it would make more sense from Skia's perspective to create a + // new SkPixelRef. That said, libhwui uses the pointer to the SkPixelRef as a key + // for its cache, so it won't realize this is the same Java Bitmap. + SkImageInfo& info = const_cast(ref->info()); + // Use the updated from the SkBitmap, which may have corrected an invalid alphatype. + // (e.g. 565 non-opaque) + info = bitmap->info(); bitmap->setPixelRef(ref); // notifyPixelsChanged will increment the generation ID even though the actual pixel data // hasn't been touched. This signals the renderer that the bitmap (including width, height, - // and config) has changed. + // colortype and alphatype) has changed. ref->notifyPixelsChanged(); - SkSafeUnref(ref); + ref->unref(); } // These must match the int values in Bitmap.java @@ -799,7 +825,7 @@ static JNINativeMethod gBitmapMethods[] = { (void*)Bitmap_copy }, { "nativeDestructor", "(J)V", (void*)Bitmap_destructor }, { "nativeRecycle", "(J)Z", (void*)Bitmap_recycle }, - { "nativeReconfigure", "(JIIII)V", (void*)Bitmap_reconfigure }, + { "nativeReconfigure", "(JIIIIZ)V", (void*)Bitmap_reconfigure }, { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z", (void*)Bitmap_compress }, { "nativeErase", "(JI)V", (void*)Bitmap_erase }, diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 06cf253a7ebdc..ef0a41151a7cf 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -194,6 +194,11 @@ public final class Bitmap implements Parcelable { * while {@link #getAllocationByteCount()} will reflect that of the initial * configuration.

* + *

Note: This may change this result of hasAlpha(). When converting to 565, + * the new bitmap will always be considered opaque. When converting from 565, + * the new bitmap will be considered non-opaque, and will respect the value + * set by setPremultiplied().

+ * *

WARNING: This method should NOT be called on a bitmap currently used * by the view system. It does not make guarantees about how the underlying * pixel buffer is remapped to the new config, just that the allocation is @@ -217,7 +222,8 @@ public final class Bitmap implements Parcelable { throw new IllegalStateException("native-backed bitmaps may not be reconfigured"); } - nativeReconfigure(mNativeBitmap, width, height, config.nativeInt, mBuffer.length); + nativeReconfigure(mNativeBitmap, width, height, config.nativeInt, mBuffer.length, + mIsPremultiplied); mWidth = width; mHeight = height; } @@ -1586,7 +1592,8 @@ public final class Bitmap implements Parcelable { private static native void nativeDestructor(long nativeBitmap); private static native boolean nativeRecycle(long nativeBitmap); private static native void nativeReconfigure(long nativeBitmap, int width, int height, - int config, int allocSize); + int config, int allocSize, + boolean isPremultiplied); private static native boolean nativeCompress(long nativeBitmap, int format, int quality, OutputStream stream,