Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
impeller::Canvas Class Reference

#include <canvas.h>

Classes

class  PathBlurShape
 
class  RRectBlurShape
 
class  RSuperellipseBlurShape
 
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 284 of file canvas.cc.

288 : renderer_(renderer),
289 render_target_(render_target),
290 is_onscreen_(is_onscreen),
291 requires_readback_(requires_readback),
292 clip_coverage_stack_(EntityPassClipStack(
293 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
294 Initialize(std::nullopt);
295 SetupRenderPass();
296}
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 298 of file canvas.cc.

303 : renderer_(renderer),
304 render_target_(render_target),
305 is_onscreen_(is_onscreen),
306 requires_readback_(requires_readback),
307 clip_coverage_stack_(EntityPassClipStack(
308 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
309 Initialize(cull_rect);
310 SetupRenderPass();
311}

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

318 : renderer_(renderer),
319 render_target_(render_target),
320 is_onscreen_(is_onscreen),
321 requires_readback_(requires_readback),
322 clip_coverage_stack_(EntityPassClipStack(
323 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
324 Initialize(Rect::MakeLTRB(cull_rect.GetLeft(), cull_rect.GetTop(),
325 cull_rect.GetRight(), cull_rect.GetBottom()));
326 SetupRenderPass();
327}
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 1024 of file canvas.cc.

1026 {
1027 if (IsSkipping()) {
1028 return;
1029 }
1030
1031 // Ideally the clip depth would be greater than the current rendering
1032 // depth because any rendering calls that follow this clip operation will
1033 // pre-increment the depth and then be rendering above our clip depth,
1034 // but that case will be caught by the CHECK in AddRenderEntity above.
1035 // In practice we sometimes have a clip set with no rendering after it
1036 // and in such cases the current depth will equal the clip depth.
1037 // Eventually the DisplayList should optimize these out, but it is hard
1038 // to know if a clip will actually be used in advance of storing it in
1039 // the DisplayList buffer.
1040 // See https://github.com/flutter/flutter/issues/147021
1041 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1042 << current_depth_ << " <=? " << transform_stack_.back().clip_depth;
1043 uint32_t clip_depth = transform_stack_.back().clip_depth;
1044
1045 const Matrix clip_transform =
1046 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
1048
1049 std::optional<Rect> clip_coverage = geometry.GetCoverage(clip_transform);
1050 if (!clip_coverage.has_value()) {
1051 return;
1052 }
1053
1054 ClipContents clip_contents(
1055 clip_coverage.value(),
1056 /*is_axis_aligned_rect=*/geometry.IsAxisAlignedRect() &&
1057 GetCurrentTransform().IsTranslationScaleOnly());
1058 clip_contents.SetClipOperation(clip_op);
1059
1060 EntityPassClipStack::ClipStateResult clip_state_result =
1061 clip_coverage_stack_.RecordClip(
1062 clip_contents, //
1063 /*transform=*/clip_transform, //
1064 /*global_pass_position=*/GetGlobalPassPosition(), //
1065 /*clip_depth=*/clip_depth, //
1066 /*clip_height_floor=*/GetClipHeightFloor(), //
1067 /*is_aa=*/is_aa);
1068
1069 if (clip_state_result.clip_did_change) {
1070 // We only need to update the pass scissor if the clip state has changed.
1071 SetClipScissor(
1072 clip_coverage_stack_.CurrentClipCoverage(),
1073 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1074 GetGlobalPassPosition());
1075 }
1076
1077 ++transform_stack_.back().clip_height;
1078 ++transform_stack_.back().num_clips;
1079
1080 if (!clip_state_result.should_render) {
1081 return;
1082 }
1083
1084 // Note: this is a bit of a hack. Its not possible to construct a geometry
1085 // result without begninning the render pass. We should refactor the geometry
1086 // objects so that they only need a reference to the render pass size and/or
1087 // orthographic transform.
1088 Entity entity;
1089 entity.SetTransform(clip_transform);
1090 entity.SetClipDepth(clip_depth);
1091
1092 GeometryResult geometry_result = geometry.GetPositionBuffer(
1093 renderer_, //
1094 entity, //
1095 *render_passes_.back().GetInlinePassContext()->GetRenderPass() //
1096 );
1097 clip_contents.SetGeometry(geometry_result);
1098 clip_coverage_stack_.GetLastReplayResult().clip_contents.SetGeometry(
1099 geometry_result);
1100
1101 clip_contents.Render(
1102 renderer_, *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1103 clip_depth);
1104}
const Matrix & GetCurrentTransform() const
Definition canvas.cc:358
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 342 of file canvas.cc.

342 {
343 transform_stack_.back().transform = GetCurrentTransform() * transform;
344}

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

873 {
874 Entity entity;
875 entity.SetTransform(GetCurrentTransform());
876 entity.SetBlendMode(paint.blend_mode);
877
878 if (paint.style == Paint::Style::kFill) {
879 ArcGeometry geom(arc);
880 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
881 return;
882 }
883
884 const Rect& oval_bounds = arc.GetOvalBounds();
885 if (paint.stroke.width > oval_bounds.GetSize().MaxDimension()) {
886 // This is a special case for rendering arcs whose stroke width is so large
887 // you are effectively drawing a sector of a circle.
888 // https://github.com/flutter/flutter/issues/158567
889 Arc expanded_arc(oval_bounds.Expand(Size(paint.stroke.width * 0.5f)),
890 arc.GetStart(), arc.GetSweep(), true);
891
892 ArcGeometry geom(expanded_arc);
893 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
894 return;
895 }
896
897 // IncludeCenter incurs lots of extra work for stroking an arc, including:
898 // - It introduces segments to/from the center point (not too hard).
899 // - It introduces joins on those segments (a bit more complicated).
900 // - Even if the sweep is >=360 degrees, we still draw the segment to
901 // the center and it basically looks like a pie cut into the complete
902 // boundary circle, as if the slice were cut, but not extracted
903 // (hard to express as a continuous kTriangleStrip).
904 if (!arc.IncludeCenter()) {
905 if (arc.IsFullCircle()) {
906 return DrawOval(oval_bounds, paint);
907 }
908
909 // Our fast stroking code only works for circular bounds as it assumes
910 // that the inner and outer radii can be scaled along each angular step
911 // of the arc - which is not true for elliptical arcs where the inner
912 // and outer samples are perpendicular to the traveling direction of the
913 // elliptical curve which may not line up with the center of the bounds.
914 if (oval_bounds.IsSquare()) {
915 ArcGeometry geom(arc, paint.stroke);
916 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
917 return;
918 }
919 }
920
921 ArcStrokeGeometry geom(arc, paint.stroke);
922 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
923}
void DrawOval(const Rect &rect, const Paint &paint)
Definition canvas.cc:832
TRect< Scalar > Rect
Definition rect.h:788
TSize< Scalar > Size
Definition size.h:159

References impeller::Paint::blend_mode, 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::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 1317 of file canvas.cc.

1318 {
1319 atlas_contents->SetAlpha(paint.color.alpha);
1320
1321 Entity entity;
1322 entity.SetTransform(GetCurrentTransform());
1323 entity.SetBlendMode(paint.blend_mode);
1324 entity.SetContents(paint.WithFilters(atlas_contents));
1325
1326 AddRenderEntityToCurrentPass(entity);
1327}

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

997 {
998 if (IsShadowBlurDrawOperation(paint)) {
999 Rect bounds = Rect::MakeLTRB(center.x - radius, center.y - radius,
1000 center.x + radius, center.y + radius);
1001 RRectBlurShape shape(bounds, radius);
1002 if (AttemptDrawBlur(shape, paint)) {
1003 return;
1004 }
1005 }
1006
1007 if (AttemptDrawAntialiasedCircle(center, radius, paint)) {
1008 return;
1009 }
1010
1011 Entity entity;
1012 entity.SetTransform(GetCurrentTransform());
1013 entity.SetBlendMode(paint.blend_mode);
1014
1015 if (paint.style == Paint::Style::kStroke) {
1016 CircleGeometry geom(center, radius, paint.stroke.width);
1017 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1018 } else {
1019 CircleGeometry geom(center, radius);
1020 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1021 }
1022}

References impeller::Paint::blend_mode, GetCurrentTransform(), impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeLTRB(), 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 785 of file canvas.cc.

789 {
790 // Reasons to defer to regular DrawLine:
791 // - performance for degenerate and "regular line" cases
792 // - length is non-positive - DrawLine will draw appropriate "dot"
793 // - off_length is non-positive - no gaps, DrawLine will draw it solid
794 // - on_length is negative - invalid dashing
795 //
796 // Note that a 0 length "on" dash will draw "dot"s every "off" distance
797 // apart so we proceed with the dashing process in that case.
798 Scalar length = p0.GetDistance(p1);
799 if (length > 0.0f && on_length >= 0.0f && off_length > 0.0f) {
800 Entity entity;
801 entity.SetTransform(GetCurrentTransform());
802 entity.SetBlendMode(paint.blend_mode);
803
804 StrokeDashedLineGeometry geom(p0, p1, on_length, off_length, paint.stroke);
805 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
806 } else {
807 DrawLine(p0, p1, paint);
808 }
809}
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
Definition canvas.cc:763
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 957 of file canvas.cc.

959 {
960 Entity entity;
961 entity.SetTransform(GetCurrentTransform());
962 entity.SetBlendMode(paint.blend_mode);
963
964 if (paint.style == Paint::Style::kFill) {
965 FillDiffRoundRectGeometry geom(outer, inner);
966 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
967 } else {
968 StrokeDiffRoundRectGeometry geom(outer, inner, paint.stroke);
969 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
970 }
971}

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

1127 {
1128 if (!image) {
1129 return;
1130 }
1131
1132 const Rect source = Rect::MakeSize(image->GetSize());
1133 const Rect dest = source.Shift(offset);
1134
1135 DrawImageRect(image, source, dest, paint, sampler);
1136}
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:1138
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 1138 of file canvas.cc.

1143 {
1144 if (!image || source.IsEmpty() || dest.IsEmpty()) {
1145 return;
1146 }
1147
1148 ISize size = image->GetSize();
1149 if (size.IsEmpty()) {
1150 return;
1151 }
1152
1153 std::optional<Rect> clipped_source =
1154 source.Intersection(Rect::MakeSize(size));
1155 if (!clipped_source) {
1156 return;
1157 }
1158
1159 if (AttemptColorFilterOptimization(image, source, dest, paint, sampler,
1160 src_rect_constraint)) {
1161 return;
1162 }
1163
1164 if (*clipped_source != source) {
1165 Scalar sx = dest.GetWidth() / source.GetWidth();
1166 Scalar sy = dest.GetHeight() / source.GetHeight();
1167 Scalar tx = dest.GetLeft() - source.GetLeft() * sx;
1168 Scalar ty = dest.GetTop() - source.GetTop() * sy;
1169 Matrix src_to_dest = Matrix::MakeTranslateScale({sx, sy, 1}, {tx, ty, 0});
1170 dest = clipped_source->TransformBounds(src_to_dest);
1171 }
1172
1173 auto texture_contents = TextureContents::MakeRect(dest);
1174 texture_contents->SetTexture(image);
1175 texture_contents->SetSourceRect(*clipped_source);
1176 texture_contents->SetStrictSourceRect(src_rect_constraint ==
1178 texture_contents->SetSamplerDescriptor(sampler);
1179 texture_contents->SetOpacity(paint.color.alpha);
1180 texture_contents->SetDeferApplyingOpacity(paint.HasColorFilter());
1181
1182 Entity entity;
1183 entity.SetBlendMode(paint.blend_mode);
1184 entity.SetTransform(GetCurrentTransform());
1185
1186 if (!paint.mask_blur_descriptor.has_value()) {
1187 entity.SetContents(paint.WithFilters(std::move(texture_contents)));
1188 AddRenderEntityToCurrentPass(entity);
1189 return;
1190 }
1191
1192 FillRectGeometry out_rect(Rect{});
1193
1194 entity.SetContents(paint.WithFilters(
1195 paint.mask_blur_descriptor->CreateMaskBlur(texture_contents, &out_rect)));
1196 AddRenderEntityToCurrentPass(entity);
1197}
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 763 of file canvas.cc.

766 {
767 Entity entity;
768 entity.SetTransform(GetCurrentTransform());
769 entity.SetBlendMode(paint.blend_mode);
770
771 auto geometry = std::make_unique<LineGeometry>(p0, p1, paint.stroke);
772
773 if (renderer_.GetContext()->GetFlags().antialiased_lines &&
774 !paint.color_filter && !paint.invert_colors && !paint.image_filter &&
775 !paint.mask_blur_descriptor.has_value() && !paint.color_source) {
776 auto contents = LineContents::Make(std::move(geometry), paint.color);
777 entity.SetContents(std::move(contents));
778 AddRenderEntityToCurrentPass(entity, reuse_depth);
779 } else {
780 AddRenderEntityWithFiltersToCurrentPass(entity, geometry.get(), paint,
781 /*reuse_depth=*/reuse_depth);
782 }
783}
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 832 of file canvas.cc.

832 {
833 // TODO(jonahwilliams): This additional condition avoids an assert in the
834 // stroke circle geometry generator. I need to verify the condition that this
835 // assert prevents.
836 if (rect.IsSquare() && (paint.style == Paint::Style::kFill ||
837 (paint.style == Paint::Style::kStroke &&
838 paint.stroke.width < rect.GetWidth()))) {
839 // Circles have slightly less overhead and can do stroking
840 DrawCircle(rect.GetCenter(), rect.GetWidth() * 0.5f, paint);
841 return;
842 }
843
844 if (IsShadowBlurDrawOperation(paint)) {
845 if (rect.IsSquare()) {
846 // RRectBlurShape takes the corner radii which are half of the
847 // overall width and height of the DrawOval bounds rect.
848 RRectBlurShape shape(rect, rect.GetWidth() * 0.5f);
849 if (AttemptDrawBlur(shape, paint)) {
850 return;
851 }
852 } else {
853 EllipsePathSource source(rect);
854 if (AttemptDrawBlurredPathSource(source, paint)) {
855 return;
856 }
857 }
858 }
859
860 Entity entity;
861 entity.SetTransform(GetCurrentTransform());
862 entity.SetBlendMode(paint.blend_mode);
863
864 if (paint.style == Paint::Style::kStroke) {
865 StrokeEllipseGeometry geom(rect, paint.stroke);
866 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
867 } else {
868 EllipseGeometry geom(rect);
869 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
870 }
871}
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition canvas.cc:995

References impeller::Paint::blend_mode, DrawCircle(), impeller::TRect< T >::GetCenter(), GetCurrentTransform(), 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 433 of file canvas.cc.

433 {
434 Entity entity;
435 entity.SetTransform(GetCurrentTransform());
436 entity.SetBlendMode(paint.blend_mode);
437
438 CoverGeometry geom;
439 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
440}

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

413 {
414 if (IsShadowBlurDrawOperation(paint)) {
415 if (AttemptDrawBlurredPathSource(path, paint)) {
416 return;
417 }
418 }
419
420 Entity entity;
421 entity.SetTransform(GetCurrentTransform());
422 entity.SetBlendMode(paint.blend_mode);
423
424 if (paint.style == Paint::Style::kFill) {
425 FillPathGeometry geom(path);
426 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
427 } else {
428 StrokePathGeometry geom(path, paint.stroke);
429 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
430 }
431}

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

1110 {
1111 if (radius <= 0) {
1112 return;
1113 }
1114
1115 Entity entity;
1116 entity.SetTransform(GetCurrentTransform());
1117 entity.SetBlendMode(paint.blend_mode);
1118
1119 PointFieldGeometry geom(points, count, radius,
1120 /*round=*/point_style == PointStyle::kRound);
1121 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1122}
@ 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 811 of file canvas.cc.

811 {
812 if (IsShadowBlurDrawOperation(paint)) {
813 RRectBlurShape shape(rect, 0.0f);
814 if (AttemptDrawBlur(shape, paint)) {
815 return;
816 }
817 }
818
819 Entity entity;
820 entity.SetTransform(GetCurrentTransform());
821 entity.SetBlendMode(paint.blend_mode);
822
823 if (paint.style == Paint::Style::kStroke) {
824 StrokeRectGeometry geom(rect, paint.stroke);
825 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
826 } else {
827 FillRectGeometry geom(rect);
828 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
829 }
830}

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

925 {
926 if (IsShadowBlurDrawOperation(paint)) {
927 if (AttemptDrawBlurredRRect(round_rect, paint)) {
928 return;
929 }
930 }
931
932 if (round_rect.GetRadii().AreAllCornersSame() &&
933 paint.style == Paint::Style::kFill) {
934 Entity entity;
935 entity.SetTransform(GetCurrentTransform());
936 entity.SetBlendMode(paint.blend_mode);
937
938 RoundRectGeometry geom(round_rect.GetBounds(),
939 round_rect.GetRadii().top_left);
940 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
941 return;
942 }
943
944 Entity entity;
945 entity.SetTransform(GetCurrentTransform());
946 entity.SetBlendMode(paint.blend_mode);
947
948 if (paint.style == Paint::Style::kFill) {
949 FillRoundRectGeometry geom(round_rect);
950 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
951 } else {
952 StrokeRoundRectGeometry geom(round_rect, paint.stroke);
953 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
954 }
955}

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

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

◆ DrawRoundSuperellipse()

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

Definition at line 973 of file canvas.cc.

974 {
975 if (IsShadowBlurDrawOperation(paint)) {
976 if (AttemptDrawBlurredRSuperellipse(round_superellipse, paint)) {
977 return;
978 }
979 }
980
981 Entity entity;
982 entity.SetTransform(GetCurrentTransform());
983 entity.SetBlendMode(paint.blend_mode);
984
985 if (paint.style == Paint::Style::kFill) {
986 RoundSuperellipseGeometry geom(round_superellipse.GetBounds(),
987 round_superellipse.GetRadii());
988 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
989 } else {
990 StrokeRoundSuperellipseGeometry geom(round_superellipse, paint.stroke);
991 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
992 }
993}

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

1871 {
1873 if (max_scale * text_frame->GetFont().GetMetrics().point_size >
1874 kMaxTextScale) {
1875 fml::StatusOr<flutter::DlPath> path = text_frame->GetPath();
1876 if (path.ok()) {
1877 Save(1);
1879 DrawPath(path.value(), paint);
1880 Restore();
1881 return;
1882 }
1883 }
1884
1885 Entity entity;
1886 entity.SetClipDepth(GetClipHeight());
1887 entity.SetBlendMode(paint.blend_mode);
1888
1889 auto text_contents = std::make_shared<TextContents>();
1890 text_contents->SetTextFrame(text_frame);
1891 text_contents->SetForceTextColor(paint.mask_blur_descriptor.has_value());
1892 text_contents->SetScale(max_scale);
1893 text_contents->SetColor(paint.color);
1894 text_contents->SetOffset(position);
1895 text_contents->SetTextProperties(paint.color,
1896 paint.style == Paint::Style::kStroke
1897 ? std::optional(paint.stroke)
1898 : std::nullopt);
1899
1900 entity.SetTransform(GetCurrentTransform() *
1901 Matrix::MakeTranslation(position));
1902
1903 if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
1904 paint)) {
1905 return;
1906 }
1907
1908 entity.SetContents(paint.WithFilters(std::move(text_contents)));
1909 AddRenderEntityToCurrentPass(entity, false);
1910}
void Concat(const Matrix &transform)
Definition canvas.cc:342
void DrawPath(const flutter::DlPath &path, const Paint &paint)
Definition canvas.cc:413
void Save(uint32_t total_content_depth=kMaxDepth)
Definition canvas.cc:1385
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:1867
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 1203 of file canvas.cc.

1205 {
1206 // Override the blend mode with kDestination in order to match the behavior
1207 // of Skia's SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER flag, which
1208 // is enabled when the Flutter engine builds Skia.
1209 if (!paint.color_source) {
1210 blend_mode = BlendMode::kDst;
1211 }
1212
1213 Entity entity;
1214 entity.SetTransform(GetCurrentTransform());
1215 entity.SetBlendMode(paint.blend_mode);
1216
1217 // If there are no vertex colors.
1218 if (UseColorSourceContents(vertices, paint)) {
1219 AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
1220 return;
1221 }
1222
1223 // If the blend mode is destination don't bother to bind or create a texture.
1224 if (blend_mode == BlendMode::kDst) {
1225 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1226 contents->SetBlendMode(blend_mode);
1227 contents->SetAlpha(paint.color.alpha);
1228 contents->SetGeometry(vertices);
1229 entity.SetContents(paint.WithFilters(std::move(contents)));
1230 AddRenderEntityToCurrentPass(entity);
1231 return;
1232 }
1233
1234 // If there is a texture, use this directly. Otherwise render the color
1235 // source to a texture.
1236 if (paint.color_source &&
1237 paint.color_source->type() == flutter::DlColorSourceType::kImage) {
1238 const flutter::DlImageColorSource* image_color_source =
1239 paint.color_source->asImage();
1240 FML_DCHECK(image_color_source &&
1241 image_color_source->image()->impeller_texture());
1242 auto texture = image_color_source->image()->impeller_texture();
1243 auto x_tile_mode = static_cast<Entity::TileMode>(
1244 image_color_source->horizontal_tile_mode());
1245 auto y_tile_mode =
1246 static_cast<Entity::TileMode>(image_color_source->vertical_tile_mode());
1247 auto sampler_descriptor =
1248 skia_conversions::ToSamplerDescriptor(image_color_source->sampling());
1249 auto effect_transform = image_color_source->matrix();
1250
1251 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1252 contents->SetBlendMode(blend_mode);
1253 contents->SetAlpha(paint.color.alpha);
1254 contents->SetGeometry(vertices);
1255 contents->SetEffectTransform(effect_transform);
1256 contents->SetTexture(texture);
1257 contents->SetTileMode(x_tile_mode, y_tile_mode);
1258 contents->SetSamplerDescriptor(sampler_descriptor);
1259
1260 entity.SetContents(paint.WithFilters(std::move(contents)));
1261 AddRenderEntityToCurrentPass(entity);
1262 return;
1263 }
1264
1265 auto src_paint = paint;
1266 src_paint.color = paint.color.WithAlpha(1.0);
1267
1268 std::shared_ptr<ColorSourceContents> src_contents =
1269 src_paint.CreateContents();
1270 src_contents->SetGeometry(vertices.get());
1271
1272 // If the color source has an intrinsic size, then we use that to
1273 // create the src contents as a simplification. Otherwise we use
1274 // the extent of the texture coordinates to determine how large
1275 // the src contents should be. If neither has a value we fall back
1276 // to using the geometry coverage data.
1277 Rect src_coverage;
1278 auto size = src_contents->GetColorSourceSize();
1279 if (size.has_value()) {
1280 src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
1281 } else {
1282 auto cvg = vertices->GetCoverage(Matrix{});
1283 FML_CHECK(cvg.has_value());
1284 auto texture_coverage = vertices->GetTextureCoordinateCoverage();
1285 if (texture_coverage.has_value()) {
1286 src_coverage =
1287 Rect::MakeOriginSize(texture_coverage->GetOrigin(),
1288 texture_coverage->GetSize().Max({1, 1}));
1289 } else {
1290 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
1291 src_coverage = cvg.value();
1292 }
1293 }
1294 src_contents = src_paint.CreateContents();
1295
1296 clip_geometry_.push_back(Geometry::MakeRect(Rect::Round(src_coverage)));
1297 src_contents->SetGeometry(clip_geometry_.back().get());
1298
1299 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1300 contents->SetBlendMode(blend_mode);
1301 contents->SetAlpha(paint.color.alpha);
1302 contents->SetGeometry(vertices);
1303 contents->SetLazyTextureCoverage(src_coverage);
1304 contents->SetLazyTexture(
1305 [src_contents, src_coverage](const ContentContext& renderer) {
1306 // Applying the src coverage as the coverage limit prevents the 1px
1307 // coverage pad from adding a border that is picked up by developer
1308 // specified UVs.
1309 auto snapshot = src_contents->RenderToSnapshot(
1310 renderer, {}, {.coverage_limit = Rect::Round(src_coverage)});
1311 return snapshot.has_value() ? snapshot->texture : nullptr;
1312 });
1313 entity.SetContents(paint.WithFilters(std::move(contents)));
1314 AddRenderEntityToCurrentPass(entity);
1315}
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 MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
Definition rect.h:144
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 2291 of file canvas.cc.

2291 {
2292 FML_DCHECK(render_passes_.size() == 1u);
2293 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2294 render_passes_.back().GetInlinePassContext()->EndPass(
2295 /*is_onscreen=*/!requires_readback_ && is_onscreen_);
2296 backdrop_data_.clear();
2297
2298 // If requires_readback_ was true, then we rendered to an offscreen texture
2299 // instead of to the onscreen provided in the render target. Now we need to
2300 // draw or blit the offscreen back to the onscreen.
2301 if (requires_readback_) {
2302 BlitToOnscreen(/*is_onscreen_=*/is_onscreen_);
2303 }
2305 VALIDATION_LOG << "Failed to generate onscreen mipmaps.";
2306 }
2307 if (!renderer_.GetContext()->FlushCommandBuffers()) {
2308 // Not much we can do.
2309 VALIDATION_LOG << "Failed to submit command buffers";
2310 }
2311 render_passes_.clear();
2312 renderer_.GetRenderTargetCache()->End();
2313 clip_geometry_.clear();
2314
2315 Reset();
2316 Initialize(initial_cull_rect_);
2317}
bool EnsureFinalMipmapGeneration() const
Definition canvas.cc:2273
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 2273 of file canvas.cc.

2273 {
2274 if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
2275 return true;
2276 }
2277 std::shared_ptr<CommandBuffer> cmd_buffer =
2278 renderer_.GetContext()->CreateCommandBuffer();
2279 if (!cmd_buffer) {
2280 return false;
2281 }
2282 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
2283 if (!blit_pass) {
2284 return false;
2285 }
2286 blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
2287 blit_pass->EncodeCommands();
2288 return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
2289}
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 1402 of file canvas.cc.

