Expose 1010102 config for bitmap

Bug: 200307898
Test: CtsGraphicsTestCases
Change-Id: I33153e080292a95c0cc3d6edada8b274f0b06ac7
This commit is contained in:
Alec Mouri 2022-01-20 13:58:23 -08:00
parent 230b32ceb6
commit 1efd0a5df6
11 changed files with 122 additions and 65 deletions

View File

@ -15254,6 +15254,7 @@ package android.graphics {
enum_constant @Deprecated public static final android.graphics.Bitmap.Config ARGB_4444;
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
enum_constant public static final android.graphics.Bitmap.Config RGBA_1010102;
enum_constant public static final android.graphics.Bitmap.Config RGBA_F16;
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
}

View File

@ -643,6 +643,8 @@ static bool checkInternalFormat(int32_t bitmapFormat, int internalformat, int ty
return (type == GL_UNSIGNED_SHORT_5_6_5 && internalformat == GL_RGB);
case ANDROID_BITMAP_FORMAT_RGBA_F16:
return (type == GL_HALF_FLOAT && internalformat == GL_RGBA16F);
case ANDROID_BITMAP_FORMAT_RGBA_1010102:
return (type == GL_UNSIGNED_INT_2_10_10_10_REV && internalformat == GL_RGB10_A2);
default:
break;
}
@ -676,6 +678,8 @@ static int getInternalFormat(int32_t bitmapFormat) {
return GL_RGB;
case ANDROID_BITMAP_FORMAT_RGBA_F16:
return GL_RGBA16F;
case ANDROID_BITMAP_FORMAT_RGBA_1010102:
return GL_RGB10_A2;
default:
return -1;
}
@ -693,6 +697,8 @@ static int getType(int32_t bitmapFormat) {
return GL_UNSIGNED_SHORT_5_6_5;
case ANDROID_BITMAP_FORMAT_RGBA_F16:
return GL_HALF_FLOAT;
case ANDROID_BITMAP_FORMAT_RGBA_1010102:
return GL_UNSIGNED_INT_2_10_10_10_REV;
default:
return -1;
}

View File

