Skip to content

Commit

Permalink
[Impeller] force software resize usage for GLES backend. (#56511)
Browse files Browse the repository at this point in the history
Should fix some of the wonderous bugs by avoiding the usage of gl blitframebuffer altogether.

Fixes flutter/flutter#158391
  • Loading branch information
jonahwilliams authored Nov 14, 2024
1 parent f192fdb commit 96a932d
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 15 deletions.
3 changes: 3 additions & 0 deletions impeller/renderer/backend/gles/capabilities_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
7 changes: 5 additions & 2 deletions lib/ui/painting/image_decoder_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ DecompressResult ImageDecoderImpeller::DecompressTexture(
SkISize target_size,
impeller::ISize max_texture_size,
bool supports_wide_gamut,
const std::shared_ptr<const impeller::Capabilities>& capabilities,
const std::shared_ptr<impeller::Allocator>& allocator) {
TRACE_EVENT0("impeller", __FUNCTION__);
if (!descriptor) {
Expand Down Expand Up @@ -238,7 +239,8 @@ DecompressResult ImageDecoderImpeller::DecompressTexture(
: std::optional<SkImageInfo>(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.
Expand Down Expand Up @@ -536,7 +538,8 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> 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;
Expand Down
2 changes: 2 additions & 0 deletions lib/ui/painting/image_decoder_impeller.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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<const impeller::Capabilities>& capabilities,
const std::shared_ptr<impeller::Allocator>& allocator);

/// @brief Create a device private texture from the provided host buffer.
Expand Down
24 changes: 19 additions & 5 deletions lib/ui/painting/image_decoder_no_gl_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
// found in the LICENSE file.

#include "flutter/lib/ui/painting/image_decoder_no_gl_unittests.h"
#include <memory>

#include "flutter/fml/endianness.h"
#include "impeller/renderer/capabilities.h"
#include "include/core/SkColorType.h"

namespace flutter {
Expand Down Expand Up @@ -80,6 +82,10 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutDisplayP3) {
#endif
auto data = flutter::testing::OpenFixtureAsSkData("DisplayP3Logo.png");
auto image = SkImages::DeferredFromEncodedData(data);
std::shared_ptr<impeller::Capabilities> capabilities =
impeller::CapabilitiesBuilder()
.SetSupportsTextureToTextureBlits(true)
.Build();
ASSERT_TRUE(image != nullptr);
ASSERT_EQ(SkISize::Make(100, 100), image->dimensions());

Expand All @@ -100,7 +106,7 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutDisplayP3) {
std::optional<DecompressResult> 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());
Expand All @@ -124,7 +130,7 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutDisplayP3) {
std::optional<DecompressResult> 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);
Expand All @@ -137,6 +143,10 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutIndexedPng) {
#endif
auto data = flutter::testing::OpenFixtureAsSkData("WideGamutIndexed.png");
auto image = SkImages::DeferredFromEncodedData(data);
std::shared_ptr<impeller::Capabilities> capabilities =
impeller::CapabilitiesBuilder()
.SetSupportsTextureToTextureBlits(true)
.Build();
ASSERT_TRUE(image != nullptr);
ASSERT_EQ(SkISize::Make(100, 100), image->dimensions());

Expand All @@ -157,7 +167,7 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutIndexedPng) {
std::optional<DecompressResult> 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());

Expand All @@ -180,7 +190,7 @@ TEST(ImageDecoderNoGLTest, ImpellerWideGamutIndexedPng) {
std::optional<DecompressResult> 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);
Expand All @@ -193,6 +203,10 @@ TEST(ImageDecoderNoGLTest, ImepllerUnmultipliedAlphaPng) {
#endif
auto data = flutter::testing::OpenFixtureAsSkData("unmultiplied_alpha.png");
auto image = SkImages::DeferredFromEncodedData(data);
std::shared_ptr<impeller::Capabilities> capabilities =
impeller::CapabilitiesBuilder()
.SetSupportsTextureToTextureBlits(true)
.Build();
ASSERT_TRUE(image != nullptr);
ASSERT_EQ(SkISize::Make(11, 11), image->dimensions());

Expand All @@ -210,7 +224,7 @@ TEST(ImageDecoderNoGLTest, ImepllerUnmultipliedAlphaPng) {
std::optional<DecompressResult> 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();
Expand Down
47 changes: 39 additions & 8 deletions lib/ui/painting/image_decoder_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -441,12 +441,16 @@ TEST_F(ImageDecoderFixtureTest, ImpellerNullColorspace) {
std::move(data), image->imageInfo(), 10 * 4);

#if IMPELLER_SUPPORTS_RENDERING
std::shared_ptr<impeller::Capabilities> capabilities =
impeller::CapabilitiesBuilder()
.SetSupportsTextureToTextureBlits(true)
.Build();
std::shared_ptr<impeller::Allocator> allocator =
std::make_shared<impeller::TestImpellerAllocator>();
std::optional<DecompressResult> 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);
Expand All @@ -468,12 +472,16 @@ TEST_F(ImageDecoderFixtureTest, ImpellerPixelConversion32F) {
std::move(data), image->imageInfo(), 10 * 16);

#if IMPELLER_SUPPORTS_RENDERING
std::shared_ptr<impeller::Capabilities> capabilities =
impeller::CapabilitiesBuilder()
.SetSupportsTextureToTextureBlits(true)
.Build();
std::shared_ptr<impeller::Allocator> allocator =
std::make_shared<impeller::TestImpellerAllocator>();
std::optional<DecompressResult> 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);
Expand All @@ -496,12 +504,16 @@ TEST_F(ImageDecoderFixtureTest, ImpellerWideGamutDisplayP3Opaque) {
std::move(generator));

#if IMPELLER_SUPPORTS_RENDERING
std::shared_ptr<impeller::Capabilities> capabilities =
impeller::CapabilitiesBuilder()
.SetSupportsTextureToTextureBlits(true)
.Build();
std::shared_ptr<impeller::Allocator> allocator =
std::make_shared<impeller::TestImpellerAllocator>();
std::optional<DecompressResult> 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);
Expand All @@ -526,7 +538,7 @@ TEST_F(ImageDecoderFixtureTest, ImpellerWideGamutDisplayP3Opaque) {
std::optional<DecompressResult> 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);
Expand All @@ -548,12 +560,16 @@ TEST_F(ImageDecoderFixtureTest, ImpellerNonWideGamut) {
std::move(generator));

#if IMPELLER_SUPPORTS_RENDERING
std::shared_ptr<impeller::Capabilities> capabilities =
impeller::CapabilitiesBuilder()
.SetSupportsTextureToTextureBlits(true)
.Build();
std::shared_ptr<impeller::Allocator> allocator =
std::make_shared<impeller::TestImpellerAllocator>();
std::optional<DecompressResult> 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);
Expand Down Expand Up @@ -802,31 +818,46 @@ TEST(ImageDecoderTest, VerifySimpleDecoding) {
EXPECT_EQ(compressed_image->alphaType(), kOpaque_SkAlphaType);

#if IMPELLER_SUPPORTS_RENDERING
std::shared_ptr<impeller::Capabilities> capabilities =
impeller::CapabilitiesBuilder()
.SetSupportsTextureToTextureBlits(true)
.Build();
std::shared_ptr<impeller::Capabilities> 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<impeller::Allocator> allocator =
std::make_shared<impeller::TestImpellerAllocator>();
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);

// Bitmap sizes reflect the scaled size if the source size is larger than
// 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);

// If the destination size is larger than the max texture size the image
// 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
}

Expand Down

0 comments on commit 96a932d

Please sign in to comment.