1402 {
1403 if (!clip_coverage_stack_.HasCoverage()) {
1404 // The current clip is empty. This means the pass texture won't be
1405 // visible, so skip it.
1406 return std::nullopt;
1407 }
1408
1409 std::optional<Rect> maybe_current_clip_coverage =
1410 clip_coverage_stack_.CurrentClipCoverage();
1411 if (!maybe_current_clip_coverage.has_value()) {
1412 return std::nullopt;
1413 }
1414
1415 Rect current_clip_coverage = maybe_current_clip_coverage.value();
1416
1417 FML_CHECK(!render_passes_.empty());
1418 const LazyRenderingConfig& back_render_pass = render_passes_.back();
1419 std::shared_ptr<Texture> back_texture =
1420 back_render_pass.GetInlinePassContext()->GetTexture();
1421 FML_CHECK(back_texture) << "Context is valid:"
1422 << back_render_pass.GetInlinePassContext()->IsValid();
1423
1424 // The maximum coverage of the subpass. Subpasses textures should never
1425 // extend outside the parent pass texture or the current clip coverage.
1426 std::optional<Rect> maybe_coverage_limit =
1427 Rect::MakeOriginSize(GetGlobalPassPosition(),
1428 Size(back_texture->GetSize()))
1429 .Intersection(current_clip_coverage);
1430
1431 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
1432 return std::nullopt;
1433 }
1434
1435 return maybe_coverage_limit->Intersection(
1436 Rect::MakeSize(render_target_.GetRenderTargetSize()));
1437}
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 397 of file canvas.cc.

