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