Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
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 858 of file canvas.cc.

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

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

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

833 {
834 Size half_size(radius, radius);
835 if (AttemptDrawBlurredRRect(
836 Rect::MakeOriginSize(center - half_size, half_size * 2),
837 {radius, radius}, paint)) {
838 return;
839 }
840
841 if (AttemptDrawAntialiasedCircle(center, radius, paint)) {
842 return;
843 }
844
845 Entity entity;
846 entity.SetTransform(GetCurrentTransform());
847 entity.SetBlendMode(paint.blend_mode);
848
849 if (paint.style == Paint::Style::kStroke) {
850 CircleGeometry geom(center, radius, paint.stroke.width);
851 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
852 } else {
853 CircleGeometry geom(center, radius);
854 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
855 }
856}
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 793 of file canvas.cc.

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

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

961 {
962 if (!image) {
963 return;
964 }
965
966 const Rect source = Rect::MakeSize(image->GetSize());
967 const Rect dest = source.Shift(offset);
968
969 DrawImageRect(image, source, dest, paint, sampler);
970}
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:972
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 972 of file canvas.cc.

977 {
978 if (!image || source.IsEmpty() || dest.IsEmpty()) {
979 return;
980 }
981
982 ISize size = image->GetSize();
983 if (size.IsEmpty()) {
984 return;
985 }
986
987 std::optional<Rect> clipped_source =
988 source.Intersection(Rect::MakeSize(size));
989 if (!clipped_source) {
990 return;
991 }
992
993 if (AttemptColorFilterOptimization(image, source, dest, paint, sampler,
994 src_rect_constraint)) {
995 return;
996 }
997
998 if (*clipped_source != source) {
999 Scalar sx = dest.GetWidth() / source.GetWidth();
1000 Scalar sy = dest.GetHeight() / source.GetHeight();
1001 Scalar tx = dest.GetLeft() - source.GetLeft() * sx;
1002 Scalar ty = dest.GetTop() - source.GetTop() * sy;
1003 Matrix src_to_dest = Matrix::MakeTranslateScale({sx, sy, 1}, {tx, ty, 0});
1004 dest = clipped_source->TransformBounds(src_to_dest);
1005 }
1006
1007 auto texture_contents = TextureContents::MakeRect(dest);
1008 texture_contents->SetTexture(image);
1009 texture_contents->SetSourceRect(*clipped_source);
1010 texture_contents->SetStrictSourceRect(src_rect_constraint ==
1012 texture_contents->SetSamplerDescriptor(sampler);
1013 texture_contents->SetOpacity(paint.color.alpha);
1014 texture_contents->SetDeferApplyingOpacity(paint.HasColorFilter());
1015
1016 Entity entity;
1017 entity.SetBlendMode(paint.blend_mode);
1018 entity.SetTransform(GetCurrentTransform());
1019
1020 if (!paint.mask_blur_descriptor.has_value()) {
1021 entity.SetContents(paint.WithFilters(std::move(texture_contents)));
1022 AddRenderEntityToCurrentPass(entity);
1023 return;
1024 }
1025
1026 FillRectGeometry out_rect(Rect{});
1027
1028 entity.SetContents(paint.WithFilters(
1029 paint.mask_blur_descriptor->CreateMaskBlur(texture_contents, &out_rect)));
1030 AddRenderEntityToCurrentPass(entity);
1031}
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:831

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

944 {
945 if (radius <= 0) {
946 return;
947 }
948
949 Entity entity;
950 entity.SetTransform(GetCurrentTransform());
951 entity.SetBlendMode(paint.blend_mode);
952
953 PointFieldGeometry geom(points, count, radius,
954 /*round=*/point_style == PointStyle::kRound);
955 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
956}
@ 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 761 of file canvas.cc.

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

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

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

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

1703 {
1705 if (max_scale * text_frame->GetFont().GetMetrics().point_size >
1706 kMaxTextScale) {
1707 fml::StatusOr<flutter::DlPath> path = text_frame->GetPath();
1708 if (path.ok()) {
1709 Save(1);
1711 DrawPath(path.value(), paint);
1712 Restore();
1713 return;
1714 }
1715 }
1716
1717 Entity entity;
1718 entity.SetClipDepth(GetClipHeight());
1719 entity.SetBlendMode(paint.blend_mode);
1720
1721 auto text_contents = std::make_shared<TextContents>();
1722 text_contents->SetTextFrame(text_frame);
1723 text_contents->SetForceTextColor(paint.mask_blur_descriptor.has_value());
1724 text_contents->SetScale(max_scale);
1725 text_contents->SetColor(paint.color);
1726 text_contents->SetOffset(position);
1727 text_contents->SetTextProperties(paint.color,
1728 paint.style == Paint::Style::kStroke
1729 ? std::optional(paint.stroke)
1730 : std::nullopt);
1731
1732 entity.SetTransform(GetCurrentTransform() *
1733 Matrix::MakeTranslation(position));
1734
1735 if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
1736 paint)) {
1737 return;
1738 }
1739
1740 entity.SetContents(paint.WithFilters(std::move(text_contents)));
1741 AddRenderEntityToCurrentPass(entity, false);
1742}
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:1217
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:1699
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 1037 of file canvas.cc.

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

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

2105 {
2106 if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
2107 return true;
2108 }
2109 std::shared_ptr<CommandBuffer> cmd_buffer =
2110 renderer_.GetContext()->CreateCommandBuffer();
2111 if (!cmd_buffer) {
2112 return false;
2113 }
2114 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
2115 if (!blit_pass) {
2116 return false;
2117 }
2118 blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
2119 blit_pass->EncodeCommands();
2120 return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
2121}
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 1234 of file canvas.cc.

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

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

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

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

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

1926 {
1927 backdrop_data_ = std::move(backdrop_data);
1928 backdrop_count_ = backdrop_count;
1929}

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

2047 {
2048 return renderer_.GetContext()
2049 ->GetCapabilities()
2050 ->SupportsTextureToTextureBlits() &&
2051 renderer_.GetContext()->GetBackendType() ==
2053}

◆ 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: