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"
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"
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(),
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 =
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 =
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
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
A wrapper around data provided by a drawAtlas call.
VertexBuffer CreateBlendVertexBuffer(HostBuffer &host_buffer) const override
bool ShouldUseBlend() const override
Whether the blend shader should be used.
bool ShouldSkip() const override
VertexBuffer CreateSimpleVertexBuffer(HostBuffer &host_buffer) const override
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
int32_t x
AiksPlayground AiksTest
TEST_P(AiksTest, DrawAtlasNoColor)
@ kNone
Does not use the index buffer.
float Scalar
Definition: scalar.h:18
static constexpr RSTransform Make(Point origin, Scalar scale, Radians radians)
Definition: rstransform.h:38