Flutter Impeller
canvas_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <unordered_map>
6 #include "flutter/display_list/dl_tile_mode.h"
7 #include "flutter/display_list/effects/dl_image_filter.h"
8 #include "flutter/display_list/geometry/dl_geometry_types.h"
9 #include "flutter/testing/testing.h"
10 #include "gtest/gtest.h"
11 #include "impeller/core/formats.h"
22 #include "third_party/abseil-cpp/absl/status/status_matchers.h"
23 
24 namespace impeller {
25 namespace testing {
26 
27 std::unique_ptr<Canvas> CreateTestCanvas(
29  std::optional<Rect> cull_rect = std::nullopt,
30  bool requires_readback = false) {
31  TextureDescriptor onscreen_desc;
32  onscreen_desc.size = {100, 100};
33  onscreen_desc.format =
34  context.GetDeviceCapabilities().GetDefaultColorFormat();
35  onscreen_desc.usage = TextureUsage::kRenderTarget;
37  onscreen_desc.sample_count = SampleCount::kCount1;
38  std::shared_ptr<Texture> onscreen =
39  context.GetContext()->GetResourceAllocator()->CreateTexture(
40  onscreen_desc);
41 
42  ColorAttachment color0;
44  if (context.GetContext()->GetCapabilities()->SupportsOffscreenMSAA()) {
45  TextureDescriptor onscreen_msaa_desc = onscreen_desc;
46  onscreen_msaa_desc.sample_count = SampleCount::kCount4;
47  onscreen_msaa_desc.storage_mode = StorageMode::kDeviceTransient;
48  onscreen_msaa_desc.type = TextureType::kTexture2DMultisample;
49 
50  std::shared_ptr<Texture> onscreen_msaa =
51  context.GetContext()->GetResourceAllocator()->CreateTexture(
52  onscreen_msaa_desc);
53  color0.resolve_texture = onscreen;
54  color0.texture = onscreen_msaa;
56  } else {
57  color0.texture = onscreen;
58  }
59 
60  RenderTarget render_target;
61  render_target.SetColorAttachment(color0, 0);
62 
63  if (cull_rect.has_value()) {
64  return std::make_unique<Canvas>(
65  context, render_target, /*is_onscreen=*/false,
66  /*requires_readback=*/requires_readback, cull_rect.value());
67  }
68  return std::make_unique<Canvas>(context, render_target, /*is_onscreen=*/false,
69  /*requires_readback=*/requires_readback);
70 }
71 
72 TEST_P(AiksTest, TransformMultipliesCorrectly) {
73  ContentContext& context = GetContentContext();
74  auto canvas = CreateTestCanvas(context);
75 
76  ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), Matrix());
77 
78  // clang-format off
79  canvas->Translate(Vector3(100, 200));
81  canvas->GetCurrentTransform(),
82  Matrix( 1, 0, 0, 0,
83  0, 1, 0, 0,
84  0, 0, 1, 0,
85  100, 200, 0, 1));
86 
87  canvas->Rotate(Radians(kPiOver2));
89  canvas->GetCurrentTransform(),
90  Matrix( 0, 1, 0, 0,
91  -1, 0, 0, 0,
92  0, 0, 1, 0,
93  100, 200, 0, 1));
94 
95  canvas->Scale(Vector3(2, 3));
97  canvas->GetCurrentTransform(),
98  Matrix( 0, 2, 0, 0,
99  -3, 0, 0, 0,
100  0, 0, 0, 0,
101  100, 200, 0, 1));
102 
103  canvas->Translate(Vector3(100, 200));
105  canvas->GetCurrentTransform(),
106  Matrix( 0, 2, 0, 0,
107  -3, 0, 0, 0,
108  0, 0, 0, 0,
109  -500, 400, 0, 1));
110  // clang-format on
111 }
112 
113 TEST_P(AiksTest, CanvasCanPushPopCTM) {
114  ContentContext& context = GetContentContext();
115  auto canvas = CreateTestCanvas(context);
116 
117  ASSERT_EQ(canvas->GetSaveCount(), 1u);
118  ASSERT_EQ(canvas->Restore(), false);
119 
120  canvas->Translate(Size{100, 100});
121  canvas->Save(10);
122  ASSERT_EQ(canvas->GetSaveCount(), 2u);
123  ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
124  Matrix::MakeTranslation({100.0, 100.0, 0.0}));
125  ASSERT_TRUE(canvas->Restore());
126  ASSERT_EQ(canvas->GetSaveCount(), 1u);
127  ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
128  Matrix::MakeTranslation({100.0, 100.0, 0.0}));
129 }
130 
131 TEST_P(AiksTest, CanvasCTMCanBeUpdated) {
132  ContentContext& context = GetContentContext();
133  auto canvas = CreateTestCanvas(context);
134 
135  Matrix identity;
136  ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), identity);
137  canvas->Translate(Size{100, 100});
138  ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
139  Matrix::MakeTranslation({100.0, 100.0, 0.0}));
140 }
141 
142 TEST_P(AiksTest, BackdropCountDownNormal) {
143  ContentContext& context = GetContentContext();
144  if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
145  GTEST_SKIP() << "Test requires device with framebuffer fetch";
146  }
147  auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
148  /*requires_readback=*/true);
149  // 3 backdrop filters
150  canvas->SetBackdropData({}, 3);
151 
152  auto blur =
153  flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
154  flutter::DlRect rect = flutter::DlRect::MakeLTRB(0, 0, 50, 50);
155 
156  EXPECT_TRUE(canvas->RequiresReadback());
157  canvas->DrawRect(rect, {.color = Color::Azure()});
158  canvas->SaveLayer({}, rect, blur.get(),
160  /*total_content_depth=*/1);
161  canvas->Restore();
162  EXPECT_TRUE(canvas->RequiresReadback());
163 
164  canvas->SaveLayer({}, rect, blur.get(),
166  /*total_content_depth=*/1);
167  canvas->Restore();
168  EXPECT_TRUE(canvas->RequiresReadback());
169 
170  canvas->SaveLayer({}, rect, blur.get(),
172  /*total_content_depth=*/1);
173  canvas->Restore();
174  EXPECT_FALSE(canvas->RequiresReadback());
175 }
176 
177 TEST_P(AiksTest, BackdropCountDownBackdropId) {
178  ContentContext& context = GetContentContext();
179  if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
180  GTEST_SKIP() << "Test requires device with framebuffer fetch";
181  }
182  auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
183  /*requires_readback=*/true);
184  // 3 backdrop filters all with same id.
185  std::unordered_map<int64_t, BackdropData> data;
186  data[1] = BackdropData{.backdrop_count = 3};
187  canvas->SetBackdropData(data, 3);
188 
189  auto blur =
190  flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
191 
192  EXPECT_TRUE(canvas->RequiresReadback());
193  canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
194  {.color = Color::Azure()});
195  canvas->SaveLayer({}, std::nullopt, blur.get(),
197  /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
198  /*backdrop_id=*/1);
199  canvas->Restore();
200  EXPECT_FALSE(canvas->RequiresReadback());
201 
202  canvas->SaveLayer({}, std::nullopt, blur.get(),
204  /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
205  /*backdrop_id=*/1);
206  canvas->Restore();
207  EXPECT_FALSE(canvas->RequiresReadback());
208 
209  canvas->SaveLayer({}, std::nullopt, blur.get(),
211  /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
212  /*backdrop_id=*/1);
213  canvas->Restore();
214  EXPECT_FALSE(canvas->RequiresReadback());
215 }
216 
217 TEST_P(AiksTest, BackdropCountDownBackdropIdMixed) {
218  ContentContext& context = GetContentContext();
219  if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
220  GTEST_SKIP() << "Test requires device with framebuffer fetch";
221  }
222  auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
223  /*requires_readback=*/true);
224  // 3 backdrop filters, 2 with same id.
225  std::unordered_map<int64_t, BackdropData> data;
226  data[1] = BackdropData{.backdrop_count = 2};
227  canvas->SetBackdropData(data, 3);
228 
229  auto blur =
230  flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
231 
232  EXPECT_TRUE(canvas->RequiresReadback());
233  canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
234  {.color = Color::Azure()});
235  canvas->SaveLayer({}, std::nullopt, blur.get(),
237  canvas->Restore();
238  EXPECT_TRUE(canvas->RequiresReadback());
239 
240  canvas->SaveLayer({}, std::nullopt, blur.get(),
242  canvas->Restore();
243  EXPECT_FALSE(canvas->RequiresReadback());
244 
245  canvas->SaveLayer({}, std::nullopt, blur.get(),
247  canvas->Restore();
248  EXPECT_FALSE(canvas->RequiresReadback());
249 }
250 
251 // We only know the total number of backdrop filters, not the number of backdrop
252 // filters in the root pass. If we reach a count of 0 while in a nested
253 // saveLayer, we should not restore to the onscreen.
254 TEST_P(AiksTest, BackdropCountDownWithNestedSaveLayers) {
255  ContentContext& context = GetContentContext();
256  if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
257  GTEST_SKIP() << "Test requires device with framebuffer fetch";
258  }
259  auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
260  /*requires_readback=*/true);
261 
262  canvas->SetBackdropData({}, 2);
263 
264  auto blur =
265  flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
266 
267  EXPECT_TRUE(canvas->RequiresReadback());
268  canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
269  {.color = Color::Azure()});
270  canvas->SaveLayer({}, std::nullopt, blur.get(),
272  /*total_content_depth=*/3);
273 
274  // This filter is nested in the first saveLayer. We cannot restore to onscreen
275  // here.
276  canvas->SaveLayer({}, std::nullopt, blur.get(),
278  /*total_content_depth=*/1);
279  canvas->Restore();
280  EXPECT_TRUE(canvas->RequiresReadback());
281 
282  canvas->Restore();
283  EXPECT_TRUE(canvas->RequiresReadback());
284 }
285 
286 TEST_P(AiksTest, DrawVerticesLinearGradientWithEmptySize) {
287  RenderCallback callback = [&](RenderTarget& render_target) {
288  ContentContext& context = GetContentContext();
289  Canvas canvas(context, render_target, true, false);
290 
291  std::vector<flutter::DlPoint> vertex_coordinates = {
292  flutter::DlPoint(0, 0),
293  flutter::DlPoint(600, 0),
294  flutter::DlPoint(0, 600),
295  };
296  std::vector<flutter::DlPoint> texture_coordinates = {
297  flutter::DlPoint(0, 0),
298  flutter::DlPoint(500, 0),
299  flutter::DlPoint(0, 500),
300  };
301  std::vector<uint16_t> indices = {0, 1, 2};
302  flutter::DlVertices::Builder vertices_builder(
303  flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
304  flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
305  vertices_builder.store_vertices(vertex_coordinates.data());
306  vertices_builder.store_indices(indices.data());
307  vertices_builder.store_texture_coordinates(texture_coordinates.data());
308  auto vertices = vertices_builder.build();
309 
310  // The start and end points of the gradient form an empty rectangle.
311  std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
312  flutter::DlColor::kRed()};
313  std::vector<Scalar> stops = {0.0, 1.0};
314  auto gradient = flutter::DlColorSource::MakeLinear(
315  {0, 0}, {0, 600}, 2, colors.data(), stops.data(),
316  flutter::DlTileMode::kClamp);
317 
318  Paint paint;
319  paint.color_source = gradient.get();
320  canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
321  BlendMode::kSrcOver, paint);
322 
323  canvas.EndReplay();
324  return true;
325  };
326 
327  ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
328 }
329 
330 TEST_P(AiksTest, DrawVerticesWithEmptyTextureCoordinates) {
331  auto runtime_stages_result =
332  OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
333  ABSL_ASSERT_OK(runtime_stages_result);
334  std::shared_ptr<RuntimeStage> runtime_stage =
335  runtime_stages_result.value()[GetRuntimeStageBackend()];
336  ASSERT_TRUE(runtime_stage);
337 
338  auto runtime_effect = flutter::DlRuntimeEffectImpeller::Make(runtime_stage);
339  auto uniform_data = std::make_shared<std::vector<uint8_t>>();
340  auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
341  runtime_effect, {}, uniform_data);
342 
343  RenderCallback callback = [&](RenderTarget& render_target) {
344  ContentContext& context = GetContentContext();
345  Canvas canvas(context, render_target, true, false);
346 
347  std::vector<flutter::DlPoint> vertex_coordinates = {
348  flutter::DlPoint(100, 100),
349  flutter::DlPoint(300, 100),
350  flutter::DlPoint(100, 300),
351  };
352  // The bounding box of the texture coordinates is empty.
353  std::vector<flutter::DlPoint> texture_coordinates = {
354  flutter::DlPoint(0, 0),
355  flutter::DlPoint(0, 100),
356  flutter::DlPoint(0, 0),
357  };
358  std::vector<uint16_t> indices = {0, 1, 2};
359  flutter::DlVertices::Builder vertices_builder(
360  flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
361  flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
362  vertices_builder.store_vertices(vertex_coordinates.data());
363  vertices_builder.store_indices(indices.data());
364  vertices_builder.store_texture_coordinates(texture_coordinates.data());
365  auto vertices = vertices_builder.build();
366 
367  Paint paint;
368  paint.color_source = color_source.get();
369  canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
370  BlendMode::kSrcOver, paint);
371 
372  canvas.EndReplay();
373  return true;
374  };
375 
376  ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
377 }
378 
379 TEST_P(AiksTest, SupportsBlitToOnscreen) {
380  ContentContext& context = GetContentContext();
381  auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
382  /*requires_readback=*/true);
383 
384  if (GetBackend() != PlaygroundBackend::kMetal &&
385  GetBackend() != PlaygroundBackend::kMetalSDF) {
386  EXPECT_FALSE(canvas->SupportsBlitToOnscreen());
387  } else {
388  EXPECT_TRUE(canvas->SupportsBlitToOnscreen());
389  }
390 }
391 
392 TEST_P(AiksTest, RoundSuperellipseShadowComparison) {
393  // Config
394  Size default_size(600, 400);
395  Point left_center(400, 700);
396  Point right_center(1300, 700);
397  Color color = Color::Red();
398 
399  // Convert `color` to a `color_source`. This forces
400  // `canvas.DrawRoundSuperellipse` to use the regular shadow algorithm
401  // (blurring) instead of the fast shadow algorithm.
402  std::shared_ptr<flutter::DlColorSource> color_source;
403  {
404  flutter::DlColor dl_color = flutter::DlColor(color.ToARGB());
405  std::vector<flutter::DlColor> colors = {dl_color, dl_color};
406  std::vector<Scalar> stops = {0.0, 1.0};
407  color_source = flutter::DlColorSource::MakeLinear(
408  {0, 0}, {1000, 1000}, 2, colors.data(), stops.data(),
409  flutter::DlTileMode::kClamp);
410  }
411 
412  RenderCallback callback = [&](RenderTarget& render_target) {
413  ContentContext& context = GetContentContext();
414  Canvas canvas(context, render_target, true, false);
415  // Somehow there's a scaling factor between PlaygroundPoint and Canvas.
416  Matrix ctm = Matrix::MakeScale(Vector2(1, 1) * 0.5);
417  Matrix i_ctm = ctm.Invert();
418 
419  static Scalar sigma = 0.05;
420  static Scalar radius = 200;
421 
422  // Define the ImGui
423  ImGui::Begin("Shadow", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
424  {
425  ImGui::SliderFloat("Sigma", &sigma, 0, 100);
426  ImGui::SliderFloat("Radius", &radius, 0, 1000);
427  }
428  ImGui::End();
429 
430  static PlaygroundPoint right_reference_var(
431  ctm * (right_center + default_size / 2), 30, Color::White());
432  Point right_reference = i_ctm * DrawPlaygroundPoint(right_reference_var);
433  Point half_size = (right_reference - right_center).Abs();
434  Rect left_bounds = Rect::MakeEllipseBounds(left_center, half_size);
435  Rect right_bounds = Rect::MakeEllipseBounds(right_center, half_size);
436 
437  Paint paint{
438  .color = color,
439  .mask_blur_descriptor =
441  .sigma = Sigma(sigma),
442  },
443  };
444 
445  // Left: Draw with canvas
446  canvas.DrawRoundSuperellipse(
447  RoundSuperellipse::MakeRectRadius(left_bounds, radius), paint);
448 
449  // Right: Direct draw
450  paint.color_source = color_source.get();
451  canvas.DrawRoundSuperellipse(
452  RoundSuperellipse::MakeRectRadius(right_bounds, radius), paint);
453 
454  canvas.EndReplay();
455  return true;
456  };
457 
458  ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
459 }
460 
461 TEST_P(AiksTest, ImageTextureCacheBehavesCorrectly) {
462  ContentContext& context = GetContentContext();
463 
464  TextureDescriptor desc;
465  desc.size = {100, 100};
466  desc.format = context.GetDeviceCapabilities().GetDefaultColorFormat();
467  auto texture =
468  context.GetContext()->GetResourceAllocator()->CreateTexture(desc);
469 
470  auto dl_image = impeller::DlImageImpeller::Make(texture);
471 
472  context.SetTextureCachingEnabled(true);
473  auto cached_tex1 = dl_image->GetCachedTexture(context);
474  ASSERT_EQ(cached_tex1, texture);
475 
476  auto cached_tex2 = context.GetCachedTexture(dl_image.get());
477  ASSERT_EQ(cached_tex2, texture);
478 
479  context.RemoveCachedTexture(dl_image.get());
480  auto cached_tex3 = context.GetCachedTexture(dl_image.get());
481  ASSERT_EQ(cached_tex3, nullptr);
482 
483  auto cached_tex4 = dl_image->GetCachedTexture(context);
484  ASSERT_EQ(cached_tex4, texture);
485 
486  context.ClearCachedTextures();
487  auto cached_tex5 = context.GetCachedTexture(dl_image.get());
488  ASSERT_EQ(cached_tex5, nullptr);
489 
490  context.SetTextureCachingEnabled(false);
491 }
492 
493 /// Verifies blend mode compatibility with SDF rendering.
494 ///
495 /// The compatibility condition is:
496 /// `mix(blend(src, dst), dst, 1 - sdf_alpha) == blend(src * sdf_alpha, dst)`
497 TEST_P(AiksTest, BlendModeCompatibilityWithSDFRendering) {
498  std::vector<Color> colors = {
500  Color::Black(),
501  Color::White(),
506  };
507 
508  for (int i = 0; i <= static_cast<int>(BlendMode::kLastMode); i++) {
509  BlendMode blend_mode = static_cast<BlendMode>(i);
510  bool blend_mode_is_compatible = true;
511 
512  for (const auto& src : colors) {
513  for (const auto& dst : colors) {
514  for (Scalar sdf_alpha = 0.0; sdf_alpha < 1.01; sdf_alpha += 0.2) {
515  // `mix(blend(src, dst), dst, 1 - sdf_alpha)`:
516  // 1. Blend src onto dst.
517  Color blended = dst.Blend(src, blend_mode);
518  // 2. Mix with dst using sdf_alpha. Mix by lerping using
519  // pre-multiplied colors.
520  Color blended_then_sdf_alpha_applied =
521  Color::Lerp(blended.Premultiply(), dst.Premultiply(),
522  1.0 - sdf_alpha)
523  .Unpremultiply();
524 
525  // `blend(src * sdf_alpha, dst)`:
526  // 1. Apply sdf_alpha to src's alpha.
527  Color sdf_alpha_applied = src.WithAlpha(src.alpha * sdf_alpha);
528  // 2. Blend onto dst.
529  Color sdf_alpha_applied_then_blended =
530  dst.Blend(sdf_alpha_applied, blend_mode);
531 
532  // Compare results.
533  if (blended_then_sdf_alpha_applied !=
534  sdf_alpha_applied_then_blended) {
535  blend_mode_is_compatible = false;
536  }
537  }
538  }
539  }
540 
541  Paint paint = {.blend_mode = blend_mode};
542  EXPECT_EQ(blend_mode_is_compatible,
544  << "Failure for BlendMode: " << BlendModeToString(blend_mode);
545  }
546 }
547 
548 TEST(CanvasTest, NonAntialiasedPaintIncompatibleWithSDFRendering) {
549  Paint paint;
550  paint.anti_alias = false;
551  EXPECT_FALSE(Canvas::IsCompatibleWithSDFRendering(paint));
552 }
553 
554 TEST(CanvasTest, AntialiasedPaintCompatibleWithSDFRendering) {
555  Paint paint;
556  EXPECT_TRUE(Canvas::IsCompatibleWithSDFRendering(paint));
557 }
558 
559 } // namespace testing
560 } // namespace impeller
static sk_sp< DlRuntimeEffect > Make(std::shared_ptr< impeller::RuntimeStage > runtime_stage)
void DrawRoundSuperellipse(const RoundSuperellipse &rse, const Paint &paint)
Definition: canvas.cc:1186
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
Definition: canvas.cc:1473
static bool IsCompatibleWithSDFRendering(const Paint &paint)
Definition: canvas.cc:2635
void EndReplay()
Definition: canvas.cc:2607
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
bool OpenPlaygroundHere(const RenderCallback &render_callback)
Definition: playground.cc:287
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
#define ASSERT_MATRIX_NEAR(a, b)
static std::optional< RuntimeStageBackend > GetRuntimeStageBackend(TargetPlatform target_platform)
Definition: reflector.cc:347
std::unique_ptr< Canvas > CreateTestCanvas(ContentContext &context, std::optional< Rect > cull_rect=std::nullopt, bool requires_readback=false)
TEST(AllocationSizeTest, CanCreateTypedAllocations)
TEST_P(AiksTest, DrawAtlasNoColor)
Point Vector2
Definition: point.h:430
flutter::DlRect DlRect
Definition: dl_dispatcher.h:30
float Scalar
Definition: scalar.h:19
Point DrawPlaygroundPoint(PlaygroundPoint &point)
Definition: widgets.cc:11
const char * BlendModeToString(BlendMode blend_mode)
Definition: color.cc:45
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:29
constexpr float kPiOver2
Definition: constants.h:32
BlendMode
Definition: color.h:58
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
std::shared_ptr< ContextGLES > context
std::shared_ptr< Texture > resolve_texture
Definition: formats.h:910
LoadAction load_action
Definition: formats.h:911
std::shared_ptr< Texture > texture
Definition: formats.h:909
StoreAction store_action
Definition: formats.h:912
size_t backdrop_count
Definition: canvas.h:42
uint32_t ToARGB() const
Convert to ARGB 32 bit color.
Definition: color.h:259
static constexpr Color LimeGreen()
Definition: color.h:607
static constexpr Color Azure()
Definition: color.h:303
static constexpr Color BlackTransparent()
Definition: color.h:275
static constexpr Color Black()
Definition: color.h:271
static constexpr Color CornflowerBlue()
Definition: color.h:347
static constexpr Color White()
Definition: color.h:269
constexpr Color WithAlpha(Scalar new_alpha) const
Definition: color.h:283
static constexpr Color Red()
Definition: color.h:277
constexpr Color Unpremultiply() const
Definition: color.h:216
constexpr Color Premultiply() const
Definition: color.h:212
constexpr static Color Lerp(Color a, Color b, Scalar t)
Return a color that is linearly interpolated between colors a and b, according to the value of t.
Definition: color.h:232
Color Blend(Color source, BlendMode blend_mode) const
Blends an unpremultiplied destination color into a given unpremultiplied source color to form a new u...
Definition: color.cc:155
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
Matrix Invert() const
Definition: matrix.cc:99
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
const flutter::DlColorSource * color_source
Definition: paint.h:80
bool anti_alias
Definition: paint.h:88
Color color
Definition: paint.h:79
BlendMode blend_mode
Definition: paint.h:86
static RoundSuperellipse MakeRectRadius(const Rect &rect, Scalar radius)
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition: sigma.h:32
constexpr static TRect MakeEllipseBounds(const TPoint< Type > &center, const TSize< Type > &radii)
Definition: rect.h:164
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...