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