Flutter Engine
 
Loading...
Searching...
No Matches
image_decoder_no_gl_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6#include <memory>
7
10#include "include/core/SkColorType.h"
11
12namespace flutter {
13namespace testing {
14
15// Tests are disabled for fuchsia.
16#if defined(OS_FUCHSIA)
17#pragma GCC diagnostic ignored "-Wunreachable-code"
18#endif
19
20namespace {
21
22bool IsPngWithPLTE(const uint8_t* bytes, size_t size) {
23 constexpr std::string_view kPngMagic = "\x89PNG\x0d\x0a\x1a\x0a";
24 constexpr std::string_view kPngPlte = "PLTE";
25 constexpr uint32_t kLengthBytes = 4;
26 constexpr uint32_t kTypeBytes = 4;
27 constexpr uint32_t kCrcBytes = 4;
28
29 if (size < kPngMagic.size()) {
30 return false;
31 }
32
33 if (memcmp(bytes, kPngMagic.data(), kPngMagic.size()) != 0) {
34 return false;
35 }
36
37 const uint8_t* end = bytes + size;
38 const uint8_t* loc = bytes + kPngMagic.size();
39 while (loc + kLengthBytes + kTypeBytes <= end) {
40 uint32_t chunk_length =
41 fml::BigEndianToArch(*reinterpret_cast<const uint32_t*>(loc));
42
43 if (memcmp(loc + kLengthBytes, kPngPlte.data(), kPngPlte.size()) == 0) {
44 return true;
45 }
46
47 loc += kLengthBytes + kTypeBytes + chunk_length + kCrcBytes;
48 }
49
50 return false;
51}
52
53} // namespace
54
55float HalfToFloat(uint16_t half) {
56 switch (half) {
57 case 0x7c00:
58 return std::numeric_limits<float>::infinity();
59 case 0xfc00:
60 return -std::numeric_limits<float>::infinity();
61 }
62 bool negative = half >> 15;
63 uint16_t exponent = (half >> 10) & 0x1f;
64 uint16_t fraction = half & 0x3ff;
65 float fExponent = exponent - 15.0f;
66 float fFraction = static_cast<float>(fraction) / 1024.f;
67 float pow_value = powf(2.0f, fExponent);
68 return (negative ? -1.f : 1.f) * pow_value * (1.0f + fFraction);
69}
70
71float DecodeBGR10(uint32_t x) {
72 const float max = 1.25098f;
73 const float min = -0.752941f;
74 const float intercept = min;
75 const float slope = (max - min) / 1024.0f;
76 return (x * slope) + intercept;
77}
78
79TEST(ImageDecoderNoGLTest, ImpellerWideGamutDisplayP3) {
80#if defined(OS_FUCHSIA)
81 GTEST_SKIP() << "Fuchsia can't load the test fixtures.";
82#endif
83 auto data = flutter::testing::OpenFixtureAsSkData("DisplayP3Logo.png");
84 auto image = SkImages::DeferredFromEncodedData(data);
85 std::shared_ptr<impeller::Capabilities> capabilities =
88 .Build();
89 ASSERT_TRUE(image != nullptr);
90 ASSERT_EQ(SkISize::Make(100, 100), image->dimensions());
91
93 std::shared_ptr<ImageGenerator> generator =
95 ASSERT_TRUE(generator);
96
97 auto descriptor = fml::MakeRefCounted<ImageDescriptor>(std::move(data),
98 std::move(generator));
99
100 ASSERT_FALSE(
101 IsPngWithPLTE(descriptor->data()->bytes(), descriptor->data()->size()));
102
103#if IMPELLER_SUPPORTS_RENDERING
104 std::shared_ptr<impeller::Allocator> allocator =
105 std::make_shared<impeller::TestImpellerAllocator>();
106 std::optional<DecompressResult> wide_result =
108 descriptor.get(), SkISize::Make(100, 100), {100, 100},
109 /*supports_wide_gamut=*/true, capabilities, allocator);
110 ASSERT_TRUE(wide_result.has_value());
111 ASSERT_EQ(wide_result->image_info.colorType(), kRGBA_F16_SkColorType);
112 ASSERT_TRUE(wide_result->image_info.colorSpace()->isSRGB());
113
114 const SkPixmap& wide_pixmap = wide_result->sk_bitmap->pixmap();
115 const uint16_t* half_ptr = static_cast<const uint16_t*>(wide_pixmap.addr());
116 bool found_deep_red = false;
117 for (int i = 0; i < wide_pixmap.width() * wide_pixmap.height(); ++i) {
118 float red = HalfToFloat(*half_ptr++);
119 float green = HalfToFloat(*half_ptr++);
120 float blue = HalfToFloat(*half_ptr++);
121 half_ptr++; // alpha
122 if (fabsf(red - 1.0931f) < 0.01f && fabsf(green - -0.2268f) < 0.01f &&
123 fabsf(blue - -0.1501f) < 0.01f) {
124 found_deep_red = true;
125 break;
126 }
127 }
128
129 ASSERT_TRUE(found_deep_red);
130 std::optional<DecompressResult> narrow_result =
132 descriptor.get(), SkISize::Make(100, 100), {100, 100},
133 /*supports_wide_gamut=*/false, capabilities, allocator);
134
135 ASSERT_TRUE(narrow_result.has_value());
136 ASSERT_EQ(narrow_result->image_info.colorType(), kRGBA_8888_SkColorType);
137#endif // IMPELLER_SUPPORTS_RENDERING
138}
139
140TEST(ImageDecoderNoGLTest, ImpellerWideGamutIndexedPng) {
141#if defined(OS_FUCHSIA)
142 GTEST_SKIP() << "Fuchsia can't load the test fixtures.";
143#endif
144 auto data = flutter::testing::OpenFixtureAsSkData("WideGamutIndexed.png");
145 auto image = SkImages::DeferredFromEncodedData(data);
146 std::shared_ptr<impeller::Capabilities> capabilities =
149 .Build();
150 ASSERT_TRUE(image != nullptr);
151 ASSERT_EQ(SkISize::Make(100, 100), image->dimensions());
152
153 ImageGeneratorRegistry registry;
154 std::shared_ptr<ImageGenerator> generator =
156 ASSERT_TRUE(generator);
157
158 auto descriptor = fml::MakeRefCounted<ImageDescriptor>(std::move(data),
159 std::move(generator));
160
161 ASSERT_TRUE(
162 IsPngWithPLTE(descriptor->data()->bytes(), descriptor->data()->size()));
163
164#if IMPELLER_SUPPORTS_RENDERING
165 std::shared_ptr<impeller::Allocator> allocator =
166 std::make_shared<impeller::TestImpellerAllocator>();
167 std::optional<DecompressResult> wide_result =
169 descriptor.get(), SkISize::Make(100, 100), {100, 100},
170 /*supports_wide_gamut=*/true, capabilities, allocator);
171 ASSERT_EQ(wide_result->image_info.colorType(), kBGR_101010x_XR_SkColorType);
172 ASSERT_TRUE(wide_result->image_info.colorSpace()->isSRGB());
173
174 const SkPixmap& wide_pixmap = wide_result->sk_bitmap->pixmap();
175 const uint32_t* pixel_ptr = static_cast<const uint32_t*>(wide_pixmap.addr());
176 bool found_deep_red = false;
177 for (int i = 0; i < wide_pixmap.width() * wide_pixmap.height(); ++i) {
178 uint32_t pixel = *pixel_ptr++;
179 float blue = DecodeBGR10((pixel >> 0) & 0x3ff);
180 float green = DecodeBGR10((pixel >> 10) & 0x3ff);
181 float red = DecodeBGR10((pixel >> 20) & 0x3ff);
182 if (fabsf(red - 1.0931f) < 0.01f && fabsf(green - -0.2268f) < 0.01f &&
183 fabsf(blue - -0.1501f) < 0.01f) {
184 found_deep_red = true;
185 break;
186 }
187 }
188
189 ASSERT_TRUE(found_deep_red);
190 std::optional<DecompressResult> narrow_result =
192 descriptor.get(), SkISize::Make(100, 100), {100, 100},
193 /*supports_wide_gamut=*/false, capabilities, allocator);
194
195 ASSERT_TRUE(narrow_result.has_value());
196 ASSERT_EQ(narrow_result->image_info.colorType(), kRGBA_8888_SkColorType);
197#endif // IMPELLER_SUPPORTS_RENDERING
198}
199
200TEST(ImageDecoderNoGLTest, ImpellerUnmultipliedAlphaPng) {
201#if defined(OS_FUCHSIA)
202 GTEST_SKIP() << "Fuchsia can't load the test fixtures.";
203#endif
204 auto data = flutter::testing::OpenFixtureAsSkData("unmultiplied_alpha.png");
205 auto image = SkImages::DeferredFromEncodedData(data);
206 std::shared_ptr<impeller::Capabilities> capabilities =
209 .Build();
210 ASSERT_TRUE(image != nullptr);
211 ASSERT_EQ(SkISize::Make(11, 11), image->dimensions());
212
213 ImageGeneratorRegistry registry;
214 std::shared_ptr<ImageGenerator> generator =
216 ASSERT_TRUE(generator);
217
218 auto descriptor = fml::MakeRefCounted<ImageDescriptor>(std::move(data),
219 std::move(generator));
220
221#if IMPELLER_SUPPORTS_RENDERING
222 std::shared_ptr<impeller::Allocator> allocator =
223 std::make_shared<impeller::TestImpellerAllocator>();
224 std::optional<DecompressResult> result =
226 descriptor.get(), SkISize::Make(11, 11), {11, 11},
227 /*supports_wide_gamut=*/true, capabilities, allocator);
228 ASSERT_EQ(result->image_info.colorType(), kRGBA_8888_SkColorType);
229
230 const SkPixmap& pixmap = result->sk_bitmap->pixmap();
231 const uint32_t* pixel_ptr = static_cast<const uint32_t*>(pixmap.addr());
232 // Test the upper left pixel is premultiplied and not solid red.
233 ASSERT_EQ(*pixel_ptr, (uint32_t)0x1000001);
234 // Test a pixel in the green box is still green.
235 ASSERT_EQ(*(pixel_ptr + 11 * 4 + 4), (uint32_t)0xFF00FF00);
236
237#endif // IMPELLER_SUPPORTS_RENDERING
238}
239
240} // namespace testing
241} // namespace flutter
static DecompressResult DecompressTexture(ImageDescriptor *descriptor, 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)
Keeps a priority-ordered registry of image generator builders to be used when decoding images....
std::shared_ptr< ImageGenerator > CreateCompatibleGenerator(const sk_sp< SkData > &buffer)
Walks the list of image generator builders in descending priority order until a compatible ImageGener...
CapabilitiesBuilder & SetSupportsTextureToTextureBlits(bool value)
std::unique_ptr< Capabilities > Build()
int32_t x
FlutterVulkanImage * image
sk_sp< SkData > OpenFixtureAsSkData(const std::string &fixture_name)
Opens a fixture of the given file name and returns a Skia SkData holding its contents.
Definition testing.cc:63
TEST(NativeAssetsManagerTest, NoAvailableAssets)
float HalfToFloat(uint16_t half)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
constexpr T BigEndianToArch(T n)
Convert a known big endian value to match the endianness of the current architecture....
Definition endianness.h:59
const size_t end