diff --git a/impeller/renderer/backend/gles/capabilities_gles.cc b/impeller/renderer/backend/gles/capabilities_gles.cc index 6fe142bbe5ab2..18a5e1accb9e6 100644 --- a/impeller/renderer/backend/gles/capabilities_gles.cc +++ b/impeller/renderer/backend/gles/capabilities_gles.cc @@ -158,6 +158,9 @@ bool CapabilitiesGLES::SupportsSSBO() const { } bool CapabilitiesGLES::SupportsTextureToTextureBlits() const { + // TODO(158523): Switch this to true for improved performance + // on GLES 3.0+ devices. Note that this wasn't enabled because + // there were some rendering issues on some devices. return false; } diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc index a73310c492b2e..1355653d59a7e 100644 --- a/lib/ui/painting/image_decoder_impeller.cc +++ b/lib/ui/painting/image_decoder_impeller.cc @@ -114,6 +114,7 @@ DecompressResult ImageDecoderImpeller::DecompressTexture( SkISize target_size, impeller::ISize max_texture_size, bool supports_wide_gamut, + const std::shared_ptr& capabilities, const std::shared_ptr& allocator) { TRACE_EVENT0("impeller", __FUNCTION__); if (!descriptor) { @@ -238,7 +239,8 @@ DecompressResult ImageDecoderImpeller::DecompressTexture( : std::optional(image_info.makeDimensions(target_size)); if (source_size.width() > max_texture_size.width || - source_size.height() > max_texture_size.height) { + source_size.height() > max_texture_size.height || + !capabilities->SupportsTextureToTextureBlits()) { //---------------------------------------------------------------------------- /// 2. If the decoded image isn't the requested target size and the src size /// exceeds the device max texture size, perform a slow CPU reisze. @@ -536,7 +538,8 @@ void ImageDecoderImpeller::Decode(fml::RefPtr descriptor, // Always decompress on the concurrent runner. auto bitmap_result = DecompressTexture( raw_descriptor, target_size, max_size_supported, - supports_wide_gamut, context->GetResourceAllocator()); + /*supports_wide_gamut=*/supports_wide_gamut, + context->GetCapabilities(), context->GetResourceAllocator()); if (!bitmap_result.device_buffer) { result(nullptr, bitmap_result.decode_error); return; diff --git a/lib/ui/painting/image_decoder_impeller.h b/lib/ui/painting/image_decoder_impeller.h index 1d956a30a936c..3a1e5172a9917 100644 --- a/lib/ui/painting/image_decoder_impeller.h +++ b/lib/ui/painting/image_decoder_impeller.h @@ -11,6 +11,7 @@ #include "flutter/lib/ui/painting/image_decoder.h" #include "impeller/core/formats.h" #include "impeller/geometry/size.h" +#include "impeller/renderer/capabilities.h" #include "include/core/SkImageInfo.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -68,6 +69,7 @@ class ImageDecoderImpeller final : public ImageDecoder { SkISize target_size, impeller::ISize max_texture_size, bool supports_wide_gamut, + const std::shared_ptr& capabilities, const std::shared_ptr& allocator); /// @brief Create a device private texture from the provided host buffer. diff --git a/lib/ui/painting/image_decoder_no_gl_unittests.cc b/lib/ui/painting/image_decoder_no_gl_unittests.cc index d935fa2e3e9f9..04a0229c112dd 100644 --- a/lib/ui/painting/image_decoder_no_gl_unittests.cc +++ b/lib/ui/painting/image_decoder_no_gl_unittests.cc @@ -3,8 +3,10 @@ // found in the LICENSE file. #include "flutter/lib/ui/painting/image_decoder_no_gl_unittests.h" +#include #include "flutter/fml/endianness.h" +#include "impeller/renderer/capabilities.h" #include "include/core/SkColorType.h" namespace flutter { @@ -80,6 +82,10 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutDisplayP3) { #endif auto data = flutter::testing::OpenFixtureAsSkData("DisplayP3Logo.png"); auto image = SkImages::DeferredFromEncodedData(data); + std::shared_ptr capabilities = + impeller::CapabilitiesBuilder() + .SetSupportsTextureToTextureBlits(true) + .Build(); ASSERT_TRUE(image != nullptr); ASSERT_EQ(SkISize::Make(100, 100), image->dimensions()); @@ -100,7 +106,7 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutDisplayP3) { std::optional wide_result = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(100, 100), {100, 100}, - /*supports_wide_gamut=*/true, allocator); + /*supports_wide_gamut=*/true, capabilities, allocator); ASSERT_TRUE(wide_result.has_value()); ASSERT_EQ(wide_result->image_info.colorType(), kRGBA_F16_SkColorType); ASSERT_TRUE(wide_result->image_info.colorSpace()->isSRGB()); @@ -124,7 +130,7 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutDisplayP3) { std::optional narrow_result = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(100, 100), {100, 100}, - /*supports_wide_gamut=*/false, allocator); + /*supports_wide_gamut=*/false, capabilities, allocator); ASSERT_TRUE(narrow_result.has_value()); ASSERT_EQ(narrow_result->image_info.colorType(), kRGBA_8888_SkColorType); @@ -137,6 +143,10 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutIndexedPng) { #endif auto data = flutter::testing::OpenFixtureAsSkData("WideGamutIndexed.png"); auto image = SkImages::DeferredFromEncodedData(data); + std::shared_ptr capabilities = + impeller::CapabilitiesBuilder() + .SetSupportsTextureToTextureBlits(true) + .Build(); ASSERT_TRUE(image != nullptr); ASSERT_EQ(SkISize::Make(100, 100), image->dimensions()); @@ -157,7 +167,7 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutIndexedPng) { std::optional wide_result = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(100, 100), {100, 100}, - /*supports_wide_gamut=*/true, allocator); + /*supports_wide_gamut=*/true, capabilities, allocator); ASSERT_EQ(wide_result->image_info.colorType(), kBGR_101010x_XR_SkColorType); ASSERT_TRUE(wide_result->image_info.colorSpace()->isSRGB()); @@ -180,7 +190,7 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutIndexedPng) { std::optional narrow_result = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(100, 100), {100, 100}, - /*supports_wide_gamut=*/false, allocator); + /*supports_wide_gamut=*/false, capabilities, allocator); ASSERT_TRUE(narrow_result.has_value()); ASSERT_EQ(narrow_result->image_info.colorType(), kRGBA_8888_SkColorType); @@ -193,6 +203,10 @@ TEST(ImageDecoderNoGLTest, ImepllerUnmultipliedAlphaPng) { #endif auto data = flutter::testing::OpenFixtureAsSkData("unmultiplied_alpha.png"); auto image = SkImages::DeferredFromEncodedData(data); + std::shared_ptr capabilities = + impeller::CapabilitiesBuilder() + .SetSupportsTextureToTextureBlits(true) + .Build(); ASSERT_TRUE(image != nullptr); ASSERT_EQ(SkISize::Make(11, 11), image->dimensions()); @@ -210,7 +224,7 @@ TEST(ImageDecoderNoGLTest, ImepllerUnmultipliedAlphaPng) { std::optional result = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(11, 11), {11, 11}, - /*supports_wide_gamut=*/true, allocator); + /*supports_wide_gamut=*/true, capabilities, allocator); ASSERT_EQ(result->image_info.colorType(), kRGBA_8888_SkColorType); const SkPixmap& pixmap = result->sk_bitmap->pixmap(); diff --git a/lib/ui/painting/image_decoder_unittests.cc b/lib/ui/painting/image_decoder_unittests.cc index 69096eeca3866..1e41ab5cc82e3 100644 --- a/lib/ui/painting/image_decoder_unittests.cc +++ b/lib/ui/painting/image_decoder_unittests.cc @@ -441,12 +441,16 @@ TEST_F(ImageDecoderFixtureTest, ImpellerNullColorspace) { std::move(data), image->imageInfo(), 10 * 4); #if IMPELLER_SUPPORTS_RENDERING + std::shared_ptr capabilities = + impeller::CapabilitiesBuilder() + .SetSupportsTextureToTextureBlits(true) + .Build(); std::shared_ptr allocator = std::make_shared(); std::optional decompressed = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(100, 100), {100, 100}, - /*supports_wide_gamut=*/true, allocator); + /*supports_wide_gamut=*/true, capabilities, allocator); ASSERT_TRUE(decompressed.has_value()); ASSERT_EQ(decompressed->image_info.colorType(), kRGBA_8888_SkColorType); ASSERT_EQ(decompressed->image_info.colorSpace(), nullptr); @@ -468,12 +472,16 @@ TEST_F(ImageDecoderFixtureTest, ImpellerPixelConversion32F) { std::move(data), image->imageInfo(), 10 * 16); #if IMPELLER_SUPPORTS_RENDERING + std::shared_ptr capabilities = + impeller::CapabilitiesBuilder() + .SetSupportsTextureToTextureBlits(true) + .Build(); std::shared_ptr allocator = std::make_shared(); std::optional decompressed = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(100, 100), {100, 100}, - /*supports_wide_gamut=*/true, allocator); + /*supports_wide_gamut=*/true, capabilities, allocator); ASSERT_TRUE(decompressed.has_value()); ASSERT_EQ(decompressed->image_info.colorType(), kRGBA_F16_SkColorType); @@ -496,12 +504,16 @@ TEST_F(ImageDecoderFixtureTest, ImpellerWideGamutDisplayP3Opaque) { std::move(generator)); #if IMPELLER_SUPPORTS_RENDERING + std::shared_ptr capabilities = + impeller::CapabilitiesBuilder() + .SetSupportsTextureToTextureBlits(true) + .Build(); std::shared_ptr allocator = std::make_shared(); std::optional wide_result = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(100, 100), {100, 100}, - /*supports_wide_gamut=*/true, allocator); + /*supports_wide_gamut=*/true, capabilities, allocator); ASSERT_TRUE(wide_result.has_value()); ASSERT_EQ(wide_result->image_info.colorType(), kBGR_101010x_XR_SkColorType); @@ -526,7 +538,7 @@ TEST_F(ImageDecoderFixtureTest, ImpellerWideGamutDisplayP3Opaque) { std::optional narrow_result = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(100, 100), {100, 100}, - /*supports_wide_gamut=*/false, allocator); + /*supports_wide_gamut=*/false, capabilities, allocator); ASSERT_TRUE(narrow_result.has_value()); ASSERT_EQ(narrow_result->image_info.colorType(), kRGBA_8888_SkColorType); @@ -548,12 +560,16 @@ TEST_F(ImageDecoderFixtureTest, ImpellerNonWideGamut) { std::move(generator)); #if IMPELLER_SUPPORTS_RENDERING + std::shared_ptr capabilities = + impeller::CapabilitiesBuilder() + .SetSupportsTextureToTextureBlits(true) + .Build(); std::shared_ptr allocator = std::make_shared(); std::optional result = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(600, 200), {600, 200}, - /*supports_wide_gamut=*/true, allocator); + /*supports_wide_gamut=*/true, capabilities, allocator); ASSERT_TRUE(result.has_value()); ASSERT_EQ(result->image_info.colorType(), kRGBA_8888_SkColorType); @@ -802,13 +818,21 @@ TEST(ImageDecoderTest, VerifySimpleDecoding) { EXPECT_EQ(compressed_image->alphaType(), kOpaque_SkAlphaType); #if IMPELLER_SUPPORTS_RENDERING + std::shared_ptr capabilities = + impeller::CapabilitiesBuilder() + .SetSupportsTextureToTextureBlits(true) + .Build(); + std::shared_ptr capabilities_no_blit = + impeller::CapabilitiesBuilder() + .SetSupportsTextureToTextureBlits(false) + .Build(); // Bitmap sizes reflect the original image size as resizing is done on the // GPU if the src size is smaller than the max texture size. std::shared_ptr allocator = std::make_shared(); auto result_1 = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(6, 2), {1000, 1000}, - /*supports_wide_gamut=*/false, allocator); + /*supports_wide_gamut=*/false, capabilities, allocator); EXPECT_EQ(result_1.sk_bitmap->width(), 75); EXPECT_EQ(result_1.sk_bitmap->height(), 25); @@ -816,7 +840,7 @@ TEST(ImageDecoderTest, VerifySimpleDecoding) { // max texture size even if destination size isn't max texture size. auto result_2 = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(6, 2), {10, 10}, - /*supports_wide_gamut=*/false, allocator); + /*supports_wide_gamut=*/false, capabilities, allocator); EXPECT_EQ(result_2.sk_bitmap->width(), 6); EXPECT_EQ(result_2.sk_bitmap->height(), 2); @@ -824,9 +848,16 @@ TEST(ImageDecoderTest, VerifySimpleDecoding) { // is scaled down. auto result_3 = ImageDecoderImpeller::DecompressTexture( descriptor.get(), SkISize::Make(60, 20), {10, 10}, - /*supports_wide_gamut=*/false, allocator); + /*supports_wide_gamut=*/false, capabilities, allocator); EXPECT_EQ(result_3.sk_bitmap->width(), 10); EXPECT_EQ(result_3.sk_bitmap->height(), 10); + + // CPU resize is forced. + auto result_4 = ImageDecoderImpeller::DecompressTexture( + descriptor.get(), SkISize::Make(6, 2), {1000, 1000}, + /*supports_wide_gamut=*/false, capabilities_no_blit, allocator); + EXPECT_EQ(result_4.sk_bitmap->width(), 6); + EXPECT_EQ(result_4.sk_bitmap->height(), 2); #endif // IMPELLER_SUPPORTS_RENDERING }