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"
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"
28 #include "impeller/core/formats.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 
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.
1073  desc.size = texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
1074  desc.readback = true;
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
ContentContext & GetContentContext() const
Definition: aiks_context.cc:42
std::shared_ptr< Context > GetContext() const
Definition: aiks_context.cc:38
static bool ImGuiBegin(const char *name, bool *p_open, ImGuiWindowFlags flags)
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
Path TakePath(FillType fill=FillType::kNonZero)
Definition: path_builder.cc:28
PathBuilder & AddArc(const Rect &oval_bounds, Radians start, Radians sweep, bool use_center=false)
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:53
int32_t x
TEST_P(AiksTest, DrawAtlasNoColor)
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.
float Scalar
Definition: scalar.h:18
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
flutter::DlPath DlPath
Definition: dl_dispatcher.h:28
ISize64 ISize
Definition: size.h:174
constexpr float k1OverSqrt2
Definition: constants.h:50
const Scalar scale
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
constexpr size_t MipCount() const
Definition: size.h:140
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
constexpr size_t GetByteSizeOfBaseMipLevel() const