@ -458,7 +458,7 @@ public final class Bitmap implements Parcelable {
* No color information is stored.
* With this configuration, each pixel requires 1 byte of memory.
*/
ALPHA_8 (1),
ALPHA_8(1),
/**
* Each pixel is stored on 2 bytes and only the RGB channels are
@ -479,7 +479,7 @@ public final class Bitmap implements Parcelable {
* short color = (R & 0x1f) << 11 | (G & 0x3f) << 5 | (B & 0x1f);
* </pre>
*/
RGB_565 (3),
RGB_565(3),
/**
* Each pixel is stored on 2 bytes. The three RGB color channels
@ -501,7 +501,7 @@ public final class Bitmap implements Parcelable {
* it is advised to use {@link #ARGB_8888} instead.
*/
@Deprecated
ARGB_4444 (4),
ARGB_4444(4),
/**
* Each pixel is stored on 4 bytes. Each channel (RGB and alpha
@ -516,10 +516,10 @@ public final class Bitmap implements Parcelable {
* int color = (A & 0xff) << 24 | (B & 0xff) << 16 | (G & 0xff) << 8 | (R & 0xff);
* </pre>
*/
ARGB_8888 (5),
ARGB_8888(5),
/**
* Each pixels is stored on 8 bytes. Each channel (RGB and alpha
* Each pixel is stored on 8 bytes. Each channel (RGB and alpha
* for translucency) is stored as a
* {@link android.util.Half half-precision floating point value}.
*
@ -531,7 +531,7 @@ public final class Bitmap implements Parcelable {
* long color = (A & 0xffff) << 48 | (B & 0xffff) << 32 | (G & 0xffff) << 16 | (R & 0xffff);
* </pre>
*/
RGBA_F16 (6),
RGBA_F16(6),
/**
* Special configuration, when bitmap is stored only in graphic memory.
@ -540,13 +540,29 @@ public final class Bitmap implements Parcelable {
* It is optimal for cases, when the only operation with the bitmap is to draw it on a
* screen.
*/
HARDWARE (7);
HARDWARE(7),
/**
* Each pixel is stored on 4 bytes. Each RGB channel is stored with 10 bits of precision
* (1024 possible values). There is an additional alpha channel that is stored with 2 bits
* of precision (4 possible values).
*
* This configuration is suited for wide-gamut and HDR content which does not require alpha
* blending, such that the memory cost is the same as ARGB_8888 while enabling higher color
* precision.
*
* <p>Use this formula to pack into 32 bits:</p>
* <pre class="prettyprint">
* int color = (A & 0x3) << 30 | (B & 0x3ff) << 20 | (G & 0x3ff) << 10 | (R & 0x3ff);
* </pre>
*/
RGBA_1010102(8);
@UnsupportedAppUsage
final int nativeInt;
private static Config sConfigs[] = {
null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE
null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE, RGBA_1010102
};
Config(int ni) {
@ -1000,8 +1016,8 @@ public final class Bitmap implements Parcelable {
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
* @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
* mark the bitmap as opaque. Doing so will clear the bitmap in black
* @param hasAlpha If the bitmap is ARGB_8888, RGBA_16F, or RGBA_1010102 this flag can be
* used to mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
*
* @throws IllegalArgumentException if the width or height are <= 0, or if
@ -1019,8 +1035,8 @@ public final class Bitmap implements Parcelable {
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
* @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
* mark the bitmap as opaque. Doing so will clear the bitmap in black
* @param hasAlpha If the bitmap is ARGB_8888, RGBA_16F, or RGBA_1010102 this flag can be
* used to mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
* @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16}
* and {@link ColorSpace.Named#SRGB sRGB} or
@ -1050,8 +1066,8 @@ public final class Bitmap implements Parcelable {
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
* @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
* mark the bitmap as opaque. Doing so will clear the bitmap in black
* @param hasAlpha If the bitmap is ARGB_8888, RGBA_16F, or RGBA_1010102 this flag can be
* used to mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
*
* @throws IllegalArgumentException if the width or height are <= 0, or if
@ -1074,8 +1090,8 @@ public final class Bitmap implements Parcelable {
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
* @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
* mark the bitmap as opaque. Doing so will clear the bitmap in black
* @param hasAlpha If the bitmap is ARGB_8888, RGBA_16F, or RGBA_1010102 this flag can be
* used to mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
* @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16}
* and {@link ColorSpace.Named#SRGB sRGB} or

View File

@ -287,29 +287,29 @@ private:
std::mutex mVkLock;
};
static bool checkSupport(AHardwareBuffer_Format format) {
AHardwareBuffer_Desc desc = {
.width = 1,
.height = 1,
.layers = 1,
.format = format,
.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE,
};
UniqueAHardwareBuffer buffer = allocateAHardwareBuffer(desc);
return buffer != nullptr;
}
bool HardwareBitmapUploader::hasFP16Support() {
static std::once_flag sOnce;
static bool hasFP16Support = false;
// Gralloc shouldn't let us create a USAGE_HW_TEXTURE if GLES is unable to consume it, so
// we don't need to double-check the GLES version/extension.
std::call_once(sOnce, []() {
AHardwareBuffer_Desc desc = {
.width = 1,
.height = 1,
.layers = 1,
.format = AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT,
.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE,
};
UniqueAHardwareBuffer buffer = allocateAHardwareBuffer(desc);
hasFP16Support = buffer != nullptr;
});
static bool hasFP16Support = checkSupport(AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT);
return hasFP16Support;
}
bool HardwareBitmapUploader::has1010102Support() {
static bool has101012Support = checkSupport(AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM);
return has101012Support;
}
static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) {
FormatInfo formatInfo;
switch (skBitmap.info().colorType()) {
@ -350,6 +350,19 @@ static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) {
formatInfo.type = GL_UNSIGNED_BYTE;
formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
break;
case kRGBA_1010102_SkColorType:
formatInfo.isSupported = HardwareBitmapUploader::has1010102Support();
if (formatInfo.isSupported) {
formatInfo.type = GL_UNSIGNED_INT_2_10_10_10_REV;
formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
formatInfo.vkFormat = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
} else {
formatInfo.type = GL_UNSIGNED_BYTE;
formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
}
formatInfo.format = GL_RGBA;
break;
default:
ALOGW("unable to create hardware bitmap of colortype: %d", skBitmap.info().colorType());
formatInfo.valid = false;

View File

@ -29,10 +29,12 @@ public:
#ifdef __ANDROID__
static bool hasFP16Support();
static bool has1010102Support();
#else
static bool hasFP16Support() {
return true;
}
static bool has1010102Support() { return true; }
#endif
};

View File

@ -57,6 +57,8 @@ static AndroidBitmapFormat getFormat(const SkImageInfo& info) {
return ANDROID_BITMAP_FORMAT_A_8;
case kRGBA_F16_SkColorType:
return ANDROID_BITMAP_FORMAT_RGBA_F16;
case kRGBA_1010102_SkColorType:
return ANDROID_BITMAP_FORMAT_RGBA_1010102;
default:
return ANDROID_BITMAP_FORMAT_NONE;
}
@ -74,6 +76,8 @@ static SkColorType getColorType(AndroidBitmapFormat format) {
return kAlpha_8_SkColorType;
case ANDROID_BITMAP_FORMAT_RGBA_F16:
return kRGBA_F16_SkColorType;
case ANDROID_BITMAP_FORMAT_RGBA_1010102:
return kRGBA_1010102_SkColorType;
default:
return kUnknown_SkColorType;
}
@ -249,6 +253,9 @@ int ABitmap_compress(const AndroidBitmapInfo* info, ADataSpace dataSpace, const
case ANDROID_BITMAP_FORMAT_RGBA_F16:
colorType = kRGBA_F16_SkColorType;
break;
case ANDROID_BITMAP_FORMAT_RGBA_1010102:
colorType = kRGBA_1010102_SkColorType;
break;
default:
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}

View File

@ -159,6 +159,8 @@ bool ImageDecoder::setOutColorType(SkColorType colorType) {
break;
case kRGBA_F16_SkColorType:
break;
case kRGBA_1010102_SkColorType:
break;
default:
return false;
}

View File

@ -137,9 +137,16 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in
auto* brd = reinterpret_cast<skia::BitmapRegionDecoder*>(brdHandle);
SkColorType decodeColorType = brd->computeOutputColorType(colorType);
if (decodeColorType == kRGBA_F16_SkColorType && isHardware &&
if (isHardware) {
if (decodeColorType == kRGBA_F16_SkColorType &&
!uirenderer::HardwareBitmapUploader::hasFP16Support()) {
decodeColorType = kN32_SkColorType;
decodeColorType = kN32_SkColorType;
}
if (decodeColorType == kRGBA_1010102_SkColorType &&
!uirenderer::HardwareBitmapUploader::has1010102Support()) {
decodeColorType = kN32_SkColorType;
}
}
// Set up the pixel allocator

View File

@ -365,6 +365,8 @@ jint GraphicsJNI::colorTypeToLegacyBitmapConfig(SkColorType colorType) {
return kRGB_565_LegacyBitmapConfig;
case kAlpha_8_SkColorType:
return kA8_LegacyBitmapConfig;
case kRGBA_1010102_SkColorType:
return kRGBA_1010102_LegacyBitmapConfig;
case kUnknown_SkColorType:
default:
break;
@ -374,14 +376,10 @@ jint GraphicsJNI::colorTypeToLegacyBitmapConfig(SkColorType colorType) {
SkColorType GraphicsJNI::legacyBitmapConfigToColorType(jint legacyConfig) {
const uint8_t gConfig2ColorType[] = {
kUnknown_SkColorType,
kAlpha_8_SkColorType,
kUnknown_SkColorType, // Previously kIndex_8_SkColorType,
kRGB_565_SkColorType,
kARGB_4444_SkColorType,
kN32_SkColorType,
kRGBA_F16_SkColorType,
kN32_SkColorType
kUnknown_SkColorType, kAlpha_8_SkColorType,
kUnknown_SkColorType, // Previously kIndex_8_SkColorType,
kRGB_565_SkColorType, kARGB_4444_SkColorType, kN32_SkColorType,
kRGBA_F16_SkColorType, kN32_SkColorType, kRGBA_1010102_SkColorType,
};
if (legacyConfig < 0 || legacyConfig > kLastEnum_LegacyBitmapConfig) {
@ -399,15 +397,12 @@ AndroidBitmapFormat GraphicsJNI::getFormatFromConfig(JNIEnv* env, jobject jconfi
jint javaConfigId = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID);
const AndroidBitmapFormat config2BitmapFormat[] = {
ANDROID_BITMAP_FORMAT_NONE,
ANDROID_BITMAP_FORMAT_A_8,
ANDROID_BITMAP_FORMAT_NONE, // Previously Config.Index_8
ANDROID_BITMAP_FORMAT_RGB_565,
ANDROID_BITMAP_FORMAT_RGBA_4444,
ANDROID_BITMAP_FORMAT_RGBA_8888,
ANDROID_BITMAP_FORMAT_RGBA_F16,
ANDROID_BITMAP_FORMAT_NONE // Congfig.HARDWARE
};
ANDROID_BITMAP_FORMAT_NONE, ANDROID_BITMAP_FORMAT_A_8,
ANDROID_BITMAP_FORMAT_NONE, // Previously Config.Index_8
ANDROID_BITMAP_FORMAT_RGB_565, ANDROID_BITMAP_FORMAT_RGBA_4444,
ANDROID_BITMAP_FORMAT_RGBA_8888, ANDROID_BITMAP_FORMAT_RGBA_F16,
ANDROID_BITMAP_FORMAT_NONE, // Congfig.HARDWARE
ANDROID_BITMAP_FORMAT_RGBA_1010102};
return config2BitmapFormat[javaConfigId];
}
@ -430,6 +425,9 @@ jobject GraphicsJNI::getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format
case ANDROID_BITMAP_FORMAT_RGBA_F16:
configId = kRGBA_16F_LegacyBitmapConfig;
break;
case ANDROID_BITMAP_FORMAT_RGBA_1010102:
configId = kRGBA_1010102_LegacyBitmapConfig;
break;
default:
break;
}

View File

@ -34,16 +34,17 @@ public:
// This enum must keep these int values, to match the int values
// in the java Bitmap.Config enum.
enum LegacyBitmapConfig {
kNo_LegacyBitmapConfig = 0,
kA8_LegacyBitmapConfig = 1,
kIndex8_LegacyBitmapConfig = 2,
kRGB_565_LegacyBitmapConfig = 3,
kARGB_4444_LegacyBitmapConfig = 4,
kARGB_8888_LegacyBitmapConfig = 5,
kRGBA_16F_LegacyBitmapConfig = 6,
kHardware_LegacyBitmapConfig = 7,
kNo_LegacyBitmapConfig = 0,
kA8_LegacyBitmapConfig = 1,
kIndex8_LegacyBitmapConfig = 2,
kRGB_565_LegacyBitmapConfig = 3,
kARGB_4444_LegacyBitmapConfig = 4,
kARGB_8888_LegacyBitmapConfig = 5,
kRGBA_16F_LegacyBitmapConfig = 6,
kHardware_LegacyBitmapConfig = 7,
kRGBA_1010102_LegacyBitmapConfig = 8,
kLastEnum_LegacyBitmapConfig = kHardware_LegacyBitmapConfig
kLastEnum_LegacyBitmapConfig = kRGBA_1010102_LegacyBitmapConfig
};
static void setJavaVM(JavaVM* javaVM);

View File

@ -198,14 +198,16 @@ static SkColorType getColorType(AndroidBitmapFormat format) {
return kGray_8_SkColorType;
case ANDROID_BITMAP_FORMAT_RGBA_F16:
return kRGBA_F16_SkColorType;
case ANDROID_BITMAP_FORMAT_RGBA_1010102:
return kRGBA_1010102_SkColorType;
default:
return kUnknown_SkColorType;
}
}
int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE
|| format > ANDROID_BITMAP_FORMAT_RGBA_F16) {
if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE ||
format > ANDROID_BITMAP_FORMAT_RGBA_1010102) {
return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
}
@ -290,6 +292,8 @@ static AndroidBitmapFormat getFormat(SkColorType colorType) {
return ANDROID_BITMAP_FORMAT_A_8;
case kRGBA_F16_SkColorType:
return ANDROID_BITMAP_FORMAT_RGBA_F16;
case kRGBA_1010102_SkColorType:
return ANDROID_BITMAP_FORMAT_RGBA_1010102;
default:
return ANDROID_BITMAP_FORMAT_NONE;
}