Flutter Impeller
impeller::Canvas Class Reference

#include <canvas.h>

Classes

struct  SaveLayerState
 

Public Types

using BackdropFilterProc = std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)>
 

Public Member Functions

 Canvas (ContentContext &renderer, RenderTarget &render_target, bool requires_readback)
 
 Canvas (ContentContext &renderer, RenderTarget &render_target, bool requires_readback, Rect cull_rect)
 
 Canvas (ContentContext &renderer, RenderTarget &render_target, bool requires_readback, IRect cull_rect)
 
 ~Canvas ()=default
 
std::optional< RectGetLocalCoverageLimit () const
 Return the culling bounds of the current render target, or nullopt if there is no coverage. More...
 
void Save (uint32_t total_content_depth=kMaxDepth)
 
void SaveLayer (const Paint &paint, std::optional< Rect > bounds=std::nullopt, const flutter::DlImageFilter *backdrop_filter=nullptr, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, uint32_t total_content_depth=kMaxDepth, bool can_distribute_opacity=false)
 
bool Restore ()
 
size_t GetSaveCount () const
 
void RestoreToCount (size_t count)
 
const MatrixGetCurrentTransform () const
 
void ResetTransform ()
 
void Transform (const Matrix &transform)
 
void Concat (const Matrix &transform)
 
void PreConcat (const Matrix &transform)
 
void Translate (const Vector3 &offset)
 
void Scale (const Vector2 &scale)
 
void Scale (const Vector3 &scale)
 
void Skew (Scalar sx, Scalar sy)
 
void Rotate (Radians radians)
 
void DrawPath (const Path &path, const Paint &paint)
 
void DrawPaint (const Paint &paint)
 
void DrawLine (const Point &p0, const Point &p1, const Paint &paint)
 
void DrawRect (const Rect &rect, const Paint &paint)
 
void DrawOval (const Rect &rect, const Paint &paint)
 
void DrawRRect (const Rect &rect, const Size &corner_radii, const Paint &paint)
 
void DrawCircle (const Point &center, Scalar radius, const Paint &paint)
 
void DrawPoints (std::vector< Point > points, Scalar radius, const Paint &paint, PointStyle point_style)
 
void DrawImage (const std::shared_ptr< Texture > &image, Point offset, const Paint &paint, SamplerDescriptor sampler={})
 
