Flutter Impeller
aiks_dl_vertices_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 "display_list/dl_tile_mode.h"
7 #include "display_list/dl_vertices.h"
9 
10 #include "flutter/display_list/dl_blend_mode.h"
11 #include "flutter/display_list/dl_builder.h"
12 #include "flutter/display_list/dl_color.h"
13 #include "flutter/display_list/dl_paint.h"
14 #include "flutter/testing/testing.h"
16 
17 namespace impeller {
18 namespace testing {
19 
20 using namespace flutter;
21 
22 namespace {
23 std::shared_ptr<DlVertices> MakeVertices(
24  DlVertexMode mode,
25  std::vector<SkPoint> vertices,
26  std::vector<uint16_t> indices,
27  std::vector<SkPoint> texture_coordinates,
28  std::vector<DlColor> colors) {
29  DlVertices::Builder::Flags flags(
30  {{texture_coordinates.size() > 0, colors.size() > 0}});
31  DlVertices::Builder builder(mode, vertices.size(), flags, indices.size());
32  if (colors.size() > 0) {
33  builder.store_colors(colors.data());
34  }
35  if (texture_coordinates.size() > 0) {
36  builder.store_texture_coordinates(texture_coordinates.data());
37  }
38  if (indices.size() > 0) {
39  builder.store_indices(indices.data());
40  }
41  builder.store_vertices(vertices.data());
42  return builder.build();
43 }
44 }; // namespace
45 
46 // Regression test for https://github.com/flutter/flutter/issues/135441 .
47 TEST_P(AiksTest, VerticesGeometryUVPositionData) {
48  DisplayListBuilder builder;
49  DlPaint paint;
50  auto image =
51  DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
52  auto size = image->impeller_texture()->GetSize();
53 
54  paint.setColorSource(std::make_shared<DlImageColorSource>(
55  image, DlTileMode::kClamp, DlTileMode::kClamp));
56 
57  std::vector<SkPoint> vertex_coordinates = {SkPoint::Make(0, 0),
58  SkPoint::Make(size.width, 0),
59  SkPoint::Make(0, size.height)};
60  auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
61  {0, 1, 2}, {}, {});
62 
63  builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
64  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
65 }
66 
67 // Regression test for https://github.com/flutter/flutter/issues/135441 .
68 TEST_P(AiksTest, VerticesGeometryUVPositionDataWithTranslate) {
69  DisplayListBuilder builder;
70  DlPaint paint;
71  auto image =
72  DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
73  auto size = image->impeller_texture()->GetSize();
74 
75  SkMatrix matrix;
76  matrix.setTranslateX(100);
77  matrix.setTranslateY(100);
78  paint.setColorSource(std::make_shared<DlImageColorSource>(
79  image, DlTileMode::kClamp, DlTileMode::kClamp, DlImageSampling::kLinear,
80  &matrix));
81 
82  std::vector<SkPoint> positions = {SkPoint::Make(0, 0),
83  SkPoint::Make(size.width, 0),
84  SkPoint::Make(0, size.height)};
85  auto vertices =
86  MakeVertices(DlVertexMode::kTriangleStrip, positions, {0, 1, 2}, {}, {});
87 
88  builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
89  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
90 }
91 
92 // Regression test for https://github.com/flutter/flutter/issues/145707
93 TEST_P(AiksTest, VerticesGeometryColorUVPositionData) {
94  DisplayListBuilder builder;
95  DlPaint paint;
96  auto image =
97  DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
98  auto size = image->impeller_texture()->GetSize();
99 
100  paint.setColorSource(std::make_shared<DlImageColorSource>(
101  image, DlTileMode::kClamp, DlTileMode::kClamp));
102 
103  std::vector<SkPoint> positions = {
104  SkPoint::Make(0, 0), SkPoint::Make(size.width, 0),
105  SkPoint::Make(0, size.height), SkPoint::Make(size.width, 0),
106  SkPoint::Make(0, 0), SkPoint::Make(size.width, size.height),
107  };
108  std::vector<DlColor> colors = {
109  DlColor::kRed().withAlpha(128), DlColor::kBlue().withAlpha(128),
110  DlColor::kGreen().withAlpha(128), DlColor::kRed().withAlpha(128),
111  DlColor::kBlue().withAlpha(128), DlColor::kGreen().withAlpha(128),
112  };
113 
114  auto vertices =
115  MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
116 
117  builder.DrawVertices(vertices, DlBlendMode::kDstOver, paint);
118  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
119 }
120 
121 TEST_P(AiksTest, VerticesGeometryColorUVPositionDataAdvancedBlend) {
122  DisplayListBuilder builder;
123  DlPaint paint;
124  auto image =
125  DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
126  auto size = image->impeller_texture()->GetSize();
127 
128  paint.setColorSource(std::make_shared<DlImageColorSource>(
129  image, DlTileMode::kClamp, DlTileMode::kClamp));
130 
131  std::vector<SkPoint> positions = {
132  SkPoint::Make(0, 0), SkPoint::Make(size.width, 0),
133  SkPoint::Make(0, size.height), SkPoint::Make(size.width, 0),
134  SkPoint::Make(0, 0), SkPoint::Make(size.width, size.height),
135  };
136  std::vector<DlColor> colors = {
137  DlColor::kRed().modulateOpacity(0.5),
138  DlColor::kBlue().modulateOpacity(0.5),
139  DlColor::kGreen().modulateOpacity(0.5),
140  DlColor::kRed().modulateOpacity(0.5),
141  DlColor::kBlue().modulateOpacity(0.5),
142  DlColor::kGreen().modulateOpacity(0.5),
143  };
144 
145  auto vertices =
146  MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
147 
148  builder.DrawVertices(vertices, DlBlendMode::kColorBurn, paint);
149  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
150 }
151 
152 // Draw a hexagon using triangle fan
153 TEST_P(AiksTest, CanConvertTriangleFanToTriangles) {
154  constexpr Scalar hexagon_radius = 125;
155  auto hex_start = Point(200.0, -hexagon_radius + 200.0);
156  auto center_to_flat = 1.73 / 2 * hexagon_radius;
157 
158  // clang-format off
159  std::vector<SkPoint> vertices = {
160  SkPoint::Make(hex_start.x, hex_start.y),
161  SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 0.5 * hexagon_radius),
162  SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
163  SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
164  SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
165  SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
166  SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
167  SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
168  SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 0.5 * hexagon_radius)
169  };
170  // clang-format on
171  auto paint = flutter::DlPaint(flutter::DlColor::kDarkGrey());
172  auto dl_vertices = flutter::DlVertices::Make(
173  flutter::DlVertexMode::kTriangleFan, vertices.size(), vertices.data(),
174  nullptr, nullptr);
175  flutter::DisplayListBuilder builder;
176  builder.DrawVertices(dl_vertices, flutter::DlBlendMode::kSrcOver, paint);
177  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
178 }
179 
180 TEST_P(AiksTest, DrawVerticesSolidColorTrianglesWithoutIndices) {
181  // Use negative coordinates and then scale the transform by -1, -1 to make
182  // sure coverage is taking the transform into account.
183  std::vector<SkPoint> positions = {SkPoint::Make(-100, -300),
184  SkPoint::Make(-200, -100),
185  SkPoint::Make(-300, -300)};
186  std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
187  flutter::DlColor::kGreen(),
188  flutter::DlColor::kWhite()};
189 
190  auto vertices = flutter::DlVertices::Make(
191  flutter::DlVertexMode::kTriangles, 3, positions.data(),
192  /*texture_coordinates=*/nullptr, colors.data());
193 
194  flutter::DisplayListBuilder builder;
195  flutter::DlPaint paint;
196 
197  paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
198  builder.Scale(-1, -1);
199  builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
200 
201  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
202 }
203 
204 TEST_P(AiksTest, DrawVerticesLinearGradientWithoutIndices) {
205  std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
206  SkPoint::Make(200, 100),
207  SkPoint::Make(300, 300)};
208 
209  auto vertices = flutter::DlVertices::Make(
210  flutter::DlVertexMode::kTriangles, 3, positions.data(),
211  /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
212 
213  std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
214  flutter::DlColor::kRed()};
215  const float stops[2] = {0.0, 1.0};
216 
217  auto linear = flutter::DlColorSource::MakeLinear(
218  {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
219  flutter::DlTileMode::kRepeat);
220 
221  flutter::DisplayListBuilder builder;
222  flutter::DlPaint paint;
223 
224  paint.setColorSource(linear);
225  builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
226 
227  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
228 }
229 
230 TEST_P(AiksTest, DrawVerticesLinearGradientWithTextureCoordinates) {
231  std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
232  SkPoint::Make(200, 100),
233  SkPoint::Make(300, 300)};
234  std::vector<SkPoint> texture_coordinates = {SkPoint::Make(300, 100),
235  SkPoint::Make(100, 200),
236  SkPoint::Make(300, 300)};
237 
238  auto vertices = flutter::DlVertices::Make(
239  flutter::DlVertexMode::kTriangles, 3, positions.data(),
240  texture_coordinates.data(), /*colors=*/nullptr);
241 
242  std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
243  flutter::DlColor::kRed()};
244  const float stops[2] = {0.0, 1.0};
245 
246  auto linear = flutter::DlColorSource::MakeLinear(
247  {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
248  flutter::DlTileMode::kRepeat);
249 
250  flutter::DisplayListBuilder builder;
251  flutter::DlPaint paint;
252 
253  paint.setColorSource(linear);
254  builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
255 
256  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
257 }
258 
259 TEST_P(AiksTest, DrawVerticesImageSourceWithTextureCoordinates) {
260  auto texture = CreateTextureForFixture("embarcadero.jpg");
261  auto dl_image = DlImageImpeller::Make(texture);
262  std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
263  SkPoint::Make(200, 100),
264  SkPoint::Make(300, 300)};
265  std::vector<SkPoint> texture_coordinates = {
266  SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
267 
268  auto vertices = flutter::DlVertices::Make(
269  flutter::DlVertexMode::kTriangles, 3, positions.data(),
270  texture_coordinates.data(), /*colors=*/nullptr);
271 
272  flutter::DisplayListBuilder builder;
273  flutter::DlPaint paint;
274 
275  auto image_source = flutter::DlImageColorSource(
276  dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
277 
278  paint.setColorSource(&image_source);
279  builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
280 
281  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
282 }
283 
285  DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending) {
286  auto texture = CreateTextureForFixture("embarcadero.jpg");
287  auto dl_image = DlImageImpeller::Make(texture);
288  std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
289  SkPoint::Make(200, 100),
290  SkPoint::Make(300, 300)};
291  std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
292  flutter::DlColor::kGreen(),
293  flutter::DlColor::kWhite()};
294  std::vector<SkPoint> texture_coordinates = {
295  SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
296 
297  auto vertices = flutter::DlVertices::Make(
298  flutter::DlVertexMode::kTriangles, 3, positions.data(),
299  texture_coordinates.data(), colors.data());
300 
301  flutter::DisplayListBuilder builder;
302  flutter::DlPaint paint;
303 
304  auto image_source = flutter::DlImageColorSource(
305  dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
306 
307  paint.setColorSource(&image_source);
308  builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
309 
310  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
311 }
312 
313 TEST_P(AiksTest, DrawVerticesSolidColorTrianglesWithIndices) {
314  std::vector<SkPoint> positions = {
315  SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
316  SkPoint::Make(200, 500)};
317  std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
318 
319  auto vertices = flutter::DlVertices::Make(
320  flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
321  /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
322  indices.data());
323 
324  flutter::DisplayListBuilder builder;
325  flutter::DlPaint paint;
326 
327  paint.setColor(flutter::DlColor::kRed());
328  builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
329 
330  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
331 }
332 
333 TEST_P(AiksTest, DrawVerticesPremultipliesColors) {
334  std::vector<SkPoint> positions = {
335  SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
336  SkPoint::Make(200, 500)};
337  auto color = flutter::DlColor::kBlue().withAlpha(0x99);
338  std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
339  std::vector<flutter::DlColor> colors = {color, color, color, color};
340 
341  auto vertices = flutter::DlVertices::Make(
342  flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
343  /*texture_coordinates=*/nullptr, colors.data(), indices.size(),
344  indices.data());
345 
346  flutter::DisplayListBuilder builder;
347  flutter::DlPaint paint;
348  paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
349  paint.setColor(flutter::DlColor::kRed());
350 
351  builder.DrawRect(SkRect::MakeLTRB(0, 0, 400, 400), paint);
352  builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
353 
354  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
355 }
356 
357 // All four vertices should form a solid red rectangle with no gaps.
358 // The blur rectangle drawn under them should not be visible.
359 TEST_P(AiksTest, DrawVerticesTextureCoordinatesWithFragmentShader) {
360  std::vector<SkPoint> positions_lt = {
361  SkPoint::Make(0, 0), //
362  SkPoint::Make(50, 0), //
363  SkPoint::Make(0, 50), //
364  SkPoint::Make(50, 50), //
365  };
366 
367  auto vertices_lt = flutter::DlVertices::Make(
368  flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
369  positions_lt.data(),
370  /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
371  /*index_count=*/0,
372  /*indices=*/nullptr);
373 
374  std::vector<SkPoint> positions_rt = {
375  SkPoint::Make(50, 0), //
376  SkPoint::Make(100, 0), //
377  SkPoint::Make(50, 50), //
378  SkPoint::Make(100, 50), //
379  };
380 
381  auto vertices_rt = flutter::DlVertices::Make(
382  flutter::DlVertexMode::kTriangleStrip, positions_rt.size(),
383  positions_rt.data(),
384  /*texture_coordinates=*/positions_rt.data(), /*colors=*/nullptr,
385  /*index_count=*/0,
386  /*indices=*/nullptr);
387 
388  std::vector<SkPoint> positions_lb = {
389  SkPoint::Make(0, 50), //
390  SkPoint::Make(50, 50), //
391  SkPoint::Make(0, 100), //
392  SkPoint::Make(50, 100), //
393  };
394 
395  auto vertices_lb = flutter::DlVertices::Make(
396  flutter::DlVertexMode::kTriangleStrip, positions_lb.size(),
397  positions_lb.data(),
398  /*texture_coordinates=*/positions_lb.data(), /*colors=*/nullptr,
399  /*index_count=*/0,
400  /*indices=*/nullptr);
401 
402  std::vector<SkPoint> positions_rb = {
403  SkPoint::Make(50, 50), //
404  SkPoint::Make(100, 50), //
405  SkPoint::Make(50, 100), //
406  SkPoint::Make(100, 100), //
407  };
408 
409  auto vertices_rb = flutter::DlVertices::Make(
410  flutter::DlVertexMode::kTriangleStrip, positions_rb.size(),
411  positions_rb.data(),
412  /*texture_coordinates=*/positions_rb.data(), /*colors=*/nullptr,
413  /*index_count=*/0,
414  /*indices=*/nullptr);
415 
416  flutter::DisplayListBuilder builder;
417  flutter::DlPaint paint;
418  flutter::DlPaint rect_paint;
419  rect_paint.setColor(DlColor::kBlue());
420 
421  auto runtime_stages =
422  OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
423 
424  auto runtime_stage =
425  runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
426  ASSERT_TRUE(runtime_stage);
427 
428  auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
429  auto uniform_data = std::make_shared<std::vector<uint8_t>>();
430  auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
431  runtime_effect, {}, uniform_data);
432 
433  paint.setColorSource(color_source);
434 
435  builder.Scale(GetContentScale().x, GetContentScale().y);
436  builder.Save();
437  builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), rect_paint);
438  builder.DrawVertices(vertices_lt, flutter::DlBlendMode::kSrcOver, paint);
439  builder.DrawVertices(vertices_rt, flutter::DlBlendMode::kSrcOver, paint);
440  builder.DrawVertices(vertices_lb, flutter::DlBlendMode::kSrcOver, paint);
441  builder.DrawVertices(vertices_rb, flutter::DlBlendMode::kSrcOver, paint);
442  builder.Restore();
443 
444  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
445 }
446 
447 } // namespace testing
448 } // namespace impeller
impeller::AiksPlayground
Definition: aiks_playground.h:17
impeller::Scalar
float Scalar
Definition: scalar.h:18
aiks_unittests.h
impeller::PlaygroundBackendToRuntimeStageBackend
constexpr RuntimeStageBackend PlaygroundBackendToRuntimeStageBackend(PlaygroundBackend backend)
Definition: playground.h:33
impeller::DlImageImpeller::Make
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
Definition: dl_image_impeller.cc:12
impeller::testing::TEST_P
TEST_P(AiksTest, CanRenderAdvancedBlendColorFilterWithSaveLayer)
Definition: aiks_blend_unittests.cc:21
impeller::Point
TPoint< Scalar > Point
Definition: point.h:322
flutter
Definition: dl_golden_blur_unittests.cc:14
paint
const Paint & paint
Definition: color_source.cc:38
color
DlColor color
Definition: dl_golden_blur_unittests.cc:23
impeller
Definition: aiks_blend_unittests.cc:18
impeller::MakeVertices
std::shared_ptr< impeller::VerticesGeometry > MakeVertices(const std::shared_ptr< const flutter::DlVertices > &vertices)
Definition: dl_vertices_geometry.cc:31
dl_image_impeller.h