Flutter Engine
 
Loading...
Searching...
No Matches
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, const RenderTarget &render_target, bool is_onscreen, bool requires_readback)
 
 Canvas (ContentContext &renderer, const RenderTarget &render_target, bool is_onscreen, bool requires_readback, Rect cull_rect)
 
 Canvas (ContentContext &renderer, const RenderTarget &render_target, bool is_onscreen, bool requires_readback, IRect32 cull_rect)
 
 ~Canvas ()=default
 
void SetBackdropData (std::unordered_map< int64_t, BackdropData > backdrop_data, size_t backdrop_count)
 Update the backdrop data used to group together backdrop filters within the same layer.
 
std::optional< RectGetLocalCoverageLimit () const
 Return the culling bounds of the current render target, or nullopt if there is no coverage.
 
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, std::optional< int64_t > backdrop_id=std::nullopt)
 
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 flutter::DlPath &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 DrawDashedLine (const Point &p0, const Point &p1, Scalar on_length, Scalar off_length, const Paint &paint)
 
void DrawRect (const Rect &rect, const Paint &paint)
 
void DrawOval (const Rect &rect, const Paint &paint)
 
void DrawArc (const Arc &arc, const Paint &paint)
 
void DrawRoundRect (const RoundRect &rect, const Paint &paint)
 
void DrawDiffRoundRect (const RoundRect &outer, const RoundRect &inner, const Paint &paint)
 
void DrawRoundSuperellipse (const RoundSuperellipse &rse, const Paint &paint)
 
void DrawCircle (const Point &center, Scalar radius, const Paint &paint)
 
void DrawPoints (const Point points[], uint32_t count, Scalar radius, const Paint &paint, PointStyle point_style)
 
void DrawImage (const std::shared_ptr< Texture > &image, Point offset, const Paint &paint, const SamplerDescriptor &sampler={})
 
void DrawImageRect (const std::shared_ptr< Texture > &image, Rect source, Rect dest, const Paint &paint, const 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 (const Geometry &geometry, Entity::ClipOperation clip_op, bool is_aa=true)
 
void EndReplay ()
 
uint64_t GetOpDepth () const
 
uint64_t GetMaxOpDepth () const
 
bool RequiresReadback () const
 
bool SupportsBlitToOnscreen () const
 
bool EnsureFinalMipmapGeneration () const
 

Static Public Attributes

static constexpr uint32_t kMaxDepth = 1 << 24
 

Detailed Description

Definition at line 118 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 122 of file canvas.h.

Constructor & Destructor Documentation

◆ Canvas() [1/3]

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

Definition at line 199 of file canvas.cc.

203 : renderer_(renderer),
204 render_target_(render_target),
205 is_onscreen_(is_onscreen),
206 requires_readback_(requires_readback),
207 clip_coverage_stack_(EntityPassClipStack(
208 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
209 Initialize(std::nullopt);
210 SetupRenderPass();
211}
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150

◆ Canvas() [2/3]

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

Definition at line 213 of file canvas.cc.

218 : renderer_(renderer),
219 render_target_(render_target),
220 is_onscreen_(is_onscreen),
221 requires_readback_(requires_readback),
222 clip_coverage_stack_(EntityPassClipStack(
223 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
224 Initialize(cull_rect);
225 SetupRenderPass();
226}

◆ Canvas() [3/3]

impeller::Canvas::Canvas ( ContentContext renderer,
const RenderTarget render_target,
bool  is_onscreen,
bool  requires_readback,
IRect32  cull_rect 
)
explicit

Definition at line 228 of file canvas.cc.

233 : renderer_(renderer),
234 render_target_(render_target),
235 is_onscreen_(is_onscreen),
236 requires_readback_(requires_readback),
237 clip_coverage_stack_(EntityPassClipStack(
238 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
239 Initialize(Rect::MakeLTRB(cull_rect.GetLeft(), cull_rect.GetTop(),
240 cull_rect.GetRight(), cull_rect.GetBottom()));
241 SetupRenderPass();
242}
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129

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

◆ ~Canvas()

flutter::Canvas::~Canvas ( )
default

Definition at line 48 of file canvas.cc.

48{}

Member Function Documentation

◆ ClipGeometry()

void impeller::Canvas::ClipGeometry ( const Geometry geometry,
Entity::ClipOperation  clip_op,
bool  is_aa = true 
)

Definition at line 861 of file canvas.cc.

863 {
864 if (IsSkipping()) {
865 return;
866 }
867
868 // Ideally the clip depth would be greater than the current rendering
869 // depth because any rendering calls that follow this clip operation will
870 // pre-increment the depth and then be rendering above our clip depth,
871 // but that case will be caught by the CHECK in AddRenderEntity above.
872 // In practice we sometimes have a clip set with no rendering after it
873 // and in such cases the current depth will equal the clip depth.
874 // Eventually the DisplayList should optimize these out, but it is hard
875 // to know if a clip will actually be used in advance of storing it in
876 // the DisplayList buffer.
877 // See https://github.com/flutter/flutter/issues/147021
878 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
879 << current_depth_ << " <=? " << transform_stack_.back().clip_depth;
880 uint32_t clip_depth = transform_stack_.back().clip_depth;
881
882 const Matrix clip_transform =
883 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
885
886 std::optional<Rect> clip_coverage = geometry.GetCoverage(clip_transform);
887 if (!clip_coverage.has_value()) {
888 return;
889 }
890
891 ClipContents clip_contents(
892 clip_coverage.value(),
893 /*is_axis_aligned_rect=*/geometry.IsAxisAlignedRect() &&
894 GetCurrentTransform().IsTranslationScaleOnly());
895 clip_contents.SetClipOperation(clip_op);
896
897 EntityPassClipStack::ClipStateResult clip_state_result =
898 clip_coverage_stack_.RecordClip(
899 clip_contents, //
900 /*transform=*/clip_transform, //
901 /*global_pass_position=*/GetGlobalPassPosition(), //
902 /*clip_depth=*/clip_depth, //
903 /*clip_height_floor=*/GetClipHeightFloor(), //
904 /*is_aa=*/is_aa);
905
906 if (clip_state_result.clip_did_change) {
907 // We only need to update the pass scissor if the clip state has changed.
908 SetClipScissor(
909 clip_coverage_stack_.CurrentClipCoverage(),
910 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
911 GetGlobalPassPosition());
912 }
913
914 ++transform_stack_.back().clip_height;
915 ++transform_stack_.back().num_clips;
916
917 if (!clip_state_result.should_render) {
918 return;
919 }
920
921 // Note: this is a bit of a hack. Its not possible to construct a geometry
922 // result without begninning the render pass. We should refactor the geometry
923 // objects so that they only need a reference to the render pass size and/or
924 // orthographic transform.
925 Entity entity;
926 entity.SetTransform(clip_transform);
927 entity.SetClipDepth(clip_depth);
928
929 GeometryResult geometry_result = geometry.GetPositionBuffer(
930 renderer_, //
931 entity, //
932 *render_passes_.back().GetInlinePassContext()->GetRenderPass() //
933 );
934 clip_contents.SetGeometry(geometry_result);
935 clip_coverage_stack_.GetLastReplayResult().clip_contents.SetGeometry(
936 geometry_result);
937
938 clip_contents.Render(
939 renderer_, *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
940 clip_depth);
941}
const Matrix & GetCurrentTransform() const
Definition canvas.cc:273
void SetGeometry(GeometryResult geometry)
Set the pre-tessellated clip geometry.
std::optional< Rect > CurrentClipCoverage() const
ClipStateResult RecordClip(const ClipContents &clip_contents, Matrix transform, Point global_pass_position, uint32_t clip_depth, size_t clip_height_floor, bool is_aa)
#define FML_DCHECK(condition)
Definition logging.h:122
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95

References impeller::EntityPassClipStack::ReplayResult::clip_contents, impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::CurrentClipCoverage(), FML_DCHECK, impeller::Geometry::GetCoverage(), GetCurrentTransform(), impeller::EntityPassClipStack::GetLastReplayResult(), impeller::Geometry::GetPositionBuffer(), impeller::Geometry::IsAxisAlignedRect(), impeller::Matrix::MakeTranslation(), impeller::EntityPassClipStack::RecordClip(), impeller::ClipContents::Render(), impeller::Entity::SetClipDepth(), impeller::ClipContents::SetClipOperation(), impeller::ClipContents::SetGeometry(), impeller::Entity::SetTransform(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

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

◆ Concat()

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

Definition at line 257 of file canvas.cc.

257 {
258 transform_stack_.back().transform = GetCurrentTransform() * transform;
259}

References GetCurrentTransform(), and transform.

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

◆ DrawArc()

void impeller::Canvas::DrawArc ( const Arc arc,
const Paint paint 
)

Definition at line 709 of file canvas.cc.

709 {
710 Entity entity;
711 entity.SetTransform(GetCurrentTransform());
712 entity.SetBlendMode(paint.blend_mode);
713
714 if (paint.style == Paint::Style::kFill) {
715 ArcGeometry geom(arc);
716 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
717 return;
718 }
719
720 const Rect& oval_bounds = arc.GetOvalBounds();
721 if (paint.stroke.width > oval_bounds.GetSize().MaxDimension()) {
722 // This is a special case for rendering arcs whose stroke width is so large
723 // you are effectively drawing a sector of a circle.
724 // https://github.com/flutter/flutter/issues/158567
725 Arc expanded_arc(oval_bounds.Expand(Size(paint.stroke.width * 0.5f)),
726 arc.GetStart(), arc.GetSweep(), true);
727
728 ArcGeometry geom(expanded_arc);
729 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
730 return;
731 }
732
733 // IncludeCenter incurs lots of extra work for stroking an arc, including:
734 // - It introduces segments to/from the center point (not too hard).
735 // - It introduces joins on those segments (a bit more complicated).
736 // - Even if the sweep is >=360 degrees, we still draw the segment to
737 // the center and it basically looks like a pie cut into the complete
738 // boundary circle, as if the slice were cut, but not extracted
739 // (hard to express as a continuous kTriangleStrip).
740 if (!arc.IncludeCenter()) {
741 if (arc.IsFullCircle()) {
742 return DrawOval(oval_bounds, paint);
743 }
744
745 // Our fast stroking code only works for circular bounds as it assumes
746 // that the inner and outer radii can be scaled along each angular step
747 // of the arc - which is not true for elliptical arcs where the inner
748 // and outer samples are perpendicular to the traveling direction of the
749 // elliptical curve which may not line up with the center of the bounds.
750 //
751 // TODO(flar): It also only supports Butt and Square caps for now.
752 // See https://github.com/flutter/flutter/issues/169400
753 if (oval_bounds.IsSquare() && paint.stroke.cap != Cap::kRound) {
754 ArcGeometry geom(arc, paint.stroke);
755 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
756 return;
757 }
758 }
759
760 ArcStrokeGeometry geom(arc, paint.stroke);
761 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
762}
void DrawOval(const Rect &rect, const Paint &paint)
Definition canvas.cc:680
TRect< Scalar > Rect
Definition rect.h:788
TSize< Scalar > Size
Definition size.h:159

References impeller::Paint::blend_mode, impeller::StrokeParameters::cap, DrawOval(), impeller::TRect< T >::Expand(), GetCurrentTransform(), impeller::Arc::GetOvalBounds(), impeller::TRect< T >::GetSize(), impeller::Arc::GetStart(), impeller::Arc::GetSweep(), impeller::Arc::IncludeCenter(), impeller::Arc::IsFullCircle(), impeller::TRect< T >::IsSquare(), impeller::Paint::kFill, impeller::kRound, impeller::Entity::SetBlendMode(), impeller::Entity::SetTransform(), impeller::Paint::stroke, impeller::Paint::style, and impeller::StrokeParameters::width.

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

◆ DrawAtlas()

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

Definition at line 1154 of file canvas.cc.

1155 {
1156 atlas_contents->SetAlpha(paint.color.alpha);
1157
1158 Entity entity;
1159 entity.SetTransform(GetCurrentTransform());
1160 entity.SetBlendMode(paint.blend_mode);
1161 entity.SetContents(paint.WithFilters(atlas_contents));
1162
1163 AddRenderEntityToCurrentPass(entity);
1164}

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

836 {
837 Size half_size(radius, radius);
838 if (AttemptDrawBlurredRRect(
839 Rect::MakeOriginSize(center - half_size, half_size * 2),
840 {radius, radius}, paint)) {
841 return;
842 }
843
844 if (AttemptDrawAntialiasedCircle(center, radius, paint)) {
845 return;
846 }
847
848 Entity entity;
849 entity.SetTransform(GetCurrentTransform());
850 entity.SetBlendMode(paint.blend_mode);
851
852 if (paint.style == Paint::Style::kStroke) {
853 CircleGeometry geom(center, radius, paint.stroke.width);
854 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
855 } else {
856 CircleGeometry geom(center, radius);
857 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
858 }
859}
static constexpr TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
Definition rect.h:144

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

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

◆ DrawDashedLine()

void impeller::Canvas::DrawDashedLine ( const Point p0,
const Point p1,
Scalar  on_length,
Scalar  off_length,
const Paint paint 
)

Definition at line 636 of file canvas.cc.

640 {
641 // Reasons to defer to regular DrawLine:
642 // - performance for degenerate and "regular line" cases
643 // - length is non-positive - DrawLine will draw appropriate "dot"
644 // - off_length is non-positive - no gaps, DrawLine will draw it solid
645 // - on_length is negative - invalid dashing
646 //
647 // Note that a 0 length "on" dash will draw "dot"s every "off" distance
648 // apart so we proceed with the dashing process in that case.
649 Scalar length = p0.GetDistance(p1);
650 if (length > 0.0f && on_length >= 0.0f && off_length > 0.0f) {
651 Entity entity;
652 entity.SetTransform(GetCurrentTransform());
653 entity.SetBlendMode(paint.blend_mode);
654
655 StrokeDashedLineGeometry geom(p0, p1, on_length, off_length, paint.stroke);
656 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
657 } else {
658 DrawLine(p0, p1, paint);
659 }
660}
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
Definition canvas.cc:614
size_t length
float Scalar
Definition scalar.h:19

References impeller::Paint::blend_mode, DrawLine(), GetCurrentTransform(), impeller::TPoint< T >::GetDistance(), length, impeller::Entity::SetBlendMode(), impeller::Entity::SetTransform(), and impeller::Paint::stroke.

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

◆ DrawDiffRoundRect()

void impeller::Canvas::DrawDiffRoundRect ( const RoundRect outer,
const RoundRect inner,
const Paint paint 
)

Definition at line 796 of file canvas.cc.

798 {
799 Entity entity;
800 entity.SetTransform(GetCurrentTransform());
801 entity.SetBlendMode(paint.blend_mode);
802
803 if (paint.style == Paint::Style::kFill) {
804 FillDiffRoundRectGeometry geom(outer, inner);
805 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
806 } else {
807 StrokeDiffRoundRectGeometry geom(outer, inner, paint.stroke);
808 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
809 }
810}

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

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

◆ DrawImage()

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

Definition at line 961 of file canvas.cc.

964 {
965 if (!image) {
966 return;
967 }
968
969 const Rect source = Rect::MakeSize(image->GetSize());
970 const Rect dest = source.Shift(offset);
971
972 DrawImageRect(image, source, dest, paint, sampler);
973}
void DrawImageRect(const std::shared_ptr< Texture > &image, Rect source, Rect dest, const Paint &paint, const SamplerDescriptor &sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
Definition canvas.cc:975
FlutterVulkanImage * image
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition rect.h:602

References DrawImageRect(), image, impeller::TRect< Scalar >::MakeSize(), and impeller::TRect< T >::Shift().

◆ DrawImageRect()

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

Definition at line 975 of file canvas.cc.

980 {
981 if (!image || source.IsEmpty() || dest.IsEmpty()) {
982 return;
983 }
984
985 ISize size = image->GetSize();
986 if (size.IsEmpty()) {
987 return;
988 }
989
990 std::optional<Rect> clipped_source =
991 source.Intersection(Rect::MakeSize(size));
992 if (!clipped_source) {
993 return;
994 }
995
996 if (AttemptColorFilterOptimization(image, source, dest, paint, sampler,
997 src_rect_constraint)) {
998 return;
999 }
1000
1001 if (*clipped_source != source) {
1002 Scalar sx = dest.GetWidth() / source.GetWidth();
1003 Scalar sy = dest.GetHeight() / source.GetHeight();
1004 Scalar tx = dest.GetLeft() - source.GetLeft() * sx;
1005 Scalar ty = dest.GetTop() - source.GetTop() * sy;
1006 Matrix src_to_dest = Matrix::MakeTranslateScale({sx, sy, 1}, {tx, ty, 0});
1007 dest = clipped_source->TransformBounds(src_to_dest);
1008 }
1009
1010 auto texture_contents = TextureContents::MakeRect(dest);
1011 texture_contents->SetTexture(image);
1012 texture_contents->SetSourceRect(*clipped_source);
1013 texture_contents->SetStrictSourceRect(src_rect_constraint ==
1015 texture_contents->SetSamplerDescriptor(sampler);
1016 texture_contents->SetOpacity(paint.color.alpha);
1017 texture_contents->SetDeferApplyingOpacity(paint.HasColorFilter());
1018
1019 Entity entity;
1020 entity.SetBlendMode(paint.blend_mode);
1021 entity.SetTransform(GetCurrentTransform());
1022
1023 if (!paint.mask_blur_descriptor.has_value()) {
1024 entity.SetContents(paint.WithFilters(std::move(texture_contents)));
1025 AddRenderEntityToCurrentPass(entity);
1026 return;
1027 }
1028
1029 FillRectGeometry out_rect(Rect{});
1030
1031 entity.SetContents(paint.WithFilters(
1032 paint.mask_blur_descriptor->CreateMaskBlur(texture_contents, &out_rect)));
1033 AddRenderEntityToCurrentPass(entity);
1034}
static std::shared_ptr< TextureContents > MakeRect(Rect destination)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
@ kStrict
Sample only within the source rectangle. May be slower.
ISize64 ISize
Definition size.h:162
static constexpr Matrix MakeTranslateScale(const Vector3 &s, const Vector3 &t)
Definition matrix.h:113

References impeller::Color::alpha, impeller::Paint::blend_mode, impeller::Paint::color, GetCurrentTransform(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::Paint::HasColorFilter(), image, impeller::TRect< T >::Intersection(), impeller::TRect< T >::IsEmpty(), impeller::kStrict, impeller::TextureContents::MakeRect(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeTranslateScale(), impeller::Paint::mask_blur_descriptor, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::TRect< T >::TransformBounds(), 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 614 of file canvas.cc.

617 {
618 Entity entity;
619 entity.SetTransform(GetCurrentTransform());
620 entity.SetBlendMode(paint.blend_mode);
621
622 auto geometry = std::make_unique<LineGeometry>(p0, p1, paint.stroke);
623
624 if (renderer_.GetContext()->GetFlags().antialiased_lines &&
625 !paint.color_filter && !paint.invert_colors && !paint.image_filter &&
626 !paint.mask_blur_descriptor.has_value() && !paint.color_source) {
627 auto contents = LineContents::Make(std::move(geometry), paint.color);
628 entity.SetContents(std::move(contents));
629 AddRenderEntityToCurrentPass(entity, reuse_depth);
630 } else {
631 AddRenderEntityWithFiltersToCurrentPass(entity, geometry.get(), paint,
632 /*reuse_depth=*/reuse_depth);
633 }
634}
std::shared_ptr< Context > GetContext() const
static std::unique_ptr< LineContents > Make(std::unique_ptr< LineGeometry > geometry, Color color)

References impeller::Paint::blend_mode, impeller::Paint::color, impeller::Paint::color_filter, impeller::Paint::color_source, impeller::ContentContext::GetContext(), GetCurrentTransform(), impeller::Paint::image_filter, impeller::Paint::invert_colors, impeller::LineContents::Make(), impeller::Paint::mask_blur_descriptor, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Paint::stroke.

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

◆ DrawOval()

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

Definition at line 680 of file canvas.cc.

680 {
681 // TODO(jonahwilliams): This additional condition avoids an assert in the
682 // stroke circle geometry generator. I need to verify the condition that this
683 // assert prevents.
684 if (rect.IsSquare() && (paint.style == Paint::Style::kFill ||
685 (paint.style == Paint::Style::kStroke &&
686 paint.stroke.width < rect.GetWidth()))) {
687 // Circles have slightly less overhead and can do stroking
688 DrawCircle(rect.GetCenter(), rect.GetWidth() * 0.5f, paint);
689 return;
690 }
691
692 if (AttemptDrawBlurredRRect(rect, rect.GetSize() * 0.5f, paint)) {
693 return;
694 }
695
696 Entity entity;
697 entity.SetTransform(GetCurrentTransform());
698 entity.SetBlendMode(paint.blend_mode);
699
700 if (paint.style == Paint::Style::kStroke) {
701 StrokeEllipseGeometry geom(rect, paint.stroke);
702 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
703 } else {
704 EllipseGeometry geom(rect);
705 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
706 }
707}
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition canvas.cc:834

References impeller::Paint::blend_mode, DrawCircle(), 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, impeller::Paint::style, and impeller::StrokeParameters::width.

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

◆ DrawPaint()

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

Definition at line 342 of file canvas.cc.

342 {
343 Entity entity;
344 entity.SetTransform(GetCurrentTransform());
345 entity.SetBlendMode(paint.blend_mode);
346
347 CoverGeometry geom;
348 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
349}

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 flutter::DlPath path,
const Paint paint 
)

Definition at line 328 of file canvas.cc.

328 {
329 Entity entity;
330 entity.SetTransform(GetCurrentTransform());
331 entity.SetBlendMode(paint.blend_mode);
332
333 if (paint.style == Paint::Style::kFill) {
334 FillPathGeometry geom(path);
335 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
336 } else {
337 StrokePathGeometry geom(path, paint.stroke);
338 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
339 }
340}

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

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

◆ DrawPoints()

void impeller::Canvas::DrawPoints ( const Point  points[],
uint32_t  count,
Scalar  radius,
const Paint paint,
PointStyle  point_style 
)

Definition at line 943 of file canvas.cc.

947 {
948 if (radius <= 0) {
949 return;
950 }
951
952 Entity entity;
953 entity.SetTransform(GetCurrentTransform());
954 entity.SetBlendMode(paint.blend_mode);
955
956 PointFieldGeometry geom(points, count, radius,
957 /*round=*/point_style == PointStyle::kRound);
958 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
959}
@ kRound
Points are drawn as squares.
std::vector< Point > points

References impeller::Paint::blend_mode, GetCurrentTransform(), impeller::kRound, points, 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 662 of file canvas.cc.

662 {
663 if (AttemptDrawBlurredRRect(rect, {}, paint)) {
664 return;
665 }
666
667 Entity entity;
668 entity.SetTransform(GetCurrentTransform());
669 entity.SetBlendMode(paint.blend_mode);
670
671 if (paint.style == Paint::Style::kStroke) {
672 StrokeRectGeometry geom(rect, paint.stroke);
673 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
674 } else {
675 FillRectGeometry geom(rect);
676 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
677 }
678}

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

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

◆ DrawRoundRect()

void impeller::Canvas::DrawRoundRect ( const RoundRect rect,
const Paint paint 
)

Definition at line 764 of file canvas.cc.

764 {
765 auto& rect = round_rect.GetBounds();
766 auto& radii = round_rect.GetRadii();
767 if (radii.AreAllCornersSame()) {
768 if (AttemptDrawBlurredRRect(rect, radii.top_left, paint)) {
769 return;
770 }
771
772 if (paint.style == Paint::Style::kFill) {
773 Entity entity;
774 entity.SetTransform(GetCurrentTransform());
775 entity.SetBlendMode(paint.blend_mode);
776
777 RoundRectGeometry geom(rect, radii.top_left);
778 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
779 return;
780 }
781 }
782
783 Entity entity;
784 entity.SetTransform(GetCurrentTransform());
785 entity.SetBlendMode(paint.blend_mode);
786
787 if (paint.style == Paint::Style::kFill) {
788 FillRoundRectGeometry geom(round_rect);
789 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
790 } else {
791 StrokeRoundRectGeometry geom(round_rect, paint.stroke);
792 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
793 }
794}

References impeller::Paint::blend_mode, impeller::RoundRect::GetBounds(), GetCurrentTransform(), impeller::RoundRect::GetRadii(), impeller::Paint::kFill, impeller::Entity::SetBlendMode(), impeller::Entity::SetTransform(), impeller::Paint::stroke, and impeller::Paint::style.

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

◆ DrawRoundSuperellipse()

void impeller::Canvas::DrawRoundSuperellipse ( const RoundSuperellipse rse,
const Paint paint 
)

Definition at line 812 of file canvas.cc.

813 {
814 auto& rect = round_superellipse.GetBounds();
815 auto& radii = round_superellipse.GetRadii();
816 if (radii.AreAllCornersSame() &&
817 AttemptDrawBlurredRSuperellipse(rect, radii.top_left, paint)) {
818 return;
819 }
820
821 Entity entity;
822 entity.SetTransform(GetCurrentTransform());
823 entity.SetBlendMode(paint.blend_mode);
824
825 if (paint.style == Paint::Style::kFill) {
826 RoundSuperellipseGeometry geom(rect, radii);
827 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
828 } else {
829 StrokeRoundSuperellipseGeometry geom(round_superellipse, paint.stroke);
830 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
831 }
832}

References impeller::Paint::blend_mode, impeller::RoundSuperellipse::GetBounds(), GetCurrentTransform(), impeller::RoundSuperellipse::GetRadii(), impeller::Paint::kFill, impeller::Entity::SetBlendMode(), impeller::Entity::SetTransform(), impeller::Paint::stroke, and impeller::Paint::style.

Referenced by impeller::DlDispatcherBase::drawRoundSuperellipse(), and impeller::testing::TEST_P().

◆ DrawTextFrame()

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

Definition at line 1704 of file canvas.cc.

1706 {
1708 if (max_scale * text_frame->GetFont().GetMetrics().point_size >
1709 kMaxTextScale) {
1710 fml::StatusOr<flutter::DlPath> path = text_frame->GetPath();
1711 if (path.ok()) {
1712 Save(1);
1714 DrawPath(path.value(), paint);
1715 Restore();
1716 return;
1717 }
1718 }
1719
1720 Entity entity;
1721 entity.SetClipDepth(GetClipHeight());
1722 entity.SetBlendMode(paint.blend_mode);
1723
1724 auto text_contents = std::make_shared<TextContents>();
1725 text_contents->SetTextFrame(text_frame);
1726 text_contents->SetForceTextColor(paint.mask_blur_descriptor.has_value());
1727 text_contents->SetScale(max_scale);
1728 text_contents->SetColor(paint.color);
1729 text_contents->SetOffset(position);
1730 text_contents->SetTextProperties(paint.color,
1731 paint.style == Paint::Style::kStroke
1732 ? std::optional(paint.stroke)
1733 : std::nullopt);
1734
1735 entity.SetTransform(GetCurrentTransform() *
1736 Matrix::MakeTranslation(position));
1737
1738 if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
1739 paint)) {
1740 return;
1741 }
1742
1743 entity.SetContents(paint.WithFilters(std::move(text_contents)));
1744 AddRenderEntityToCurrentPass(entity, false);
1745}
void Concat(const Matrix &transform)
Definition canvas.cc:257
void DrawPath(const flutter::DlPath &path, const Paint &paint)
Definition canvas.cc:328
void Save(uint32_t total_content_depth=kMaxDepth)
Definition canvas.cc:1220
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
static constexpr Scalar kMaxTextScale
Definition canvas.cc:1702
Definition ref_ptr.h:261
Scalar GetMaxBasisLengthXY() const
Return the maximum scale applied specifically to either the X axis or Y axis unit vectors (the bases)...
Definition matrix.h:328

References impeller::Paint::blend_mode, impeller::Paint::color, Concat(), DrawPath(), GetCurrentTransform(), impeller::Matrix::GetMaxBasisLengthXY(), impeller::kMaxTextScale, impeller::Paint::kStroke, impeller::Matrix::MakeTranslation(), impeller::Paint::mask_blur_descriptor, Restore(), Save(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::Paint::stroke, impeller::Paint::style, and impeller::Paint::WithFilters().

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

◆ DrawVertices()

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

Definition at line 1040 of file canvas.cc.

1042 {
1043 // Override the blend mode with kDestination in order to match the behavior
1044 // of Skia's SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER flag, which
1045 // is enabled when the Flutter engine builds Skia.
1046 if (!paint.color_source) {
1047 blend_mode = BlendMode::kDst;
1048 }
1049
1050 Entity entity;
1051 entity.SetTransform(GetCurrentTransform());
1052 entity.SetBlendMode(paint.blend_mode);
1053
1054 // If there are no vertex colors.
1055 if (UseColorSourceContents(vertices, paint)) {
1056 AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
1057 return;
1058 }
1059
1060 // If the blend mode is destination don't bother to bind or create a texture.
1061 if (blend_mode == BlendMode::kDst) {
1062 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1063 contents->SetBlendMode(blend_mode);
1064 contents->SetAlpha(paint.color.alpha);
1065 contents->SetGeometry(vertices);
1066 entity.SetContents(paint.WithFilters(std::move(contents)));
1067 AddRenderEntityToCurrentPass(entity);
1068 return;
1069 }
1070
1071 // If there is a texture, use this directly. Otherwise render the color
1072 // source to a texture.
1073 if (paint.color_source &&
1074 paint.color_source->type() == flutter::DlColorSourceType::kImage) {
1075 const flutter::DlImageColorSource* image_color_source =
1076 paint.color_source->asImage();
1077 FML_DCHECK(image_color_source &&
1078 image_color_source->image()->impeller_texture());
1079 auto texture = image_color_source->image()->impeller_texture();
1080 auto x_tile_mode = static_cast<Entity::TileMode>(
1081 image_color_source->horizontal_tile_mode());
1082 auto y_tile_mode =
1083 static_cast<Entity::TileMode>(image_color_source->vertical_tile_mode());
1084 auto sampler_descriptor =
1085 skia_conversions::ToSamplerDescriptor(image_color_source->sampling());
1086 auto effect_transform = image_color_source->matrix();
1087
1088 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1089 contents->SetBlendMode(blend_mode);
1090 contents->SetAlpha(paint.color.alpha);
1091 contents->SetGeometry(vertices);
1092 contents->SetEffectTransform(effect_transform);
1093 contents->SetTexture(texture);
1094 contents->SetTileMode(x_tile_mode, y_tile_mode);
1095 contents->SetSamplerDescriptor(sampler_descriptor);
1096
1097 entity.SetContents(paint.WithFilters(std::move(contents)));
1098 AddRenderEntityToCurrentPass(entity);
1099 return;
1100 }
1101
1102 auto src_paint = paint;
1103 src_paint.color = paint.color.WithAlpha(1.0);
1104
1105 std::shared_ptr<ColorSourceContents> src_contents =
1106 src_paint.CreateContents();
1107 src_contents->SetGeometry(vertices.get());
1108
1109 // If the color source has an intrinsic size, then we use that to
1110 // create the src contents as a simplification. Otherwise we use
1111 // the extent of the texture coordinates to determine how large
1112 // the src contents should be. If neither has a value we fall back
1113 // to using the geometry coverage data.
1114 Rect src_coverage;
1115 auto size = src_contents->GetColorSourceSize();
1116 if (size.has_value()) {
1117 src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
1118 } else {
1119 auto cvg = vertices->GetCoverage(Matrix{});
1120 FML_CHECK(cvg.has_value());
1121 auto texture_coverage = vertices->GetTextureCoordinateCoverage();
1122 if (texture_coverage.has_value()) {
1123 src_coverage =
1124 Rect::MakeOriginSize(texture_coverage->GetOrigin(),
1125 texture_coverage->GetSize().Max({1, 1}));
1126 } else {
1127 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
1128 src_coverage = cvg.value();
1129 }
1130 }
1131 src_contents = src_paint.CreateContents();
1132
1133 clip_geometry_.push_back(Geometry::MakeRect(Rect::Round(src_coverage)));
1134 src_contents->SetGeometry(clip_geometry_.back().get());
1135
1136 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1137 contents->SetBlendMode(blend_mode);
1138 contents->SetAlpha(paint.color.alpha);
1139 contents->SetGeometry(vertices);
1140 contents->SetLazyTextureCoverage(src_coverage);
1141 contents->SetLazyTexture(
1142 [src_contents, src_coverage](const ContentContext& renderer) {
1143 // Applying the src coverage as the coverage limit prevents the 1px
1144 // coverage pad from adding a border that is picked up by developer
1145 // specified UVs.
1146 auto snapshot = src_contents->RenderToSnapshot(
1147 renderer, {}, {.coverage_limit = Rect::Round(src_coverage)});
1148 return snapshot.has_value() ? snapshot->texture : nullptr;
1149 });
1150 entity.SetContents(paint.WithFilters(std::move(contents)));
1151 AddRenderEntityToCurrentPass(entity);
1152}
DlImageSampling sampling() const
const DlImageColorSource * asImage() const override
DlTileMode horizontal_tile_mode() const
sk_sp< const DlImage > image() const
static std::unique_ptr< Geometry > MakeRect(const Rect &rect)
Definition geometry.cc:83
#define FML_CHECK(condition)
Definition logging.h:104
FlTexture * texture
impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
Round(const TRect< U > &r)
Definition rect.h:695
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136

References impeller::Color::alpha, flutter::DlColorSource::asImage(), impeller::Paint::blend_mode, impeller::Paint::color, impeller::Paint::color_source, FML_CHECK, FML_DCHECK, GetCurrentTransform(), flutter::DlImageColorSource::horizontal_tile_mode(), flutter::DlImageColorSource::image(), impeller::kDst, flutter::kImage, impeller::TRect< Scalar >::MakeOriginSize(), impeller::Geometry::MakeRect(), impeller::TRect< Scalar >::MakeXYWH(), flutter::DlMatrixColorSourceBase::matrix(), impeller::TRect< Scalar >::Round(), flutter::DlImageColorSource::sampling(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), texture, impeller::skia_conversions::ToSamplerDescriptor(), flutter::DlAttribute< D, T >::type(), flutter::DlImageColorSource::vertical_tile_mode(), impeller::Color::WithAlpha(), and impeller::Paint::WithFilters().

Referenced by impeller::CanvasDlDispatcher::drawVertices(), impeller::testing::TEST_P(), and impeller::testing::TEST_P().

◆ EndReplay()

void impeller::Canvas::EndReplay ( )

Definition at line 2126 of file canvas.cc.

2126 {
2127 FML_DCHECK(render_passes_.size() == 1u);
2128 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2129 render_passes_.back().GetInlinePassContext()->EndPass(
2130 /*is_onscreen=*/!requires_readback_ && is_onscreen_);
2131 backdrop_data_.clear();
2132
2133 // If requires_readback_ was true, then we rendered to an offscreen texture
2134 // instead of to the onscreen provided in the render target. Now we need to
2135 // draw or blit the offscreen back to the onscreen.
2136 if (requires_readback_) {
2137 BlitToOnscreen(/*is_onscreen_=*/is_onscreen_);
2138 }
2140 VALIDATION_LOG << "Failed to generate onscreen mipmaps.";
2141 }
2142 if (!renderer_.GetContext()->FlushCommandBuffers()) {
2143 // Not much we can do.
2144 VALIDATION_LOG << "Failed to submit command buffers";
2145 }
2146 render_passes_.clear();
2147 renderer_.GetRenderTargetCache()->End();
2148 clip_geometry_.clear();
2149
2150 Reset();
2151 Initialize(initial_cull_rect_);
2152}
bool EnsureFinalMipmapGeneration() const
Definition canvas.cc:2108
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
#define VALIDATION_LOG
Definition validation.h:91

References FML_DCHECK, and VALIDATION_LOG.

Referenced by impeller::CanvasDlDispatcher::FinishRecording(), impeller::testing::TEST_P(), impeller::testing::TEST_P(), and impeller::testing::TEST_P().

◆ EnsureFinalMipmapGeneration()

bool impeller::Canvas::EnsureFinalMipmapGeneration ( ) const

For picture snapshots we need addition steps to verify that final mipmaps are generated.

Definition at line 2108 of file canvas.cc.

2108 {
2109 if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
2110 return true;
2111 }
2112 std::shared_ptr<CommandBuffer> cmd_buffer =
2113 renderer_.GetContext()->CreateCommandBuffer();
2114 if (!cmd_buffer) {
2115 return false;
2116 }
2117 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
2118 if (!blit_pass) {
2119 return false;
2120 }
2121 blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
2122 blit_pass->EncodeCommands();
2123 return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
2124}
std::shared_ptr< Texture > GetRenderTargetTexture() const

◆ GetCurrentTransform()

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

1237 {
1238 if (!clip_coverage_stack_.HasCoverage()) {
1239 // The current clip is empty. This means the pass texture won't be
1240 // visible, so skip it.
1241 return std::nullopt;
1242 }
1243
1244 std::optional<Rect> maybe_current_clip_coverage =
1245 clip_coverage_stack_.CurrentClipCoverage();
1246 if (!maybe_current_clip_coverage.has_value()) {
1247 return std::nullopt;
1248 }
1249
1250 Rect current_clip_coverage = maybe_current_clip_coverage.value();
1251
1252 FML_CHECK(!render_passes_.empty());
1253 const LazyRenderingConfig& back_render_pass = render_passes_.back();
1254 std::shared_ptr<Texture> back_texture =
1255 back_render_pass.GetInlinePassContext()->GetTexture();
1256 FML_CHECK(back_texture) << "Context is valid:"
1257 << back_render_pass.GetInlinePassContext()->IsValid();
1258
1259 // The maximum coverage of the subpass. Subpasses textures should never
1260 // extend outside the parent pass texture or the current clip coverage.
1261 std::optional<Rect> maybe_coverage_limit =
1262 Rect::MakeOriginSize(GetGlobalPassPosition(),
1263 Size(back_texture->GetSize()))
1264 .Intersection(current_clip_coverage);
1265
1266 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
1267 return std::nullopt;
1268 }
1269
1270 return maybe_coverage_limit->Intersection(
1271 Rect::MakeSize(render_target_.GetRenderTargetSize()));
1272}
ISize GetRenderTargetSize() const
constexpr std::optional< TRect > Intersection(const TRect &o) const
Definition rect.h:528

References impeller::EntityPassClipStack::CurrentClipCoverage(), FML_CHECK, impeller::LazyRenderingConfig::GetInlinePassContext(), impeller::RenderTarget::GetRenderTargetSize(), impeller::InlinePassContext::GetTexture(), impeller::EntityPassClipStack::HasCoverage(), impeller::TRect< T >::Intersection(), impeller::InlinePassContext::IsValid(), 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 261 of file canvas.h.

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

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

◆ GetOpDepth()

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

Definition at line 259 of file canvas.h.

259{ return current_depth_; }

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

◆ GetSaveCount()

size_t impeller::Canvas::GetSaveCount ( ) const

Definition at line 312 of file canvas.cc.

312 {
313 return transform_stack_.size();
314}

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

◆ PreConcat()

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

Definition at line 261 of file canvas.cc.

261 {
262 transform_stack_.back().transform = transform * GetCurrentTransform();
263}

References GetCurrentTransform(), and transform.

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

◆ RequiresReadback()

bool impeller::Canvas::RequiresReadback ( ) const
inline

Definition at line 269 of file canvas.h.

269{ return requires_readback_; }

◆ ResetTransform()

void impeller::Canvas::ResetTransform ( )

Definition at line 265 of file canvas.cc.

265 {
266 transform_stack_.back().transform = {};
267}

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

◆ Restore()

bool impeller::Canvas::Restore ( )

Definition at line 1512 of file canvas.cc.

1512 {
1513 FML_DCHECK(transform_stack_.size() > 0);
1514 if (transform_stack_.size() == 1) {
1515 return false;
1516 }
1517
1518 // This check is important to make sure we didn't exceed the depth
1519 // that the clips were rendered at while rendering any of the
1520 // rendering ops. It is OK for the current depth to equal the
1521 // outgoing clip depth because that means the clipping would have
1522 // been successful up through the last rendering op, but it cannot
1523 // be greater.
1524 // Also, we bump the current rendering depth to the outgoing clip
1525 // depth so that future rendering operations are not clipped by
1526 // any of the pixels set by the expiring clips. It is OK for the
1527 // estimates used to determine the clip depth in save/saveLayer
1528 // to be overly conservative, but we need to jump the depth to
1529 // the clip depth so that the next rendering op will get a
1530 // larger depth (it will pre-increment the current_depth_ value).
1531 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1532 << current_depth_ << " <=? " << transform_stack_.back().clip_depth;
1533 current_depth_ = transform_stack_.back().clip_depth;
1534
1535 if (IsSkipping()) {
1536 transform_stack_.pop_back();
1537 return true;
1538 }
1539
1540 if (transform_stack_.back().rendering_mode ==
1542 transform_stack_.back().rendering_mode ==
1544 auto lazy_render_pass = std::move(render_passes_.back());
1545 render_passes_.pop_back();
1546 // Force the render pass to be constructed if it never was.
1547 lazy_render_pass.GetInlinePassContext()->GetRenderPass();
1548
1549 SaveLayerState save_layer_state = save_layer_state_.back();
1550 save_layer_state_.pop_back();
1551 auto global_pass_position = GetGlobalPassPosition();
1552
1553 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1554 save_layer_state.paint, //
1555 lazy_render_pass.GetInlinePassContext()->GetTexture(), //
1556 Matrix::MakeTranslation(Vector3{-global_pass_position}) * //
1557 transform_stack_.back().transform //
1558 );
1559
1560 lazy_render_pass.GetInlinePassContext()->EndPass();
1561
1562 // Round the subpass texture position for pixel alignment with the parent
1563 // pass render target. By default, we draw subpass textures with nearest
1564 // sampling, so aligning here is important for avoiding visual nearest
1565 // sampling errors caused by limited floating point precision when
1566 // straddling a half pixel boundary.
1567 Point subpass_texture_position;
1568 if (transform_stack_.back().did_round_out) {
1569 // Subpass coverage was rounded out, origin potentially moved "down" by
1570 // as much as a pixel.
1571 subpass_texture_position =
1572 (save_layer_state.coverage.GetOrigin() - global_pass_position)
1573 .Floor();
1574 } else {
1575 // Subpass coverage was truncated. Pick the closest phyiscal pixel.
1576 subpass_texture_position =
1577 (save_layer_state.coverage.GetOrigin() - global_pass_position)
1578 .Round();
1579 }
1580
1581 Entity element_entity;
1582 element_entity.SetClipDepth(++current_depth_);
1583 element_entity.SetContents(std::move(contents));
1584 element_entity.SetBlendMode(save_layer_state.paint.blend_mode);
1585 element_entity.SetTransform(
1586 Matrix::MakeTranslation(Vector3(subpass_texture_position)));
1587
1588 if (element_entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
1590 ApplyFramebufferBlend(element_entity);
1591 } else {
1592 // End the active pass and flush the buffer before rendering "advanced"
1593 // blends. Advanced blends work by binding the current render target
1594 // texture as an input ("destination"), blending with a second texture
1595 // input ("source"), writing the result to an intermediate texture, and
1596 // finally copying the data from the intermediate texture back to the
1597 // render target texture. And so all of the commands that have written
1598 // to the render target texture so far need to execute before it's bound
1599 // for blending (otherwise the blend pass will end up executing before
1600 // all the previous commands in the active pass).
1601 auto input_texture = FlipBackdrop(GetGlobalPassPosition());
1602 if (!input_texture) {
1603 return false;
1604 }
1605
1606 FilterInput::Vector inputs = {
1607 FilterInput::Make(input_texture,
1608 element_entity.GetTransform().Invert()),
1609 FilterInput::Make(element_entity.GetContents())};
1610 auto contents = ColorFilterContents::MakeBlend(
1611 element_entity.GetBlendMode(), inputs);
1612 contents->SetCoverageHint(element_entity.GetCoverage());
1613 element_entity.SetContents(std::move(contents));
1614 element_entity.SetBlendMode(BlendMode::kSrc);
1615 }
1616 }
1617
1618 element_entity.Render(
1619 renderer_, //
1620 *render_passes_.back().GetInlinePassContext()->GetRenderPass() //
1621 );
1622 clip_coverage_stack_.PopSubpass();
1623 transform_stack_.pop_back();
1624
1625 // We don't need to restore clips if a saveLayer was performed, as the clip
1626 // state is per render target, and no more rendering operations will be
1627 // performed as the render target workloaded is completed in the restore.
1628 return true;
1629 }
1630
1631 size_t num_clips = transform_stack_.back().num_clips;
1632 transform_stack_.pop_back();
1633
1634 if (num_clips > 0) {
1635 EntityPassClipStack::ClipStateResult clip_state_result =
1636 clip_coverage_stack_.RecordRestore(GetGlobalPassPosition(),
1637 GetClipHeight());
1638
1639 // Clip restores are never required with depth based clipping.
1640 FML_DCHECK(!clip_state_result.should_render);
1641 if (clip_state_result.clip_did_change) {
1642 // We only need to update the pass scissor if the clip state has changed.
1643 SetClipScissor(
1644 clip_coverage_stack_.CurrentClipCoverage(), //
1645 *render_passes_.back().GetInlinePassContext()->GetRenderPass(), //
1646 GetGlobalPassPosition() //
1647 );
1648 }
1649 }
1650
1651 return true;
1652}
virtual bool SupportsFramebufferFetch() const =0
Whether the context backend is able to support pipelines with shaders that read from the framebuffer ...
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.
const Capabilities & GetDeviceCapabilities() const
static constexpr BlendMode kLastPipelineBlendMode
Definition entity.h:28
ClipStateResult RecordRestore(Point global_pass_position, size_t restore_height)
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
std::vector< FilterInput::Ref > Vector
TPoint< Scalar > Point
Definition point.h:327

References impeller::Paint::blend_mode, impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::Canvas::SaveLayerState::coverage, impeller::EntityPassClipStack::CurrentClipCoverage(), FML_DCHECK, impeller::Entity::GetBlendMode(), impeller::Entity::GetContents(), impeller::Entity::GetCoverage(), impeller::ContentContext::GetDeviceCapabilities(), impeller::TRect< T >::GetOrigin(), impeller::Entity::GetTransform(), impeller::Matrix::Invert(), impeller::Entity::kLastPipelineBlendMode, impeller::kSrc, impeller::Entity::kSubpassAppendSnapshotTransform, impeller::Entity::kSubpassPrependSnapshotTransform, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeTranslation(), impeller::Canvas::SaveLayerState::paint, impeller::EntityPassClipStack::PopSubpass(), impeller::EntityPassClipStack::RecordRestore(), 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(), DrawTextFrame(), impeller::DlDispatcherBase::restore(), and RestoreToCount().

◆ RestoreToCount()

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

Definition at line 320 of file canvas.cc.

320 {
321 while (GetSaveCount() > count) {
322 if (!Restore()) {
323 return;
324 }
325 }
326}
size_t GetSaveCount() const
Definition canvas.cc:312

References GetSaveCount(), and Restore().

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

◆ Rotate()

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

Definition at line 293 of file canvas.cc.

293 {
295}
static Matrix MakeRotationZ(Radians r)
Definition matrix.h:223

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

1220 {
1221 if (IsSkipping()) {
1222 return SkipUntilMatchingRestore(total_content_depth);
1223 }
1224
1225 auto entry = CanvasStackEntry{};
1226 entry.transform = transform_stack_.back().transform;
1227 entry.clip_depth = current_depth_ + total_content_depth;
1228 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
1229 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1230 << entry.clip_depth << " <=? " << transform_stack_.back().clip_depth
1231 << " after allocating " << total_content_depth;
1232 entry.clip_height = transform_stack_.back().clip_height;
1233 entry.rendering_mode = Entity::RenderingMode::kDirect;
1234 transform_stack_.push_back(entry);
1235}

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

Referenced by impeller::DlDispatcherBase::drawDisplayList(), impeller::DlDispatcherBase::drawShadow(), DrawTextFrame(), 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,
std::optional< int64_t >  backdrop_id = std::nullopt 
)

Definition at line 1274 of file canvas.cc.

1280 {
1281 TRACE_EVENT0("flutter", "Canvas::saveLayer");
1282 if (IsSkipping()) {
1283 return SkipUntilMatchingRestore(total_content_depth);
1284 }
1285
1286 auto maybe_coverage_limit = GetLocalCoverageLimit();
1287 if (!maybe_coverage_limit.has_value()) {
1288 return SkipUntilMatchingRestore(total_content_depth);
1289 }
1290 auto coverage_limit = maybe_coverage_limit.value();
1291
1292 if (can_distribute_opacity && !backdrop_filter &&
1294 bounds_promise != ContentBoundsPromise::kMayClipContents) {
1295 Save(total_content_depth);
1296 transform_stack_.back().distributed_opacity *= paint.color.alpha;
1297 return;
1298 }
1299
1300 std::shared_ptr<FilterContents> filter_contents = paint.WithImageFilter(
1301 Rect(), transform_stack_.back().transform,
1303
1304 std::optional<Rect> maybe_subpass_coverage = ComputeSaveLayerCoverage(
1305 bounds.value_or(Rect::MakeMaximum()),
1306 transform_stack_.back().transform, //
1307 coverage_limit, //
1308 filter_contents, //
1309 /*flood_output_coverage=*/
1310 Entity::IsBlendModeDestructive(paint.blend_mode), //
1311 /*flood_input_coverage=*/!!backdrop_filter ||
1312 (paint.color_filter &&
1313 paint.color_filter->modifies_transparent_black()) //
1314 );
1315
1316 if (!maybe_subpass_coverage.has_value()) {
1317 return SkipUntilMatchingRestore(total_content_depth);
1318 }
1319
1320 auto subpass_coverage = maybe_subpass_coverage.value();
1321
1322 // When an image filter is present, clamp to avoid flicking due to nearest
1323 // sampled image. For other cases, round out to ensure than any geometry is
1324 // not cut off.
1325 //
1326 // See also this bug: https://github.com/flutter/flutter/issues/144213
1327 //
1328 // TODO(jonahwilliams): this could still round out for filters that use decal
1329 // sampling mode.
1331 bool did_round_out = false;
1332 Point coverage_origin_adjustment = Point{0, 0};
1333 if (paint.image_filter) {
1334 subpass_size = ISize(subpass_coverage.GetSize());
1335 } else {
1336 did_round_out = true;
1337 subpass_size =
1338 static_cast<ISize>(IRect::RoundOut(subpass_coverage).GetSize());
1339 // If rounding out, adjust the coverage to account for the subpixel shift.
1340 coverage_origin_adjustment =
1341 Point(subpass_coverage.GetLeftTop().x -
1342 std::floor(subpass_coverage.GetLeftTop().x),
1343 subpass_coverage.GetLeftTop().y -
1344 std::floor(subpass_coverage.GetLeftTop().y));
1345 }
1346 if (subpass_size.IsEmpty()) {
1347 return SkipUntilMatchingRestore(total_content_depth);
1348 }
1349
1350 // When there are scaling filters present, these contents may exceed the
1351 // maximum texture size. Perform a clamp here, which may cause rendering
1352 // artifacts.
1353 subpass_size = subpass_size.Min(renderer_.GetContext()
1354 ->GetCapabilities()
1355 ->GetMaximumRenderPassAttachmentSize());
1356
1357 // Backdrop filter state, ignored if there is no BDF.
1358 std::shared_ptr<FilterContents> backdrop_filter_contents;
1359 Point local_position = Point(0, 0);
1360 if (backdrop_filter) {
1361 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1362 Canvas::BackdropFilterProc backdrop_filter_proc =
1363 [backdrop_filter = backdrop_filter](
1364 const FilterInput::Ref& input, const Matrix& effect_transform,
1365 Entity::RenderingMode rendering_mode) {
1366 auto filter = WrapInput(backdrop_filter, input);
1367 filter->SetEffectTransform(effect_transform);
1368 filter->SetRenderingMode(rendering_mode);
1369 return filter;
1370 };
1371
1372 std::shared_ptr<Texture> input_texture;
1373
1374 // If the backdrop ID is not nullopt and there is more than one usage
1375 // of it in the current scene, cache the backdrop texture and remove it from
1376 // the current entity pass flip.
1377 bool will_cache_backdrop_texture = false;
1378 BackdropData* backdrop_data = nullptr;
1379 // If we've reached this point, there is at least one backdrop filter. But
1380 // potentially more if there is a backdrop id. We may conditionally set this
1381 // to a higher value in the if block below.
1382 size_t backdrop_count = 1;
1383 if (backdrop_id.has_value()) {
1384 std::unordered_map<int64_t, BackdropData>::iterator backdrop_data_it =
1385 backdrop_data_.find(backdrop_id.value());
1386 if (backdrop_data_it != backdrop_data_.end()) {
1387 backdrop_data = &backdrop_data_it->second;
1388 will_cache_backdrop_texture =
1389 backdrop_data_it->second.backdrop_count > 1;
1390 backdrop_count = backdrop_data_it->second.backdrop_count;
1391 }
1392 }
1393
1394 if (!will_cache_backdrop_texture || !backdrop_data->texture_slot) {
1395 backdrop_count_ -= backdrop_count;
1396
1397 // The onscreen texture can be flipped to if:
1398 // 1. The device supports framebuffer fetch
1399 // 2. There are no more backdrop filters
1400 // 3. The current render pass is for the onscreen pass.
1401 const bool should_use_onscreen =
1403 backdrop_count_ == 0 && render_passes_.size() == 1u;
1404 input_texture = FlipBackdrop(
1405 GetGlobalPassPosition(), //
1406 /*should_remove_texture=*/will_cache_backdrop_texture, //
1407 /*should_use_onscreen=*/should_use_onscreen //
1408 );
1409 if (!input_texture) {
1410 // Validation failures are logged in FlipBackdrop.
1411 return;
1412 }
1413
1414 if (will_cache_backdrop_texture) {
1415 backdrop_data->texture_slot = input_texture;
1416 }
1417 } else {
1418 input_texture = backdrop_data->texture_slot;
1419 }
1420
1421 backdrop_filter_contents = backdrop_filter_proc(
1422 FilterInput::Make(std::move(input_texture)),
1423 transform_stack_.back().transform.Basis(),
1424 // When the subpass has a translation that means the math with
1425 // the snapshot has to be different.
1426 transform_stack_.back().transform.HasTranslation()
1428 : Entity::RenderingMode::kSubpassAppendSnapshotTransform);
1429
1430 if (will_cache_backdrop_texture) {
1431 FML_DCHECK(backdrop_data);
1432 // If all filters on the shared backdrop layer are equal, process the
1433 // layer once.
1434 if (backdrop_data->all_filters_equal &&
1435 !backdrop_data->shared_filter_snapshot.has_value()) {
1436 // TODO(157110): compute minimum input hint.
1437 backdrop_data->shared_filter_snapshot =
1438 backdrop_filter_contents->RenderToSnapshot(renderer_, {}, {});
1439 }
1440
1441 std::optional<Snapshot> maybe_snapshot =
1442 backdrop_data->shared_filter_snapshot;
1443 if (maybe_snapshot.has_value()) {
1444 const Snapshot& snapshot = maybe_snapshot.value();
1445 std::shared_ptr<TextureContents> contents = TextureContents::MakeRect(
1446 subpass_coverage.Shift(-GetGlobalPassPosition()));
1447 auto scaled =
1448 subpass_coverage.TransformBounds(snapshot.transform.Invert());
1449 contents->SetTexture(snapshot.texture);
1450 contents->SetSourceRect(scaled);
1451 contents->SetSamplerDescriptor(snapshot.sampler_descriptor);
1452
1453 // This backdrop entity sets a depth value as it is written to the newly
1454 // flipped backdrop and not into a new saveLayer.
1455 Entity backdrop_entity;
1456 backdrop_entity.SetContents(std::move(contents));
1457 backdrop_entity.SetClipDepth(++current_depth_);
1458 backdrop_entity.SetBlendMode(paint.blend_mode);
1459
1460 backdrop_entity.Render(renderer_, GetCurrentRenderPass());
1461 Save(0);
1462 return;
1463 }
1464 }
1465 }
1466
1467 // When applying a save layer, absorb any pending distributed opacity.
1468 Paint paint_copy = paint;
1469 paint_copy.color.alpha *= transform_stack_.back().distributed_opacity;
1470 transform_stack_.back().distributed_opacity = 1.0;
1471
1472 render_passes_.push_back(
1473 LazyRenderingConfig(renderer_, //
1474 CreateRenderTarget(renderer_, //
1475 subpass_size, //
1477 )));
1478 save_layer_state_.push_back(SaveLayerState{
1479 paint_copy, subpass_coverage.Shift(-coverage_origin_adjustment)});
1480
1481 CanvasStackEntry entry;
1482 entry.transform = transform_stack_.back().transform;
1483 entry.clip_depth = current_depth_ + total_content_depth;
1484 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1485 << entry.clip_depth << " <=? " << transform_stack_.back().clip_depth
1486 << " after allocating " << total_content_depth;
1487 entry.clip_height = transform_stack_.back().clip_height;
1489 entry.did_round_out = did_round_out;
1490 transform_stack_.emplace_back(entry);
1491
1492 // Start non-collapsed subpasses with a fresh clip coverage stack limited by
1493 // the subpass coverage. This is important because image filters applied to
1494 // save layers may transform the subpass texture after it's rendered,
1495 // causing parent clip coverage to get misaligned with the actual area that
1496 // the subpass will affect in the parent pass.
1497 clip_coverage_stack_.PushSubpass(subpass_coverage, GetClipHeight());
1498
1499 if (!backdrop_filter_contents) {
1500 return;
1501 }
1502
1503 // Render the backdrop entity.
1504 Entity backdrop_entity;
1505 backdrop_entity.SetContents(std::move(backdrop_filter_contents));
1506 backdrop_entity.SetTransform(
1507 Matrix::MakeTranslation(Vector3(-local_position)));
1508 backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
1509 backdrop_entity.Render(renderer_, GetCurrentRenderPass());
1510}
std::optional< Rect > GetLocalCoverageLimit() const
Return the culling bounds of the current render target, or nullopt if there is no coverage.
Definition canvas.cc:1237
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
Definition canvas.h:125
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:127
void PushSubpass(std::optional< Rect > subpass_coverage, size_t clip_height)
std::shared_ptr< FilterInput > Ref
static int input(yyscan_t yyscanner)
ISize subpass_size
The output size of the down-sampling pass.
std::shared_ptr< FilterContents > WrapInput(const flutter::DlImageFilter *filter, const FilterInput::Ref &input)
Generate a new FilterContents using this filter's configuration.
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
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.
static constexpr Color BlackTransparent()
Definition color.h:270
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:40
RoundOut(const TRect< U > &r)
Definition rect.h:679
static constexpr TRect MakeMaximum()
Definition rect.h:188
#define TRACE_EVENT0(category_group, name)

References impeller::BackdropData::all_filters_equal, impeller::Color::alpha, impeller::BackdropData::backdrop_count, impeller::Color::BlackTransparent(), impeller::Paint::blend_mode, impeller::Paint::CanApplyOpacityPeephole(), impeller::CanvasStackEntry::clip_depth, impeller::CanvasStackEntry::clip_height, impeller::Paint::color, impeller::Paint::color_filter, impeller::ComputeSaveLayerCoverage(), impeller::CanvasStackEntry::did_round_out, FML_DCHECK, impeller::ContentContext::GetContext(), impeller::ContentContext::GetDeviceCapabilities(), GetLocalCoverageLimit(), impeller::Paint::image_filter, input(), impeller::Matrix::Invert(), impeller::Entity::IsBlendModeDestructive(), impeller::kMayClipContents, impeller::Entity::kSubpassAppendSnapshotTransform, impeller::Entity::kSubpassPrependSnapshotTransform, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TextureContents::MakeRect(), impeller::Matrix::MakeTranslation(), flutter::DlColorFilter::modifies_transparent_black(), impeller::EntityPassClipStack::PushSubpass(), impeller::Entity::Render(), impeller::CanvasStackEntry::rendering_mode, impeller::TRect< T >::RoundOut(), impeller::Snapshot::sampler_descriptor, Save(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::BackdropData::shared_filter_snapshot, subpass_size, impeller::Capabilities::SupportsFramebufferFetch(), impeller::Snapshot::texture, impeller::BackdropData::texture_slot, TRACE_EVENT0, impeller::CanvasStackEntry::transform, impeller::Snapshot::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 281 of file canvas.cc.

281 {
283}
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104

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

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

◆ Scale() [2/2]

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

Definition at line 285 of file canvas.cc.

285 {
287}

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

◆ SetBackdropData()

void impeller::Canvas::SetBackdropData ( std::unordered_map< int64_t, BackdropData backdrop_data,
size_t  backdrop_count 
)

Update the backdrop data used to group together backdrop filters within the same layer.

Definition at line 1927 of file canvas.cc.

1929 {
1930 backdrop_data_ = std::move(backdrop_data);
1931 backdrop_count_ = backdrop_count;
1932}

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

◆ Skew()

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

Definition at line 289 of file canvas.cc.

289 {
290 Concat(Matrix::MakeSkew(sx, sy));
291}
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
Definition matrix.h:127

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

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

◆ SupportsBlitToOnscreen()

bool impeller::Canvas::SupportsBlitToOnscreen ( ) const

Definition at line 2050 of file canvas.cc.

2050 {
2051 return renderer_.GetContext()
2052 ->GetCapabilities()
2053 ->SupportsTextureToTextureBlits() &&
2054 renderer_.GetContext()->GetBackendType() ==
2056}

◆ Transform()

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

◆ Translate()

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

Definition at line 277 of file canvas.cc.

277 {
279}

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

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

Member Data Documentation

◆ kMaxDepth

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

Definition at line 120 of file canvas.h.


The documentation for this class was generated from the following files: