From ee3bfe7681d44da520ec646c3e500ccecaaab228 Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Thu, 31 Jan 2019 08:42:23 -0500 Subject: [PATCH] Only decode to F16 if HARDWARE supports it Bug: 123301974 Test: Infeasible If a Bitmap is going to be decoded to F16 and then converted to HARDWARE, only decode to F16 if HARDWARE supports it. Previously, if we discovered after the decode that HARDWARE did not support F16, we had to copy back to 8888 before the upload. Change-Id: I3ceb9d053ba134bb96cfb9d638e54ac652e5db29 --- core/jni/android/graphics/BitmapFactory.cpp | 6 ++++++ .../android/graphics/BitmapRegionDecoder.cpp | 5 +++++ core/jni/android/graphics/ImageDecoder.cpp | 17 +++++++++++++---- libs/hwui/HardwareBitmapUploader.cpp | 4 ++-- libs/hwui/HardwareBitmapUploader.h | 4 +++- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 3f9ec452749fa..7ef30f7ee7869 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -15,6 +15,7 @@ #include "Utils.h" #include "core_jni_helpers.h" +#include #include #include #include @@ -278,6 +279,11 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr stream, // Set the decode colorType SkColorType decodeColorType = codec->computeOutputColorType(prefColorType); + if (decodeColorType == kRGBA_F16_SkColorType && isHardware && + !uirenderer::HardwareBitmapUploader::hasFP16Support()) { + decodeColorType = kN32_SkColorType; + } + sk_sp decodeColorSpace = codec->computeOutputColorSpace( decodeColorType, prefColorSpace); diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp index b4ba749b75bfb..d65f324d10658 100644 --- a/core/jni/android/graphics/BitmapRegionDecoder.cpp +++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp @@ -33,6 +33,7 @@ #include "android_util_Binder.h" #include "core_jni_helpers.h" +#include #include #include #include @@ -166,6 +167,10 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in SkBitmapRegionDecoder* brd = reinterpret_cast(brdHandle); SkColorType decodeColorType = brd->computeOutputColorType(colorType); + if (decodeColorType == kRGBA_F16_SkColorType && isHardware && + !uirenderer::HardwareBitmapUploader::hasFP16Support()) { + decodeColorType = kN32_SkColorType; + } // Set up the pixel allocator SkBRDAllocator* allocator = nullptr; diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp index 72e14e79f4f54..2d83ac3207332 100644 --- a/core/jni/android/graphics/ImageDecoder.cpp +++ b/core/jni/android/graphics/ImageDecoder.cpp @@ -24,6 +24,7 @@ #include "core_jni_helpers.h" #include +#include #include #include @@ -256,6 +257,17 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong // This is currently the only way to know that we should decode to F16. colorType = codec->computeOutputColorType(colorType); } + + const bool isHardware = !requireMutable + && (allocator == ImageDecoder::kDefault_Allocator || + allocator == ImageDecoder::kHardware_Allocator) + && colorType != kGray_8_SkColorType; + + if (colorType == kRGBA_F16_SkColorType && isHardware && + !uirenderer::HardwareBitmapUploader::hasFP16Support()) { + colorType = kN32_SkColorType; + } + sk_sp colorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle); colorSpace = codec->computeOutputColorSpace(colorType, colorSpace); decodeInfo = decodeInfo.makeColorType(colorType).makeColorSpace(colorSpace); @@ -449,10 +461,7 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong if (requireMutable) { bitmapCreateFlags |= bitmap::kBitmapCreateFlag_Mutable; } else { - if ((allocator == ImageDecoder::kDefault_Allocator || - allocator == ImageDecoder::kHardware_Allocator) - && bm.colorType() != kAlpha_8_SkColorType) - { + if (isHardware) { sk_sp hwBitmap = Bitmap::allocateHardwareBitmap(bm); if (hwBitmap) { hwBitmap->setImmutable(); diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp index 39bfcdd944a46..6b7ec97de4c87 100644 --- a/libs/hwui/HardwareBitmapUploader.cpp +++ b/libs/hwui/HardwareBitmapUploader.cpp @@ -86,7 +86,7 @@ static EGLDisplay getUploadEglDisplay() { return sEglManager.eglDisplay(); } -static bool hasFP16Support() { +bool HardwareBitmapUploader::hasFP16Support() { static std::once_flag sOnce; static bool hasFP16Support = false; @@ -127,7 +127,7 @@ static FormatInfo determineFormat(const SkBitmap& skBitmap) { formatInfo.type = GL_UNSIGNED_BYTE; break; case kRGBA_F16_SkColorType: - formatInfo.isSupported = hasFP16Support(); + formatInfo.isSupported = HardwareBitmapUploader::hasFP16Support(); if (formatInfo.isSupported) { formatInfo.type = GL_HALF_FLOAT; formatInfo.pixelFormat = PIXEL_FORMAT_RGBA_FP16; diff --git a/libs/hwui/HardwareBitmapUploader.h b/libs/hwui/HardwareBitmapUploader.h index 40f2b0c7873cd..6f41e6db4e322 100644 --- a/libs/hwui/HardwareBitmapUploader.h +++ b/libs/hwui/HardwareBitmapUploader.h @@ -20,10 +20,12 @@ namespace android::uirenderer { -class HardwareBitmapUploader { +class ANDROID_API HardwareBitmapUploader { public: static sk_sp allocateHardwareBitmap(const SkBitmap& sourceBitmap); static void terminate(); + + static bool hasFP16Support(); }; } // namespace android::uirenderer