void DrawImageRect (const std::shared_ptr< Texture > &image, Rect source, Rect dest, const Paint &paint, SamplerDescriptor sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
 
void DrawTextFrame (const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
 
void DrawVertices (const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
 
void DrawAtlas (const std::shared_ptr< AtlasContents > &atlas_contents, const Paint &paint)
 
void ClipGeometry (std::unique_ptr< Geometry > geometry, Entity::ClipOperation clip_op)
 
void EndReplay ()
 
uint64_t GetOpDepth () const
 
uint64_t GetMaxOpDepth () const
 

Static Public Attributes

static constexpr uint32_t kMaxDepth = 1 << 24
 

Detailed Description

Definition at line 101 of file canvas.h.

Member Typedef Documentation

◆ BackdropFilterProc

using impeller::Canvas::BackdropFilterProc = std::function<std::shared_ptr<FilterContents>( FilterInput::Ref, const Matrix& effect_transform, Entity::RenderingMode rendering_mode)>

Definition at line 108 of file canvas.h.

Constructor & Destructor Documentation

◆ Canvas() [1/3]

impeller::Canvas::Canvas ( ContentContext renderer,
RenderTarget render_target,
bool  requires_readback 
)

Definition at line 263 of file canvas.cc.

266  : renderer_(renderer),
267  render_target_(render_target),
268  requires_readback_(requires_readback),
269  clip_coverage_stack_(EntityPassClipStack(
270  Rect::MakeSize(render_target.GetRenderTargetSize()))) {
271  Initialize(std::nullopt);
272  SetupRenderPass();
273 }

◆ Canvas() [2/3]

impeller::Canvas::Canvas ( ContentContext renderer,
RenderTarget render_target,
bool  requires_readback,
Rect  cull_rect 
)
explicit

Definition at line 275 of file canvas.cc.

279  : renderer_(renderer),
280  render_target_(render_target),
281  requires_readback_(requires_readback),
282  clip_coverage_stack_(EntityPassClipStack(
283  Rect::MakeSize(render_target.GetRenderTargetSize()))) {
284  Initialize(cull_rect);
285  SetupRenderPass();
286 }

◆ Canvas() [3/3]

impeller::Canvas::Canvas ( ContentContext renderer,
RenderTarget render_target,
bool  requires_readback,
IRect  cull_rect 
)
explicit

Definition at line 288 of file canvas.cc.

292  : renderer_(renderer),
293  render_target_(render_target),
294  requires_readback_(requires_readback),
295  clip_coverage_stack_(EntityPassClipStack(
296  Rect::MakeSize(render_target.GetRenderTargetSize()))) {
297  Initialize(Rect::MakeLTRB(cull_rect.GetLeft(), cull_rect.GetTop(),
298  cull_rect.GetRight(), cull_rect.GetBottom()));
299  SetupRenderPass();
300 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), and impeller::TRect< Scalar >::MakeLTRB().

◆ ~Canvas()

impeller::Canvas::~Canvas ( )
default

Member Function Documentation

◆ ClipGeometry()

void impeller::Canvas::ClipGeometry ( std::unique_ptr< Geometry geometry,
Entity::ClipOperation  clip_op 
)

Definition at line 651 of file canvas.cc.

652  {
653  clip_geometry_.push_back(std::move(geometry));
654 
655  auto contents = std::make_shared<ClipContents>();
656  contents->SetGeometry(clip_geometry_.back().get());
657  contents->SetClipOperation(clip_op);
658 
659  Entity entity;
660  entity.SetTransform(GetCurrentTransform());
661  entity.SetContents(std::move(contents));
662 
663  AddClipEntityToCurrentPass(entity);
664 
665  ++transform_stack_.back().clip_height;
666  ++transform_stack_.back().num_clips;
667 }

References GetCurrentTransform(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::clipOval(), impeller::DlDispatcherBase::clipPath(), impeller::DlDispatcherBase::clipRect(), and impeller::DlDispatcherBase::clipRRect().

◆ Concat()

void impeller::Canvas::Concat ( const Matrix transform)

Definition at line 315 of file canvas.cc.

315  {
316  transform_stack_.back().transform = GetCurrentTransform() * transform;
317 }

References GetCurrentTransform(), and transform.

Referenced by Rotate(), Scale(), Skew(), Transform(), and Translate().

◆ DrawAtlas()

void impeller::Canvas::DrawAtlas ( const std::shared_ptr< AtlasContents > &  atlas_contents,
const Paint paint 
)

Definition at line 868 of file canvas.cc.

869  {
870  atlas_contents->SetAlpha(paint.color.alpha);
871 
872  Entity entity;
873  entity.SetTransform(GetCurrentTransform());
874  entity.SetBlendMode(paint.blend_mode);
875  entity.SetContents(paint.WithFilters(atlas_contents));
876 
877  AddRenderEntityToCurrentPass(entity);
878 }

References impeller::Color::alpha, impeller::Paint::blend_mode, impeller::Paint::color, GetCurrentTransform(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Paint::WithFilters().

Referenced by impeller::DlDispatcherBase::drawAtlas().

◆ DrawCircle()

void impeller::Canvas::DrawCircle ( const Point center,
Scalar  radius,
const Paint paint 
)

Definition at line 628 of file canvas.cc.

630  {
631  Size half_size(radius, radius);
632  if (AttemptDrawBlurredRRect(
633  Rect::MakeOriginSize(center - half_size, half_size * 2),
634  {radius, radius}, paint)) {
635  return;
636  }
637 
638  Entity entity;
639  entity.SetTransform(GetCurrentTransform());
640  entity.SetBlendMode(paint.blend_mode);
641 
642  if (paint.style == Paint::Style::kStroke) {
643  CircleGeometry geom(center, radius, paint.stroke_width);
644  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
645  } else {
646  CircleGeometry geom(center, radius);
647  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
648  }
649 }

References impeller::Paint::blend_mode, GetCurrentTransform(), impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeOriginSize(), impeller::Entity::SetBlendMode(), impeller::Entity::SetTransform(), impeller::Paint::stroke_width, and impeller::Paint::style.

Referenced by impeller::DlDispatcherBase::drawCircle(), and DrawOval().

◆ DrawImage()

void impeller::Canvas::DrawImage ( const std::shared_ptr< Texture > &  image,
Point  offset,
const Paint paint,
SamplerDescriptor  sampler = {} 
)

Definition at line 698 of file canvas.cc.

701  {
702  if (!image) {
703  return;
704  }
705 
706  const auto source = Rect::MakeSize(image->GetSize());
707  const auto dest = source.Shift(offset);
708 
709  DrawImageRect(image, source, dest, paint, std::move(sampler));
710 }

References DrawImageRect(), impeller::TRect< Scalar >::MakeSize(), and offset.

◆ DrawImageRect()

void impeller::Canvas::DrawImageRect ( const std::shared_ptr< Texture > &  image,
Rect  source,
Rect  dest,
const Paint paint,
SamplerDescriptor  sampler = {},
SourceRectConstraint  src_rect_constraint = SourceRectConstraint::kFast 
)

Definition at line 712 of file canvas.cc.

717  {
718  if (!image || source.IsEmpty() || dest.IsEmpty()) {
719  return;
720  }
721 
722  auto size = image->GetSize();
723 
724  if (size.IsEmpty()) {
725  return;
726  }
727 
728  auto texture_contents = TextureContents::MakeRect(dest);
729  texture_contents->SetTexture(image);
730  texture_contents->SetSourceRect(source);
731  texture_contents->SetStrictSourceRect(src_rect_constraint ==
733  texture_contents->SetSamplerDescriptor(std::move(sampler));
734  texture_contents->SetOpacity(paint.color.alpha);
735  texture_contents->SetDeferApplyingOpacity(paint.HasColorFilter());
736 
737  Entity entity;
738  entity.SetBlendMode(paint.blend_mode);
739  entity.SetTransform(GetCurrentTransform());
740 
741  if (!paint.mask_blur_descriptor.has_value()) {
742  entity.SetContents(paint.WithFilters(std::move(texture_contents)));
743  AddRenderEntityToCurrentPass(entity);
744  return;
745  }
746 
747  RectGeometry out_rect(Rect{});
748 
749  entity.SetContents(paint.WithFilters(
750  paint.mask_blur_descriptor->CreateMaskBlur(texture_contents, &out_rect)));
751  AddRenderEntityToCurrentPass(entity);
752 }

References impeller::Color::alpha, impeller::Paint::blend_mode, impeller::Paint::color, GetCurrentTransform(), impeller::Paint::HasColorFilter(), impeller::TRect< T >::IsEmpty(), impeller::kStrict, impeller::TextureContents::MakeRect(), impeller::Paint::mask_blur_descriptor, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Paint::WithFilters().

Referenced by DrawImage(), impeller::DlDispatcherBase::drawImageRect(), and impeller::NinePatchConverter::DrawNinePatch().

◆ DrawLine()

void impeller::Canvas::DrawLine ( const Point p0,
const Point p1,
const Paint paint 
)

Definition at line 546 of file canvas.cc.

546  {
547  Entity entity;
548  entity.SetTransform(GetCurrentTransform());
549  entity.SetBlendMode(paint.blend_mode);
550 
551  LineGeometry geom(p0, p1, paint.stroke_width, paint.stroke_cap);
552  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
553 }

References impeller::Paint::blend_mode, GetCurrentTransform(), impeller::Entity::SetBlendMode(), impeller::Entity::SetTransform(), impeller::Paint::stroke_cap, and impeller::Paint::stroke_width.

Referenced by impeller::DlDispatcherBase::drawLine(), and impeller::DlDispatcherBase::drawPoints().

◆ DrawOval()

void impeller::Canvas::DrawOval ( const Rect rect,
const Paint paint 
)

Definition at line 573 of file canvas.cc.

573  {
574  // TODO(jonahwilliams): This additional condition avoids an assert in the
575  // stroke circle geometry generator. I need to verify the condition that this
576  // assert prevents.
577  if (rect.IsSquare() && (paint.style == Paint::Style::kFill ||
578  (paint.style == Paint::Style::kStroke &&
579  paint.stroke_width < rect.GetWidth()))) {
580  // Circles have slightly less overhead and can do stroking
581  DrawCircle(rect.GetCenter(), rect.GetWidth() * 0.5f, paint);
582  return;
583  }
584 
585  if (paint.style == Paint::Style::kStroke) {
586  // No stroked ellipses yet
587  DrawPath(PathBuilder{}.AddOval(rect).TakePath(), paint);
588  return;
589  }
590 
591  if (AttemptDrawBlurredRRect(rect, rect.GetSize() * 0.5f, paint)) {
592  return;
593  }
594 
595  Entity entity;
596  entity.SetTransform(GetCurrentTransform());
597  entity.SetBlendMode(paint.blend_mode);
598 
599  EllipseGeometry geom(rect);
600  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
601 }

References impeller::PathBuilder::AddOval(), impeller::Paint::blend_mode, DrawCircle(), DrawPath(), impeller::TRect< T >::GetCenter(), GetCurrentTransform(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::IsSquare(), impeller::Paint::kFill, impeller::Paint::kStroke, impeller::Entity::SetBlendMode(), impeller::Entity::SetTransform(), impeller::Paint::stroke_width, and impeller::Paint::style.

Referenced by impeller::DlDispatcherBase::drawOval(), and impeller::DlDispatcherBase::SimplifyOrDrawPath().

◆ DrawPaint()

void impeller::Canvas::DrawPaint ( const Paint paint)

Definition at line 401 of file canvas.cc.

401  {
402  Entity entity;
403  entity.SetTransform(GetCurrentTransform());
404  entity.SetBlendMode(paint.blend_mode);
405 
406  CoverGeometry geom;
407  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
408 }

References impeller::Paint::blend_mode, GetCurrentTransform(), impeller::Entity::SetBlendMode(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawColor(), and impeller::DlDispatcherBase::drawPaint().

◆ DrawPath()

void impeller::Canvas::DrawPath ( const Path path,
const Paint paint 
)

Definition at line 386 of file canvas.cc.

386  {
387  Entity entity;
388  entity.SetTransform(GetCurrentTransform());
389  entity.SetBlendMode(paint.blend_mode);
390 
391  if (paint.style == Paint::Style::kFill) {
392  FillPathGeometry geom(path);
393  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
394  } else {
395  StrokePathGeometry geom(path, paint.stroke_width, paint.stroke_miter,
396  paint.stroke_cap, paint.stroke_join);
397  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
398  }
399 }

References impeller::Paint::blend_mode, GetCurrentTransform(), impeller::Paint::kFill, impeller::Entity::SetBlendMode(), impeller::Entity::SetTransform(), impeller::Paint::stroke_cap, impeller::Paint::stroke_join, impeller::Paint::stroke_miter, impeller::Paint::stroke_width, and impeller::Paint::style.

Referenced by impeller::DlDispatcherBase::drawArc(), impeller::DlDispatcherBase::drawDashedLine(), impeller::DlDispatcherBase::drawDRRect(), DrawOval(), DrawRect(), impeller::DlDispatcherBase::drawRRect(), DrawRRect(), and impeller::DlDispatcherBase::SimplifyOrDrawPath().

◆ DrawPoints()

void impeller::Canvas::DrawPoints ( std::vector< Point points,
Scalar  radius,
const Paint paint,
PointStyle  point_style 
)

Definition at line 681 of file canvas.cc.

684  {
685  if (radius <= 0) {
686  return;
687  }
688 
689  Entity entity;
690  entity.SetTransform(GetCurrentTransform());
691  entity.SetBlendMode(paint.blend_mode);
692 
693  PointFieldGeometry geom(std::move(points), radius,
694  /*round=*/point_style == PointStyle::kRound);
695  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
696 }

References impeller::Paint::blend_mode, GetCurrentTransform(), impeller::kRound, impeller::Entity::SetBlendMode(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawPoints().

◆ DrawRect()

void impeller::Canvas::DrawRect ( const Rect rect,
const Paint paint 
)

Definition at line 555 of file canvas.cc.

555  {
556  if (paint.style == Paint::Style::kStroke) {
557  DrawPath(PathBuilder{}.AddRect(rect).TakePath(), paint);
558  return;
559  }
560 
561  if (AttemptDrawBlurredRRect(rect, {}, paint)) {
562  return;
563  }
564 
565  Entity entity;
566  entity.SetTransform(GetCurrentTransform());
567  entity.SetBlendMode(paint.blend_mode);
568 
569  RectGeometry geom(rect);
570  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
571 }

References impeller::PathBuilder::AddRect(), impeller::Paint::blend_mode, DrawPath(), GetCurrentTransform(), impeller::Paint::kStroke, impeller::Entity::SetBlendMode(), impeller::Entity::SetTransform(), and impeller::Paint::style.

Referenced by impeller::DlDispatcherBase::drawRect(), and impeller::DlDispatcherBase::SimplifyOrDrawPath().

◆ DrawRRect()

void impeller::Canvas::DrawRRect ( const Rect rect,
const Size corner_radii,
const Paint paint 
)

Definition at line 603 of file canvas.cc.

605  {
606  if (AttemptDrawBlurredRRect(rect, corner_radii, paint)) {
607  return;
608  }
609 
610  if (paint.style == Paint::Style::kFill) {
611  Entity entity;
612  entity.SetTransform(GetCurrentTransform());
613  entity.SetBlendMode(paint.blend_mode);
614 
615  RoundRectGeometry geom(rect, corner_radii);
616  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
617  return;
618  }
619 
620  auto path = PathBuilder{}
621  .SetConvexity(Convexity::kConvex)
622  .AddRoundedRect(rect, corner_radii)
623  .SetBounds(rect)
624  .TakePath();
625  DrawPath(path, paint);
626 }

References impeller::PathBuilder::AddRoundedRect(), impeller::Paint::blend_mode, DrawPath(), GetCurrentTransform(), impeller::kConvex, impeller::Paint::kFill, impeller::Entity::SetBlendMode(), impeller::PathBuilder::SetBounds(), impeller::PathBuilder::SetConvexity(), impeller::Entity::SetTransform(), impeller::Paint::style, and impeller::PathBuilder::TakePath().

Referenced by impeller::DlDispatcherBase::drawRRect(), and impeller::DlDispatcherBase::SimplifyOrDrawPath().

◆ DrawTextFrame()

void impeller::Canvas::DrawTextFrame ( const std::shared_ptr< TextFrame > &  text_frame,
Point  position,
const Paint paint 
)

Definition at line 1309 of file canvas.cc.

1311  {
1312  Entity entity;
1313  entity.SetClipDepth(GetClipHeight());
1314  entity.SetBlendMode(paint.blend_mode);
1315 
1316  auto text_contents = std::make_shared<TextContents>();
1317  text_contents->SetTextFrame(text_frame);
1318  text_contents->SetForceTextColor(paint.mask_blur_descriptor.has_value());
1319  text_contents->SetScale(GetCurrentTransform().GetMaxBasisLengthXY());
1320  text_contents->SetColor(paint.color);
1321  text_contents->SetOffset(position);
1322  text_contents->SetTextProperties(paint.color, //
1323  paint.style == Paint::Style::kStroke, //
1324  paint.stroke_width, //
1325  paint.stroke_cap, //
1326  paint.stroke_join, //
1327  paint.stroke_miter //
1328  );
1329 
1330  entity.SetTransform(GetCurrentTransform() *
1331  Matrix::MakeTranslation(position));
1332 
1333  // TODO(bdero): This mask blur application is a hack. It will always wind up
1334  // doing a gaussian blur that affects the color source itself
1335  // instead of just the mask. The color filter text support
1336  // needs to be reworked in order to interact correctly with
1337  // mask filters.
1338  // https://github.com/flutter/flutter/issues/133297
1339  entity.SetContents(paint.WithFilters(paint.WithMaskBlur(
1340  std::move(text_contents), true, GetCurrentTransform())));
1341 
1342  AddRenderEntityToCurrentPass(entity, false);
1343 }

References impeller::Paint::blend_mode, impeller::Paint::color, GetCurrentTransform(), impeller::Paint::kStroke, impeller::Matrix::MakeTranslation(), impeller::Paint::mask_blur_descriptor, impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::Paint::stroke_cap, impeller::Paint::stroke_join, impeller::Paint::stroke_miter, impeller::Paint::stroke_width, impeller::Paint::style, impeller::Paint::WithFilters(), and impeller::Paint::WithMaskBlur().

Referenced by impeller::DlDispatcherBase::drawTextFrame().

◆ DrawVertices()

void impeller::Canvas::DrawVertices ( const std::shared_ptr< VerticesGeometry > &  vertices,
BlendMode  blend_mode,
const Paint paint 
)

Definition at line 758 of file canvas.cc.

760  {
761  // Override the blend mode with kDestination in order to match the behavior
762  // of Skia's SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER flag, which
763  // is enabled when the Flutter engine builds Skia.
764  if (!paint.color_source ||
765  paint.color_source->type() == flutter::DlColorSourceType::kColor) {
766  blend_mode = BlendMode::kDestination;
767  }
768 
769  Entity entity;
770  entity.SetTransform(GetCurrentTransform());
771  entity.SetBlendMode(paint.blend_mode);
772 
773  // If there are no vertex colors.
774  if (UseColorSourceContents(vertices, paint)) {
775  AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
776  return;
777  }
778 
779  // If the blend mode is destination don't bother to bind or create a texture.
780  if (blend_mode == BlendMode::kDestination) {
781  auto contents = std::make_shared<VerticesSimpleBlendContents>();
782  contents->SetBlendMode(blend_mode);
783  contents->SetAlpha(paint.color.alpha);
784  contents->SetGeometry(vertices);
785  entity.SetContents(paint.WithFilters(std::move(contents)));
786  AddRenderEntityToCurrentPass(entity);
787  return;
788  }
789 
790  // If there is a texture, use this directly. Otherwise render the color
791  // source to a texture.
792  if (paint.color_source &&
793  paint.color_source->type() == flutter::DlColorSourceType::kImage) {
794  const flutter::DlImageColorSource* image_color_source =
795  paint.color_source->asImage();
796  FML_DCHECK(image_color_source &&
797  image_color_source->image()->impeller_texture());
798  auto texture = image_color_source->image()->impeller_texture();
799  auto x_tile_mode = static_cast<Entity::TileMode>(
800  image_color_source->horizontal_tile_mode());
801  auto y_tile_mode =
802  static_cast<Entity::TileMode>(image_color_source->vertical_tile_mode());
803  auto sampler_descriptor =
804  skia_conversions::ToSamplerDescriptor(image_color_source->sampling());
805  auto effect_transform =
806  skia_conversions::ToMatrix(image_color_source->matrix());
807 
808  auto contents = std::make_shared<VerticesSimpleBlendContents>();
809  contents->SetBlendMode(blend_mode);
810  contents->SetAlpha(paint.color.alpha);
811  contents->SetGeometry(vertices);
812  contents->SetEffectTransform(effect_transform);
813  contents->SetTexture(texture);
814  contents->SetTileMode(x_tile_mode, y_tile_mode);
815 
816  entity.SetContents(paint.WithFilters(std::move(contents)));
817  AddRenderEntityToCurrentPass(entity);
818  return;
819  }
820 
821  auto src_paint = paint;
822  src_paint.color = paint.color.WithAlpha(1.0);
823 
824  std::shared_ptr<ColorSourceContents> src_contents =
825  src_paint.CreateContents();
826  src_contents->SetGeometry(vertices.get());
827 
828  // If the color source has an intrinsic size, then we use that to
829  // create the src contents as a simplification. Otherwise we use
830  // the extent of the texture coordinates to determine how large
831  // the src contents should be. If neither has a value we fall back
832  // to using the geometry coverage data.
833  Rect src_coverage;
834  auto size = src_contents->GetColorSourceSize();
835  if (size.has_value()) {
836  src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
837  } else {
838  auto cvg = vertices->GetCoverage(Matrix{});
839  FML_CHECK(cvg.has_value());
840  src_coverage =
841  // Covered by FML_CHECK.
842  // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
843  vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
844  }
845  src_contents = src_paint.CreateContents();
846 
847  clip_geometry_.push_back(Geometry::MakeRect(Rect::Round(src_coverage)));
848  src_contents->SetGeometry(clip_geometry_.back().get());
849 
850  auto contents = std::make_shared<VerticesSimpleBlendContents>();
851  contents->SetBlendMode(blend_mode);
852  contents->SetAlpha(paint.color.alpha);
853  contents->SetGeometry(vertices);
854  contents->SetLazyTextureCoverage(src_coverage);
855  contents->SetLazyTexture(
856  [src_contents, src_coverage](const ContentContext& renderer) {
857  // Applying the src coverage as the coverage limit prevents the 1px
858  // coverage pad from adding a border that is picked up by developer
859  // specified UVs.
860  return src_contents
861  ->RenderToSnapshot(renderer, {}, Rect::Round(src_coverage))
862  ->texture;
863  });
864  entity.SetContents(paint.WithFilters(std::move(contents)));
865  AddRenderEntityToCurrentPass(entity);
866 }

References impeller::Color::alpha, impeller::Paint::blend_mode, impeller::Paint::color, impeller::Paint::color_source, GetCurrentTransform(), impeller::kDestination, impeller::Geometry::MakeRect(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TRect< Scalar >::Round(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::skia_conversions::ToMatrix(), impeller::skia_conversions::ToSamplerDescriptor(), impeller::Color::WithAlpha(), and impeller::Paint::WithFilters().

Referenced by impeller::CanvasDlDispatcher::drawVertices().

◆ EndReplay()

void impeller::Canvas::EndReplay ( )

Definition at line 1639 of file canvas.cc.

1639  {
1640  FML_DCHECK(render_passes_.size() == 1u);
1641  render_passes_.back().inline_pass_context->GetRenderPass(0);
1642  render_passes_.back().inline_pass_context->EndPass();
1643 
1644  // If requires_readback_ was true, then we rendered to an offscreen texture
1645  // instead of to the onscreen provided in the render target. Now we need to
1646  // draw or blit the offscreen back to the onscreen.
1647  if (requires_readback_) {
1648  BlitToOnscreen();
1649  }
1650 
1651  render_passes_.clear();
1652  renderer_.GetRenderTargetCache()->End();
1653  clip_geometry_.clear();
1654 
1655  Reset();
1656  Initialize(initial_cull_rect_);
1657 }

Referenced by impeller::CanvasDlDispatcher::FinishRecording().

◆ GetCurrentTransform()

const Matrix & impeller::Canvas::GetCurrentTransform ( ) const

◆ GetLocalCoverageLimit()

std::optional< Rect > impeller::Canvas::GetLocalCoverageLimit ( ) const

Return the culling bounds of the current render target, or nullopt if there is no coverage.

Definition at line 951 of file canvas.cc.

951  {
952  if (!clip_coverage_stack_.HasCoverage()) {
953  // The current clip is empty. This means the pass texture won't be
954  // visible, so skip it.
955  return std::nullopt;
956  }
957 
958  auto maybe_current_clip_coverage = clip_coverage_stack_.CurrentClipCoverage();
959  if (!maybe_current_clip_coverage.has_value()) {
960  return std::nullopt;
961  }
962 
963  auto current_clip_coverage = maybe_current_clip_coverage.value();
964 
965  // The maximum coverage of the subpass. Subpasses textures should never
966  // extend outside the parent pass texture or the current clip coverage.
967  std::optional<Rect> maybe_coverage_limit =
968  Rect::MakeOriginSize(GetGlobalPassPosition(),
969  Size(render_passes_.back()
970  .inline_pass_context->GetTexture()
971  ->GetSize()))
972  .Intersection(current_clip_coverage);
973 
974  if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
975  return std::nullopt;
976  }
977 
978  return maybe_coverage_limit->Intersection(
979  Rect::MakeSize(render_target_.GetRenderTargetSize()));
980 }

References impeller::EntityPassClipStack::CurrentClipCoverage(), impeller::RenderTarget::GetRenderTargetSize(), impeller::EntityPassClipStack::HasCoverage(), impeller::TRect< T >::Intersection(), impeller::TRect< Scalar >::MakeOriginSize(), and impeller::TRect< Scalar >::MakeSize().

Referenced by impeller::DlDispatcherBase::drawDisplayList(), and SaveLayer().

◆ GetMaxOpDepth()

uint64_t impeller::Canvas::GetMaxOpDepth ( ) const
inline

Definition at line 218 of file canvas.h.

218 { return transform_stack_.back().clip_depth; }

◆ GetOpDepth()

uint64_t impeller::Canvas::GetOpDepth ( ) const
inline

Definition at line 216 of file canvas.h.

216 { return current_depth_; }

◆ GetSaveCount()

size_t impeller::Canvas::GetSaveCount ( ) const

Definition at line 370 of file canvas.cc.

370  {
371  return transform_stack_.size();
372 }

Referenced by impeller::DlDispatcherBase::drawDisplayList(), and RestoreToCount().

◆ PreConcat()

void impeller::Canvas::PreConcat ( const Matrix transform)

Definition at line 319 of file canvas.cc.

319  {
320  transform_stack_.back().transform = transform * GetCurrentTransform();
321 }

References GetCurrentTransform(), and transform.

Referenced by impeller::DlDispatcherBase::drawShadow().

◆ ResetTransform()

void impeller::Canvas::ResetTransform ( )

Definition at line 323 of file canvas.cc.

323  {
324  transform_stack_.back().transform = {};
325 }

Referenced by impeller::DlDispatcherBase::transformReset().

◆ Restore()

bool impeller::Canvas::Restore ( )

Definition at line 1134 of file canvas.cc.

1134  {
1135  FML_DCHECK(transform_stack_.size() > 0);
1136  if (transform_stack_.size() == 1) {
1137  return false;
1138  }
1139 
1140  // This check is important to make sure we didn't exceed the depth
1141  // that the clips were rendered at while rendering any of the
1142  // rendering ops. It is OK for the current depth to equal the
1143  // outgoing clip depth because that means the clipping would have
1144  // been successful up through the last rendering op, but it cannot
1145  // be greater.
1146  // Also, we bump the current rendering depth to the outgoing clip
1147  // depth so that future rendering operations are not clipped by
1148  // any of the pixels set by the expiring clips. It is OK for the
1149  // estimates used to determine the clip depth in save/saveLayer
1150  // to be overly conservative, but we need to jump the depth to
1151  // the clip depth so that the next rendering op will get a
1152  // larger depth (it will pre-increment the current_depth_ value).
1153  FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1154  << current_depth_ << " <=? " << transform_stack_.back().clip_depth;
1155  current_depth_ = transform_stack_.back().clip_depth;
1156 
1157  if (IsSkipping()) {
1158  transform_stack_.pop_back();
1159  return true;
1160  }
1161 
1162  if (transform_stack_.back().rendering_mode ==
1164  transform_stack_.back().rendering_mode ==
1166  auto lazy_render_pass = std::move(render_passes_.back());
1167  render_passes_.pop_back();
1168  // Force the render pass to be constructed if it never was.
1169  lazy_render_pass.inline_pass_context->GetRenderPass(0);
1170 
1171  SaveLayerState save_layer_state = save_layer_state_.back();
1172  save_layer_state_.pop_back();
1173  auto global_pass_position = GetGlobalPassPosition();
1174 
1175  std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1176  save_layer_state.paint, //
1177  lazy_render_pass.inline_pass_context->GetTexture(), //
1178  Matrix::MakeTranslation(Vector3{-global_pass_position}) * //
1179  transform_stack_.back().transform //
1180  );
1181 
1182  lazy_render_pass.inline_pass_context->EndPass();
1183 
1184  // Round the subpass texture position for pixel alignment with the parent
1185  // pass render target. By default, we draw subpass textures with nearest
1186  // sampling, so aligning here is important for avoiding visual nearest
1187  // sampling errors caused by limited floating point precision when
1188  // straddling a half pixel boundary.
1189  Point subpass_texture_position;
1190  if (transform_stack_.back().did_round_out) {
1191  // Subpass coverage was rounded out, origin potentially moved "down" by
1192  // as much as a pixel.
1193  subpass_texture_position =
1194  (save_layer_state.coverage.GetOrigin() - global_pass_position)
1195  .Floor();
1196  } else {
1197  // Subpass coverage was truncated. Pick the closest phyiscal pixel.
1198  subpass_texture_position =
1199  (save_layer_state.coverage.GetOrigin() - global_pass_position)
1200  .Round();
1201  }
1202 
1203  Entity element_entity;
1204  element_entity.SetClipDepth(++current_depth_);
1205  element_entity.SetContents(std::move(contents));
1206  element_entity.SetBlendMode(save_layer_state.paint.blend_mode);
1207  element_entity.SetTransform(
1208  Matrix::MakeTranslation(Vector3(subpass_texture_position)));
1209 
1210  if (element_entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
1211  if (renderer_.GetDeviceCapabilities().SupportsFramebufferFetch()) {
1212  ApplyFramebufferBlend(element_entity);
1213  } else {
1214  // End the active pass and flush the buffer before rendering "advanced"
1215  // blends. Advanced blends work by binding the current render target
1216  // texture as an input ("destination"), blending with a second texture
1217  // input ("source"), writing the result to an intermediate texture, and
1218  // finally copying the data from the intermediate texture back to the
1219  // render target texture. And so all of the commands that have written
1220  // to the render target texture so far need to execute before it's bound
1221  // for blending (otherwise the blend pass will end up executing before
1222  // all the previous commands in the active pass).
1223  auto input_texture =
1224  FlipBackdrop(render_passes_, GetGlobalPassPosition(),
1225  clip_coverage_stack_, renderer_);
1226  if (!input_texture) {
1227  return false;
1228  }
1229 
1230  FilterInput::Vector inputs = {
1231  FilterInput::Make(input_texture,
1232  element_entity.GetTransform().Invert()),
1233  FilterInput::Make(element_entity.GetContents())};
1234  auto contents = ColorFilterContents::MakeBlend(
1235  element_entity.GetBlendMode(), inputs);
1236  contents->SetCoverageHint(element_entity.GetCoverage());
1237  element_entity.SetContents(std::move(contents));
1238  element_entity.SetBlendMode(BlendMode::kSource);
1239  }
1240  }
1241 
1242  element_entity.Render(
1243  renderer_, //
1244  *render_passes_.back().inline_pass_context->GetRenderPass(0).pass //
1245  );
1246  clip_coverage_stack_.PopSubpass();
1247  transform_stack_.pop_back();
1248 
1249  // We don't need to restore clips if a saveLayer was performed, as the clip
1250  // state is per render target, and no more rendering operations will be
1251  // performed as the render target workloaded is completed in the restore.
1252  return true;
1253  }
1254 
1255  size_t num_clips = transform_stack_.back().num_clips;
1256  transform_stack_.pop_back();
1257 
1258  if (num_clips > 0) {
1259  Entity entity;
1260  entity.SetTransform(
1261  Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
1263  // This path is empty because ClipRestoreContents just generates a quad that
1264  // takes up the full render target.
1265  auto clip_restore = std::make_shared<ClipRestoreContents>();
1266  clip_restore->SetRestoreHeight(GetClipHeight());
1267  entity.SetContents(std::move(clip_restore));
1268 
1269  auto current_clip_coverage = clip_coverage_stack_.CurrentClipCoverage();
1270  if (current_clip_coverage.has_value()) {
1271  // Entity transforms are relative to the current pass position, so we need
1272  // to check clip coverage in the same space.
1273  current_clip_coverage =
1274  current_clip_coverage->Shift(-GetGlobalPassPosition());
1275  }
1276 
1277  auto clip_coverage = entity.GetClipCoverage(current_clip_coverage);
1278  if (clip_coverage.coverage.has_value()) {
1279  clip_coverage.coverage =
1280  clip_coverage.coverage->Shift(GetGlobalPassPosition());
1281  }
1282 
1283  EntityPassClipStack::ClipStateResult clip_state_result =
1284  clip_coverage_stack_.ApplyClipState(clip_coverage, entity,
1285  GetClipHeightFloor(),
1286  GetGlobalPassPosition());
1287 
1288  if (clip_state_result.clip_did_change) {
1289  // We only need to update the pass scissor if the clip state has changed.
1290  SetClipScissor(
1291  clip_coverage_stack_.CurrentClipCoverage(), //
1292  *render_passes_.back().inline_pass_context->GetRenderPass(0).pass, //
1293  GetGlobalPassPosition() //
1294  );
1295  }
1296 
1297  if (!clip_state_result.should_render) {
1298  return true;
1299  }
1300 
1301  entity.Render(
1302  renderer_,
1303  *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
1304  }
1305 
1306  return true;
1307 }

References impeller::EntityPassClipStack::ApplyClipState(), impeller::Paint::blend_mode, impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::Contents::ClipCoverage::coverage, impeller::Canvas::SaveLayerState::coverage, impeller::EntityPassClipStack::CurrentClipCoverage(), impeller::Entity::GetBlendMode(), impeller::Entity::GetClipCoverage(), impeller::Entity::GetContents(), impeller::Entity::GetCoverage(), GetCurrentTransform(), impeller::ContentContext::GetDeviceCapabilities(), impeller::TRect< T >::GetOrigin(), impeller::Entity::GetTransform(), impeller::Matrix::Invert(), impeller::Entity::kLastPipelineBlendMode, impeller::kSource, impeller::Entity::kSubpassAppendSnapshotTransform, impeller::Entity::kSubpassPrependSnapshotTransform, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeTranslation(), impeller::Canvas::SaveLayerState::paint, impeller::EntityPassClipStack::PopSubpass(), impeller::Entity::Render(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Capabilities::SupportsFramebufferFetch().

Referenced by impeller::DlDispatcherBase::drawShadow(), impeller::DlDispatcherBase::restore(), and RestoreToCount().

◆ RestoreToCount()

void impeller::Canvas::RestoreToCount ( size_t  count)

Definition at line 378 of file canvas.cc.

378  {
379  while (GetSaveCount() > count) {
380  if (!Restore()) {
381  return;
382  }
383  }
384 }

References GetSaveCount(), and Restore().

Referenced by impeller::DlDispatcherBase::drawDisplayList().

◆ Rotate()

void impeller::Canvas::Rotate ( Radians  radians)

Definition at line 351 of file canvas.cc.

351  {
352  Concat(Matrix::MakeRotationZ(radians));
353 }

References Concat(), and impeller::Matrix::MakeRotationZ().

Referenced by impeller::DlDispatcherBase::rotate().

◆ Save()

void impeller::Canvas::Save ( uint32_t  total_content_depth = kMaxDepth)

Definition at line 934 of file canvas.cc.

934  {
935  if (IsSkipping()) {
936  return SkipUntilMatchingRestore(total_content_depth);
937  }
938 
939  auto entry = CanvasStackEntry{};
940  entry.transform = transform_stack_.back().transform;
941  entry.clip_depth = current_depth_ + total_content_depth;
942  entry.distributed_opacity = transform_stack_.back().distributed_opacity;
943  FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
944  << entry.clip_depth << " <=? " << transform_stack_.back().clip_depth
945  << " after allocating " << total_content_depth;
946  entry.clip_height = transform_stack_.back().clip_height;
947  entry.rendering_mode = Entity::RenderingMode::kDirect;
948  transform_stack_.push_back(entry);
949 }

References impeller::Entity::kDirect, and impeller::CanvasStackEntry::transform.

Referenced by impeller::DlDispatcherBase::drawDisplayList(), impeller::DlDispatcherBase::drawShadow(), impeller::DlDispatcherBase::save(), and SaveLayer().

◆ SaveLayer()

void impeller::Canvas::SaveLayer ( const Paint paint,
std::optional< Rect bounds = std::nullopt,
const flutter::DlImageFilter *  backdrop_filter = nullptr,
ContentBoundsPromise  bounds_promise = ContentBoundsPromise::kUnknown,
uint32_t  total_content_depth = kMaxDepth,
bool  can_distribute_opacity = false 
)

Definition at line 982 of file canvas.cc.

987  {
988  TRACE_EVENT0("flutter", "Canvas::saveLayer");
989  if (IsSkipping()) {
990  return SkipUntilMatchingRestore(total_content_depth);
991  }
992 
993  auto maybe_coverage_limit = GetLocalCoverageLimit();
994  if (!maybe_coverage_limit.has_value()) {
995  return SkipUntilMatchingRestore(total_content_depth);
996  }
997  auto coverage_limit = maybe_coverage_limit.value();
998 
999  if (can_distribute_opacity && !backdrop_filter &&
1001  bounds_promise != ContentBoundsPromise::kMayClipContents) {
1002  Save(total_content_depth);
1003  transform_stack_.back().distributed_opacity *= paint.color.alpha;
1004  return;
1005  }
1006 
1007  std::shared_ptr<FilterContents> filter_contents = paint.WithImageFilter(
1008  Rect(), transform_stack_.back().transform,
1010 
1011  std::optional<Rect> maybe_subpass_coverage = ComputeSaveLayerCoverage(
1012  bounds.value_or(Rect::MakeMaximum()),
1013  transform_stack_.back().transform, //
1014  coverage_limit, //
1015  filter_contents, //
1016  /*flood_output_coverage=*/
1017  Entity::IsBlendModeDestructive(paint.blend_mode), //
1018  /*flood_input_coverage=*/!!backdrop_filter //
1019  );
1020 
1021  if (!maybe_subpass_coverage.has_value()) {
1022  return SkipUntilMatchingRestore(total_content_depth);
1023  }
1024 
1025  auto subpass_coverage = maybe_subpass_coverage.value();
1026 
1027  // When an image filter is present, clamp to avoid flicking due to nearest
1028  // sampled image. For other cases, round out to ensure than any geometry is
1029  // not cut off.
1030  //
1031  // See also this bug: https://github.com/flutter/flutter/issues/144213
1032  //
1033  // TODO(jonahwilliams): this could still round out for filters that use decal
1034  // sampling mode.
1036  bool did_round_out = false;
1037  if (paint.image_filter) {
1038  subpass_size = ISize(subpass_coverage.GetSize());
1039  } else {
1040  did_round_out = true;
1041  subpass_size = ISize(IRect::RoundOut(subpass_coverage).GetSize());
1042  }
1043  if (subpass_size.IsEmpty()) {
1044  return SkipUntilMatchingRestore(total_content_depth);
1045  }
1046 
1047  // When there are scaling filters present, these contents may exceed the
1048  // maximum texture size. Perform a clamp here, which may cause rendering
1049  // artifacts.
1050  subpass_size = subpass_size.Min(renderer_.GetContext()
1051  ->GetCapabilities()
1052  ->GetMaximumRenderPassAttachmentSize());
1053 
1054  // Backdrop filter state, ignored if there is no BDF.
1055  std::shared_ptr<FilterContents> backdrop_filter_contents;
1056  Point local_position = {0, 0};
1057  if (backdrop_filter) {
1058  local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1059  Canvas::BackdropFilterProc backdrop_filter_proc =
1060  [backdrop_filter = backdrop_filter](
1061  const FilterInput::Ref& input, const Matrix& effect_transform,
1062  Entity::RenderingMode rendering_mode) {
1063  auto filter = WrapInput(backdrop_filter, input);
1064  filter->SetEffectTransform(effect_transform);
1065  filter->SetRenderingMode(rendering_mode);
1066  return filter;
1067  };
1068 
1069  auto input_texture = FlipBackdrop(render_passes_, //
1070  GetGlobalPassPosition(), //
1071  clip_coverage_stack_, //
1072  renderer_ //
1073  );
1074  if (!input_texture) {
1075  // Validation failures are logged in FlipBackdrop.
1076  return;
1077  }
1078 
1079  backdrop_filter_contents = backdrop_filter_proc(
1080  FilterInput::Make(std::move(input_texture)),
1081  transform_stack_.back().transform.Basis(),
1082  // When the subpass has a translation that means the math with
1083  // the snapshot has to be different.
1084  transform_stack_.back().transform.HasTranslation()
1087  }
1088 
1089  // When applying a save layer, absorb any pending distributed opacity.
1090  Paint paint_copy = paint;
1091  paint_copy.color.alpha *= transform_stack_.back().distributed_opacity;
1092  transform_stack_.back().distributed_opacity = 1.0;
1093 
1094  render_passes_.push_back(
1095  LazyRenderingConfig(renderer_, //
1096  CreateRenderTarget(renderer_, //
1097  subpass_size, //
1099  )));
1100  save_layer_state_.push_back(SaveLayerState{paint_copy, subpass_coverage});
1101 
1102  CanvasStackEntry entry;
1103  entry.transform = transform_stack_.back().transform;
1104  entry.clip_depth = current_depth_ + total_content_depth;
1105  FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1106  << entry.clip_depth << " <=? " << transform_stack_.back().clip_depth
1107  << " after allocating " << total_content_depth;
1108  entry.clip_height = transform_stack_.back().clip_height;
1110  entry.did_round_out = did_round_out;
1111  transform_stack_.emplace_back(entry);
1112 
1113  // Start non-collapsed subpasses with a fresh clip coverage stack limited by
1114  // the subpass coverage. This is important because image filters applied to
1115  // save layers may transform the subpass texture after it's rendered,
1116  // causing parent clip coverage to get misaligned with the actual area that
1117  // the subpass will affect in the parent pass.
1118  clip_coverage_stack_.PushSubpass(subpass_coverage, GetClipHeight());
1119 
1120  if (backdrop_filter_contents) {
1121  // Render the backdrop entity.
1122  Entity backdrop_entity;
1123  backdrop_entity.SetContents(std::move(backdrop_filter_contents));
1124  backdrop_entity.SetTransform(
1125  Matrix::MakeTranslation(Vector3(-local_position)));
1126  backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
1127 
1128  backdrop_entity.Render(
1129  renderer_,
1130  *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
1131  }
1132 }

References impeller::Color::alpha, impeller::Color::BlackTransparent(), impeller::Paint::blend_mode, impeller::Paint::CanApplyOpacityPeephole(), impeller::CanvasStackEntry::clip_depth, impeller::CanvasStackEntry::clip_height, impeller::Paint::color, impeller::ComputeSaveLayerCoverage(), impeller::CanvasStackEntry::did_round_out, impeller::ContentContext::GetContext(), GetLocalCoverageLimit(), impeller::Paint::image_filter, impeller::Entity::IsBlendModeDestructive(), impeller::kMayClipContents, impeller::Entity::kSubpassAppendSnapshotTransform, impeller::Entity::kSubpassPrependSnapshotTransform, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeMaximum(), impeller::Matrix::MakeTranslation(), impeller::EntityPassClipStack::PushSubpass(), impeller::Entity::Render(), impeller::CanvasStackEntry::rendering_mode, impeller::TRect< T >::RoundOut(), Save(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), subpass_size, impeller::CanvasStackEntry::transform, impeller::Paint::WithImageFilter(), and impeller::WrapInput().

Referenced by impeller::DlDispatcherBase::drawDisplayList(), and impeller::DlDispatcherBase::saveLayer().

◆ Scale() [1/2]

void impeller::Canvas::Scale ( const Vector2 scale)

Definition at line 339 of file canvas.cc.

339  {
341 }

References Concat(), impeller::Matrix::MakeScale(), and scale.

Referenced by impeller::DlDispatcherBase::scale().

◆ Scale() [2/2]

void impeller::Canvas::Scale ( const Vector3 scale)

Definition at line 343 of file canvas.cc.

343  {
345 }

References Concat(), impeller::Matrix::MakeScale(), and scale.

◆ Skew()

void impeller::Canvas::Skew ( Scalar  sx,
Scalar  sy 
)

Definition at line 347 of file canvas.cc.

347  {
348  Concat(Matrix::MakeSkew(sx, sy));
349 }

References Concat(), and impeller::Matrix::MakeSkew().

Referenced by impeller::DlDispatcherBase::skew().

◆ Transform()

void impeller::Canvas::Transform ( const Matrix transform)

Definition at line 327 of file canvas.cc.

327  {
328  Concat(transform);
329 }

References Concat(), and transform.

Referenced by impeller::DlDispatcherBase::transformFullPerspective(), and impeller::DlDispatcherBase::transformReset().

◆ Translate()

void impeller::Canvas::Translate ( const Vector3 offset)

Definition at line 335 of file canvas.cc.

335  {
337 }

References Concat(), impeller::Matrix::MakeTranslation(), and offset.

Referenced by impeller::DlDispatcherBase::translate().

Member Data Documentation

◆ kMaxDepth

constexpr uint32_t impeller::Canvas::kMaxDepth = 1 << 24
staticconstexpr

Definition at line 103 of file canvas.h.


The documentation for this class was generated from the following files:
impeller::Matrix::MakeSkew
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
Definition: matrix.h:117
impeller::ISize
ISize64 ISize
Definition: size.h:140
impeller::Entity::kLastPipelineBlendMode
static constexpr BlendMode kLastPipelineBlendMode
Definition: entity.h:22
impeller::ContentBoundsPromise::kMayClipContents
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
impeller::EntityPassClipStack::PushSubpass
void PushSubpass(std::optional< Rect > subpass_coverage, size_t clip_height)
Definition: entity_pass_clip_stack.cc:33
impeller::Paint::Style::kStroke
@ kStroke
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
impeller::skia_conversions::ToSamplerDescriptor
impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
Definition: skia_conversions.cc:169
impeller::FilterInput::Make
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
impeller::BlendMode::kSource
@ kSource
impeller::BlendMode::kDestination
@ kDestination
impeller::Entity::IsBlendModeDestructive
static bool IsBlendModeDestructive(BlendMode blend_mode)
Returns true if the blend mode is "destructive", meaning that even fully transparent source colors wo...
Definition: entity.cc:139
impeller::Entity::RenderingMode::kSubpassAppendSnapshotTransform
@ kSubpassAppendSnapshotTransform
impeller::ComputeSaveLayerCoverage
std::optional< Rect > ComputeSaveLayerCoverage(const Rect &content_coverage, const Matrix &effect_transform, const Rect &coverage_limit, const std::shared_ptr< FilterContents > &image_filter, bool flood_output_coverage, bool flood_input_coverage)
Compute the coverage of a subpass in the global coordinate space.
Definition: save_layer_utils.cc:16
impeller::EntityPassClipStack::HasCoverage
bool HasCoverage() const
Definition: entity_pass_clip_stack.cc:29
impeller::PointStyle::kRound
@ kRound
Points are drawn as squares.
impeller::TRect::Intersection
constexpr std::optional< TRect > Intersection(const TRect &o) const
Definition: rect.h:522
impeller::FilterInput::Ref
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:32
impeller::skia_conversions::ToMatrix
Matrix ToMatrix(const SkMatrix &m)
Definition: skia_conversions.cc:193
impeller::TRect< Scalar >::Round
Round(const TRect< U > &r)
Definition: rect.h:681
impeller::Size
TSize< Scalar > Size
Definition: size.h:137
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
subpass_size
ISize subpass_size
The output size of the down-sampling pass.
Definition: gaussian_blur_filter_contents.cc:201
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:304
impeller::Canvas::GetCurrentTransform
const Matrix & GetCurrentTransform() const
Definition: canvas.cc:331
impeller::Canvas::Concat
void Concat(const Matrix &transform)
Definition: canvas.cc:315
impeller::TRect::RoundOut
RoundOut(const TRect< U > &r)
Definition: rect.h:673
impeller::EntityPassClipStack::ApplyClipState
ClipStateResult ApplyClipState(Contents::ClipCoverage global_clip_coverage, Entity &entity, size_t clip_height_floor, Point global_pass_position)
Applies the current clip state to an Entity. If the given Entity is a clip operation,...
Definition: entity_pass_clip_stack.cc:55
impeller::SourceRectConstraint::kStrict
@ kStrict
Sample only within the source rectangle. May be slower.
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::EntityPassClipStack::CurrentClipCoverage
std::optional< Rect > CurrentClipCoverage() const
Definition: entity_pass_clip_stack.cc:25
impeller::Canvas::GetLocalCoverageLimit
std::optional< Rect > GetLocalCoverageLimit() const
Return the culling bounds of the current render target, or nullopt if there is no coverage.
Definition: canvas.cc:951
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:213
impeller::ContentContext::GetContext
std::shared_ptr< Context > GetContext() const
Definition: content_context.cc:550
impeller::Paint::Style::kFill
@ kFill
impeller::TRect< Scalar >::MakeOriginSize
constexpr static TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
Definition: rect.h:144
impeller::Canvas::DrawCircle
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition: canvas.cc:628
impeller::Canvas::Restore
bool Restore()
Definition: canvas.cc:1134
impeller::Entity::RenderingMode::kDirect
@ kDirect
impeller::Canvas::DrawPath
void DrawPath(const Path &path, const Paint &paint)
Definition: canvas.cc:386
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:776
impeller::Canvas::GetSaveCount
size_t GetSaveCount() const
Definition: canvas.cc:370
impeller::Canvas::DrawImageRect
void DrawImageRect(const std::shared_ptr< Texture > &image, Rect source, Rect dest, const Paint &paint, SamplerDescriptor sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
Definition: canvas.cc:712
impeller::Entity::TileMode
TileMode
Definition: entity.h:42
impeller::EntityPassClipStack::PopSubpass
void PopSubpass()
Definition: entity_pass_clip_stack.cc:45
impeller::WrapInput
std::shared_ptr< FilterContents > WrapInput(const flutter::DlImageFilter *filter, const FilterInput::Ref &input)
Generate a new FilterContents using this filter's configuration.
Definition: image_filter.cc:15
impeller::Canvas::BackdropFilterProc
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
Definition: canvas.h:108
impeller::RenderTarget::GetRenderTargetSize
ISize GetRenderTargetSize() const
Definition: render_target.cc:139
impeller::Geometry::MakeRect
static std::unique_ptr< Geometry > MakeRect(const Rect &rect)
Definition: geometry.cc:89
impeller::ContentContext::GetRenderTargetCache
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
Definition: content_context.h:725
impeller::Matrix::MakeRotationZ
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:213
impeller::ContentContext::GetDeviceCapabilities
const Capabilities & GetDeviceCapabilities() const
Definition: content_context.cc:554
impeller::Entity::RenderingMode::kSubpassPrependSnapshotTransform
@ kSubpassPrependSnapshotTransform
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
impeller::TRect< Scalar >::MakeMaximum
constexpr static TRect MakeMaximum()
Definition: rect.h:178
impeller::Color::BlackTransparent
static constexpr Color BlackTransparent()
Definition: color.h:269
impeller::Canvas::Save
void Save(uint32_t total_content_depth=kMaxDepth)
Definition: canvas.cc:934
scale
const Scalar scale
Definition: stroke_path_geometry.cc:301
impeller::Paint::CanApplyOpacityPeephole
static bool CanApplyOpacityPeephole(const Paint &paint)
Whether or not a save layer with the provided paint can perform the opacity peephole optimization.
Definition: paint.h:39
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::Entity::RenderingMode
RenderingMode
Definition: entity.h:27
impeller::FilterInput::Vector
std::vector< FilterInput::Ref > Vector
Definition: filter_input.h:33
impeller::Convexity::kConvex
@ kConvex
impeller::ColorFilterContents::MakeBlend
static std::shared_ptr< ColorFilterContents > MakeBlend(BlendMode blend_mode, FilterInput::Vector inputs, std::optional< Color > foreground_color=std::nullopt)
the [inputs] are expected to be in the order of dst, src.
Definition: color_filter_contents.cc:17
impeller::Capabilities::SupportsFramebufferFetch
virtual bool SupportsFramebufferFetch() const =0
Whether the context backend is able to support pipelines with shaders that read from the framebuffer ...
impeller::TextureContents::MakeRect
static std::shared_ptr< TextureContents > MakeRect(Rect destination)
A common case factory that marks the texture contents as having a destination rectangle....
Definition: texture_contents.cc:28
impeller::Matrix::MakeScale
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104