Flutter Impeller
aiks_dl_basic_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/display_list.h"
6 #include "display_list/dl_sampling_options.h"
7 #include "display_list/dl_tile_mode.h"
8 #include "display_list/effects/dl_color_filter.h"
9 #include "display_list/effects/dl_color_source.h"
10 #include "display_list/effects/dl_image_filter.h"
11 #include "display_list/effects/dl_mask_filter.h"
13 
14 #include "flutter/display_list/dl_blend_mode.h"
15 #include "flutter/display_list/dl_builder.h"
16 #include "flutter/display_list/dl_color.h"
17 #include "flutter/display_list/dl_paint.h"
20 #include "flutter/testing/display_list_testing.h"
21 #include "flutter/testing/testing.h"
23 
24 namespace impeller {
25 namespace testing {
26 
27 using namespace flutter;
28 
29 TEST_P(AiksTest, CanRenderColoredRect) {
30  DisplayListBuilder builder;
31  DlPaint paint;
32  paint.setColor(DlColor::kBlue());
33  builder.DrawPath(DlPath::MakeRectXYWH(100.0f, 100.0f, 100.0f, 100.0f), paint);
34  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
35 }
36 
37 TEST_P(AiksTest, CanRenderImage) {
38  DisplayListBuilder builder;
39  DlPaint paint;
40  paint.setColor(DlColor::kRed());
41  auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
42  builder.DrawImage(image, DlPoint(100.0, 100.0),
43  DlImageSampling::kNearestNeighbor, &paint);
44  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
45 }
46 
47 TEST_P(AiksTest, CanRenderInvertedImageWithColorFilter) {
48  DisplayListBuilder builder;
49  DlPaint paint;
50  paint.setColor(DlColor::kRed());
51  paint.setColorFilter(
52  DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
53  paint.setInvertColors(true);
54  auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
55 
56  builder.DrawImage(image, DlPoint(100.0, 100.0),
57  DlImageSampling::kNearestNeighbor, &paint);
58  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
59 }
60 
61 TEST_P(AiksTest, CanRenderColorFilterWithInvertColors) {
62  DisplayListBuilder builder;
63  DlPaint paint;
64  paint.setColor(DlColor::kRed());
65  paint.setColorFilter(
66  DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
67  paint.setInvertColors(true);
68 
69  builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
70  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
71 }
72 
73 TEST_P(AiksTest, CanRenderColorFilterWithInvertColorsDrawPaint) {
74  DisplayListBuilder builder;
75  DlPaint paint;
76  paint.setColor(DlColor::kRed());
77  paint.setColorFilter(
78  DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
79  paint.setInvertColors(true);
80 
81  builder.DrawPaint(paint);
82  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
83 }
84 
85 namespace {
86 bool GenerateMipmap(const std::shared_ptr<Context>& context,
87  std::shared_ptr<Texture> texture,
88  std::string_view label) {
89  auto buffer = context->CreateCommandBuffer();
90  if (!buffer) {
91  return false;
92  }
93  auto pass = buffer->CreateBlitPass();
94  if (!pass) {
95  return false;
96  }
97  pass->GenerateMipmap(std::move(texture), label);
98 
99  pass->EncodeCommands();
100  return context->GetCommandQueue()->Submit({buffer}).ok();
101 }
102 
103 void CanRenderTiledTexture(AiksTest* aiks_test,
104  DlTileMode tile_mode,
105  Matrix local_matrix = {}) {
106  auto context = aiks_test->GetContext();
107  ASSERT_TRUE(context);
108  auto texture = aiks_test->CreateTextureForFixture("table_mountain_nx.png",
109  /*enable_mipmapping=*/true);
110  GenerateMipmap(context, texture, "table_mountain_nx");
111  auto image = DlImageImpeller::Make(texture);
112  auto color_source = DlColorSource::MakeImage(
113  image, tile_mode, tile_mode, DlImageSampling::kNearestNeighbor,
114  &local_matrix);
115 
116  DisplayListBuilder builder;
117  DlPaint paint;
118  paint.setColor(DlColor::kWhite());
119  paint.setColorSource(color_source);
120 
121  builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
122  builder.Translate(100.0f, 100.0f);
123  builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
124 
125  // Should not change the image.
126  constexpr auto stroke_width = 64;
127  paint.setDrawStyle(DlDrawStyle::kStroke);
128  paint.setStrokeWidth(stroke_width);
129  if (tile_mode == DlTileMode::kDecal) {
130  builder.DrawRect(DlRect::MakeXYWH(stroke_width, stroke_width, 600, 600),
131  paint);
132  } else {
133  builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
134  }
135 
136  {
137  // Should not change the image.
138  DlPathBuilder path_builder;
139  path_builder.AddCircle(DlPoint(150, 150), 150);
140  path_builder.AddRoundRect(
141  RoundRect::MakeRectXY(DlRect::MakeLTRB(300, 300, 600, 600), 10, 10));
142  DlPath path(path_builder);
143 
144  // Make sure path cannot be simplified...
145  EXPECT_FALSE(path.IsRect(nullptr));
146  EXPECT_FALSE(path.IsOval(nullptr));
147  EXPECT_FALSE(path.IsRoundRect(nullptr));
148 
149  // Make sure path will not trigger the optimal convex code
150  EXPECT_FALSE(path.IsConvex());
151 
152  paint.setDrawStyle(DlDrawStyle::kFill);
153  builder.DrawPath(path, paint);
154  }
155 
156  {
157  // Should not change the image. Tests the Convex short-cut code.
158  DlPath circle = DlPath::MakeCircle(DlPoint(150, 450), 150);
159 
160  // Unfortunately, the circle path can be simplified...
161  EXPECT_TRUE(circle.IsOval(nullptr));
162  // At least it's convex, though...
163  EXPECT_TRUE(circle.IsConvex());
164 
165  // Let's make a copy that doesn't remember that it's just a circle...
166  DlPathBuilder path_builder;
167  // This moveTo confuses addPath into appending rather than replacing,
168  // which prevents it from noticing that it's just a circle...
169  path_builder.MoveTo({10, 10});
170  path_builder.AddPath(circle.GetPath());
171  path_builder.SetConvexity(Convexity::kConvex);
172  DlPath path(path_builder);
173 
174  // Make sure path cannot be simplified...
175  EXPECT_FALSE(path.IsRect(nullptr));
176  EXPECT_FALSE(path.IsOval(nullptr));
177  EXPECT_FALSE(path.IsRoundRect(nullptr));
178 
179  // But check that we will trigger the optimal convex code
180  EXPECT_TRUE(path.GetPath().IsConvex());
181 
182  paint.setDrawStyle(DlDrawStyle::kFill);
183  builder.DrawPath(path, paint);
184  }
185 
186  ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
187 }
188 } // namespace
189 
190 TEST_P(AiksTest, CanRenderTiledTextureClamp) {
191  CanRenderTiledTexture(this, DlTileMode::kClamp);
192 }
193 
194 TEST_P(AiksTest, CanRenderTiledTextureRepeat) {
195  CanRenderTiledTexture(this, DlTileMode::kRepeat);
196 }
197 
198 TEST_P(AiksTest, CanRenderTiledTextureMirror) {
199  CanRenderTiledTexture(this, DlTileMode::kMirror);
200 }
201 
202 TEST_P(AiksTest, CanRenderTiledTextureDecal) {
203  CanRenderTiledTexture(this, DlTileMode::kDecal);
204 }
205 
206 TEST_P(AiksTest, CanRenderTiledTextureClampWithTranslate) {
207  CanRenderTiledTexture(this, DlTileMode::kClamp,
208  Matrix::MakeTranslation({172.f, 172.f, 0.f}));
209 }
210 
211 TEST_P(AiksTest, CanRenderImageRect) {
212  DisplayListBuilder builder;
213  auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
214 
215  DlISize image_half_size = DlISize(image->dimensions().fWidth * 0.5f,
216  image->dimensions().fHeight * 0.5f);
217 
218  // Render the bottom right quarter of the source image in a stretched rect.
219  auto source_rect = DlRect::MakeSize(image_half_size);
220  source_rect =
221  source_rect.Shift(image_half_size.width, image_half_size.height);
222 
223  builder.DrawImageRect(image, source_rect,
224  DlRect::MakeXYWH(100, 100, 600, 600),
225  DlImageSampling::kNearestNeighbor);
226  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
227 }
228 
229 TEST_P(AiksTest, DrawImageRectSrcOutsideBounds) {
230  DisplayListBuilder builder;
231  auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
232 
233  // Use a source rect that is partially outside the bounds of the image.
234  auto source_rect = DlRect::MakeXYWH(
235  image->dimensions().fWidth * 0.25f, image->dimensions().fHeight * 0.4f,
236  image->dimensions().fWidth, image->dimensions().fHeight);
237 
238  auto dest_rect = DlRect::MakeXYWH(100, 100, 600, 600);
239 
240  DlPaint paint;
241  paint.setColor(DlColor::kMidGrey());
242  builder.DrawRect(dest_rect, paint);
243 
244  builder.DrawImageRect(image, source_rect, dest_rect,
245  DlImageSampling::kNearestNeighbor);
246  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
247 }
248 
249 TEST_P(AiksTest, CanRenderSimpleClips) {
250  DisplayListBuilder builder;
251  builder.Scale(GetContentScale().x, GetContentScale().y);
252  DlPaint paint;
253 
254  paint.setColor(DlColor::kWhite());
255  builder.DrawPaint(paint);
256 
257  auto draw = [&builder](const DlPaint& paint, Scalar x, Scalar y) {
258  builder.Save();
259  builder.Translate(x, y);
260  {
261  builder.Save();
262  builder.ClipRect(DlRect::MakeLTRB(50, 50, 150, 150));
263  builder.DrawPaint(paint);
264  builder.Restore();
265  }
266  {
267  builder.Save();
268  builder.ClipOval(DlRect::MakeLTRB(200, 50, 300, 150));
269  builder.DrawPaint(paint);
270  builder.Restore();
271  }
272  {
273  builder.Save();
274  builder.ClipRoundRect(
275  DlRoundRect::MakeRectXY(DlRect::MakeLTRB(50, 200, 150, 300), 20, 20));
276  builder.DrawPaint(paint);
277  builder.Restore();
278  }
279  {
280  builder.Save();
281  builder.ClipRoundRect(DlRoundRect::MakeRectXY(
282  DlRect::MakeLTRB(200, 230, 300, 270), 20, 20));
283  builder.DrawPaint(paint);
284  builder.Restore();
285  }
286  {
287  builder.Save();
288  builder.ClipRoundRect(DlRoundRect::MakeRectXY(
289  DlRect::MakeLTRB(230, 200, 270, 300), 20, 20));
290  builder.DrawPaint(paint);
291  builder.Restore();
292  }
293  builder.Restore();
294  };
295 
296  paint.setColor(DlColor::kBlue());
297  draw(paint, 0, 0);
298 
299  DlColor gradient_colors[7] = {
300  DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
301  DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
302  DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
303  DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
304  DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
305  DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
306  DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
307  };
308  Scalar stops[7] = {
309  0.0,
310  (1.0 / 6.0) * 1,
311  (1.0 / 6.0) * 2,
312  (1.0 / 6.0) * 3,
313  (1.0 / 6.0) * 4,
314  (1.0 / 6.0) * 5,
315  1.0,
316  };
317  auto texture = CreateTextureForFixture("airplane.jpg",
318  /*enable_mipmapping=*/true);
319  auto image = DlImageImpeller::Make(texture);
320 
321  paint.setColorSource(DlColorSource::MakeRadial(
322  DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
323  draw(paint, 0, 300);
324 
325  paint.setColorSource(
326  DlColorSource::MakeImage(image, DlTileMode::kRepeat, DlTileMode::kRepeat,
327  DlImageSampling::kNearestNeighbor));
328  draw(paint, 300, 0);
329 
330  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
331 }
332 
333 TEST_P(AiksTest, CanSaveLayerStandalone) {
334  DisplayListBuilder builder;
335 
336  DlPaint red;
337  red.setColor(DlColor::kRed());
338 
339  DlPaint alpha;
340  alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
341 
342  builder.SaveLayer(std::nullopt, &alpha);
343 
344  builder.DrawCircle(DlPoint(125, 125), 125, red);
345 
346  builder.Restore();
347 
348  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
349 }
350 
351 TEST_P(AiksTest, CanRenderDifferentShapesWithSameColorSource) {
352  DisplayListBuilder builder;
353  DlPaint paint;
354 
355  DlColor colors[2] = {
356  DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
357  DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0),
358  };
359  DlScalar stops[2] = {
360  0.0,
361  1.0,
362  };
363 
364  paint.setColorSource(DlColorSource::MakeLinear(
365  /*start_point=*/DlPoint(0, 0), //
366  /*end_point=*/DlPoint(100, 100), //
367  /*stop_count=*/2, //
368  /*colors=*/colors, //
369  /*stops=*/stops, //
370  /*tile_mode=*/DlTileMode::kRepeat //
371  ));
372 
373  builder.Save();
374  builder.Translate(100, 100);
375  builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
376  builder.Restore();
377 
378  builder.Save();
379  builder.Translate(100, 400);
380  builder.DrawCircle(DlPoint(100, 100), 100, paint);
381  builder.Restore();
382  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
383 }
384 
385 TEST_P(AiksTest, CanRenderRoundedRectWithNonUniformRadii) {
386  DisplayListBuilder builder;
387  DlPaint paint;
388  paint.setColor(DlColor::kRed());
389 
390  RoundingRadii radii = {
391  .top_left = DlSize(50, 25),
392  .top_right = DlSize(25, 50),
393  .bottom_left = DlSize(25, 50),
394  .bottom_right = DlSize(50, 25),
395  };
396  DlRoundRect rrect =
397  DlRoundRect::MakeRectRadii(DlRect::MakeXYWH(100, 100, 500, 500), radii);
398 
399  builder.DrawRoundRect(rrect, paint);
400 
401  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
402 }
403 
404 TEST_P(AiksTest, CanDrawPaint) {
405  auto medium_turquoise =
406  DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
407 
408  DisplayListBuilder builder;
409  builder.Scale(0.2, 0.2);
410  builder.DrawPaint(DlPaint().setColor(medium_turquoise));
411  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
412 }
413 
414 TEST_P(AiksTest, CanDrawPaintMultipleTimes) {
415  auto medium_turquoise =
416  DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
417  auto orange_red =
418  DlColor::RGBA(255.0f / 255.0f, 69.0f / 255.0f, 0.0f / 255.0f, 1.0f);
419 
420  DisplayListBuilder builder;
421  builder.Scale(0.2, 0.2);
422  builder.DrawPaint(DlPaint().setColor(medium_turquoise));
423  builder.DrawPaint(DlPaint().setColor(orange_red.modulateOpacity(0.5f)));
424  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
425 }
426 
427 TEST_P(AiksTest, FilledCirclesRenderCorrectly) {
428  DisplayListBuilder builder;
429  builder.Scale(GetContentScale().x, GetContentScale().y);
430  DlPaint paint;
431  const int color_count = 3;
432  DlColor colors[color_count] = {
433  DlColor::kBlue(),
434  DlColor::kGreen(),
435  DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
436  };
437 
438  paint.setColor(DlColor::kWhite());
439  builder.DrawPaint(paint);
440 
441  int c_index = 0;
442  int radius = 600;
443  while (radius > 0) {
444  paint.setColor(colors[(c_index++) % color_count]);
445  builder.DrawCircle(DlPoint(10, 10), radius, paint);
446  if (radius > 30) {
447  radius -= 10;
448  } else {
449  radius -= 2;
450  }
451  }
452 
453  DlColor gradient_colors[7] = {
454  DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
455  DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
456  DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
457  DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
458  DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
459  DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
460  DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
461  };
462  DlScalar stops[7] = {
463  0.0,
464  (1.0 / 6.0) * 1,
465  (1.0 / 6.0) * 2,
466  (1.0 / 6.0) * 3,
467  (1.0 / 6.0) * 4,
468  (1.0 / 6.0) * 5,
469  1.0,
470  };
471  auto texture = CreateTextureForFixture("airplane.jpg",
472  /*enable_mipmapping=*/true);
473  auto image = DlImageImpeller::Make(texture);
474 
475  paint.setColorSource(DlColorSource::MakeRadial(
476  DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
477  builder.DrawCircle(DlPoint(500, 600), 100, paint);
478 
479  DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
480  paint.setColorSource(DlColorSource::MakeImage(
481  image, DlTileMode::kRepeat, DlTileMode::kRepeat,
482  DlImageSampling::kNearestNeighbor, &local_matrix));
483  builder.DrawCircle(DlPoint(800, 300), 100, paint);
484 
485  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
486 }
487 
488 TEST_P(AiksTest, StrokedCirclesRenderCorrectly) {
489  DisplayListBuilder builder;
490  builder.Scale(GetContentScale().x, GetContentScale().y);
491  DlPaint paint;
492  const int color_count = 3;
493  DlColor colors[color_count] = {
494  DlColor::kBlue(),
495  DlColor::kGreen(),
496  DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
497  };
498 
499  paint.setColor(DlColor::kWhite());
500  builder.DrawPaint(paint);
501 
502  int c_index = 0;
503 
504  auto draw = [&paint, &colors, &c_index](DlCanvas& canvas, DlPoint center,
505  Scalar r, Scalar dr, int n) {
506  for (int i = 0; i < n; i++) {
507  paint.setColor(colors[(c_index++) % color_count]);
508  canvas.DrawCircle(center, r, paint);
509  r += dr;
510  }
511  };
512 
513  paint.setDrawStyle(DlDrawStyle::kStroke);
514  paint.setStrokeWidth(1);
515  draw(builder, DlPoint(10, 10), 2, 2, 14); // r = [2, 28], covers [1,29]
516  paint.setStrokeWidth(5);
517  draw(builder, DlPoint(10, 10), 35, 10, 56); // r = [35, 585], covers [30,590]
518 
519  DlColor gradient_colors[7] = {
520  DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
521  DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
522  DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
523  DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
524  DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
525  DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
526  DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
527  };
528  DlScalar stops[7] = {
529  0.0,
530  (1.0 / 6.0) * 1,
531  (1.0 / 6.0) * 2,
532  (1.0 / 6.0) * 3,
533  (1.0 / 6.0) * 4,
534  (1.0 / 6.0) * 5,
535  1.0,
536  };
537  auto texture = CreateTextureForFixture("airplane.jpg",
538  /*enable_mipmapping=*/true);
539  auto image = DlImageImpeller::Make(texture);
540 
541  paint.setColorSource(DlColorSource::MakeRadial(
542  DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
543  draw(builder, DlPoint(500, 600), 5, 10, 10);
544 
545  DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
546  paint.setColorSource(DlColorSource::MakeImage(
547  image, DlTileMode::kRepeat, DlTileMode::kRepeat,
548  DlImageSampling::kNearestNeighbor, &local_matrix));
549  draw(builder, DlPoint(800, 300), 5, 10, 10);
550 
551  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
552 }
553 
554 TEST_P(AiksTest, FilledEllipsesRenderCorrectly) {
555  DisplayListBuilder builder;
556  builder.Scale(GetContentScale().x, GetContentScale().y);
557  DlPaint paint;
558  const int color_count = 3;
559  DlColor colors[color_count] = {
560  DlColor::kBlue(),
561  DlColor::kGreen(),
562  DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
563  };
564 
565  paint.setColor(DlColor::kWhite());
566  builder.DrawPaint(paint);
567 
568  int c_index = 0;
569  int long_radius = 600;
570  int short_radius = 600;
571  while (long_radius > 0 && short_radius > 0) {
572  paint.setColor(colors[(c_index++) % color_count]);
573  builder.DrawOval(DlRect::MakeXYWH(10 - long_radius, 10 - short_radius,
574  long_radius * 2, short_radius * 2),
575  paint);
576  builder.DrawOval(DlRect::MakeXYWH(1000 - short_radius, 750 - long_radius,
577  short_radius * 2, long_radius * 2),
578  paint);
579  if (short_radius > 30) {
580  short_radius -= 10;
581  long_radius -= 5;
582  } else {
583  short_radius -= 2;
584  long_radius -= 1;
585  }
586  }
587 
588  DlColor gradient_colors[7] = {
589  DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
590  DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
591  DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
592  DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
593  DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
594  DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
595  DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
596  };
597  DlScalar stops[7] = {
598  0.0,
599  (1.0 / 6.0) * 1,
600  (1.0 / 6.0) * 2,
601  (1.0 / 6.0) * 3,
602  (1.0 / 6.0) * 4,
603  (1.0 / 6.0) * 5,
604  1.0,
605  };
606  auto texture = CreateTextureForFixture("airplane.jpg",
607  /*enable_mipmapping=*/true);
608  auto image = DlImageImpeller::Make(texture);
609 
610  paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
611 
612  paint.setColorSource(DlColorSource::MakeRadial(
613  DlPoint(300, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
614  builder.DrawOval(DlRect::MakeXYWH(200, 625, 200, 50), paint);
615  builder.DrawOval(DlRect::MakeXYWH(275, 550, 50, 200), paint);
616 
617  DlMatrix local_matrix = DlMatrix::MakeTranslation({610, 15});
618  paint.setColorSource(DlColorSource::MakeImage(
619  image, DlTileMode::kRepeat, DlTileMode::kRepeat,
620  DlImageSampling::kNearestNeighbor, &local_matrix));
621  builder.DrawOval(DlRect::MakeXYWH(610, 90, 200, 50), paint);
622  builder.DrawOval(DlRect::MakeXYWH(685, 15, 50, 200), paint);
623 
624  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
625 }
626 
627 TEST_P(AiksTest, FilledRoundRectsRenderCorrectly) {
628  DisplayListBuilder builder;
629  builder.Scale(GetContentScale().x, GetContentScale().y);
630  DlPaint paint;
631  const int color_count = 3;
632  DlColor colors[color_count] = {
633  DlColor::kBlue(),
634  DlColor::kGreen(),
635  DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
636  };
637 
638  paint.setColor(DlColor::kWhite());
639  builder.DrawPaint(paint);
640 
641  int c_index = 0;
642  for (int i = 0; i < 4; i++) {
643  for (int j = 0; j < 4; j++) {
644  paint.setColor(colors[(c_index++) % color_count]);
645  builder.DrawRoundRect(
646  DlRoundRect::MakeRectXY(
647  DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80), //
648  i * 5 + 10, j * 5 + 10),
649  paint);
650  }
651  }
652  paint.setColor(colors[(c_index++) % color_count]);
653  builder.DrawRoundRect(
654  DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40),
655  paint);
656  paint.setColor(colors[(c_index++) % color_count]);
657  builder.DrawRoundRect(
658  DlRoundRect::MakeRectXY(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40),
659  paint);
660 
661  DlColor gradient_colors[7] = {
662  DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
663  DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
664  DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
665  DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
666  DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
667  DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
668  DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
669  };
670  DlScalar stops[7] = {
671  0.0,
672  (1.0 / 6.0) * 1,
673  (1.0 / 6.0) * 2,
674  (1.0 / 6.0) * 3,
675  (1.0 / 6.0) * 4,
676  (1.0 / 6.0) * 5,
677  1.0,
678  };
679  auto texture = CreateTextureForFixture("airplane.jpg",
680  /*enable_mipmapping=*/true);
681  auto image = DlImageImpeller::Make(texture);
682 
683  paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
684  paint.setColorSource(DlColorSource::MakeRadial(
685  DlPoint(550, 550), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
686  for (int i = 1; i <= 10; i++) {
687  int j = 11 - i;
688  builder.DrawRoundRect(
689  DlRoundRect::MakeRectXY(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
690  550 + i * 20, 550 + j * 20),
691  i * 10, j * 10),
692  paint);
693  }
694 
695  paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
696  paint.setColorSource(DlColorSource::MakeRadial(
697  DlPoint(200, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
698  paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
699  builder.DrawRoundRect(
700  DlRoundRect::MakeRectXY(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40),
701  paint);
702  builder.DrawRoundRect(
703  DlRoundRect::MakeRectXY(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40),
704  paint);
705 
706  paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
707  DlMatrix local_matrix = DlMatrix::MakeTranslation({520, 20});
708  paint.setColorSource(DlColorSource::MakeImage(
709  image, DlTileMode::kRepeat, DlTileMode::kRepeat,
710  DlImageSampling::kNearestNeighbor, &local_matrix));
711  for (int i = 1; i <= 10; i++) {
712  int j = 11 - i;
713  builder.DrawRoundRect(
714  DlRoundRect::MakeRectXY(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
715  720 + i * 20, 220 + j * 20),
716  i * 10, j * 10),
717  paint);
718  }
719 
720  paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
721  local_matrix = DlMatrix::MakeTranslation({800, 300});
722  paint.setColorSource(DlColorSource::MakeImage(
723  image, DlTileMode::kRepeat, DlTileMode::kRepeat,
724  DlImageSampling::kNearestNeighbor, &local_matrix));
725  builder.DrawRoundRect(
726  DlRoundRect::MakeRectXY(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40),
727  paint);
728  builder.DrawRoundRect(
729  DlRoundRect::MakeRectXY(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40),
730  paint);
731 
732  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
733 }
734 
735 TEST_P(AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly) {
736  DisplayListBuilder builder;
737  builder.Scale(GetContentScale().x, GetContentScale().y);
738  DlPaint paint;
739  paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1.0f));
740 
741  builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
742 
743  paint.setColor(
744  DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f));
745  Scalar y = 100.0f;
746  for (int i = 0; i < 5; i++) {
747  Scalar x = (i + 1) * 100;
748  Scalar radius = x / 10.0f;
749  builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
750  radius, 60.0f - radius),
751  paint);
752  }
753 
754  paint.setColor(DlColor::kBlue());
755  y += 100.0f;
756  for (int i = 0; i < 5; i++) {
757  Scalar x = (i + 1) * 100;
758  Scalar radius = x / 10.0f;
759  builder.DrawCircle(DlPoint(x + 25, y + 25), radius, paint);
760  }
761 
762  paint.setColor(DlColor::kGreen());
763  y += 100.0f;
764  for (int i = 0; i < 5; i++) {
765  Scalar x = (i + 1) * 100;
766  Scalar radius = x / 10.0f;
767  builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
768  radius, 60.0f - radius),
769  paint);
770  }
771 
772  paint.setColor(
773  DlColor::RGBA(128.0f / 255.0f, 0.0f / 255.0f, 128.0f / 255.0f, 1.0f));
774  y += 100.0f;
775  for (int i = 0; i < 5; i++) {
776  Scalar x = (i + 1) * 100;
777  Scalar radius = x / 20.0f;
778  builder.DrawRoundRect(
779  DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
780  radius, radius),
781  paint);
782  }
783 
784  paint.setColor(
785  DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f));
786  y += 100.0f;
787  for (int i = 0; i < 5; i++) {
788  Scalar x = (i + 1) * 100;
789  Scalar radius = x / 20.0f;
790  builder.DrawRoundRect(
791  DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
792  radius, 5.0f),
793  paint);
794  }
795 
796  auto dl = builder.Build();
797  ASSERT_TRUE(OpenPlaygroundHere(dl));
798 }
799 
800 TEST_P(AiksTest, CanRenderClippedBackdropFilter) {
801  DisplayListBuilder builder;
802 
803  builder.Scale(GetContentScale().x, GetContentScale().y);
804 
805  // Draw something interesting in the background.
806  std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
807  DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
808  std::vector<Scalar> stops = {
809  0.0,
810  1.0,
811  };
812  DlPaint paint;
813  paint.setColorSource(DlColorSource::MakeLinear(
814  /*start_point=*/DlPoint(0, 0), //
815  /*end_point=*/DlPoint(100, 100), //
816  /*stop_count=*/2, //
817  /*colors=*/colors.data(), //
818  /*stops=*/stops.data(), //
819  /*tile_mode=*/DlTileMode::kRepeat //
820  ));
821 
822  builder.DrawPaint(paint);
823 
824  DlRect clip_rect = DlRect::MakeLTRB(50, 50, 400, 300);
825  DlRoundRect clip_rrect = DlRoundRect::MakeRectXY(clip_rect, 100, 100);
826 
827  // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
828  // the same.
829  builder.ClipRoundRect(clip_rrect, DlClipOp::kIntersect);
830 
831  DlPaint save_paint;
832  auto backdrop_filter = DlImageFilter::MakeColorFilter(
833  DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kExclusion));
834  builder.SaveLayer(clip_rect, &save_paint, backdrop_filter.get());
835 
836  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
837 }
838 
839 TEST_P(AiksTest, CanDrawPerspectiveTransformWithClips) {
840  // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
841  int time = 0;
842  auto callback = [&]() -> sk_sp<DisplayList> {
843  DisplayListBuilder builder;
844 
845  builder.Save();
846  {
847  builder.Translate(300, 300);
848 
849  // 1. Draw/restore a clip before drawing the image, which will get drawn
850  // to the depth buffer behind the image.
851  builder.Save();
852  {
853  DlPaint paint;
854  paint.setColor(DlColor::kGreen());
855  builder.DrawPaint(paint);
856  builder.ClipRect(DlRect::MakeLTRB(-180, -180, 180, 180),
857  DlClipOp::kDifference);
858 
859  paint.setColor(DlColor::kBlack());
860  builder.DrawPaint(paint);
861  }
862  builder.Restore(); // Restore rectangle difference clip.
863 
864  builder.Save();
865  {
866  // 2. Draw an oval clip that applies to the image, which will get drawn
867  // in front of the image on the depth buffer.
868  builder.ClipOval(DlRect::MakeLTRB(-200, -200, 200, 200));
869 
870  Matrix result =
871  Matrix(1.0, 0.0, 0.0, 0.0, //
872  0.0, 1.0, 0.0, 0.0, //
873  0.0, 0.0, 1.0, 0.003, //
874  0.0, 0.0, 0.0, 1.0) *
875  Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}});
876 
877  // 3. Draw the rotating image with a perspective transform.
878  builder.Transform(result);
879 
880  auto image =
881  DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
882  auto position =
883  -DlPoint(image->dimensions().fWidth, image->dimensions().fHeight) *
884  0.5;
885  builder.DrawImage(image, position, {});
886  }
887  builder.Restore(); // Restore oval intersect clip.
888 
889  // 4. Draw a semi-translucent blue circle atop all previous draws.
890  DlPaint paint;
891  paint.setColor(DlColor::kBlue().modulateOpacity(0.4));
892  builder.DrawCircle(DlPoint(), 230, paint);
893  }
894  builder.Restore(); // Restore translation.
895 
896  return builder.Build();
897  };
898  ASSERT_TRUE(OpenPlaygroundHere(callback));
899 }
900 
901 TEST_P(AiksTest, ImageColorSourceEffectTransform) {
902  // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
903 
904  DisplayListBuilder builder;
905  auto texture = DlImageImpeller::Make(CreateTextureForFixture("monkey.png"));
906 
907  DlPaint paint;
908  paint.setColor(DlColor::kWhite());
909  builder.DrawPaint(paint);
910 
911  // Translation
912  {
913  DlMatrix matrix = DlMatrix::MakeTranslation({50, 50});
914  DlPaint paint;
915  paint.setColorSource(DlColorSource::MakeImage(
916  texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
917  DlImageSampling::kNearestNeighbor, &matrix));
918 
919  builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
920  }
921 
922  // Rotation/skew
923  {
924  builder.Save();
925  builder.Rotate(45);
926  DlPaint paint;
927 
928  Matrix matrix(1, -1, 0, 0, //
929  1, 1, 0, 0, //
930  0, 0, 1, 0, //
931  0, 0, 0, 1);
932  paint.setColorSource(DlColorSource::MakeImage(
933  texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
934  DlImageSampling::kNearestNeighbor, &matrix));
935  builder.DrawRect(DlRect::MakeLTRB(100, 0, 200, 100), paint);
936  builder.Restore();
937  }
938 
939  // Scale
940  {
941  builder.Save();
942  builder.Translate(100, 0);
943  builder.Scale(100, 100);
944  DlPaint paint;
945 
946  DlMatrix matrix = DlMatrix::MakeScale({0.005, 0.005, 1});
947  paint.setColorSource(DlColorSource::MakeImage(
948  texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
949  DlImageSampling::kNearestNeighbor, &matrix));
950 
951  builder.DrawRect(DlRect::MakeLTRB(0, 0, 1, 1), paint);
952  builder.Restore();
953  }
954 
955  // Perspective
956  {
957  builder.Save();
958  builder.Translate(150, 150);
959  DlPaint paint;
960 
961  DlMatrix matrix =
962  DlMatrix::MakePerspective(Radians{0.5}, ISize{200, 200}, 0.05, 1);
963  paint.setColorSource(DlColorSource::MakeImage(
964  texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
965  DlImageSampling::kNearestNeighbor, &matrix));
966 
967  builder.DrawRect(DlRect::MakeLTRB(0, 0, 200, 200), paint);
968  builder.Restore();
969  }
970 
971  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
972 }
973 
974 TEST_P(AiksTest, SubpassWithClearColorOptimization) {
975  DisplayListBuilder builder;
976 
977  // Use a non-srcOver blend mode to ensure that we don't detect this as an
978  // opacity peephole optimization.
979  DlPaint paint;
980  paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
981  paint.setBlendMode(DlBlendMode::kSrc);
982 
983  DlRect bounds = DlRect::MakeLTRB(0, 0, 200, 200);
984  builder.SaveLayer(bounds, &paint);
985 
986  paint.setColor(DlColor::kTransparent());
987  paint.setBlendMode(DlBlendMode::kSrc);
988  builder.DrawPaint(paint);
989  builder.Restore();
990 
991  paint.setColor(DlColor::kBlue());
992  paint.setBlendMode(DlBlendMode::kDstOver);
993  builder.SaveLayer(std::nullopt, &paint);
994  builder.Restore();
995 
996  // This playground should appear blank on CI since we are only drawing
997  // transparent black. If the clear color optimization is broken, the texture
998  // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
999  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1000 }
1001 
1002 // Render a white circle at the top left corner of the screen.
1003 TEST_P(AiksTest, MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen) {
1004  DisplayListBuilder builder;
1005  builder.Scale(GetContentScale().x, GetContentScale().y);
1006  builder.Translate(100, 100);
1007  // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1008  // +300 translation applied by a SaveLayer image filter.
1009  DlPaint paint;
1010  DlMatrix translate = DlMatrix::MakeTranslation({300, 0});
1011  paint.setImageFilter(
1012  DlImageFilter::MakeMatrix(translate, DlImageSampling::kLinear));
1013  builder.SaveLayer(std::nullopt, &paint);
1014 
1015  DlPaint circle_paint;
1016  circle_paint.setColor(DlColor::kGreen());
1017  builder.DrawCircle(DlPoint(-300, 0), 100, circle_paint);
1018  builder.Restore();
1019 
1020  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1021 }
1022 
1023 // Render a white circle at the top left corner of the screen.
1025  MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen) {
1026  DisplayListBuilder builder;
1027  builder.Scale(GetContentScale().x, GetContentScale().y);
1028  builder.Translate(100, 100);
1029  // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1030  // +300 translation applied by a SaveLayer image filter.
1031 
1032  DlPaint paint;
1033  paint.setImageFilter(DlImageFilter::MakeMatrix(
1034  DlMatrix::MakeTranslation({300, 0}) * DlMatrix::MakeScale({2, 2, 1}),
1035  DlImageSampling::kNearestNeighbor));
1036  builder.SaveLayer(std::nullopt, &paint);
1037 
1038  DlPaint circle_paint;
1039  circle_paint.setColor(DlColor::kGreen());
1040  builder.DrawCircle(DlPoint(-150, 0), 50, circle_paint);
1041  builder.Restore();
1042 
1043  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1044 }
1045 
1046 // This should be solid red, if you see a little red box this is broken.
1047 TEST_P(AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass) {
1048  SetWindowSize({400, 400});
1049  DisplayListBuilder builder;
1050 
1051  builder.Scale(GetContentScale().x, GetContentScale().y);
1052 
1053  DlPaint paint;
1054  paint.setColor(DlColor::kRed());
1055  builder.DrawRect(DlRect::MakeLTRB(200, 200, 300, 300), paint);
1056 
1057  paint.setImageFilter(DlImageFilter::MakeMatrix(DlMatrix::MakeScale({2, 2, 1}),
1058  DlImageSampling::kLinear));
1059  builder.SaveLayer(std::nullopt, &paint);
1060  // Draw a rectangle that would fully cover the parent pass size, but not
1061  // the subpass that it is rendered in.
1062  paint.setColor(DlColor::kGreen());
1063  builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
1064  // Draw a bigger rectangle to force the subpass to be bigger.
1065 
1066  paint.setColor(DlColor::kRed());
1067  builder.DrawRect(DlRect::MakeLTRB(0, 0, 800, 800), paint);
1068  builder.Restore();
1069 
1070  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1071 }
1072 
1073 TEST_P(AiksTest, EmptySaveLayerIgnoresPaint) {
1074  DisplayListBuilder builder;
1075  builder.Scale(GetContentScale().x, GetContentScale().y);
1076 
1077  DlPaint paint;
1078  paint.setColor(DlColor::kRed());
1079  builder.DrawPaint(paint);
1080  builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1081  paint.setColor(DlColor::kBlue());
1082  builder.SaveLayer(std::nullopt, &paint);
1083  builder.Restore();
1084 
1085  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1086 }
1087 
1088 TEST_P(AiksTest, EmptySaveLayerRendersWithClear) {
1089  DisplayListBuilder builder;
1090  builder.Scale(GetContentScale().x, GetContentScale().y);
1091  auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1092  builder.DrawImage(image, DlPoint(10, 10), {});
1093  builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1094 
1095  DlPaint paint;
1096  paint.setBlendMode(DlBlendMode::kClear);
1097  builder.SaveLayer(std::nullopt, &paint);
1098  builder.Restore();
1099 
1100  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1101 }
1102 
1104  CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated) {
1105  DisplayListBuilder builder;
1106 
1107  DlPaint red;
1108  red.setColor(DlColor::kRed());
1109 
1110  DlPaint green;
1111  green.setColor(DlColor::kGreen());
1112 
1113  DlPaint blue;
1114  blue.setColor(DlColor::kBlue());
1115 
1116  DlPaint save;
1117  save.setColor(DlColor::kBlack().modulateOpacity(0.5));
1118 
1119  DlRect huge_bounds = DlRect::MakeXYWH(0, 0, 100000, 100000);
1120  builder.SaveLayer(huge_bounds, &save);
1121 
1122  builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1123  builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), green);
1124  builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), blue);
1125 
1126  builder.Restore();
1127 
1128  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1129 }
1130 
1131 // This makes sure the WideGamut named tests use 16bit float pixel format.
1132 TEST_P(AiksTest, FormatWideGamut) {
1133  EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
1135 }
1136 
1137 TEST_P(AiksTest, FormatSRGB) {
1138  PixelFormat pixel_format =
1139  GetContext()->GetCapabilities()->GetDefaultColorFormat();
1140  EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
1141  pixel_format == PixelFormat::kB8G8R8A8UNormInt)
1142  << "pixel format: " << PixelFormatToString(pixel_format);
1143 }
1144 
1145 TEST_P(AiksTest, CoordinateConversionsAreCorrect) {
1146  DisplayListBuilder builder;
1147 
1148  // Render a texture directly.
1149  {
1150  auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1151 
1152  builder.Save();
1153  builder.Translate(100, 200);
1154  builder.Scale(0.5, 0.5);
1155  builder.DrawImage(image, DlPoint(100.0, 100.0),
1156  DlImageSampling::kNearestNeighbor);
1157  builder.Restore();
1158  }
1159 
1160  // Render an offscreen rendered texture.
1161  {
1162  DlPaint alpha;
1163  alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1164 
1165  builder.SaveLayer(std::nullopt, &alpha);
1166 
1167  DlPaint paint;
1168  paint.setColor(DlColor::kRed());
1169  builder.DrawRect(DlRect::MakeXYWH(000, 000, 100, 100), paint);
1170  paint.setColor(DlColor::kGreen());
1171  builder.DrawRect(DlRect::MakeXYWH(020, 020, 100, 100), paint);
1172  paint.setColor(DlColor::kBlue());
1173  builder.DrawRect(DlRect::MakeXYWH(040, 040, 100, 100), paint);
1174 
1175  builder.Restore();
1176  }
1177 
1178  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1179 }
1180 
1181 TEST_P(AiksTest, CanPerformFullScreenMSAA) {
1182  DisplayListBuilder builder;
1183 
1184  DlPaint paint;
1185  paint.setColor(DlColor::kRed());
1186  builder.DrawCircle(DlPoint(250, 250), 125, paint);
1187 
1188  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1189 }
1190 
1191 TEST_P(AiksTest, CanPerformSkew) {
1192  DisplayListBuilder builder;
1193 
1194  DlPaint red;
1195  red.setColor(DlColor::kRed());
1196  builder.Skew(2, 5);
1197  builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1198 
1199  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1200 }
1201 
1202 TEST_P(AiksTest, CanPerformSaveLayerWithBounds) {
1203  DisplayListBuilder builder;
1204 
1205  DlPaint save;
1206  save.setColor(DlColor::kBlack());
1207 
1208  DlRect save_bounds = DlRect::MakeXYWH(0, 0, 50, 50);
1209  builder.SaveLayer(save_bounds, &save);
1210 
1211  DlPaint paint;
1212  paint.setColor(DlColor::kRed());
1213  builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1214  paint.setColor(DlColor::kGreen());
1215  builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), paint);
1216  paint.setColor(DlColor::kBlue());
1217  builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), paint);
1218 
1219  builder.Restore();
1220 
1221  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1222 }
1223 
1224 TEST_P(AiksTest, FilledRoundRectPathsRenderCorrectly) {
1225  DisplayListBuilder builder;
1226  builder.Scale(GetContentScale().x, GetContentScale().y);
1227 
1228  DlPaint paint;
1229  const int color_count = 3;
1230  DlColor colors[color_count] = {
1231  DlColor::kBlue(),
1232  DlColor::kGreen(),
1233  DlColor::ARGB(1.0, 220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f),
1234  };
1235 
1236  paint.setColor(DlColor::kWhite());
1237  builder.DrawPaint(paint);
1238 
1239  auto draw_rrect_as_path = [&builder](const DlRect& rect, Scalar x, Scalar y,
1240  const DlPaint& paint) {
1241  builder.DrawPath(DlPath::MakeRoundRectXY(rect, x, y), paint);
1242  };
1243 
1244  int c_index = 0;
1245  for (int i = 0; i < 4; i++) {
1246  for (int j = 0; j < 4; j++) {
1247  paint.setColor(colors[(c_index++) % color_count]);
1248  draw_rrect_as_path(DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1249  i * 5 + 10, j * 5 + 10, paint);
1250  }
1251  }
1252  paint.setColor(colors[(c_index++) % color_count]);
1253  draw_rrect_as_path(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40, paint);
1254  paint.setColor(colors[(c_index++) % color_count]);
1255  draw_rrect_as_path(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40, paint);
1256 
1257  std::vector<DlColor> gradient_colors = {
1258  DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1259  DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1260  DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1261  DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1262  DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1263  DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1264  DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0)};
1265  std::vector<Scalar> stops = {
1266  0.0,
1267  (1.0 / 6.0) * 1,
1268  (1.0 / 6.0) * 2,
1269  (1.0 / 6.0) * 3,
1270  (1.0 / 6.0) * 4,
1271  (1.0 / 6.0) * 5,
1272  1.0,
1273  };
1274  auto texture = DlImageImpeller::Make(
1275  CreateTextureForFixture("airplane.jpg",
1276  /*enable_mipmapping=*/true));
1277 
1278  paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1279  paint.setColorSource(DlColorSource::MakeRadial(
1280  /*center=*/DlPoint(550, 550),
1281  /*radius=*/75,
1282  /*stop_count=*/gradient_colors.size(),
1283  /*colors=*/gradient_colors.data(),
1284  /*stops=*/stops.data(),
1285  /*tile_mode=*/DlTileMode::kMirror));
1286  for (int i = 1; i <= 10; i++) {
1287  int j = 11 - i;
1288  draw_rrect_as_path(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1289  550 + i * 20, 550 + j * 20),
1290  i * 10, j * 10, paint);
1291  }
1292  paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1293  paint.setColorSource(DlColorSource::MakeRadial(
1294  /*center=*/DlPoint(200, 650),
1295  /*radius=*/75,
1296  /*stop_count=*/gradient_colors.size(),
1297  /*colors=*/gradient_colors.data(),
1298  /*stops=*/stops.data(),
1299  /*tile_mode=*/DlTileMode::kMirror));
1300  draw_rrect_as_path(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40, paint);
1301  draw_rrect_as_path(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40, paint);
1302 
1303  auto matrix = DlMatrix::MakeTranslation({520, 20});
1304  paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1305  paint.setColorSource(DlColorSource::MakeImage(
1306  texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1307  DlImageSampling::kMipmapLinear, &matrix));
1308  for (int i = 1; i <= 10; i++) {
1309  int j = 11 - i;
1310  draw_rrect_as_path(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1311  720 + i * 20, 220 + j * 20),
1312  i * 10, j * 10, paint);
1313  }
1314  matrix = DlMatrix::MakeTranslation({800, 300});
1315  paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1316  paint.setColorSource(DlColorSource::MakeImage(
1317  texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1318  DlImageSampling::kMipmapLinear, &matrix));
1319 
1320  draw_rrect_as_path(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40, paint);
1321  draw_rrect_as_path(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40, paint);
1322 
1323  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1324 }
1325 
1326 TEST_P(AiksTest, CoverageOriginShouldBeAccountedForInSubpasses) {
1327  auto callback = [&]() -> sk_sp<DisplayList> {
1328  DisplayListBuilder builder;
1329  builder.Scale(GetContentScale().x, GetContentScale().y);
1330 
1331  DlPaint alpha;
1332  alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1333 
1334  auto current = Point{25, 25};
1335  const auto offset = Point{25, 25};
1336  const auto size = Size(100, 100);
1337 
1338  static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1339  static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1340  auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1341  DlRect bounds = DlRect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1342 
1343  DlPaint stroke_paint;
1344  stroke_paint.setColor(DlColor::kYellow());
1345  stroke_paint.setStrokeWidth(5);
1346  stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
1347  builder.DrawRect(bounds, stroke_paint);
1348 
1349  builder.SaveLayer(bounds, &alpha);
1350 
1351  DlPaint paint;
1352  paint.setColor(DlColor::kRed());
1353  builder.DrawRect(
1354  DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1355 
1356  paint.setColor(DlColor::kGreen());
1357  current += offset;
1358  builder.DrawRect(
1359  DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1360 
1361  paint.setColor(DlColor::kBlue());
1362  current += offset;
1363  builder.DrawRect(
1364  DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1365 
1366  builder.Restore();
1367 
1368  return builder.Build();
1369  };
1370 
1371  ASSERT_TRUE(OpenPlaygroundHere(callback));
1372 }
1373 
1374 TEST_P(AiksTest, SaveLayerDrawsBehindSubsequentEntities) {
1375  // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1376  DisplayListBuilder builder;
1377  DlPaint paint;
1378 
1379  paint.setColor(DlColor::kBlack());
1380  DlRect rect = DlRect::MakeXYWH(25, 25, 25, 25);
1381  builder.DrawRect(rect, paint);
1382 
1383  builder.Translate(10, 10);
1384 
1385  DlPaint save_paint;
1386  builder.SaveLayer(std::nullopt, &save_paint);
1387 
1388  paint.setColor(DlColor::kGreen());
1389  builder.DrawRect(rect, paint);
1390 
1391  builder.Restore();
1392 
1393  builder.Translate(10, 10);
1394  paint.setColor(DlColor::kRed());
1395  builder.DrawRect(rect, paint);
1396 
1397  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1398 }
1399 
1400 TEST_P(AiksTest, SiblingSaveLayerBoundsAreRespected) {
1401  DisplayListBuilder builder;
1402  DlPaint paint;
1403  DlRect rect = DlRect::MakeXYWH(0, 0, 1000, 1000);
1404 
1405  // Black, green, and red squares offset by [10, 10].
1406  {
1407  DlPaint save_paint;
1408  DlRect bounds = DlRect::MakeXYWH(25, 25, 25, 25);
1409  builder.SaveLayer(bounds, &save_paint);
1410  paint.setColor(DlColor::kBlack());
1411  builder.DrawRect(rect, paint);
1412  builder.Restore();
1413  }
1414 
1415  {
1416  DlPaint save_paint;
1417  DlRect bounds = DlRect::MakeXYWH(35, 35, 25, 25);
1418  builder.SaveLayer(bounds, &save_paint);
1419  paint.setColor(DlColor::kGreen());
1420  builder.DrawRect(rect, paint);
1421  builder.Restore();
1422  }
1423 
1424  {
1425  DlPaint save_paint;
1426  DlRect bounds = DlRect::MakeXYWH(45, 45, 25, 25);
1427  builder.SaveLayer(bounds, &save_paint);
1428  paint.setColor(DlColor::kRed());
1429  builder.DrawRect(rect, paint);
1430  builder.Restore();
1431  }
1432 
1433  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1434 }
1435 
1436 TEST_P(AiksTest, CanRenderClippedLayers) {
1437  DisplayListBuilder builder;
1438 
1439  DlPaint paint;
1440  paint.setColor(DlColor::kWhite());
1441  builder.DrawPaint(paint);
1442 
1443  // Draw a green circle on the screen.
1444  {
1445  // Increase the clip depth for the savelayer to contend with.
1446  DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 50);
1447  builder.ClipPath(path);
1448 
1449  DlRect bounds = DlRect::MakeXYWH(50, 50, 100, 100);
1450  DlPaint save_paint;
1451  builder.SaveLayer(bounds, &save_paint);
1452 
1453  // Fill the layer with white.
1454  paint.setColor(DlColor::kWhite());
1455  builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
1456  // Fill the layer with green, but do so with a color blend that can't be
1457  // collapsed into the parent pass.
1458  paint.setColor(DlColor::kGreen());
1459  paint.setBlendMode(DlBlendMode::kHardLight);
1460  builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
1461  }
1462 
1463  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1464 }
1465 
1466 TEST_P(AiksTest, SaveLayerFiltersScaleWithTransform) {
1467  DisplayListBuilder builder;
1468 
1469  builder.Scale(GetContentScale().x, GetContentScale().y);
1470  builder.Translate(100, 100);
1471 
1472  auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
1473  auto draw_image_layer = [&builder, &texture](const DlPaint& paint) {
1474  builder.SaveLayer(std::nullopt, &paint);
1475  builder.DrawImage(texture, DlPoint(), DlImageSampling::kLinear);
1476  builder.Restore();
1477  };
1478 
1479  DlPaint effect_paint;
1480  effect_paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 6));
1481  draw_image_layer(effect_paint);
1482 
1483  builder.Translate(300, 300);
1484  builder.Scale(3, 3);
1485  draw_image_layer(effect_paint);
1486 
1487  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1488 }
1489 
1490 TEST_P(AiksTest, FastEllipticalRRectMaskBlursRenderCorrectly) {
1491  DisplayListBuilder builder;
1492 
1493  builder.Scale(GetContentScale().x, GetContentScale().y);
1494  DlPaint paint;
1495  paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
1496 
1497  DlPaint save_paint;
1498  save_paint.setColor(DlColor::kWhite());
1499  builder.DrawPaint(save_paint);
1500 
1501  paint.setColor(DlColor::kBlue());
1502  for (int i = 0; i < 5; i++) {
1503  Scalar y = i * 125;
1504  Scalar y_radius = i * 15;
1505  for (int j = 0; j < 5; j++) {
1506  Scalar x = j * 125;
1507  Scalar x_radius = j * 15;
1508  builder.DrawRoundRect(
1509  DlRoundRect::MakeRectXY(
1510  DlRect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f), //
1511  x_radius, y_radius),
1512  paint);
1513  }
1514  }
1515 
1516  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1517 }
1518 
1519 TEST_P(AiksTest, PipelineBlendSingleParameter) {
1520  DisplayListBuilder builder;
1521 
1522  // Should render a green square in the middle of a blue circle.
1523  DlPaint paint;
1524  builder.SaveLayer(std::nullopt, &paint);
1525  {
1526  builder.Translate(100, 100);
1527  paint.setColor(DlColor::kBlue());
1528  builder.DrawCircle(DlPoint(200, 200), 200, paint);
1529  builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1530 
1531  paint.setColor(DlColor::kGreen());
1532  paint.setBlendMode(DlBlendMode::kSrcOver);
1533  paint.setImageFilter(DlImageFilter::MakeColorFilter(
1534  DlColorFilter::MakeBlend(DlColor::kWhite(), DlBlendMode::kDst)));
1535  builder.DrawCircle(DlPoint(200, 200), 200, paint);
1536  builder.Restore();
1537  }
1538 
1539  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1540 }
1541 
1542 // Creates an image matrix filter that scales large content such that it would
1543 // exceed the max texture size. See
1544 // https://github.com/flutter/flutter/issues/128912
1545 TEST_P(AiksTest, MassiveScalingMatrixImageFilter) {
1546  if (GetBackend() == PlaygroundBackend::kVulkan) {
1547  GTEST_SKIP() << "Swiftshader is running out of memory on this example.";
1548  }
1549  DisplayListBuilder builder(DlRect::MakeSize(DlSize(1000, 1000)));
1550 
1551  auto filter = DlImageFilter::MakeMatrix(
1552  DlMatrix::MakeScale({0.001, 0.001, 1}), DlImageSampling::kLinear);
1553 
1554  DlPaint paint;
1555  paint.setImageFilter(filter);
1556  builder.SaveLayer(std::nullopt, &paint);
1557  {
1558  DlPaint paint;
1559  paint.setColor(DlColor::kRed());
1560  builder.DrawRect(DlRect::MakeLTRB(0, 0, 100000, 100000), paint);
1561  }
1562  builder.Restore();
1563 
1564  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1565 }
1566 
1567 TEST_P(AiksTest, NoDimplesInRRectPath) {
1568  Scalar width = 200.f;
1569  Scalar height = 60.f;
1570  Scalar corner = 1.f;
1571  auto callback = [&]() -> sk_sp<DisplayList> {
1572  if (AiksTest::ImGuiBegin("Controls", nullptr,
1573  ImGuiWindowFlags_AlwaysAutoResize)) {
1574  ImGui::SliderFloat("width", &width, 0, 200);
1575  ImGui::SliderFloat("height", &height, 0, 200);
1576  ImGui::SliderFloat("corner", &corner, 0, 1);
1577  ImGui::End();
1578  }
1579 
1580  DisplayListBuilder builder;
1581  builder.Scale(GetContentScale().x, GetContentScale().y);
1582 
1583  DlPaint background_paint;
1584  background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
1585  builder.DrawPaint(background_paint);
1586 
1587  std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
1588  std::vector<Scalar> stops = {0.0, 1.0};
1589 
1590  DlPaint paint;
1591  auto gradient = DlColorSource::MakeLinear(DlPoint(0, 0), DlPoint(200, 200),
1592  2, colors.data(), stops.data(),
1593  DlTileMode::kClamp);
1594  paint.setColorSource(gradient);
1595  paint.setColor(DlColor::kWhite());
1596  paint.setDrawStyle(DlDrawStyle::kStroke);
1597  paint.setStrokeWidth(20);
1598 
1599  builder.Save();
1600  builder.Translate(100, 100);
1601 
1602  Scalar corner_x = ((1 - corner) * 50) + 50;
1603  Scalar corner_y = corner * 50 + 50;
1604  DlRoundRect rrect = DlRoundRect::MakeRectXY(
1605  DlRect::MakeXYWH(0, 0, width, height), corner_x, corner_y);
1606  builder.DrawRoundRect(rrect, paint);
1607  builder.Restore();
1608  return builder.Build();
1609  };
1610  ASSERT_TRUE(OpenPlaygroundHere(callback));
1611 }
1612 
1613 TEST_P(AiksTest, BackdropFilterOverUnclosedClip) {
1614  DisplayListBuilder builder;
1615 
1616  builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
1617  builder.Save();
1618  {
1619  builder.ClipRect(DlRect::MakeLTRB(100, 100, 800, 800));
1620 
1621  builder.Save();
1622  {
1623  builder.ClipRect(DlRect::MakeLTRB(600, 600, 800, 800));
1624  builder.DrawPaint(DlPaint().setColor(DlColor::kRed()));
1625  builder.DrawPaint(DlPaint().setColor(DlColor::kBlue().withAlphaF(0.5)));
1626  builder.ClipRect(DlRect::MakeLTRB(700, 700, 750, 800));
1627  builder.DrawPaint(DlPaint().setColor(DlColor::kRed().withAlphaF(0.5)));
1628  }
1629  builder.Restore();
1630 
1631  auto image_filter = DlImageFilter::MakeBlur(10, 10, DlTileMode::kDecal);
1632  builder.SaveLayer(std::nullopt, nullptr, image_filter.get());
1633  }
1634  builder.Restore();
1635  builder.DrawCircle(DlPoint(100, 100), 100,
1636  DlPaint().setColor(DlColor::kAqua()));
1637 
1638  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1639 }
1640 
1641 } // namespace testing
1642 } // namespace impeller
static bool ImGuiBegin(const char *name, bool *p_open, ImGuiWindowFlags flags)
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
int32_t x
AiksPlayground AiksTest
TEST_P(AiksTest, DrawAtlasNoColor)
flutter::DlRect DlRect
Definition: dl_dispatcher.h:25
float Scalar
Definition: scalar.h:18
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition: widgets.cc:50
flutter::DlRoundRect DlRoundRect
Definition: dl_dispatcher.h:27
TPoint< Scalar > Point
Definition: point.h:327
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
flutter::DlPath DlPath
Definition: dl_dispatcher.h:29
TSize< Scalar > Size
Definition: size.h:159
constexpr const char * PixelFormatToString(PixelFormat format)
Definition: formats.h:140
flutter::DlScalar DlScalar
Definition: dl_dispatcher.h:23
const Scalar stroke_width
SeparatedVector2 offset
static constexpr Color White()
Definition: color.h:264
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
static Matrix MakeRotationY(Radians r)
Definition: matrix.h:208
constexpr Quad Transform(const Quad &quad) const
Definition: matrix.h:556
constexpr static RoundRect MakeRectXY(const Rect &rect, Scalar x_radius, Scalar y_radius)
Definition: round_rect.h:30