397 {
398 return transform_stack_.size();
399}

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

◆ PreConcat()

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

Definition at line 346 of file canvas.cc.

346 {
347 transform_stack_.back().transform = transform * GetCurrentTransform();
348}

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

350 {
351 transform_stack_.back().transform = {};
352}

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

◆ Restore()

bool impeller::Canvas::Restore ( )

Definition at line 1677 of file canvas.cc.

1677 {
1678 FML_DCHECK(transform_stack_.size() > 0);
1679 if (transform_stack_.size() == 1) {
1680 return false;
1681 }
1682
1683 // This check is important to make sure we didn't exceed the depth
1684 // that the clips were rendered at while rendering any of the
1685 // rendering ops. It is OK for the current depth to equal the
1686 // outgoing clip depth because that means the clipping would have
1687 // been successful up through the last rendering op, but it cannot
1688 // be greater.
1689 // Also, we bump the current rendering depth to the outgoing clip
1690 // depth so that future rendering operations are not clipped by
1691 // any of the pixels set by the expiring clips. It is OK for the
1692 // estimates used to determine the clip depth in save/saveLayer
1693 // to be overly conservative, but we need to jump the depth to
1694 // the clip depth so that the next rendering op will get a
1695 // larger depth (it will pre-increment the current_depth_ value).
1696 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1697 << current_depth_ << " <=? " << transform_stack_.back().clip_depth;
1698 current_depth_ = transform_stack_.back().clip_depth;
1699
1700 if (IsSkipping()) {
1701 transform_stack_.pop_back();
1702 return true;
1703 }
1704
1705 if (transform_stack_.back().rendering_mode ==
1707 transform_stack_.back().rendering_mode ==
1709 auto lazy_render_pass = std::move(render_passes_.back());
1710 render_passes_.pop_back();
1711 // Force the render pass to be constructed if it never was.
1712 lazy_render_pass.GetInlinePassContext()->GetRenderPass();
1713
1714 SaveLayerState save_layer_state = save_layer_state_.back();
1715 save_layer_state_.pop_back();
1716 auto global_pass_position = GetGlobalPassPosition();
1717
1718 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1719 save_layer_state.paint, //
1720 lazy_render_pass.GetInlinePassContext()->GetTexture(), //
1721 Matrix::MakeTranslation(Vector3{-global_pass_position}) * //
1722 transform_stack_.back().transform //
1723 );
1724
1725 lazy_render_pass.GetInlinePassContext()->EndPass();
1726
1727 // Round the subpass texture position for pixel alignment with the parent
1728 // pass render target. By default, we draw subpass textures with nearest
1729 // sampling, so aligning here is important for avoiding visual nearest
1730 // sampling errors caused by limited floating point precision when
1731 // straddling a half pixel boundary.
1732 Point subpass_texture_position;
1733 if (transform_stack_.back().did_round_out) {
1734 // Subpass coverage was rounded out, origin potentially moved "down" by
1735 // as much as a pixel.
1736 subpass_texture_position =
1737 (save_layer_state.coverage.GetOrigin() - global_pass_position)
1738 .Floor();
1739 } else {
1740 // Subpass coverage was truncated. Pick the closest phyiscal pixel.
1741 subpass_texture_position =
1742 (save_layer_state.coverage.GetOrigin() - global_pass_position)
1743 .Round();
1744 }
1745
1746 Entity element_entity;
1747 element_entity.SetClipDepth(++current_depth_);
1748 element_entity.SetContents(std::move(contents));
1749 element_entity.SetBlendMode(save_layer_state.paint.blend_mode);
1750 element_entity.SetTransform(
1751 Matrix::MakeTranslation(Vector3(subpass_texture_position)));
1752
1753 if (element_entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
1755 ApplyFramebufferBlend(element_entity);
1756 } else {
1757 // End the active pass and flush the buffer before rendering "advanced"
1758 // blends. Advanced blends work by binding the current render target
1759 // texture as an input ("destination"), blending with a second texture
1760 // input ("source"), writing the result to an intermediate texture, and
1761 // finally copying the data from the intermediate texture back to the
1762 // render target texture. And so all of the commands that have written
1763 // to the render target texture so far need to execute before it's bound
1764 // for blending (otherwise the blend pass will end up executing before
1765 // all the previous commands in the active pass).
1766 auto input_texture = FlipBackdrop(GetGlobalPassPosition());
1767 if (!input_texture) {
1768 return false;
1769 }
1770
1771 FilterInput::Vector inputs = {
1772 FilterInput::Make(input_texture,
1773 element_entity.GetTransform().Invert()),
1774 FilterInput::Make(element_entity.GetContents())};
1775 auto contents = ColorFilterContents::MakeBlend(
1776 element_entity.GetBlendMode(), inputs);
1777 contents->SetCoverageHint(element_entity.GetCoverage());
1778 element_entity.SetContents(std::move(contents));
1779 element_entity.SetBlendMode(BlendMode::kSrc);
1780 }
1781 }
1782
1783 element_entity.Render(
1784 renderer_, //
1785 *render_passes_.back().GetInlinePassContext()->GetRenderPass() //
1786 );
1787 clip_coverage_stack_.PopSubpass();
1788 transform_stack_.pop_back();
1789
1790 // We don't need to restore clips if a saveLayer was performed, as the clip
1791 // state is per render target, and no more rendering operations will be
1792 // performed as the render target workloaded is completed in the restore.
1793 return true;
1794 }
1795
1796 size_t num_clips = transform_stack_.back().num_clips;
1797 transform_stack_.pop_back();
1798
1799 if (num_clips > 0) {
1800 EntityPassClipStack::ClipStateResult clip_state_result =
1801 clip_coverage_stack_.RecordRestore(GetGlobalPassPosition(),
1802 GetClipHeight());
1803
1804 // Clip restores are never required with depth based clipping.
1805 FML_DCHECK(!clip_state_result.should_render);
1806 if (clip_state_result.clip_did_change) {
1807 // We only need to update the pass scissor if the clip state has changed.
1808 SetClipScissor(
1809 clip_coverage_stack_.CurrentClipCoverage(), //
1810 *render_passes_.back().GetInlinePassContext()->GetRenderPass(), //
1811 GetGlobalPassPosition() //
1812 );
1813 }
1814 }
1815
1816 return true;
1817}
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:425

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

