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  auto context = MakeContext();
596  std::weak_ptr<Texture> weak_texture;
597 
598  {
599  auto texture = CreateTextureForFixture("table_mountain_nx.png");
600  weak_texture = texture;
601 
602  DisplayListBuilder builder;
603  builder.Scale(GetContentScale().x, GetContentScale().y);
604  builder.Translate(100.0f, 100.0f);
605 
606  DlPaint paint;
607  paint.setColorSource(DlColorSource::MakeImage(
608  DlImageImpeller::Make(texture), DlTileMode::kClamp, DlTileMode::kClamp,
609  DlImageSampling::kLinear, nullptr));
610 
611  builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
612 
613  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
614  }
615 
616  // See https://github.com/flutter/flutter/issues/134751.
617  //
618  // If the fence waiter was working this may not be released by the end of the
619  // scope above. Adding a manual shutdown so that future changes to the fence
620  // waiter will not flake this test.
621  context->Shutdown();
622 
623  // The texture should be released by now.
624  ASSERT_TRUE(weak_texture.expired()) << "When the texture is no longer in use "
625  "by the backend, it should be "
626  "released.";
627 }
628 
629 TEST_P(AiksTest, MatrixImageFilterMagnify) {
630  Scalar scale = 2.0;
631  auto callback = [&]() -> sk_sp<DisplayList> {
632  if (AiksTest::ImGuiBegin("Controls", nullptr,
633  ImGuiWindowFlags_AlwaysAutoResize)) {
634  ImGui::SliderFloat("Scale", &scale, 1, 2);
635  ImGui::End();
636  }
637  DisplayListBuilder builder;
638  builder.Scale(GetContentScale().x, GetContentScale().y);
639  auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
640 
641  builder.Translate(600, -200);
642 
643  DlMatrix matrix = DlMatrix::MakeScale({scale, scale, 1});
644  DlPaint paint;
645  paint.setImageFilter(
646  DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear));
647  builder.SaveLayer(std::nullopt, &paint);
648 
649  DlPaint rect_paint;
650  rect_paint.setAlpha(0.5 * 255);
651  builder.DrawImage(image, DlPoint(0, 0), DlImageSampling::kLinear,
652  &rect_paint);
653  builder.Restore();
654 
655  return builder.Build();
656  };
657 
658  ASSERT_TRUE(OpenPlaygroundHere(callback));
659 }
660 
661 TEST_P(AiksTest, ImageFilteredSaveLayerWithUnboundedContents) {
662  DisplayListBuilder builder;
663  builder.Scale(GetContentScale().x, GetContentScale().y);
664 
665  auto test = [&builder](const std::shared_ptr<DlImageFilter>& filter) {
666  auto DrawLine = [&builder](const DlPoint& p0, const DlPoint& p1,
667  const DlPaint& p) {
668  DlPaint paint = p;
669  paint.setDrawStyle(DlDrawStyle::kStroke);
670  builder.DrawPath(DlPath::MakeLine(p0, p1), paint);
671  };
672  // Registration marks for the edge of the SaveLayer
673  DlPaint paint;
674  paint.setColor(DlColor::kWhite());
675  DrawLine(DlPoint(75, 100), DlPoint(225, 100), paint);
676  DrawLine(DlPoint(75, 200), DlPoint(225, 200), paint);
677  DrawLine(DlPoint(100, 75), DlPoint(100, 225), paint);
678  DrawLine(DlPoint(200, 75), DlPoint(200, 225), paint);
679 
680  DlPaint save_paint;
681  save_paint.setImageFilter(filter);
682  DlRect bounds = DlRect::MakeLTRB(100, 100, 200, 200);
683  builder.SaveLayer(bounds, &save_paint);
684 
685  {
686  // DrawPaint to verify correct behavior when the contents are unbounded.
687  DlPaint paint;
688  paint.setColor(DlColor::kYellow());
689  builder.DrawPaint(paint);
690 
691  // Contrasting rectangle to see interior blurring
692  paint.setColor(DlColor::kBlue());
693  builder.DrawRect(DlRect::MakeLTRB(125, 125, 175, 175), paint);
694  }
695  builder.Restore();
696  };
697 
698  test(DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal));
699 
700  builder.Translate(200.0, 0.0);
701 
702  test(DlImageFilter::MakeDilate(10.0, 10.0));
703 
704  builder.Translate(200.0, 0.0);
705 
706  test(DlImageFilter::MakeErode(10.0, 10.0));
707 
708  builder.Translate(-400.0, 200.0);
709 
710  DlMatrix matrix = DlMatrix::MakeRotationZ(DlDegrees(10));
711 
712  auto rotate_filter =
713  DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear);
714  test(rotate_filter);
715 
716  builder.Translate(200.0, 0.0);
717 
718  const float m[20] = {
719  0, 1, 0, 0, 0, //
720  0, 0, 1, 0, 0, //
721  1, 0, 0, 0, 0, //
722  0, 0, 0, 1, 0 //
723  };
724  auto rgb_swap_filter =
725  DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(m));
726  test(rgb_swap_filter);
727 
728  builder.Translate(200.0, 0.0);
729 
730  test(DlImageFilter::MakeCompose(rotate_filter, rgb_swap_filter));
731 
732  builder.Translate(-400.0, 200.0);
733 
734  test(rotate_filter->makeWithLocalMatrix(
735  DlMatrix::MakeTranslation({25.0, 25.0})));
736 
737  builder.Translate(200.0, 0.0);
738 
739  test(rgb_swap_filter->makeWithLocalMatrix(
740  DlMatrix::MakeTranslation({25.0, 25.0})));
741 
742  builder.Translate(200.0, 0.0);
743 
744  test(DlImageFilter::MakeCompose(rotate_filter, rgb_swap_filter)
745  ->makeWithLocalMatrix(DlMatrix::MakeTranslation({25.0, 25.0})));
746 
747  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
748 }
749 
750 TEST_P(AiksTest, MatrixBackdropFilter) {
751  DisplayListBuilder builder;
752 
753  DlPaint paint;
754  paint.setColor(DlColor::kBlack());
755  builder.DrawPaint(paint);
756  builder.SaveLayer(std::nullopt, nullptr);
757  {
758  DlPaint paint;
759  paint.setColor(DlColor::kGreen().withAlpha(0.5 * 255));
760  paint.setBlendMode(DlBlendMode::kPlus);
761 
762  DlPaint rect_paint;
763  rect_paint.setColor(DlColor::kRed());
764  rect_paint.setStrokeWidth(4);
765  rect_paint.setDrawStyle(DlDrawStyle::kStroke);
766  builder.DrawRect(DlRect::MakeLTRB(0, 0, 300, 300), rect_paint);
767  builder.DrawCircle(DlPoint(200, 200), 100, paint);
768  // Should render a second circle, centered on the bottom-right-most edge of
769  // the circle.
770  DlMatrix matrix = DlMatrix::MakeTranslation({(100 + 100 * k1OverSqrt2),
771  (100 + 100 * k1OverSqrt2)}) *
772  DlMatrix::MakeScale({0.5, 0.5, 1}) *
773  DlMatrix::MakeTranslation({-100, -100});
774  auto backdrop_filter =
775  DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear);
776  builder.SaveLayer(std::nullopt, nullptr, backdrop_filter.get());
777  builder.Restore();
778  }
779  builder.Restore();
780 
781  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
782 }
783 
784 TEST_P(AiksTest, MatrixSaveLayerFilter) {
785  DisplayListBuilder builder;
786 
787  DlPaint paint;
788  paint.setColor(DlColor::kBlack());
789  builder.DrawPaint(paint);
790  builder.SaveLayer(std::nullopt, nullptr);
791  {
792  paint.setColor(DlColor::kGreen().withAlpha(255 * 0.5));
793  paint.setBlendMode(DlBlendMode::kPlus);
794  builder.DrawCircle(DlPoint(200, 200), 100, paint);
795  // Should render a second circle, centered on the bottom-right-most edge of
796  // the circle.
797 
798  DlMatrix matrix = DlMatrix::MakeTranslation({(200 + 100 * k1OverSqrt2),
799  (200 + 100 * k1OverSqrt2)}) *
800  DlMatrix::MakeScale({0.5, 0.5, 1}) *
801  DlMatrix::MakeTranslation({-200, -200});
802  DlPaint save_paint;
803  save_paint.setImageFilter(
804  DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear));
805 
806  builder.SaveLayer(std::nullopt, &save_paint);
807 
808  DlPaint circle_paint;
809  circle_paint.setColor(DlColor::kGreen().withAlpha(255 * 0.5));
810  circle_paint.setBlendMode(DlBlendMode::kPlus);
811  builder.DrawCircle(DlPoint(200, 200), 100, circle_paint);
812  builder.Restore();
813  }
814  builder.Restore();
815 
816  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
817 }
818 
819 // Regression test for flutter/flutter#152780
820 TEST_P(AiksTest, CanDrawScaledPointsSmallScaleLargeRadius) {
821  std::vector<DlPoint> point = {
822  {0, 0}, //
823  };
824 
825  DlPaint paint;
826  paint.setStrokeCap(DlStrokeCap::kRound);
827  paint.setColor(DlColor::kRed());
828  paint.setStrokeWidth(100 * 1000000);
829 
830  DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
831  builder.Translate(200, 200);
832  builder.Scale(0.000001, 0.000001);
833 
834  builder.DrawPoints(DlPointMode::kPoints, point.size(), point.data(), paint);
835 
836  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
837 }
838 
839 // Regression test for flutter/flutter#152780
840 TEST_P(AiksTest, CanDrawScaledPointsLargeScaleSmallRadius) {
841  std::vector<DlPoint> point = {
842  {0, 0}, //
843  };
844 
845  DlPaint paint;
846  paint.setStrokeCap(DlStrokeCap::kRound);
847  paint.setColor(DlColor::kRed());
848  paint.setStrokeWidth(100 * 0.000001);
849 
850  DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
851  builder.Translate(200, 200);
852  builder.Scale(1000000, 1000000);
853 
854  builder.DrawPoints(DlPointMode::kPoints, point.size(), point.data(), paint);
855  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
856 }
857 
858 TEST_P(AiksTest, TransparentShadowProducesCorrectColor) {
859  DisplayListBuilder builder;
860  builder.Save();
861  builder.Scale(1.618, 1.618);
862  DlPath path = DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 200, 100));
863 
864  builder.DrawShadow(path, flutter::DlColor::kTransparent(), 15, false, 1);
865  builder.Restore();
866 
867  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
868 }
869 
870 // Regression test for https://github.com/flutter/flutter/issues/130613
871 TEST_P(AiksTest, DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists) {
872  flutter::DisplayListBuilder sub_builder(true);
873  sub_builder.DrawRect(DlRect::MakeXYWH(0, 0, 50, 50),
874  flutter::DlPaint(flutter::DlColor::kRed()));
875  auto display_list = sub_builder.Build();
876 
877  AiksContext context(GetContext(), nullptr);
878  RenderTarget render_target =
879  context.GetContentContext().GetRenderTargetCache()->CreateOffscreen(
880  *context.GetContext(), {2400, 1800}, 1);
881 
882  DisplayListBuilder builder;
883 
884  builder.Scale(2.0, 2.0);
885  builder.Translate(-93.0, 0.0);
886 
887  // clang-format off
888  builder.TransformFullPerspective(
889  0.8, -0.2, -0.1, -0.0,
890  0.0, 1.0, 0.0, 0.0,
891  1.4, 1.3, 1.0, 0.0,
892  63.2, 65.3, 48.6, 1.1
893  );
894  // clang-format on
895  builder.Translate(35.0, 75.0);
896  builder.DrawDisplayList(display_list, 1.0f);
897 
898  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
899 }
900 
901 // Results in a 100x100 green square. If any red is drawn, there is a bug.
902 TEST_P(AiksTest, BackdropRestoreUsesCorrectCoverageForFirstRestoredClip) {
903  DisplayListBuilder builder;
904 
905  DlPaint paint;
906  // Add a difference clip that cuts out the bottom right corner
907  builder.ClipRect(DlRect::MakeLTRB(50, 50, 100, 100), DlClipOp::kDifference);
908 
909  // Draw a red rectangle that's going to be completely covered by green later.
910  paint.setColor(DlColor::kRed());
911  builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
912 
913  // Add a clip restricting the backdrop filter to the top right corner.
914  auto count = builder.GetSaveCount();
915  builder.Save();
916  {
917  builder.ClipRect(DlRect::MakeLTRB(0, 0, 100, 100));
918  {
919  // Create a save layer with a backdrop blur filter.
920  auto backdrop_filter =
921  DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal);
922  builder.SaveLayer(std::nullopt, nullptr, backdrop_filter.get());
923  }
924  }
925  builder.RestoreToCount(count);
926 
927  // Finally, overwrite all the previous stuff with green.
928  paint.setColor(DlColor::kGreen());
929  builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
930 
931  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
932 }
933 
934 TEST_P(AiksTest, CanPictureConvertToImage) {
935  DisplayListBuilder recorder_canvas;
936  DlPaint paint;
937  paint.setColor(DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0));
938  recorder_canvas.DrawRect(DlRect::MakeXYWH(100.0, 100.0, 600, 600), paint);
939  paint.setColor(DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0));
940  recorder_canvas.DrawRect(DlRect::MakeXYWH(200.0, 200.0, 600, 600), paint);
941 
942  DisplayListBuilder canvas;
943  AiksContext renderer(GetContext(), nullptr);
944  paint.setColor(DlColor::kTransparent());
945  canvas.DrawPaint(paint);
946 
947  auto image =
948  DisplayListToTexture(recorder_canvas.Build(), {1000, 1000}, renderer);
949  if (image) {
950  canvas.DrawImage(DlImageImpeller::Make(image), DlPoint(), {});
951  paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2));
952  canvas.DrawRect(DlRect::MakeWH(1000, 1000), paint);
953  }
954 
955  ASSERT_TRUE(OpenPlaygroundHere(canvas.Build()));
956 }
957 
958 // Regression test for https://github.com/flutter/flutter/issues/142358 .
959 // Without a change to force render pass construction the image is left in an
960 // undefined layout and triggers a validation error.
961 TEST_P(AiksTest, CanEmptyPictureConvertToImage) {
962  DisplayListBuilder recorder_builder;
963 
964  DisplayListBuilder builder;
965  AiksContext renderer(GetContext(), nullptr);
966 
967  DlPaint paint;
968  paint.setColor(DlColor::kTransparent());
969  builder.DrawPaint(paint);
970 
971  auto result_image =
972  DisplayListToTexture(builder.Build(), ISize{1000, 1000}, renderer);
973  if (result_image) {
974  recorder_builder.DrawImage(DlImageImpeller::Make(result_image), DlPoint(),
975  {});
976 
977  paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2));
978  recorder_builder.DrawRect(DlRect::MakeWH(1000, 1000), paint);
979  }
980 
981  ASSERT_TRUE(OpenPlaygroundHere(recorder_builder.Build()));
982 }
983 
984 TEST_P(AiksTest, DepthValuesForLineMode) {
985  // Ensures that the additional draws created by line/polygon mode all
986  // have the same depth values.
987  DisplayListBuilder builder;
988 
989  DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 100);
990 
991  builder.DrawPath(path, DlPaint()
992  .setColor(DlColor::kRed())
993  .setDrawStyle(DlDrawStyle::kStroke)
994  .setStrokeWidth(5));
995  builder.Save();
996  builder.ClipPath(path);
997 
998  std::vector<DlPoint> points = {
999  DlPoint::MakeXY(0, -200), DlPoint::MakeXY(400, 200),
1000  DlPoint::MakeXY(0, -100), DlPoint::MakeXY(400, 300),
1001  DlPoint::MakeXY(0, 0), DlPoint::MakeXY(400, 400),
1002  DlPoint::MakeXY(0, 100), DlPoint::MakeXY(400, 500),
1003  DlPoint::MakeXY(0, 150), DlPoint::MakeXY(400, 600)};
1004 
1005  builder.DrawPoints(DlPointMode::kLines, points.size(), points.data(),
1006  DlPaint().setColor(DlColor::kBlue()).setStrokeWidth(10));
1007  builder.Restore();
1008 
1009  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1010 }
1011 
1012 TEST_P(AiksTest, DepthValuesForPolygonMode) {
1013  // Ensures that the additional draws created by line/polygon mode all
1014  // have the same depth values.
1015  DisplayListBuilder builder;
1016 
1017  DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 100);
1018 
1019  builder.DrawPath(path, DlPaint()
1020  .setColor(DlColor::kRed())
1021  .setDrawStyle(DlDrawStyle::kStroke)
1022  .setStrokeWidth(5));
1023  builder.Save();
1024  builder.ClipPath(path);
1025 
1026  std::vector<DlPoint> points = {
1027  DlPoint::MakeXY(0, -200), DlPoint::MakeXY(400, 200),
1028  DlPoint::MakeXY(0, -100), DlPoint::MakeXY(400, 300),
1029  DlPoint::MakeXY(0, 0), DlPoint::MakeXY(400, 400),
1030  DlPoint::MakeXY(0, 100), DlPoint::MakeXY(400, 500),
1031  DlPoint::MakeXY(0, 150), DlPoint::MakeXY(400, 600)};
1032 
1033  builder.DrawPoints(DlPointMode::kPolygon, points.size(), points.data(),
1034  DlPaint().setColor(DlColor::kBlue()).setStrokeWidth(10));
1035  builder.Restore();
1036 
1037  ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1038 }
1039 
1040 // Verifies that an image rasterized and readback is in the correct orientation
1041 // by re-uploading it.
1042 TEST_P(AiksTest, ToImageFromImage) {
1043  DisplayListBuilder builder;
1044  DlPath path = DlPath::MakeArc(DlRect::MakeLTRB(0, 0, 100, 100), DlDegrees(0),
1045  DlDegrees(90),
1046  /*use_center=*/true);
1047 
1048  builder.DrawPath(path, DlPaint().setColor(DlColor::kRed()));
1049 
1050  AiksContext renderer(GetContext(), nullptr);
1051  auto texture =
1052  DisplayListToTexture(builder.Build(), ISize(100, 100), renderer);
1053 
1054  // First, Readback the texture data into a host buffer.
1056  desc.size = texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
1057  desc.readback = true;
1059 
1060  auto device_buffer = GetContext()->GetResourceAllocator()->CreateBuffer(desc);
1061  {
1062  auto cmd_buffer = GetContext()->CreateCommandBuffer();
1063  auto blit_pass = cmd_buffer->CreateBlitPass();
1064 
1065  blit_pass->AddCopy(texture, device_buffer);
1066  blit_pass->EncodeCommands();
1067 
1068  auto latch = std::make_shared<fml::CountDownLatch>(1u);
1069  GetContext()->GetCommandQueue()->Submit(
1070  {cmd_buffer},
1071  [latch](CommandBuffer::Status status) { latch->CountDown(); });
1072  latch->Wait();
1073  }
1074 
1075  impeller::TextureDescriptor tex_desc = texture->GetTextureDescriptor();
1076  auto reupload_texture =
1077  GetContext()->GetResourceAllocator()->CreateTexture(tex_desc);
1078 
1079  // Next, Re-upload the data into a new texture.
1080  {
1081  auto cmd_buffer = GetContext()->CreateCommandBuffer();
1082  auto blit_pass = cmd_buffer->CreateBlitPass();
1083  blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer),
1084  reupload_texture);
1085  blit_pass->ConvertTextureToShaderRead(texture);
1086  blit_pass->EncodeCommands();
1087 
1088  auto latch = std::make_shared<fml::CountDownLatch>(1u);
1089  GetContext()->GetCommandQueue()->Submit(
1090  {cmd_buffer},
1091  [latch](CommandBuffer::Status status) { latch->CountDown(); });
1092  latch->Wait();
1093  }
1094 
1095  // Draw the results side by side. These should look the same.
1096  DisplayListBuilder canvas;
1097  DlPaint paint = DlPaint();
1098  canvas.DrawRect(
1099  DlRect::MakeLTRB(0, 0, 100, 100),
1100  DlPaint().setColor(DlColor::kBlue()).setDrawStyle(DlDrawStyle::kStroke));
1101  canvas.DrawImage(DlImageImpeller::Make(texture), DlPoint(0, 0),
1102  DlImageSampling::kNearestNeighbor, &paint);
1103 
1104  canvas.DrawRect(
1105  DlRect::MakeLTRB(0, 100, 100, 200),
1106  DlPaint().setColor(DlColor::kRed()).setDrawStyle(DlDrawStyle::kStroke));
1107  canvas.DrawImage(DlImageImpeller::Make(reupload_texture), DlPoint(0, 100),
1108  DlImageSampling::kNearestNeighbor, &paint);
1109  OpenPlaygroundHere(canvas.Build());
1110 }
1111 
1112 TEST_P(AiksTest, DisplayListToTextureAllocationFailure) {
1113  ScopedValidationDisable disable_validations;
1114  DisplayListBuilder builder;
1115 
1116  AiksContext aiks_context(GetContext(), nullptr);
1117  // Use intentionally invalid dimensions that would trigger an allocation
1118  // failure.
1119  auto texture =
1120  DisplayListToTexture(builder.Build(), ISize{0, 0}, aiks_context);
1121 
1122  EXPECT_EQ(texture, nullptr);
1123 }
1124 
1125 TEST_P(AiksTest, DisplayListToTextureWithMipGeneration) {
1126  DisplayListBuilder builder;
1127 
1128  std::shared_ptr<DlImageFilter> filter =
1129  DlImageFilter::MakeBlur(8, 8, DlTileMode::kClamp);
1130  builder.SaveLayer(std::nullopt, nullptr, filter.get());
1131  builder.Restore();
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{10, 10}, aiks_context,
1138  /*reset_host_buffer=*/true, /*generate_mips=*/true);
1139 
1140  EXPECT_FALSE(texture->NeedsMipmapGeneration());
1141 }
1142 
1143 } // namespace testing
1144 } // 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)
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.
flutter::DlRect DlRect
Definition: dl_dispatcher.h:25
float Scalar
Definition: scalar.h:19
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
flutter::DlPath DlPath
Definition: dl_dispatcher.h:29
constexpr float k1OverSqrt2
Definition: constants.h:50
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