diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index 3f12eed206863..121375ada52b7 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -206,6 +206,7 @@ if (enable_unittests) { fixtures = [ "fixtures/DashInNooglerHat.jpg", "fixtures/DashInNooglerHat%20WithSpace.jpg", + "fixtures/DisplayP3Logo.jpg", "fixtures/DisplayP3Logo.png", "fixtures/Horizontal.jpg", "fixtures/Horizontal.png", diff --git a/lib/ui/fixtures/DisplayP3Logo.jpg b/lib/ui/fixtures/DisplayP3Logo.jpg new file mode 100644 index 0000000000000..ea6a104d4faee Binary files /dev/null and b/lib/ui/fixtures/DisplayP3Logo.jpg differ diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc index 73e0888108776..dd112f792684c 100644 --- a/lib/ui/painting/image_decoder_impeller.cc +++ b/lib/ui/painting/image_decoder_impeller.cc @@ -96,6 +96,8 @@ static std::optional ToPixelFormat(SkColorType type) { return impeller::PixelFormat::kR8G8B8A8UNormInt; case kRGBA_F16_SkColorType: return impeller::PixelFormat::kR16G16B16A16Float; + case kBGR_101010x_XR_SkColorType: + return impeller::PixelFormat::kB10G10R10XR; default: return std::nullopt; } @@ -137,11 +139,9 @@ std::shared_ptr ImageDecoderImpeller::DecompressTexture( ChooseCompatibleAlphaType(base_image_info.alphaType()); SkImageInfo image_info; if (is_wide_gamut) { - // TODO(gaaclarke): Branch on alpha_type so it's 32bpp for opaque images. - // I tried using kBGRA_1010102_SkColorType and - // kBGR_101010x_SkColorType but Skia fails to decode the - // image that way. - SkColorType color_type = kRGBA_F16_SkColorType; + SkColorType color_type = alpha_type == SkAlphaType::kOpaque_SkAlphaType + ? kBGR_101010x_XR_SkColorType + : kRGBA_F16_SkColorType; image_info = base_image_info.makeWH(decode_size.width(), decode_size.height()) .makeColorType(color_type) diff --git a/lib/ui/painting/image_decoder_unittests.cc b/lib/ui/painting/image_decoder_unittests.cc index 947239321cf22..587ae4dfbaaa6 100644 --- a/lib/ui/painting/image_decoder_unittests.cc +++ b/lib/ui/painting/image_decoder_unittests.cc @@ -309,6 +309,7 @@ TEST_F(ImageDecoderFixtureTest, ImpellerWideGamutDisplayP3) { ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(100, 100), {100, 100}, /*supports_wide_gamut=*/true); + ASSERT_TRUE(wide_bitmap); ASSERT_EQ(wide_bitmap->colorType(), kRGBA_F16_SkColorType); ASSERT_TRUE(wide_bitmap->colorSpace()->isSRGB()); const SkPixmap& wide_pixmap = wide_bitmap->pixmap(); @@ -333,6 +334,60 @@ TEST_F(ImageDecoderFixtureTest, ImpellerWideGamutDisplayP3) { #endif // IMPELLER_SUPPORTS_RENDERING } +namespace { +float DecodeBGR10(uint32_t x) { + const float max = 1.25098f; + const float min = -0.752941f; + const float intercept = min; + const float slope = (max - min) / 1024.0f; + return (x * slope) + intercept; +} +} // namespace + +TEST_F(ImageDecoderFixtureTest, ImpellerWideGamutDisplayP3Opaque) { + auto data = OpenFixtureAsSkData("DisplayP3Logo.jpg"); + auto image = SkImage::MakeFromEncoded(data); + ASSERT_TRUE(image != nullptr); + ASSERT_EQ(SkISize::Make(100, 100), image->dimensions()); + + ImageGeneratorRegistry registry; + std::shared_ptr generator = + registry.CreateCompatibleGenerator(data); + ASSERT_TRUE(generator); + + auto descriptor = fml::MakeRefCounted(std::move(data), + std::move(generator)); + +#if IMPELLER_SUPPORTS_RENDERING + std::shared_ptr wide_bitmap = + ImageDecoderImpeller::DecompressTexture( + descriptor.get(), SkISize::Make(100, 100), {100, 100}, + /*supports_wide_gamut=*/true); + ASSERT_TRUE(wide_bitmap); + ASSERT_EQ(wide_bitmap->colorType(), kBGR_101010x_XR_SkColorType); + ASSERT_TRUE(wide_bitmap->colorSpace()->isSRGB()); + const SkPixmap& wide_pixmap = wide_bitmap->pixmap(); + const uint32_t* pixel_ptr = static_cast(wide_pixmap.addr()); + bool found_deep_red = false; + for (int i = 0; i < wide_pixmap.width() * wide_pixmap.height(); ++i) { + uint32_t pixel = *pixel_ptr++; + float blue = DecodeBGR10((pixel >> 0) & 0x3ff); + float green = DecodeBGR10((pixel >> 10) & 0x3ff); + float red = DecodeBGR10((pixel >> 20) & 0x3ff); + if (fabsf(red - 1.0931f) < 0.01f && fabsf(green - -0.2268f) < 0.01f && + fabsf(blue - -0.1501f) < 0.01f) { + found_deep_red = true; + break; + } + } + ASSERT_TRUE(found_deep_red); + std::shared_ptr bitmap = ImageDecoderImpeller::DecompressTexture( + descriptor.get(), SkISize::Make(100, 100), {100, 100}, + /*supports_wide_gamut=*/false); + ASSERT_EQ(bitmap->colorType(), kRGBA_8888_SkColorType); +#endif // IMPELLER_SUPPORTS_RENDERING +} + TEST_F(ImageDecoderFixtureTest, ImpellerNonWideGamut) { auto data = OpenFixtureAsSkData("Horizontal.jpg"); auto image = SkImage::MakeFromEncoded(data);