405 {
406 while (GetSaveCount() > count) {
407 if (!Restore()) {
408 return;
409 }
410 }
411}
size_t GetSaveCount() const
Definition canvas.cc:397

References GetSaveCount(), and Restore().

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

◆ Rotate()

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

Definition at line 378 of file canvas.cc.

378 {
380}
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 1385 of file canvas.cc.

1385 {
1386 if (IsSkipping()) {
1387 return SkipUntilMatchingRestore(total_content_depth);
1388 }
1389
1390 auto entry = CanvasStackEntry{};
1391 entry.transform = transform_stack_.back().transform;
1392 entry.clip_depth = current_depth_ + total_content_depth;
1393 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
1394 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1395 << entry.clip_depth << " <=? " << transform_stack_.back().clip_depth
1396 << " after allocating " << total_content_depth;
1397 entry.clip_height = transform_stack_.back().clip_height;
1398 entry.rendering_mode = Entity::RenderingMode::kDirect;
1399 transform_stack_.push_back(entry);
1400}

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

1445 {
1446 TRACE_EVENT0("flutter", "Canvas::saveLayer");
1447 if (IsSkipping()) {
1448 return SkipUntilMatchingRestore(total_content_depth);
1449 }
1450
1451 auto maybe_coverage_limit = GetLocalCoverageLimit();
1452 if (!maybe_coverage_limit.has_value()) {
1453 return SkipUntilMatchingRestore(total_content_depth);
1454 }
1455 auto coverage_limit = maybe_coverage_limit.value();
1456
1457 if (can_distribute_opacity && !backdrop_filter &&
1459 bounds_promise != ContentBoundsPromise::kMayClipContents) {
1460 Save(total_content_depth);
1461 transform_stack_.back().distributed_opacity *= paint.color.alpha;
1462 return;
1463 }
1464
1465 std::shared_ptr<FilterContents> filter_contents = paint.WithImageFilter(
1466 Rect(), transform_stack_.back().transform,
1468
1469 std::optional<Rect> maybe_subpass_coverage = ComputeSaveLayerCoverage(
1470 bounds.value_or(Rect::MakeMaximum()),
1471 transform_stack_.back().transform, //
1472 coverage_limit, //
1473 filter_contents, //
1474 /*flood_output_coverage=*/
1475 Entity::IsBlendModeDestructive(paint.blend_mode), //
1476 /*flood_input_coverage=*/!!backdrop_filter ||
1477 (paint.color_filter &&
1478 paint.color_filter->modifies_transparent_black()) //
1479 );
1480
1481 if (!maybe_subpass_coverage.has_value()) {
1482 return SkipUntilMatchingRestore(total_content_depth);
1483 }
1484
1485 auto subpass_coverage = maybe_subpass_coverage.value();
1486
1487 // When an image filter is present, clamp to avoid flicking due to nearest
1488 // sampled image. For other cases, round out to ensure than any geometry is
1489 // not cut off.
1490 //
1491 // See also this bug: https://github.com/flutter/flutter/issues/144213
1492 //
1493 // TODO(jonahwilliams): this could still round out for filters that use decal
1494 // sampling mode.
1496 bool did_round_out = false;
1497 Point coverage_origin_adjustment = Point{0, 0};
1498 if (paint.image_filter) {
1499 subpass_size = ISize(subpass_coverage.GetSize());
1500 } else {
1501 did_round_out = true;
1502 subpass_size =
1503 static_cast<ISize>(IRect::RoundOut(subpass_coverage).GetSize());
1504 // If rounding out, adjust the coverage to account for the subpixel shift.
1505 coverage_origin_adjustment =
1506 Point(subpass_coverage.GetLeftTop().x -
1507 std::floor(subpass_coverage.GetLeftTop().x),
1508 subpass_coverage.GetLeftTop().y -
1509 std::floor(subpass_coverage.GetLeftTop().y));
1510 }
1511 if (subpass_size.IsEmpty()) {
1512 return SkipUntilMatchingRestore(total_content_depth);
1513 }
1514
1515 // When there are scaling filters present, these contents may exceed the
1516 // maximum texture size. Perform a clamp here, which may cause rendering
1517 // artifacts.
1518 subpass_size = subpass_size.Min(renderer_.GetContext()
1519 ->GetCapabilities()
1520 ->GetMaximumRenderPassAttachmentSize());
1521
1522 // Backdrop filter state, ignored if there is no BDF.
1523 std::shared_ptr<FilterContents> backdrop_filter_contents;
1524 Point local_position = Point(0, 0);
1525 if (backdrop_filter) {
1526 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1527 Canvas::BackdropFilterProc backdrop_filter_proc =
1528 [backdrop_filter = backdrop_filter](
1529 const FilterInput::Ref& input, const Matrix& effect_transform,
1530 Entity::RenderingMode rendering_mode) {
1531 auto filter = WrapInput(backdrop_filter, input);
1532 filter->SetEffectTransform(effect_transform);
1533 filter->SetRenderingMode(rendering_mode);
1534 return filter;
1535 };
1536
1537 std::shared_ptr<Texture> input_texture;
1538
1539 // If the backdrop ID is not nullopt and there is more than one usage
1540 // of it in the current scene, cache the backdrop texture and remove it from
1541 // the current entity pass flip.
1542 bool will_cache_backdrop_texture = false;
1543 BackdropData* backdrop_data = nullptr;
1544 // If we've reached this point, there is at least one backdrop filter. But
1545 // potentially more if there is a backdrop id. We may conditionally set this
1546 // to a higher value in the if block below.
1547 size_t backdrop_count = 1;
1548 if (backdrop_id.has_value()) {
1549 std::unordered_map<int64_t, BackdropData>::iterator backdrop_data_it =
1550 backdrop_data_.find(backdrop_id.value());
1551 if (backdrop_data_it != backdrop_data_.end()) {
1552 backdrop_data = &backdrop_data_it->second;
1553 will_cache_backdrop_texture =
1554 backdrop_data_it->second.backdrop_count > 1;
1555 backdrop_count = backdrop_data_it->second.backdrop_count;
1556 }
1557 }
1558
1559 if (!will_cache_backdrop_texture || !backdrop_data->texture_slot) {
1560 backdrop_count_ -= backdrop_count;
1561
1562 // The onscreen texture can be flipped to if:
1563 // 1. The device supports framebuffer fetch
1564 // 2. There are no more backdrop filters
1565 // 3. The current render pass is for the onscreen pass.
1566 const bool should_use_onscreen =
1568 backdrop_count_ == 0 && render_passes_.size() == 1u;
1569 input_texture = FlipBackdrop(
1570 GetGlobalPassPosition(), //
1571 /*should_remove_texture=*/will_cache_backdrop_texture, //
1572 /*should_use_onscreen=*/should_use_onscreen //
1573 );
1574 if (!input_texture) {
1575 // Validation failures are logged in FlipBackdrop.
1576 return;
1577 }
1578
1579 if (will_cache_backdrop_texture) {
1580 backdrop_data->texture_slot = input_texture;
1581 }
1582 } else {
1583 input_texture = backdrop_data->texture_slot;
1584 }
1585
1586 backdrop_filter_contents = backdrop_filter_proc(
1587 FilterInput::Make(std::move(input_texture)),
1588 transform_stack_.back().transform.Basis(),
1589 // When the subpass has a translation that means the math with
1590 // the snapshot has to be different.
1591 transform_stack_.back().transform.HasTranslation()
1593 : Entity::RenderingMode::kSubpassAppendSnapshotTransform);
1594
1595 if (will_cache_backdrop_texture) {
1596 FML_DCHECK(backdrop_data);
1597 // If all filters on the shared backdrop layer are equal, process the
1598 // layer once.
1599 if (backdrop_data->all_filters_equal &&
1600 !backdrop_data->shared_filter_snapshot.has_value()) {
1601 // TODO(157110): compute minimum input hint.
1602 backdrop_data->shared_filter_snapshot =
1603 backdrop_filter_contents->RenderToSnapshot(renderer_, {}, {});
1604 }
1605
1606 std::optional<Snapshot> maybe_snapshot =
1607 backdrop_data->shared_filter_snapshot;
1608 if (maybe_snapshot.has_value()) {
1609 const Snapshot& snapshot = maybe_snapshot.value();
1610 std::shared_ptr<TextureContents> contents = TextureContents::MakeRect(
1611 subpass_coverage.Shift(-GetGlobalPassPosition()));
1612 auto scaled =
1613 subpass_coverage.TransformBounds(snapshot.transform.Invert());
1614 contents->SetTexture(snapshot.texture);
1615 contents->SetSourceRect(scaled);
1616 contents->SetSamplerDescriptor(snapshot.sampler_descriptor);
1617
1618 // This backdrop entity sets a depth value as it is written to the newly
1619 // flipped backdrop and not into a new saveLayer.
1620 Entity backdrop_entity;
1621 backdrop_entity.SetContents(std::move(contents));
1622 backdrop_entity.SetClipDepth(++current_depth_);
1623 backdrop_entity.SetBlendMode(paint.blend_mode);
1624
1625 backdrop_entity.Render(renderer_, GetCurrentRenderPass());
1626 Save(0);
1627 return;
1628 }
1629 }
1630 }
1631
1632 // When applying a save layer, absorb any pending distributed opacity.
1633 Paint paint_copy = paint;
1634 paint_copy.color.alpha *= transform_stack_.back().distributed_opacity;
1635 transform_stack_.back().distributed_opacity = 1.0;
1636
1637 render_passes_.push_back(
1638 LazyRenderingConfig(renderer_, //
1639 CreateRenderTarget(renderer_, //
1640 subpass_size, //
1642 )));
1643 save_layer_state_.push_back(SaveLayerState{
1644 paint_copy, subpass_coverage.Shift(-coverage_origin_adjustment)});
1645
1646 CanvasStackEntry entry;
1647 entry.transform = transform_stack_.back().transform;
1648 entry.clip_depth = current_depth_ + total_content_depth;
1649 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1650 << entry.clip_depth << " <=? " << transform_stack_.back().clip_depth
1651 << " after allocating " << total_content_depth;
1652 entry.clip_height = transform_stack_.back().clip_height;
1654 entry.did_round_out = did_round_out;
1655 transform_stack_.emplace_back(entry);
1656
1657 // Start non-collapsed subpasses with a fresh clip coverage stack limited by
1658 // the subpass coverage. This is important because image filters applied to
1659 // save layers may transform the subpass texture after it's rendered,
1660 // causing parent clip coverage to get misaligned with the actual area that
1661 // the subpass will affect in the parent pass.
1662 clip_coverage_stack_.PushSubpass(subpass_coverage, GetClipHeight());
1663
1664 if (!backdrop_filter_contents) {
1665 return;
1666 }
1667
1668 // Render the backdrop entity.
1669 Entity backdrop_entity;
1670 backdrop_entity.SetContents(std::move(backdrop_filter_contents));
1671 backdrop_entity.SetTransform(
1672 Matrix::MakeTranslation(Vector3(-local_position)));
1673 backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
1674 backdrop_entity.Render(renderer_, GetCurrentRenderPass());
1675}
std::optional< Rect > GetLocalCoverageLimit() const
Return the culling bounds of the current render target, or nullopt if there is no coverage.
Definition canvas.cc:1402
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:128
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 366 of file canvas.cc.

366 {
368}
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 370 of file canvas.cc.

370 {
372}

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

2094 {
2095 backdrop_data_ = std::move(backdrop_data);
2096 backdrop_count_ = backdrop_count;
2097}

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

◆ Skew()

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

Definition at line 374 of file canvas.cc.

374 {
375 Concat(Matrix::MakeSkew(sx, sy));
376}
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 2215 of file canvas.cc.

2215 {
2216 return renderer_.GetContext()
2217 ->GetCapabilities()
2218 ->SupportsTextureToTextureBlits() &&
2219 renderer_.GetContext()->GetBackendType() ==
2221}

◆ Transform()

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

◆ Translate()

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

Definition at line 362 of file canvas.cc.

362 {
364}

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: