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