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, bool reuse_depth=false)
 
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 655 of file canvas.cc.

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

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 872 of file canvas.cc.

873  {
874  atlas_contents->SetAlpha(paint.color.alpha);
875 
876  Entity entity;
877  entity.SetTransform(GetCurrentTransform());
878  entity.SetBlendMode(paint.blend_mode);
879  entity.SetContents(paint.WithFilters(atlas_contents));
880 
881  AddRenderEntityToCurrentPass(entity);
882 }

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 632 of file canvas.cc.

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

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 702 of file canvas.cc.

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

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 716 of file canvas.cc.

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

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,
bool  reuse_depth = false 
)

Definition at line 546 of file canvas.cc.

549  {
550  Entity entity;
551  entity.SetTransform(GetCurrentTransform());
552  entity.SetBlendMode(paint.blend_mode);
553 
554  LineGeometry geom(p0, p1, paint.stroke_width, paint.stroke_cap);
555  AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint,
556  /*reuse_depth=*/reuse_depth);
557 }

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 577 of file canvas.cc.

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

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 685 of file canvas.cc.

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

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 559 of file canvas.cc.

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

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 607 of file canvas.cc.

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

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 1313 of file canvas.cc.

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

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 762 of file canvas.cc.

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

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 1643 of file canvas.cc.

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

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 955 of file canvas.cc.

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

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 221 of file canvas.h.

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

◆ GetOpDepth()

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

Definition at line 219 of file canvas.h.

219 { 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 1138 of file canvas.cc.

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

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 938 of file canvas.cc.

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

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 986 of file canvas.cc.

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

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:955
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:632
impeller::Canvas::Restore
bool Restore()
Definition: canvas.cc:1138
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:716
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:938
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