| Flutter Impeller |

aiks_dl_unittests.cc
Go to the documentation of this file.
1
2 // Copyright 2013 The Flutter Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5
6 #include <vector>
7 #include "display_list/dl_sampling_options.h"
8 #include "display_list/dl_tile_mode.h"
9 #include "display_list/effects/dl_color_filter.h"
10 #include "display_list/effects/dl_color_source.h"
11 #include "display_list/effects/dl_image_filter.h"
12 #include "display_list/geometry/dl_geometry_types.h"
13 #include "display_list/geometry/dl_path.h"
14 #include "display_list/image/dl_image.h"
15 #include "flutter/impeller/display_list/aiks_unittests.h"
16
17 #include "flutter/display_list/dl_blend_mode.h"
18 #include "flutter/display_list/dl_builder.h"
19 #include "flutter/display_list/dl_color.h"
20 #include "flutter/display_list/dl_paint.h"
21 #include "flutter/testing/testing.h"
22 #include "fml/synchronization/count_down_latch.h"
23 #include "gtest/gtest.h"
24 #include "imgui.h"
25 #include "impeller/base/validation.h"
26 #include "impeller/core/device_buffer.h"
27 #include "impeller/core/device_buffer_descriptor.h"
28 #include "impeller/core/formats.h"
29 #include "impeller/core/texture_descriptor.h"
30 #include "impeller/display_list/aiks_context.h"
31 #include "impeller/display_list/dl_dispatcher.h"
32 #include "impeller/display_list/dl_image_impeller.h"
33 #include "impeller/geometry/path_builder.h"
34 #include "impeller/geometry/scalar.h"
35 #include "impeller/playground/playground.h"
36 #include "include/core/SkCanvas.h"
37 #include "include/core/SkMatrix.h"
38 #include "include/core/SkPath.h"
39 #include "include/core/SkRefCnt.h"
40
41 namespace impeller {
42 namespace testing {
43
44 using namespace flutter;
45
46 namespace {
47 SkRect GetCullRect(ISize window_size) {
48 return SkRect::MakeSize(SkSize::Make(window_size.width, window_size.height));
49 }
50 } // namespace
51
52 TEST_P(AiksTest, CollapsedDrawPaintInSubpass) {
53 DisplayListBuilder builder;
54
55 DlPaint paint;
56 paint.setColor(DlColor::kYellow());
57 paint.setBlendMode(DlBlendMode::kSrc);
58 builder.DrawPaint(paint);
59
60 DlPaint save_paint;
61 save_paint.setBlendMode(DlBlendMode::kMultiply);
62 builder.SaveLayer(nullptr, &save_paint);
63
64 DlPaint draw_paint;
65 draw_paint.setColor(DlColor::kCornflowerBlue().modulateOpacity(0.75f));
66 builder.DrawPaint(draw_paint);
67
68 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
69 }
70
71 TEST_P(AiksTest, CollapsedDrawPaintInSubpassBackdropFilter) {
72 // Bug: https://github.com/flutter/flutter/issues/131576
73 DisplayListBuilder builder;
74
75 DlPaint paint;
76 paint.setColor(DlColor::kYellow());
77 paint.setBlendMode(DlBlendMode::kSrc);
78 builder.DrawPaint(paint);
79
80 auto filter = DlImageFilter::MakeBlur(20.0, 20.0, DlTileMode::kDecal);
81 builder.SaveLayer(nullptr, nullptr, filter.get());
82
83 DlPaint draw_paint;
84 draw_paint.setColor(DlColor::kCornflowerBlue());
85 builder.DrawPaint(draw_paint);
86
87 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
88 }
89
90 TEST_P(AiksTest, ColorMatrixFilterSubpassCollapseOptimization) {
91 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
92
93 const float matrix[20] = {
94 -1.0, 0, 0, 1.0, 0, //
95 0, -1.0, 0, 1.0, 0, //
96 0, 0, -1.0, 1.0, 0, //
97 1.0, 1.0, 1.0, 1.0, 0 //
98 };
99 auto filter = DlColorFilter::MakeMatrix(matrix);
100
101 DlPaint paint;
102 paint.setColorFilter(filter);
103 builder.SaveLayer(nullptr, &paint);
104
105 builder.Translate(500, 300);
106 builder.Rotate(120); // 120 deg
107
108 DlPaint draw_paint;
109 draw_paint.setColor(DlColor::kBlue());
110 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
111
112 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
113 }
114
115 TEST_P(AiksTest, LinearToSrgbFilterSubpassCollapseOptimization) {
116 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
117
118 DlPaint paint;
119 paint.setColorFilter(DlColorFilter::MakeLinearToSrgbGamma());
120 builder.SaveLayer(nullptr, &paint);
121
122 builder.Translate(500, 300);
123 builder.Rotate(120); // 120 deg.
124
125 DlPaint draw_paint;
126 draw_paint.setColor(DlColor::kBlue());
127 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
128
129 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
130 }
131
132 TEST_P(AiksTest, SrgbToLinearFilterSubpassCollapseOptimization) {
133 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
134
135 DlPaint paint;
136 paint.setColorFilter(DlColorFilter::MakeLinearToSrgbGamma());
137 builder.SaveLayer(nullptr, &paint);
138
139 builder.Translate(500, 300);
140 builder.Rotate(120); // 120 deg
141
142 DlPaint draw_paint;
143 draw_paint.setColor(DlColor::kBlue());
144 builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
145
146 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
147 }
148
149 TEST_P(AiksTest, TranslucentSaveLayerDrawsCorrectly) {
150 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
151
152 DlPaint paint;
153 paint.setColor(DlColor::kBlue());
154 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
155
156 DlPaint save_paint;
157 save_paint.setColor(DlColor::kBlack().withAlpha(128));
158 builder.SaveLayer(nullptr, &save_paint);
159 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), paint);
160 builder.Restore();
161
162 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
163 }
164
165 TEST_P(AiksTest, TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly) {
166 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
167
168 DlPaint paint;
169 paint.setColor(DlColor::kBlue());
170 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
171
172 DlPaint save_paint;
173 paint.setColor(DlColor::kBlack().withAlpha(128));
174 paint.setColorFilter(
175 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kDstOver));
176 builder.Save();
177 builder.ClipRect(SkRect::MakeXYWH(100, 500, 300, 300));
178 builder.SaveLayer(nullptr, &paint);
179
180 DlPaint draw_paint;
181 draw_paint.setColor(DlColor::kBlue());
182 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
183 builder.Restore();
184 builder.Restore();
185
186 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
187 }
188
189 TEST_P(AiksTest, TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly) {
190 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
191
192 DlPaint paint;
193 paint.setColor(DlColor::kBlue());
194 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
195
196 DlPaint save_paint;
197 save_paint.setColor(DlColor::kBlack().withAlpha(128));
198 save_paint.setImageFilter(DlImageFilter::MakeColorFilter(
199 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kDstOver)));
200
201 builder.SaveLayer(nullptr, &save_paint);
202
203 DlPaint draw_paint;
204 draw_paint.setColor(DlColor::kBlue());
205 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
206 builder.Restore();
207
208 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
209 }
210
211 TEST_P(AiksTest, TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly) {
212 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
213
214 DlPaint paint;
215 paint.setColor(DlColor::kBlue());
216 builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
217
218 DlPaint save_paint;
219 save_paint.setColor(DlColor::kBlack().withAlpha(128));
220 save_paint.setColorFilter(
221 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kDstOver));
222 builder.Save();
223 builder.ClipRect(SkRect::MakeXYWH(100, 500, 300, 300));
224 builder.SaveLayer(nullptr, &save_paint);
225
226 DlPaint draw_paint;
227 draw_paint.setColor(DlColor::kBlue());
228 builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
229 builder.Restore();
230 builder.Restore();
231
232 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
233 }
234
235 TEST_P(AiksTest, ImageFilteredUnboundedSaveLayerWithUnboundedContents) {
236 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
237 builder.Scale(GetContentScale().x, GetContentScale().y);
238
239 DlPaint save_paint;
240 save_paint.setImageFilter(
241 DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal));
242 builder.SaveLayer(nullptr, &save_paint);
243
244 {
245 // DrawPaint to verify correct behavior when the contents are unbounded.
246 DlPaint draw_paint;
247 draw_paint.setColor(DlColor::kYellow());
248 builder.DrawPaint(draw_paint);
249
250 // Contrasting rectangle to see interior blurring
251 DlPaint draw_rect;
252 draw_rect.setColor(DlColor::kBlue());
253 builder.DrawRect(SkRect::MakeLTRB(125, 125, 175, 175), draw_rect);
254 }
255 builder.Restore();
256
257 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
258 }
259
260 TEST_P(AiksTest, TranslucentSaveLayerImageDrawsCorrectly) {
261 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
262
263 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
264 builder.DrawImage(image, SkPoint{100, 100}, DlImageSampling::kMipmapLinear);
265
266 DlPaint paint;
267 paint.setColor(DlColor::kBlack().withAlpha(128));
268 builder.SaveLayer(nullptr, &paint);
269 builder.DrawImage(image, SkPoint{100, 500}, DlImageSampling::kMipmapLinear);
270 builder.Restore();
271
272 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
273 }
274
275 TEST_P(AiksTest, TranslucentSaveLayerWithColorMatrixColorFilterDrawsCorrectly) {
276 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
277
278 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
279 builder.DrawImage(image, SkPoint{100, 100}, {});
280
281 const float matrix[20] = {
282 1, 0, 0, 0, 0, //
283 0, 1, 0, 0, 0, //
284 0, 0, 1, 0, 0, //
285 0, 0, 0, 2, 0 //
286 };
287 DlPaint paint;
288 paint.setColor(DlColor::kBlack().withAlpha(128));
289 paint.setColorFilter(DlColorFilter::MakeMatrix(matrix));
290 builder.SaveLayer(nullptr, &paint);
291 builder.DrawImage(image, SkPoint{100, 500}, {});
292 builder.Restore();
293
294 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
295 }
296
297 TEST_P(AiksTest, TranslucentSaveLayerWithColorMatrixImageFilterDrawsCorrectly) {
298 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
299
300 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
301 builder.DrawImage(image, SkPoint{100, 100}, {});
302
303 const float matrix[20] = {
304 1, 0, 0, 0, 0, //
305 0, 1, 0, 0, 0, //
306 0, 0, 1, 0, 0, //
307 0, 0, 0, 2, 0 //
308 };
309 DlPaint paint;
310 paint.setColor(DlColor::kBlack().withAlpha(128));
311 paint.setColorFilter(DlColorFilter::MakeMatrix(matrix));
312 builder.SaveLayer(nullptr, &paint);
313 builder.DrawImage(image, SkPoint{100, 500}, {});
314 builder.Restore();
315
316 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
317 }
318
319 TEST_P(AiksTest,
320 TranslucentSaveLayerWithColorFilterAndImageFilterDrawsCorrectly) {
321 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
322
323 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
324 builder.DrawImage(image, SkPoint{100, 100}, {});
325
326 const float matrix[20] = {
327 1, 0, 0, 0, 0, //
328 0, 1, 0, 0, 0, //
329 0, 0.2, 1, 0, 0, //
330 0, 0, 0, 0.5, 0 //
331 };
332 DlPaint paint;
333 paint.setColor(DlColor::kBlack().withAlpha(128));
334 paint.setImageFilter(
335 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(matrix)));
336 paint.setColorFilter(
337 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kModulate));
338 builder.SaveLayer(nullptr, &paint);
339 builder.DrawImage(image, SkPoint{100, 500}, {});
340 builder.Restore();
341
342 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
343 }
344
345 TEST_P(AiksTest, TranslucentSaveLayerWithAdvancedBlendModeDrawsCorrectly) {
346 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
347
348 DlPaint paint;
349 paint.setColor(DlColor::kRed());
350 builder.DrawRect(SkRect::MakeXYWH(0, 0, 400, 400), paint);
351
352 DlPaint save_paint;
353 save_paint.setAlpha(128);
354 save_paint.setBlendMode(DlBlendMode::kLighten);
355 builder.SaveLayer(nullptr, &save_paint);
356
357 DlPaint draw_paint;
358 draw_paint.setColor(DlColor::kGreen());
359 builder.DrawCircle(SkPoint{200, 200}, 100, draw_paint);
360 builder.Restore();
361
362 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
363 }
364
365 /// This is a regression check for https://github.com/flutter/engine/pull/41129
366 /// The entire screen is green if successful. If failing, no frames will render,
367 /// or the entire screen will be transparent black.
368 TEST_P(AiksTest, CanRenderTinyOverlappingSubpasses) {
369 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
370
371 DlPaint paint;
372 paint.setColor(DlColor::kRed());
373 builder.DrawPaint(paint);
374
375 // Draw two overlapping subpixel circles.
376 builder.SaveLayer({});
377
378 DlPaint yellow_paint;
379 yellow_paint.setColor(DlColor::kYellow());
380 builder.DrawCircle(SkPoint{100, 100}, 0.1, yellow_paint);
381 builder.Restore();
382 builder.SaveLayer({});
383 builder.DrawCircle(SkPoint{100, 100}, 0.1, yellow_paint);
384 builder.Restore();
385
386 DlPaint draw_paint;
387 draw_paint.setColor(DlColor::kGreen());
388 builder.DrawPaint(draw_paint);
389
390 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
391 }
392
393 TEST_P(AiksTest, CanRenderDestructiveSaveLayer) {
394 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
395
396 DlPaint paint;
397 paint.setColor(DlColor::kRed());
398 builder.DrawPaint(paint);
399 // Draw an empty savelayer with a destructive blend mode, which will replace
400 // the entire red screen with fully transparent black, except for the green
401 // circle drawn within the layer.
402
403 DlPaint save_paint;
404 save_paint.setBlendMode(DlBlendMode::kSrc);
405 builder.SaveLayer(nullptr, &save_paint);
406
407 DlPaint draw_paint;
408 draw_paint.setColor(DlColor::kGreen());
409 builder.DrawCircle(SkPoint{300, 300}, 100, draw_paint);
410 builder.Restore();
411
412 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
413 }
414
415 TEST_P(AiksTest, CanDrawPoints) {
416 std::vector<SkPoint> points = {
417 {0, 0}, //
418 {100, 100}, //
419 {100, 0}, //
420 {0, 100}, //
421 {0, 0}, //
422 {48, 48}, //
423 {52, 52}, //
424 };
425 DlPaint paint_round;
426 paint_round.setColor(DlColor::kYellow().withAlpha(128));
427 paint_round.setStrokeCap(DlStrokeCap::kRound);
428 paint_round.setStrokeWidth(20);
429
430 DlPaint paint_square;
431 paint_square.setColor(DlColor::kYellow().withAlpha(128));
432 paint_square.setStrokeCap(DlStrokeCap::kSquare);
433 paint_square.setStrokeWidth(20);
434
435 DlPaint background;
436 background.setColor(DlColor::kBlack());
437
438 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
439 builder.DrawPaint(background);
440 builder.Translate(200, 200);
441
442 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
443 paint_round);
444 builder.Translate(150, 0);
445 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
446 paint_square);
447
448 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
449 }
450
451 TEST_P(AiksTest, CanDrawPointsWithTextureMap) {
452 auto texture = DlImageImpeller::Make(
453 CreateTextureForFixture("table_mountain_nx.png",
454 /*enable_mipmapping=*/true));
455
456 std::vector<SkPoint> points = {
457 {0, 0}, //
458 {100, 100}, //
459 {100, 0}, //
460 {0, 100}, //
461 {0, 0}, //
462 {48, 48}, //
463 {52, 52}, //
464 };
465
466 auto image_src =
467 DlColorSource::MakeImage(texture, DlTileMode::kClamp, DlTileMode::kClamp);
468
469 DlPaint paint_round;
470 paint_round.setStrokeCap(DlStrokeCap::kRound);
471 paint_round.setColorSource(image_src);
472 paint_round.setStrokeWidth(200);
473
474 DlPaint paint_square;
475 paint_square.setStrokeCap(DlStrokeCap::kSquare);
476 paint_square.setColorSource(image_src);
477 paint_square.setStrokeWidth(200);
478
479 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
480 builder.Translate(200, 200);
481
482 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
483 paint_round);
484 builder.Translate(150, 0);
485 builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
486 paint_square);
487
488 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
489 }
490
491 TEST_P(AiksTest, MipmapGenerationWorksCorrectly) {
492 TextureDescriptor texture_descriptor;
493 texture_descriptor.size = ISize{1024, 1024};
494 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
495 texture_descriptor.storage_mode = StorageMode::kHostVisible;
496 texture_descriptor.mip_count = texture_descriptor.size.MipCount();
497
498 std::vector<uint8_t> bytes(4194304);
499 bool alternate = false;
500 for (auto i = 0u; i < 4194304; i += 4) {
501 if (alternate) {
502 bytes[i] = 255;
503 bytes[i + 1] = 0;
504 bytes[i + 2] = 0;
505 bytes[i + 3] = 255;
506 } else {
507 bytes[i] = 0;
508 bytes[i + 1] = 255;
509 bytes[i + 2] = 0;
510 bytes[i + 3] = 255;
511 }
512 alternate = !alternate;
513 }
514
515 ASSERT_EQ(texture_descriptor.GetByteSizeOfBaseMipLevel(), bytes.size());
516 auto mapping = std::make_shared<fml::NonOwnedMapping>(
517 bytes.data(), // data
518 texture_descriptor.GetByteSizeOfBaseMipLevel() // size
519 );
520 auto texture =
521 GetContext()->GetResourceAllocator()->CreateTexture(texture_descriptor);
522
523 auto device_buffer =
524 GetContext()->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
525 auto command_buffer = GetContext()->CreateCommandBuffer();
526 auto blit_pass = command_buffer->CreateBlitPass();
527
528 blit_pass->AddCopy(DeviceBuffer::AsBufferView(std::move(device_buffer)),
529 texture);
530 blit_pass->GenerateMipmap(texture);
531 EXPECT_TRUE(blit_pass->EncodeCommands());
532 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({command_buffer}).ok());
533
534 auto image = DlImageImpeller::Make(texture);
535
536 DisplayListBuilder builder;
537 builder.DrawImageRect(
538 image,
539 SkRect::MakeSize(
540 SkSize::Make(texture->GetSize().width, texture->GetSize().height)),
541 SkRect::MakeLTRB(0, 0, 100, 100), DlImageSampling::kMipmapLinear);
542
543 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
544 }
545
546 // https://github.com/flutter/flutter/issues/146648
547 TEST_P(AiksTest, StrokedPathWithMoveToThenCloseDrawnCorrectly) {
548 SkPath path;
549 path.moveTo(0, 400)
550 .lineTo(0, 0)
551 .lineTo(400, 0)
552 // MoveTo implicitly adds a contour, ensure that close doesn't
553 // add another nearly-empty contour.
554 .moveTo(0, 400)
555 .close();
556
557 DisplayListBuilder builder;
558 builder.Translate(50, 50);
559
560 DlPaint paint;
561 paint.setColor(DlColor::kBlue());
562 paint.setStrokeCap(DlStrokeCap::kRound);
563 paint.setStrokeWidth(10);
564 paint.setDrawStyle(DlDrawStyle::kStroke);
565 builder.DrawPath(path, paint);
566
567 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
568 }
569
570 TEST_P(AiksTest, SetContentsWithRegion) {
571 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
572
573 // Replace part of the texture with a red rectangle.
574 std::vector<uint8_t> bytes(100 * 100 * 4);
575 for (auto i = 0u; i < bytes.size(); i += 4) {
576 bytes[i] = 255;
577 bytes[i + 1] = 0;
578 bytes[i + 2] = 0;
579 bytes[i + 3] = 255;
580 }
581 auto mapping =
582 std::make_shared<fml::NonOwnedMapping>(bytes.data(), bytes.size());
583 auto device_buffer =
584 GetContext()->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
585 auto cmd_buffer = GetContext()->CreateCommandBuffer();
586 auto blit_pass = cmd_buffer->CreateBlitPass();
587 blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer), bridge,
588 IRect::MakeLTRB(50, 50, 150, 150));
589
590 auto did_submit =
591 blit_pass->EncodeCommands() &&
592 GetContext()->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok();
593 ASSERT_TRUE(did_submit);
594
595 auto image = DlImageImpeller::Make(bridge);
596
597 DisplayListBuilder builder;
598 builder.DrawImage(image, SkPoint{0, 0}, {});
599
600 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
601 }
602
603 // Regression test for https://github.com/flutter/flutter/issues/134678.
604 TEST_P(AiksTest, ReleasesTextureOnTeardown) {
605 auto context = MakeContext();
606 std::weak_ptr<Texture> weak_texture;
607
608 {
609 auto texture = CreateTextureForFixture("table_mountain_nx.png");
610 weak_texture = texture;
611
612 DisplayListBuilder builder;
613 builder.Scale(GetContentScale().x, GetContentScale().y);
614 builder.Translate(100.0f, 100.0f);
615
616 DlPaint paint;
617 paint.setColorSource(DlColorSource::MakeImage(
618 DlImageImpeller::Make(texture), DlTileMode::kClamp, DlTileMode::kClamp,
619 DlImageSampling::kLinear, nullptr));
620
621 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
622
623 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
624 }
625
626 // See https://github.com/flutter/flutter/issues/134751.
627 //
628 // If the fence waiter was working this may not be released by the end of the
629 // scope above. Adding a manual shutdown so that future changes to the fence
630 // waiter will not flake this test.
631 context->Shutdown();
632
633 // The texture should be released by now.
634 ASSERT_TRUE(weak_texture.expired()) << "When the texture is no longer in use "
635 "by the backend, it should be "
636 "released.";
637 }
638
639 TEST_P(AiksTest, MatrixImageFilterMagnify) {
640 Scalar scale = 2.0;
641 auto callback = [&]() -> sk_sp<DisplayList> {
642 if (AiksTest::ImGuiBegin("Controls", nullptr,
643 ImGuiWindowFlags_AlwaysAutoResize)) {
644 ImGui::SliderFloat("Scale", &scale, 1, 2);
645 ImGui::End();
646 }
647 DisplayListBuilder builder;
648 builder.Scale(GetContentScale().x, GetContentScale().y);
649 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
650
651 builder.Translate(600, -200);
652
653 DlMatrix matrix = DlMatrix::MakeScale({scale, scale, 1});
654 DlPaint paint;
655 paint.setImageFilter(
656 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear));
657 builder.SaveLayer(nullptr, &paint);
658
659 DlPaint rect_paint;
660 rect_paint.setAlpha(0.5 * 255);
661 builder.DrawImage(image, SkPoint{0, 0}, DlImageSampling::kLinear,
662 &rect_paint);
663 builder.Restore();
664
665 return builder.Build();
666 };
667
668 ASSERT_TRUE(OpenPlaygroundHere(callback));
669 }
670
671 TEST_P(AiksTest, ImageFilteredSaveLayerWithUnboundedContents) {
672 DisplayListBuilder builder;
673 builder.Scale(GetContentScale().x, GetContentScale().y);
674
675 auto test = [&builder](const std::shared_ptr<DlImageFilter>& filter) {
676 auto DrawLine = [&builder](const SkPoint& p0, const SkPoint& p1,
677 const DlPaint& p) {
678 DlPaint paint = p;
679 paint.setDrawStyle(DlDrawStyle::kStroke);
680 builder.DrawPath(SkPath::Line(p0, p1), paint);
681 };
682 // Registration marks for the edge of the SaveLayer
683 DlPaint paint;
684 paint.setColor(DlColor::kWhite());
685 DrawLine(SkPoint::Make(75, 100), SkPoint::Make(225, 100), paint);
686 DrawLine(SkPoint::Make(75, 200), SkPoint::Make(225, 200), paint);
687 DrawLine(SkPoint::Make(100, 75), SkPoint::Make(100, 225), paint);
688 DrawLine(SkPoint::Make(200, 75), SkPoint::Make(200, 225), paint);
689
690 DlPaint save_paint;
691 save_paint.setImageFilter(filter);
692 SkRect bounds = SkRect::MakeLTRB(100, 100, 200, 200);
693 builder.SaveLayer(&bounds, &save_paint);
694
695 {
696 // DrawPaint to verify correct behavior when the contents are unbounded.
697 DlPaint paint;
698 paint.setColor(DlColor::kYellow());
699 builder.DrawPaint(paint);
700
701 // Contrasting rectangle to see interior blurring
702 paint.setColor(DlColor::kBlue());
703 builder.DrawRect(SkRect::MakeLTRB(125, 125, 175, 175), paint);
704 }
705 builder.Restore();
706 };
707
708 test(DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal));
709
710 builder.Translate(200.0, 0.0);
711
712 test(DlImageFilter::MakeDilate(10.0, 10.0));
713
714 builder.Translate(200.0, 0.0);
715
716 test(DlImageFilter::MakeErode(10.0, 10.0));
717
718 builder.Translate(-400.0, 200.0);
719
720 DlMatrix matrix = DlMatrix::MakeRotationZ(DlDegrees(10));
721
722 auto rotate_filter =
723 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear);
724 test(rotate_filter);
725
726 builder.Translate(200.0, 0.0);
727
728 const float m[20] = {
729 0, 1, 0, 0, 0, //
730 0, 0, 1, 0, 0, //
731 1, 0, 0, 0, 0, //
732 0, 0, 0, 1, 0 //
733 };
734 auto rgb_swap_filter =
735 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(m));
736 test(rgb_swap_filter);
737
738 builder.Translate(200.0, 0.0);
739
740 test(DlImageFilter::MakeCompose(rotate_filter, rgb_swap_filter));
741
742 builder.Translate(-400.0, 200.0);
743
744 test(rotate_filter->makeWithLocalMatrix(
745 DlMatrix::MakeTranslation({25.0, 25.0})));
746
747 builder.Translate(200.0, 0.0);
748
749 test(rgb_swap_filter->makeWithLocalMatrix(
750 DlMatrix::MakeTranslation({25.0, 25.0})));
751
752 builder.Translate(200.0, 0.0);
753
754 test(DlImageFilter::MakeCompose(rotate_filter, rgb_swap_filter)
755 ->makeWithLocalMatrix(DlMatrix::MakeTranslation({25.0, 25.0})));
756
757 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
758 }
759
760 TEST_P(AiksTest, MatrixBackdropFilter) {
761 DisplayListBuilder builder;
762
763 DlPaint paint;
764 paint.setColor(DlColor::kBlack());
765 builder.DrawPaint(paint);
766 builder.SaveLayer(nullptr, nullptr);
767 {
768 DlPaint paint;
769 paint.setColor(DlColor::kGreen().withAlpha(0.5 * 255));
770 paint.setBlendMode(DlBlendMode::kPlus);
771
772 DlPaint rect_paint;
773 rect_paint.setColor(DlColor::kRed());
774 rect_paint.setStrokeWidth(4);
775 rect_paint.setDrawStyle(DlDrawStyle::kStroke);
776 builder.DrawRect(SkRect::MakeLTRB(0, 0, 300, 300), rect_paint);
777 builder.DrawCircle(SkPoint::Make(200, 200), 100, paint);
778 // Should render a second circle, centered on the bottom-right-most edge of
779 // the circle.
780 DlMatrix matrix = DlMatrix::MakeTranslation({(100 + 100 * k1OverSqrt2),
781 (100 + 100 * k1OverSqrt2)}) *
782 DlMatrix::MakeScale({0.5, 0.5, 1}) *
783 DlMatrix::MakeTranslation({-100, -100});
784 auto backdrop_filter =
785 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear);
786 builder.SaveLayer(nullptr, nullptr, backdrop_filter.get());
787 builder.Restore();
788 }
789 builder.Restore();
790
791 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
792 }
793
794 TEST_P(AiksTest, MatrixSaveLayerFilter) {
795 DisplayListBuilder builder;
796
797 DlPaint paint;
798 paint.setColor(DlColor::kBlack());
799 builder.DrawPaint(paint);
800 builder.SaveLayer(nullptr, nullptr);
801 {
802 paint.setColor(DlColor::kGreen().withAlpha(255 * 0.5));
803 paint.setBlendMode(DlBlendMode::kPlus);
804 builder.DrawCircle(SkPoint{200, 200}, 100, paint);
805 // Should render a second circle, centered on the bottom-right-most edge of
806 // the circle.
807
808 DlMatrix matrix = DlMatrix::MakeTranslation({(200 + 100 * k1OverSqrt2),
809 (200 + 100 * k1OverSqrt2)}) *
810 DlMatrix::MakeScale({0.5, 0.5, 1}) *
811 DlMatrix::MakeTranslation({-200, -200});
812 DlPaint save_paint;
813 save_paint.setImageFilter(
814 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear));
815
816 builder.SaveLayer(nullptr, &save_paint);
817
818 DlPaint circle_paint;
819 circle_paint.setColor(DlColor::kGreen().withAlpha(255 * 0.5));
820 circle_paint.setBlendMode(DlBlendMode::kPlus);
821 builder.DrawCircle(SkPoint{200, 200}, 100, circle_paint);
822 builder.Restore();
823 }
824 builder.Restore();
825
826 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
827 }
828
829 // Regression test for flutter/flutter#152780
830 TEST_P(AiksTest, CanDrawScaledPointsSmallScaleLargeRadius) {
831 std::vector<SkPoint> point = {
832 {0, 0}, //
833 };
834
835 DlPaint paint;
836 paint.setStrokeCap(DlStrokeCap::kRound);
837 paint.setColor(DlColor::kRed());
838 paint.setStrokeWidth(100 * 1000000);
839
840 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
841 builder.Translate(200, 200);
842 builder.Scale(0.000001, 0.000001);
843
844 builder.DrawPoints(DlCanvas::PointMode::kPoints, point.size(), point.data(),
845 paint);
846
847 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
848 }
849
850 // Regression test for flutter/flutter#152780
851 TEST_P(AiksTest, CanDrawScaledPointsLargeScaleSmallRadius) {
852 std::vector<SkPoint> point = {
853 {0, 0}, //
854 };
855
856 DlPaint paint;
857 paint.setStrokeCap(DlStrokeCap::kRound);
858 paint.setColor(DlColor::kRed());
859 paint.setStrokeWidth(100 * 0.000001);
860
861 DisplayListBuilder builder(GetCullRect(GetWindowSize()));
862 builder.Translate(200, 200);
863 builder.Scale(1000000, 1000000);
864
865 builder.DrawPoints(DlCanvas::PointMode::kPoints, point.size(), point.data(),
866 paint);
867 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
868 }
869
870 TEST_P(AiksTest, TransparentShadowProducesCorrectColor) {
871 DisplayListBuilder builder;
872 builder.Save();
873 builder.Scale(1.618, 1.618);
874 SkPath path = SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100));
875
876 builder.DrawShadow(path, flutter::DlColor::kTransparent(), 15, false, 1);
877 builder.Restore();
878
879 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
880 }
881
882 // Regression test for https://github.com/flutter/flutter/issues/130613
883 TEST_P(AiksTest, DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists) {
884 flutter::DisplayListBuilder sub_builder(true);
885 sub_builder.DrawRect(SkRect::MakeXYWH(0, 0, 50, 50),
886 flutter::DlPaint(flutter::DlColor::kRed()));
887 auto display_list = sub_builder.Build();
888
889 AiksContext context(GetContext(), nullptr);
890 RenderTarget render_target =
891 context.GetContentContext().GetRenderTargetCache()->CreateOffscreen(
892 *context.GetContext(), {2400, 1800}, 1);
893
894 DisplayListBuilder builder;
895
896 builder.Scale(2.0, 2.0);
897 builder.Translate(-93.0, 0.0);
898
899 // clang-format off
900 builder.TransformFullPerspective(
901 0.8, -0.2, -0.1, -0.0,
902 0.0, 1.0, 0.0, 0.0,
903 1.4, 1.3, 1.0, 0.0,
904 63.2, 65.3, 48.6, 1.1
905 );
906 // clang-format on
907 builder.Translate(35.0, 75.0);
908 builder.DrawDisplayList(display_list, 1.0f);
909
910 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
911 }
912
913 // Results in a 100x100 green square. If any red is drawn, there is a bug.
914 TEST_P(AiksTest, BackdropRestoreUsesCorrectCoverageForFirstRestoredClip) {
915 DisplayListBuilder builder;
916
917 DlPaint paint;
918 // Add a difference clip that cuts out the bottom right corner
919 builder.ClipRect(SkRect::MakeLTRB(50, 50, 100, 100),
920 DlCanvas::ClipOp::kDifference);
921
922 // Draw a red rectangle that's going to be completely covered by green later.
923 paint.setColor(DlColor::kRed());
924 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), paint);
925
926 // Add a clip restricting the backdrop filter to the top right corner.
927 auto count = builder.GetSaveCount();
928 builder.Save();
929 {
930 builder.ClipRect(SkRect::MakeLTRB(0, 0, 100, 100));
931 {
932 // Create a save layer with a backdrop blur filter.
933 auto backdrop_filter =
934 DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal);
935 builder.SaveLayer(nullptr, nullptr, backdrop_filter.get());
936 }
937 }
938 builder.RestoreToCount(count);
939
940 // Finally, overwrite all the previous stuff with green.
941 paint.setColor(DlColor::kGreen());
942 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), paint);
943
944 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
945 }
946
947 TEST_P(AiksTest, CanPictureConvertToImage) {
948 DisplayListBuilder recorder_canvas;
949 DlPaint paint;
950 paint.setColor(DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0));
951 recorder_canvas.DrawRect(SkRect::MakeXYWH(100.0, 100.0, 600, 600), paint);
952 paint.setColor(DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0));
953 recorder_canvas.DrawRect(SkRect::MakeXYWH(200.0, 200.0, 600, 600), paint);
954
955 DisplayListBuilder canvas;
956 AiksContext renderer(GetContext(), nullptr);
957 paint.setColor(DlColor::kTransparent());
958 canvas.DrawPaint(paint);
959
960 auto image =
961 DisplayListToTexture(recorder_canvas.Build(), {1000, 1000}, renderer);
962 if (image) {
963 canvas.DrawImage(DlImageImpeller::Make(image), SkPoint{}, {});
964 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2));
965 canvas.DrawRect(SkRect::MakeSize({1000, 1000}), paint);
966 }
967
968 ASSERT_TRUE(OpenPlaygroundHere(canvas.Build()));
969 }
970
971 // Regression test for https://github.com/flutter/flutter/issues/142358 .
972 // Without a change to force render pass construction the image is left in an
973 // undefined layout and triggers a validation error.
974 TEST_P(AiksTest, CanEmptyPictureConvertToImage) {
975 DisplayListBuilder recorder_builder;
976
977 DisplayListBuilder builder;
978 AiksContext renderer(GetContext(), nullptr);
979
980 DlPaint paint;
981 paint.setColor(DlColor::kTransparent());
982 builder.DrawPaint(paint);
983
984 auto result_image =
985 DisplayListToTexture(builder.Build(), ISize{1000, 1000}, renderer);
986 if (result_image) {
987 recorder_builder.DrawImage(DlImageImpeller::Make(result_image), SkPoint{},
988 {});
989
990 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2));
991 recorder_builder.DrawRect(SkRect::MakeSize({1000, 1000}), paint);
992 }
993
994 ASSERT_TRUE(OpenPlaygroundHere(recorder_builder.Build()));
995 }
996
997 TEST_P(AiksTest, DepthValuesForLineMode) {
998 // Ensures that the additional draws created by line/polygon mode all
999 // have the same depth values.
1000 DisplayListBuilder builder;
1001
1002 SkPath path = SkPath::Circle(100, 100, 100);
1003
1004 builder.DrawPath(path, DlPaint()
1005 .setColor(DlColor::kRed())
1006 .setDrawStyle(DlDrawStyle::kStroke)
1007 .setStrokeWidth(5));
1008 builder.Save();
1009 builder.ClipPath(path);
1010
1011 std::vector<DlPoint> points = {
1012 DlPoint::MakeXY(0, -200), DlPoint::MakeXY(400, 200),
1013 DlPoint::MakeXY(0, -100), DlPoint::MakeXY(400, 300),
1014 DlPoint::MakeXY(0, 0), DlPoint::MakeXY(400, 400),
1015 DlPoint::MakeXY(0, 100), DlPoint::MakeXY(400, 500),
1016 DlPoint::MakeXY(0, 150), DlPoint::MakeXY(400, 600)};
1017
1018 builder.DrawPoints(DisplayListBuilder::PointMode::kLines, points.size(),
1019 points.data(),
1020 DlPaint().setColor(DlColor::kBlue()).setStrokeWidth(10));
1021 builder.Restore();
1022
1023 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1024 }
1025
1026 TEST_P(AiksTest, DepthValuesForPolygonMode) {
1027 // Ensures that the additional draws created by line/polygon mode all
1028 // have the same depth values.
1029 DisplayListBuilder builder;
1030
1031 SkPath path = SkPath::Circle(100, 100, 100);
1032
1033 builder.DrawPath(path, DlPaint()
1034 .setColor(DlColor::kRed())
1035 .setDrawStyle(DlDrawStyle::kStroke)
1036 .setStrokeWidth(5));
1037 builder.Save();
1038 builder.ClipPath(path);
1039
1040 std::vector<DlPoint> points = {
1041 DlPoint::MakeXY(0, -200), DlPoint::MakeXY(400, 200),
1042 DlPoint::MakeXY(0, -100), DlPoint::MakeXY(400, 300),
1043 DlPoint::MakeXY(0, 0), DlPoint::MakeXY(400, 400),
1044 DlPoint::MakeXY(0, 100), DlPoint::MakeXY(400, 500),
1045 DlPoint::MakeXY(0, 150), DlPoint::MakeXY(400, 600)};
1046
1047 builder.DrawPoints(DisplayListBuilder::PointMode::kPolygon, points.size(),
1048 points.data(),
1049 DlPaint().setColor(DlColor::kBlue()).setStrokeWidth(10));
1050 builder.Restore();
1051
1052 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1053 }
1054
1055 // Verifies that an image rasterized and readback is in the correct orientation
1056 // by re-uploading it.
1057 TEST_P(AiksTest, ToImageFromImage) {
1058 DisplayListBuilder builder;
1059 Path ip_path = PathBuilder{}
1060 .AddArc(DlRect::MakeLTRB(0, 0, 100, 100), Radians(0),
1061 Radians(3.14 / 2))
1062 .TakePath();
1063 DlPath path = DlPath(ip_path);
1064
1065 builder.DrawPath(path, DlPaint().setColor(DlColor::kRed()));
1066
1067 AiksContext renderer(GetContext(), nullptr);
1068 auto texture =
1069 DisplayListToTexture(builder.Build(), ISize(100, 100), renderer);
1070
1071 // First, Readback the texture data into a host buffer.
1072 impeller::DeviceBufferDescriptor desc;
1073 desc.size = texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
1074 desc.readback = true;
1075 desc.storage_mode = StorageMode::kHostVisible;
1076
1077 auto device_buffer = GetContext()->GetResourceAllocator()->CreateBuffer(desc);
1078 {
1079 auto cmd_buffer = GetContext()->CreateCommandBuffer();
1080 auto blit_pass = cmd_buffer->CreateBlitPass();
1081
1082 blit_pass->AddCopy(texture, device_buffer);
1083 blit_pass->EncodeCommands();
1084
1085 auto latch = std::make_shared<fml::CountDownLatch>(1u);
1086 GetContext()->GetCommandQueue()->Submit(
1087 {cmd_buffer},
1088 [latch](CommandBuffer::Status status) { latch->CountDown(); });
1089 latch->Wait();
1090 }
1091
1092 impeller::TextureDescriptor tex_desc = texture->GetTextureDescriptor();
1093 auto reupload_texture =
1094 GetContext()->GetResourceAllocator()->CreateTexture(tex_desc);
1095
1096 // Next, Re-upload the data into a new texture.
1097 {
1098 auto cmd_buffer = GetContext()->CreateCommandBuffer();
1099 auto blit_pass = cmd_buffer->CreateBlitPass();
1100 blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer),
1101 reupload_texture);
1102 blit_pass->ConvertTextureToShaderRead(texture);
1103 blit_pass->EncodeCommands();
1104
1105 auto latch = std::make_shared<fml::CountDownLatch>(1u);
1106 GetContext()->GetCommandQueue()->Submit(
1107 {cmd_buffer},
1108 [latch](CommandBuffer::Status status) { latch->CountDown(); });
1109 latch->Wait();
1110 }
1111
1112 // Draw the results side by side. These should look the same.
1113 DisplayListBuilder canvas;
1114 DlPaint paint = DlPaint();
1115 canvas.DrawRect(
1116 DlRect::MakeLTRB(0, 0, 100, 100),
1117 DlPaint().setColor(DlColor::kBlue()).setDrawStyle(DlDrawStyle::kStroke));
1118 canvas.DrawImage(DlImageImpeller::Make(texture), DlPoint(0, 0),
1119 DlImageSampling::kNearestNeighbor, &paint);
1120
1121 canvas.DrawRect(
1122 DlRect::MakeLTRB(0, 100, 100, 200),
1123 DlPaint().setColor(DlColor::kRed()).setDrawStyle(DlDrawStyle::kStroke));
1124 canvas.DrawImage(DlImageImpeller::Make(reupload_texture), DlPoint(0, 100),
1125 DlImageSampling::kNearestNeighbor, &paint);
1126 OpenPlaygroundHere(canvas.Build());
1127 }
1128
1129 TEST_P(AiksTest, DisplayListToTextureAllocationFailure) {
1130 ScopedValidationDisable disable_validations;
1131 DisplayListBuilder builder;
1132
1133 AiksContext aiks_context(GetContext(), nullptr);
1134 // Use intentionally invalid dimensions that would trigger an allocation
1135 // failure.
1136 auto texture =
1137 DisplayListToTexture(builder.Build(), ISize{0, 0}, aiks_context);
1138
1139 EXPECT_EQ(texture, nullptr);
1140 }
1141
1142 TEST_P(AiksTest, DisplayListToTextureWithMipGenerationOnGLES) {
1143 if (GetBackend() != PlaygroundBackend::kOpenGLES) {
1144 GTEST_SKIP() << "Only relevant for GLES";
1145 }
1146 DisplayListBuilder builder;
1147
1148 std::shared_ptr<DlImageFilter> filter =
1149 DlImageFilter::MakeBlur(8, 8, DlTileMode::kClamp);
1150 builder.SaveLayer(std::nullopt, nullptr, filter.get());
1151 builder.Restore();
1152
1153 AiksContext aiks_context(GetContext(), nullptr);
1154 // Use intentionally invalid dimensions that would trigger an allocation
1155 // failure.
1156 auto texture =
1157 DisplayListToTexture(builder.Build(), ISize{10, 10}, aiks_context,
1158 /*reset_host_buffer=*/true, /*generate_mips=*/true);
1159
1160 EXPECT_FALSE(texture->NeedsMipmapGeneration());
1161 }
1162
1163 } // namespace testing
1164 } // namespace impeller
aiks_context.h
aiks_unittests.h
impeller::AiksContext
Definition: aiks_context.h:19
impeller::AiksContext::GetContentContext
ContentContext & GetContentContext() const
Definition: aiks_context.cc:42
impeller::AiksContext::GetContext
std::shared_ptr< Context > GetContext() const
Definition: aiks_context.cc:38
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::CommandBuffer::Status
Status
Definition: command_buffer.h:49
impeller::ContentContext::GetRenderTargetCache
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
Definition: content_context.h:838
impeller::DeviceBuffer::AsBufferView
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
Definition: device_buffer.cc:18
impeller::DlImageImpeller::Make
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
Definition: dl_image_impeller.cc:23
impeller::PathBuilder
Definition: path_builder.h:15
impeller::PathBuilder::TakePath
Path TakePath(FillType fill=FillType::kNonZero)
Definition: path_builder.cc:28
impeller::PathBuilder::AddArc
PathBuilder & AddArc(const Rect &oval_bounds, Radians start, Radians sweep, bool use_center=false)
Definition: path_builder.cc:338
impeller::Path
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:53
impeller::RenderTarget
Definition: render_target.h:38
formats.h
device_buffer.h
device_buffer_descriptor.h
dl_dispatcher.h
x
int32_t x
Definition: dl_golden_unittests.cc:443
dl_image_impeller.h
path_builder.h
flutter
Definition: dl_golden_blur_unittests.cc:16
impeller::testing::TEST_P
TEST_P(AiksTest, DrawAtlasNoColor)
Definition: aiks_dl_atlas_unittests.cc:57
impeller
Definition: allocation.cc:12
impeller::DisplayListToTexture
std::shared_ptr< Texture > DisplayListToTexture(const sk_sp< flutter::DisplayList > &display_list, ISize size, AiksContext &context, bool reset_host_buffer, bool generate_mips)
Render the provided display list to a texture with the given size.
Definition: dl_dispatcher.cc:1249
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::DlPoint
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
impeller::DlPath
flutter::DlPath DlPath
Definition: dl_dispatcher.h:28
impeller::PlaygroundBackend::kOpenGLES
@ kOpenGLES
impeller::ISize
ISize64 ISize
Definition: size.h:174
impeller::k1OverSqrt2
constexpr float k1OverSqrt2
Definition: constants.h:50
playground.h
scalar.h
scale
const Scalar scale
Definition: stroke_path_geometry.cc:316
impeller::DeviceBufferDescriptor
Definition: device_buffer_descriptor.h:14
impeller::DeviceBufferDescriptor::readback
bool readback
Definition: device_buffer_descriptor.h:19
impeller::DeviceBufferDescriptor::storage_mode
StorageMode storage_mode
Definition: device_buffer_descriptor.h:15
impeller::DeviceBufferDescriptor::size
size_t size
Definition: device_buffer_descriptor.h:16
impeller::Radians
Definition: scalar.h:43
impeller::ScopedValidationDisable
Definition: validation.h:56
impeller::TRect::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::TSize
Definition: size.h:25
impeller::TSize::MipCount
constexpr size_t MipCount() const
Definition: size.h:140
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:38
impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel
constexpr size_t GetByteSizeOfBaseMipLevel() const
Definition: texture_descriptor.h:48
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:42
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:39
impeller::TextureDescriptor::mip_count
size_t mip_count
Definition: texture_descriptor.h:43
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:41
texture_descriptor.h
validation.h