| Flutter Impeller |

Public Member Functions | List of all members
impeller::AtlasContents Class Referencefinal

`#include <atlas_contents.h>`

Inheritance diagram for impeller::AtlasContents:

## Public Member Functions
| AtlasContents ()
| ~AtlasContents () override
void | SetTexture (std::shared_ptr< Texture > texture)
std::shared_ptr< Texture > | GetTexture () const
void | SetTransforms (std::vector< Matrix > transforms)
void | SetBlendMode (BlendMode blend_mode)
void | SetTextureCoordinates (std::vector< Rect > texture_coords)
void | SetColors (std::vector< Color > colors)
void | SetCullRect (std::optional< Rect > cull_rect)
void | SetSamplerDescriptor (SamplerDescriptor desc)
void | SetAlpha (Scalar alpha)
const SamplerDescriptor & | GetSamplerDescriptor () const
const std::vector< Matrix > & | GetTransforms () const
const std::vector< Rect > & | GetTextureCoordinates () const
const std::vector< Color > & | GetColors () const
std::shared_ptr< SubAtlasResult > | GenerateSubAtlas () const
| Compress a drawAtlas call with blending into a smaller sized atlas. This atlas has no overlapping to ensure blending behaves as if it were done in the fragment shader. More...
std::optional< Rect > | GetCoverage (const Entity &entity) const override
| Get the area of the render pass that will be affected when this contents is rendered. More...
bool | Render (const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Public Member Functions inherited from impeller::Contents
| Contents ()
virtual | ~Contents ()
virtual void | PopulateGlyphAtlas (const std::shared_ptr< LazyGlyphAtlas > &lazy_glyph_atlas, Scalar scale)
| Add any text data to the specified lazy atlas. The scale parameter must be used again later when drawing the text. More...
void | SetCoverageHint (std::optional< Rect > coverage_hint)
| Hint that specifies the coverage area of this Contents that will actually be used during rendering. This is for optimization purposes only and can not be relied on as a clip. May optionally affect the result of `GetCoverage()`. More...
const std::optional< Rect > & | GetCoverageHint () const
virtual bool | IsOpaque () const
| Whether this Contents only emits opaque source colors from the fragment stage. This value does not account for any entity properties (e.g. the blend mode), clips/visibility culling, or inherited opacity. More...
virtual ClipCoverage | GetClipCoverage (const Entity &entity, const std::optional< Rect > &current_clip_coverage) const
| Given the current pass space bounding rectangle of the clip buffer, return the expected clip coverage after this draw call. This should only be implemented for contents that may write to the clip buffer. More...
virtual std::optional< Snapshot > | RenderToSnapshot (const ContentContext &renderer, const Entity &entity, std::optional< Rect > coverage_limit=std::nullopt, const std::optional< SamplerDescriptor > &sampler_descriptor=std::nullopt, bool msaa_enabled=true, int32_t mip_count=1, const std::string &label="Snapshot") const
| Render this contents to a snapshot, respecting the entity's transform, path, clip depth, and blend mode. The result texture size is always the size of `GetCoverage(entity)`. More...
virtual bool | ShouldRender (const Entity &entity, const std::optional< Rect > clip_coverage) const
std::optional< Size > | GetColorSourceSize () const
| Return the color source's intrinsic size, if available. More...
void | SetColorSourceSize (Size size)
virtual bool | CanInheritOpacity (const Entity &entity) const
| Whether or not this contents can accept the opacity peephole optimization. More...
virtual void | SetInheritedOpacity (Scalar opacity)
| Inherit the provided opacity. More...
virtual std::optional< Color > | AsBackgroundColor (const Entity &entity, ISize target_size) const
| Returns a color if this Contents will flood the given `target_size` with a color. This output color is the "Source" color that will be used for the Entity's blend operation. More...
virtual const FilterContents * | AsFilter () const
| Cast to a filter. Returns `nullptr` if this Contents is not a filter. More...
virtual bool | ApplyColorFilter (const ColorFilterProc &color_filter_proc)
| If possible, applies a color filter to this contents inputs on the CPU. More...

## Additional Inherited Members
Public Types inherited from impeller::Contents
using | ColorFilterProc = std::function< Color(Color)>
using | RenderProc = std::function< bool(const ContentContext &renderer, const Entity &entity, RenderPass &pass)>
using | CoverageProc = std::function< std::optional< Rect >(const Entity &entity)>
Static Public Member Functions inherited from impeller::Contents
static std::shared_ptr< Contents > | MakeAnonymous (RenderProc render_proc, CoverageProc coverage_proc)

## Detailed Description

Definition at line 33 of file atlas_contents.h.

## Constructor & Destructor Documentation

## ◆ AtlasContents()

impeller::AtlasContents::AtlasContents | ( |  | ) |
| explicit default

## ◆ ~AtlasContents()

impeller::AtlasContents::~AtlasContents | ( |  | ) |
| override default

## Member Function Documentation

## ◆ GenerateSubAtlas()

std::shared_ptr< SubAtlasResult > impeller::AtlasContents::GenerateSubAtlas | ( |  | ) | const

Compress a drawAtlas call with blending into a smaller sized atlas. This atlas has no overlapping to ensure blending behaves as if it were done in the fragment shader.

Definition at line 83 of file atlas_contents.cc.

83 {
84 FML_DCHECK(colors_.size() > 0 && blend_mode_ != BlendMode::kSource &&
85 blend_mode_ != BlendMode::kDestination);
86
87 std::unordered_map<AtlasBlenderKey, std::vector<Matrix>,
88 AtlasBlenderKey::Hash, AtlasBlenderKey::Equal>
89 sub_atlas = {};
90
91 for (auto i = 0u; i < texture_coords_.size(); i++) {
92 AtlasBlenderKey key = {.color = colors_[i],
93 .rect = texture_coords_[i],
94 .color_key = Color::ToIColor(colors_[i])};
95 if (sub_atlas.find(key) == sub_atlas.end()) {
96 sub_atlas[key] = {transforms_[i]};
97 } else {
98 sub_atlas[key].push_back(transforms_[i]);
99 }
100 }
101
102 auto result = std::make_shared<SubAtlasResult>();
103 Scalar x_offset = 0.0;
104 Scalar y_offset = 0.0;
105 Scalar x_extent = 0.0;
106 Scalar y_extent = 0.0;
107
108 for (auto it = sub_atlas.begin(); it != sub_atlas.end(); it++) {
109 // This size was arbitrarily chosen to keep the textures from getting too
110 // wide. We could instead use a more generic rect packer but in the majority
111 // of cases the sample rects will be fairly close in size making this a good
112 // enough approximation.
113 if (x_offset >= 1000) {
114 y_offset = y_extent + 1;
115 x_offset = 0.0;
116 }
117
118 auto key = it->first;
119 auto transforms = it->second;
120
121 auto new_rect = Rect::MakeXYWH(x_offset, y_offset, key.rect.GetWidth(),
122 key.rect.GetHeight());
123 auto sub_transform = Matrix::MakeTranslation(Vector2(x_offset, y_offset));
124
125 x_offset += std::ceil(key.rect.GetWidth()) + 1.0;
126
127 result->sub_texture_coords.push_back(key.rect);
128 result->sub_colors.push_back(key.color);
129 result->sub_transforms.push_back(sub_transform);
130
131 x_extent = std::max(x_extent, x_offset);
132 y_extent = std::max(y_extent, std::ceil(y_offset + key.rect.GetHeight()));
133
134 for (auto transform : transforms) {
135 result->result_texture_coords.push_back(new_rect);
136 result->result_transforms.push_back(transform);
137 }
138 }
139 result->size = ISize(std::ceil(x_extent), std::ceil(y_extent));
140 return result;
141 }

References impeller::AtlasBlenderKey::color, impeller::kDestination, impeller::kSource, impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Color::ToIColor().

Referenced by Render().

## ◆ GetColors()

const std::vector< Color > & impeller::AtlasContents::GetColors | ( |  | ) | const

Definition at line 181 of file atlas_contents.cc.

181 {
182 return colors_;
183 }

Referenced by impeller::AtlasColorContents::Render().

## ◆ GetCoverage()

std::optional< Rect > impeller::AtlasContents::GetCoverage | ( | const Entity & | entity | ) | const
| override virtual

Get the area of the render pass that will be affected when this contents is rendered.

During rendering, coverage coordinates count pixels from the top left corner of the framebuffer.

Returns
  The coverage rectangle. An `std::nullopt` result means that rendering this contents has no effect on the output color.

Implements impeller::Contents.

Definition at line 143 of file atlas_contents.cc.

143 {
144 if (cull_rect_.has_value()) {
145 return cull_rect_.value().TransformBounds(entity.GetTransform());
146 }
147 return ComputeBoundingBox().TransformBounds(entity.GetTransform());
148 }

References impeller::Entity::GetTransform(), and impeller::TRect< T >::TransformBounds().

## ◆ GetSamplerDescriptor()

const SamplerDescriptor & impeller::AtlasContents::GetSamplerDescriptor | ( |  | ) | const

Definition at line 169 of file atlas_contents.cc.

169 {
170 return sampler_descriptor_;
171 }

Referenced by impeller::AtlasTextureContents::Render().

## ◆ GetTexture()

std::shared_ptr< Texture > impeller::AtlasContents::GetTexture | ( |  | ) | const

Definition at line 32 of file atlas_contents.cc.

32 {
33 return texture_;
34 }

Referenced by impeller::AtlasTextureContents::Render().

## ◆ GetTextureCoordinates()

const std::vector< Rect > & impeller::AtlasContents::GetTextureCoordinates | ( |  | ) | const

Definition at line 177 of file atlas_contents.cc.

177 {
178 return texture_coords_;
179 }

Referenced by impeller::AtlasTextureContents::Render(), and impeller::AtlasColorContents::Render().

## ◆ GetTransforms()

const std::vector< Matrix > & impeller::AtlasContents::GetTransforms | ( |  | ) | const

Definition at line 173 of file atlas_contents.cc.

173 {
174 return transforms_;
175 }

Referenced by impeller::AtlasTextureContents::Render(), and impeller::AtlasColorContents::Render().

## ◆ Render()

bool impeller::AtlasContents::Render | ( | const ContentContext & | renderer,
|  | const Entity & | entity,
|  | RenderPass & | pass
| ) |  | const
| override virtual

Implements impeller::Contents.

Definition at line 185 of file atlas_contents.cc.

187 {
188 if (texture_ == nullptr || blend_mode_ == BlendMode::kClear ||
189 alpha_ <= 0.0) {
190 return true;
191 }
192
193 // Ensure that we use the actual computed bounds and not a cull-rect
194 // approximation of them.
195 auto coverage = ComputeBoundingBox();
196
197 if (blend_mode_ == BlendMode::kSource || colors_.size() == 0) {
198 auto child_contents = AtlasTextureContents(*this);
199 child_contents.SetAlpha(alpha_);
200 child_contents.SetCoverage(coverage);
201 return child_contents.Render(renderer, entity, pass);
202 }
203 if (blend_mode_ == BlendMode::kDestination) {
204 auto child_contents = AtlasColorContents(*this);
205 child_contents.SetAlpha(alpha_);
206 child_contents.SetCoverage(coverage);
207 return child_contents.Render(renderer, entity, pass);
208 }
209
210 constexpr size_t indices[6] = {0, 1, 2, 1, 2, 3};
211
212 if (blend_mode_ <= BlendMode::kModulate) {
213 // Simple Porter-Duff blends can be accomplished without a subpass.
214 using VS = PorterDuffBlendPipeline::VertexShader;
215 using FS = PorterDuffBlendPipeline::FragmentShader;
216
217 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
218 vtx_builder.Reserve(texture_coords_.size() * 6);
219 const auto texture_size = texture_->GetSize();
220 auto& host_buffer = renderer.GetTransientsBuffer();
221
222 for (size_t i = 0; i < texture_coords_.size(); i++) {
223 auto sample_rect = texture_coords_[i];
224 auto matrix = transforms_[i];
225 auto points = sample_rect.GetPoints();
226 auto transformed_points =
227 Rect::MakeSize(sample_rect.GetSize()).GetTransformedPoints(matrix);
228 auto color = colors_[i].Premultiply();
229 for (size_t j = 0; j < 6; j++) {
230 VS::PerVertexData data;
231 data.vertices = transformed_points[indices[j]];
232 data.texture_coords = points[indices[j]] / texture_size;
233 data.color = color;
234 vtx_builder.AppendVertex(data);
235 }
236 }
237
238 #ifdef IMPELLER_DEBUG
239 pass.SetCommandLabel(
240 SPrintF("DrawAtlas Blend (%s)", BlendModeToString(blend_mode_)));
241 #endif // IMPELLER_DEBUG
242 pass.SetVertexBuffer(vtx_builder.CreateVertexBuffer(host_buffer));
243 pass.SetStencilReference(entity.GetClipDepth());
244 pass.SetPipeline(
245 renderer.GetPorterDuffBlendPipeline(OptionsFromPass(pass)));
246
247 FS::FragInfo frag_info;
248 VS::FrameInfo frame_info;
249
250 auto dst_sampler_descriptor = sampler_descriptor_;
251 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
252 dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
253 dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
254 }
255 const std::unique_ptr<const Sampler>& dst_sampler =
256 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
257 dst_sampler_descriptor);
258 FS::BindTextureSamplerDst(pass, texture_, dst_sampler);
259 frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
260
261 frag_info.output_alpha = alpha_;
262 frag_info.input_alpha = 1.0;
263
264 auto inverted_blend_mode =
265 InvertPorterDuffBlend(blend_mode_).value_or(BlendMode::kSource);
266 auto blend_coefficients =
267 kPorterDuffCoefficients[static_cast<int>(inverted_blend_mode)];
268 frag_info.src_coeff = blend_coefficients[0];
269 frag_info.src_coeff_dst_alpha = blend_coefficients[1];
270 frag_info.dst_coeff = blend_coefficients[2];
271 frag_info.dst_coeff_src_alpha = blend_coefficients[3];
272 frag_info.dst_coeff_src_color = blend_coefficients[4];
273
274 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
275
276 frame_info.mvp = entity.GetShaderTransform(pass);
277
278 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
279 VS::BindFrameInfo(pass, uniform_view);
280
281 return pass.Draw().ok();
282 }
283
284 // Advanced blends.
285
286 auto sub_atlas = GenerateSubAtlas();
287 auto sub_coverage = Rect::MakeSize(sub_atlas->size);
288
289 auto src_contents = std::make_shared<AtlasTextureContents>(*this);
290 src_contents->SetSubAtlas(sub_atlas);
291 src_contents->SetCoverage(sub_coverage);
292
293 auto dst_contents = std::make_shared<AtlasColorContents>(*this);
294 dst_contents->SetSubAtlas(sub_atlas);
295 dst_contents->SetCoverage(sub_coverage);
296
297 Entity untransformed_entity;
298 auto contents = ColorFilterContents::MakeBlend(
299 blend_mode_,
300 {FilterInput::Make(dst_contents), FilterInput::Make(src_contents)});
301 auto snapshot =
302 contents->RenderToSnapshot(renderer, // renderer
303 untransformed_entity, // entity
304 std::nullopt, // coverage_limit
305 std::nullopt, // sampler_descriptor
306 true, // msaa_enabled
307 /*mip_count=*/1,
308 "AtlasContents Snapshot"); // label
309 if (!snapshot.has_value()) {
310 return false;
311 }
312
313 auto child_contents = AtlasTextureContents(*this);
314 child_contents.SetAlpha(alpha_);
315 child_contents.SetCoverage(coverage);
316 child_contents.SetTexture(snapshot.value().texture);
317 child_contents.SetUseDestination(true);
318 child_contents.SetSubAtlas(sub_atlas);
319 return child_contents.Render(renderer, entity, pass);
320 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendVertex(), impeller::BlendModeToString(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::RenderPass::Draw(), GenerateSubAtlas(), impeller::Entity::GetClipDepth(), impeller::ContentContext::GetContext(), impeller::ContentContext::GetDeviceCapabilities(), impeller::ContentContext::GetPorterDuffBlendPipeline(), impeller::Entity::GetShaderTransform(), impeller::TRect< T >::GetTransformedPoints(), impeller::ContentContext::GetTransientsBuffer(), impeller::InvertPorterDuffBlend(), impeller::kClear, impeller::kDecal, impeller::kDestination, impeller::kModulate, impeller::kPorterDuffCoefficients, impeller::kSource, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeSize(), impeller::OptionsFromPass(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::Reserve(), impeller::RenderPass::SetCommandLabel(), impeller::RenderPass::SetPipeline(), impeller::RenderPass::SetStencilReference(), impeller::RenderPass::SetVertexBuffer(), impeller::SPrintF(), impeller::Capabilities::SupportsDecalSamplerAddressMode(), and impeller::SamplerDescriptor::width_address_mode.

## ◆ SetAlpha()

void impeller::AtlasContents::SetAlpha | ( | Scalar | alpha | ) |

Definition at line 50 of file atlas_contents.cc.

50 {
51 alpha_ = alpha;
52 }

## ◆ SetBlendMode()

void impeller::AtlasContents::SetBlendMode | ( | BlendMode | blend_mode | ) |

Definition at line 54 of file atlas_contents.cc.

54 {
55 blend_mode_ = blend_mode;
56 }

## ◆ SetColors()

void impeller::AtlasContents::SetColors | ( | std::vector< Color > | colors | ) |

Definition at line 46 of file atlas_contents.cc.

46 {
47 colors_ = std::move(colors);
48 }

## ◆ SetCullRect()

void impeller::AtlasContents::SetCullRect | ( | std::optional< Rect > | cull_rect | ) |

Definition at line 58 of file atlas_contents.cc.

58 {
59 cull_rect_ = cull_rect;
60 }

## ◆ SetSamplerDescriptor()

void impeller::AtlasContents::SetSamplerDescriptor | ( | SamplerDescriptor | desc | ) |

Definition at line 165 of file atlas_contents.cc.

165 {
166 sampler_descriptor_ = std::move(desc);
167 }

## ◆ SetTexture()

void impeller::AtlasContents::SetTexture | ( | std::shared_ptr< Texture > | texture | ) |

Definition at line 28 of file atlas_contents.cc.

28 {
29 texture_ = std::move(texture);
30 }

## ◆ SetTextureCoordinates()

void impeller::AtlasContents::SetTextureCoordinates | ( | std::vector< Rect > | texture_coords | ) |

Definition at line 41 of file atlas_contents.cc.

41 {
42 texture_coords_ = std::move(texture_coords);
43 bounding_box_cache_.reset();
44 }

## ◆ SetTransforms()

void impeller::AtlasContents::SetTransforms | ( | std::vector< Matrix > | transforms | ) |

Definition at line 36 of file atlas_contents.cc.

36 {
37 transforms_ = std::move(transforms);
38 bounding_box_cache_.reset();
39 }

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

- impeller/entity/contents/atlas_contents.h
- impeller/entity/contents/atlas_contents.cc

impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:20
impeller::BlendModeToString
const char * BlendModeToString(BlendMode blend_mode)
Definition: color.cc:47
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
impeller::FilterInput::Make
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
impeller::BlendMode::kSource
@ kSource
impeller::BlendMode::kDestination
@ kDestination
impeller::TRect::TransformBounds
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:405
impeller::InvertPorterDuffBlend
std::optional< BlendMode > InvertPorterDuffBlend(BlendMode blend_mode)
Definition: blend_filter_contents.cc:26
impeller::Vector2
Point Vector2
Definition: point.h:320
impeller::RenderPipelineT::FragmentShader
FragmentShader_ FragmentShader
Definition: pipeline.h:94
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::BlendMode::kModulate
@ kModulate
impeller::VS
SolidFillVertexShader VS
Definition: stroke_path_geometry.cc:15
impeller::AtlasContents::GenerateSubAtlas
std::shared_ptr< SubAtlasResult > GenerateSubAtlas() const
Compress a drawAtlas call with blending into a smaller sized atlas. This atlas has no overlapping to ...
Definition: atlas_contents.cc:83
impeller::Color::ToIColor
static constexpr uint32_t ToIColor(Color color)
Convert this color to a 32-bit representation.
Definition: color.h:161
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
impeller::TRect::GetTransformedPoints
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
Definition: rect.h:394
impeller::BlendMode::kClear
@ kClear
impeller::SamplerDescriptor::width_address_mode
SamplerAddressMode width_address_mode
Definition: sampler_descriptor.h:20
impeller::kPorterDuffCoefficients
constexpr std::array< std::array< Scalar, 5 >, 15 > kPorterDuffCoefficients
Definition: blend_filter_contents.h:15
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:138
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:146
impeller::RenderPipelineT::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:93
impeller::ColorFilterContents::MakeBlend
static std::shared_ptr< ColorFilterContents > MakeBlend(BlendMode blend_mode, FilterInput::Vector inputs, std::optional< Color > foreground_color=std::nullopt)
the [inputs] are expected to be in the order of dst, src.
Definition: color_filter_contents.cc:17
impeller::SamplerAddressMode::kDecal
@ kDecal
decal sampling mode is only supported on devices that pass the Capabilities.SupportsDecalSamplerAddre...