| Flutter Impeller |

aiks_dl_atlas_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
5 #include "display_list/dl_sampling_options.h"
6 #include "flutter/impeller/display_list/aiks_unittests.h"
7
8 #include "flutter/display_list/dl_blend_mode.h"
9 #include "flutter/display_list/dl_builder.h"
10 #include "flutter/display_list/dl_color.h"
11 #include "flutter/display_list/dl_paint.h"
12 #include "flutter/testing/testing.h"
13 #include "impeller/core/formats.h"
14 #include "impeller/display_list/dl_atlas_geometry.h"
15 #include "impeller/display_list/dl_image_impeller.h"
16 #include "impeller/entity/contents/content_context.h"
17 #include "impeller/geometry/color.h"
18 #include "impeller/geometry/scalar.h"
19 #include "include/core/SkRefCnt.h"
20
21 namespace impeller {
22 namespace testing {
23
24 using namespace flutter;
25
26 namespace {
27 RSTransform MakeTranslation(Scalar tx, Scalar ty) {
28 return RSTransform::Make({tx, ty}, 1, DlDegrees(0));
29 }
30
31 std::tuple<std::vector<DlRect>, //
32 std::vector<RSTransform>, //
33 sk_sp<DlImageImpeller>>
34 CreateTestData(const AiksTest* test) {
35 // Draws the image as four squares stiched together.
36 auto atlas =
37 DlImageImpeller::Make(test->CreateTextureForFixture("bay_bridge.jpg"));
38 auto size = atlas->impeller_texture()->GetSize();
39 // Divide image into four quadrants.
40 Scalar half_width = size.width / 2;
41 Scalar half_height = size.height / 2;
42 std::vector<DlRect> texture_coordinates = {
43 DlRect::MakeLTRB(0, 0, half_width, half_height),
44 DlRect::MakeLTRB(half_width, 0, size.width, half_height),
45 DlRect::MakeLTRB(0, half_height, half_width, size.height),
46 DlRect::MakeLTRB(half_width, half_height, size.width, size.height)};
47 // Position quadrants adjacent to eachother.
48 std::vector<RSTransform> transforms = {
49 MakeTranslation(0, 0), MakeTranslation(half_width, 0),
50 MakeTranslation(0, half_height),
51 MakeTranslation(half_width, half_height)};
52 return std::make_tuple(texture_coordinates, transforms, atlas);
53 }
54
55 } // namespace
56
57 TEST_P(AiksTest, DrawAtlasNoColor) {
58 DisplayListBuilder builder;
59 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
60
61 builder.Scale(GetContentScale().x, GetContentScale().y);
62 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
63 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kSrcOver,
64 DlImageSampling::kNearestNeighbor, nullptr);
65
66 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
67 }
68
69 TEST_P(AiksTest, DrawAtlasWithColorAdvanced) {
70 DisplayListBuilder builder;
71 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
72
73 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
74 DlColor::kBlue(), DlColor::kYellow()};
75
76 builder.Scale(GetContentScale().x, GetContentScale().y);
77 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
78 colors.data(), /*count=*/4, DlBlendMode::kModulate,
79 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
80
81 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
82 }
83
84 TEST_P(AiksTest, DrawAtlasWithColorSimple) {
85 DisplayListBuilder builder;
86 // Draws the image as four squares stiched together.
87 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
88
89 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
90 DlColor::kBlue(), DlColor::kYellow()};
91
92 builder.Scale(GetContentScale().x, GetContentScale().y);
93 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
94 colors.data(), /*count=*/4, DlBlendMode::kSrcATop,
95 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
96
97 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
98 }
99
100 TEST_P(AiksTest, DrawAtlasWithOpacity) {
101 DisplayListBuilder builder;
102 // Draws the image as four squares stiched together slightly
103 // opaque
104 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
105
106 DlPaint paint;
107 paint.setAlpha(128);
108 builder.Scale(GetContentScale().x, GetContentScale().y);
109 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
110 /*colors=*/nullptr, 4, DlBlendMode::kSrcOver,
111 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr,
112 &paint);
113
114 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
115 }
116
117 TEST_P(AiksTest, DrawAtlasNoColorFullSize) {
118 auto atlas = DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
119 auto size = atlas->impeller_texture()->GetSize();
120 std::vector<DlRect> texture_coordinates = {
121 DlRect::MakeLTRB(0, 0, size.width, size.height)};
122 std::vector<RSTransform> transforms = {MakeTranslation(0, 0)};
123
124 DisplayListBuilder builder;
125 builder.Scale(GetContentScale().x, GetContentScale().y);
126 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
127 /*colors=*/nullptr, /*count=*/1, DlBlendMode::kSrcOver,
128 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
129
130 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
131 }
132
133 // Regression test for https://github.com/flutter/flutter/issues/127374.
134 TEST_P(AiksTest, DrawAtlasAdvancedAndTransform) {
135 DisplayListBuilder builder;
136 // Draws the image as four squares stiched together.
137 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
138
139 builder.Scale(0.25, 0.25);
140 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
141 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kModulate,
142 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
143
144 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
145 }
146
147 // Regression test for https://github.com/flutter/flutter/issues/127374.
148 TEST_P(AiksTest, DrawAtlasWithColorAdvancedAndTransform) {
149 DisplayListBuilder builder;
150 // Draws the image as four squares stiched together.
151 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
152 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
153 DlColor::kBlue(), DlColor::kYellow()};
154
155 builder.Scale(0.25, 0.25);
156 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
157 colors.data(), /*count=*/4, DlBlendMode::kModulate,
158 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
159
160 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
161 }
162
163 TEST_P(AiksTest, DrawAtlasPlusWideGamut) {
164 DisplayListBuilder builder;
165 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
166 PixelFormat::kB10G10R10A10XR);
167
168 // Draws the image as four squares stiched together.
169 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
170 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
171 DlColor::kBlue(), DlColor::kYellow()};
172
173 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
174 colors.data(), /*count=*/4, DlBlendMode::kPlus,
175 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
176
177 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
178 }
179
180 TEST_P(AiksTest, DlAtlasGeometryNoBlend) {
181 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
182
183 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
184 texture_coordinates.data(), nullptr, transforms.size(),
185 BlendMode::kSourceOver, {}, std::nullopt);
186
187 EXPECT_FALSE(geom.ShouldUseBlend());
188 EXPECT_FALSE(geom.ShouldSkip());
189
190 ContentContext context(GetContext(), nullptr);
191 auto vertex_buffer =
192 geom.CreateSimpleVertexBuffer(context.GetTransientsBuffer());
193
194 EXPECT_EQ(vertex_buffer.index_type, IndexType::kNone);
195 EXPECT_EQ(vertex_buffer.vertex_count, texture_coordinates.size() * 6);
196 }
197
198 TEST_P(AiksTest, DlAtlasGeometryBlend) {
199 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
200
201 std::vector<DlColor> colors;
202 colors.reserve(texture_coordinates.size());
203 for (auto i = 0u; i < texture_coordinates.size(); i++) {
204 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
205 }
206 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
207 texture_coordinates.data(), colors.data(),
208 transforms.size(), BlendMode::kSourceOver, {},
209 std::nullopt);
210
211 EXPECT_TRUE(geom.ShouldUseBlend());
212 EXPECT_FALSE(geom.ShouldSkip());
213
214 ContentContext context(GetContext(), nullptr);
215 auto vertex_buffer =
216 geom.CreateBlendVertexBuffer(context.GetTransientsBuffer());
217
218 EXPECT_EQ(vertex_buffer.index_type, IndexType::kNone);
219 EXPECT_EQ(vertex_buffer.vertex_count, texture_coordinates.size() * 6);
220 }
221
222 TEST_P(AiksTest, DlAtlasGeometryColorButNoBlend) {
223 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
224
225 std::vector<DlColor> colors;
226 colors.reserve(texture_coordinates.size());
227 for (auto i = 0u; i < texture_coordinates.size(); i++) {
228 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
229 }
230 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
231 texture_coordinates.data(), colors.data(),
232 transforms.size(), BlendMode::kSource, {}, std::nullopt);
233
234 // Src blend mode means that colors would be ignored, even if provided.
235 EXPECT_FALSE(geom.ShouldUseBlend());
236 EXPECT_FALSE(geom.ShouldSkip());
237 }
238
239 TEST_P(AiksTest, DlAtlasGeometrySkip) {
240 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
241
242 std::vector<DlColor> colors;
243 colors.reserve(texture_coordinates.size());
244 for (auto i = 0u; i < texture_coordinates.size(); i++) {
245 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
246 }
247 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
248 texture_coordinates.data(), colors.data(),
249 transforms.size(), BlendMode::kClear, {}, std::nullopt);
250 EXPECT_TRUE(geom.ShouldSkip());
251 }
252
253 } // namespace testing
254 } // namespace impeller
aiks_unittests.h
impeller::AiksPlayground
Definition: aiks_playground.h:16
impeller::ContentContext
Definition: content_context.h:371
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:866
impeller::DlAtlasGeometry
A wrapper around data provided by a drawAtlas call.
Definition: dl_atlas_geometry.h:17
impeller::DlAtlasGeometry::CreateBlendVertexBuffer
VertexBuffer CreateBlendVertexBuffer(HostBuffer &host_buffer) const override
Definition: dl_atlas_geometry.cc:103
impeller::DlAtlasGeometry::ShouldUseBlend
bool ShouldUseBlend() const override
Whether the blend shader should be used.
Definition: dl_atlas_geometry.cc:37
impeller::DlAtlasGeometry::ShouldSkip
bool ShouldSkip() const override
Definition: dl_atlas_geometry.cc:41
impeller::DlAtlasGeometry::CreateSimpleVertexBuffer
VertexBuffer CreateSimpleVertexBuffer(HostBuffer &host_buffer) const override
Definition: dl_atlas_geometry.cc:70
impeller::DlImageImpeller::Make
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
Definition: dl_image_impeller.cc:23
color.h
content_context.h
formats.h
dl_atlas_geometry.h
x
int32_t x
Definition: dl_golden_unittests.cc:443
dl_image_impeller.h
flutter
Definition: dl_golden_blur_unittests.cc:16
impeller::testing::AiksTest
AiksPlayground AiksTest
Definition: aiks_unittests.h:17
impeller::testing::TEST_P
TEST_P(AiksTest, DrawAtlasNoColor)
Definition: aiks_dl_atlas_unittests.cc:57
impeller
Definition: allocation.cc:12
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::PixelFormat::kB10G10R10A10XR
@ kB10G10R10A10XR
impeller::BlendMode::kSource
@ kSource
impeller::BlendMode::kClear
@ kClear
impeller::BlendMode::kSourceOver
@ kSourceOver
scalar.h
impeller::RSTransform::Make
static constexpr RSTransform Make(Point origin, Scalar scale, Radians radians)
Definition: rstransform.h:38