| 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, 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 = pass.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 Command cmd;
239 DEBUG_COMMAND_INFO(
240 cmd, SPrintF("DrawAtlas Blend (%s)", BlendModeToString(blend_mode_)));
241 cmd.BindVertices(vtx_builder.CreateVertexBuffer(host_buffer));
242 cmd.stencil_reference = entity.GetClipDepth();
243 auto options = OptionsFromPass(pass);
244 cmd.pipeline = renderer.GetPorterDuffBlendPipeline(options);
245
246 FS::FragInfo frag_info;
247 VS::FrameInfo frame_info;
248
249 auto dst_sampler_descriptor = sampler_descriptor_;
250 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
251 dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
252 dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
253 }
254 auto dst_sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler(
255 dst_sampler_descriptor);
256 FS::BindTextureSamplerDst(cmd, texture_, dst_sampler);
257 frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
258
259 frag_info.output_alpha = alpha_;
260 frag_info.input_alpha = 1.0;
261
262 auto inverted_blend_mode =
263 InvertPorterDuffBlend(blend_mode_).value_or(BlendMode::kSource);
264 auto blend_coefficients =
265 kPorterDuffCoefficients[static_cast<int>(inverted_blend_mode)];
266 frag_info.src_coeff = blend_coefficients[0];
267 frag_info.src_coeff_dst_alpha = blend_coefficients[1];
268 frag_info.dst_coeff = blend_coefficients[2];
269 frag_info.dst_coeff_src_alpha = blend_coefficients[3];
270 frag_info.dst_coeff_src_color = blend_coefficients[4];
271
272 FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
273
274 frame_info.mvp = pass.GetOrthographicTransform() * entity.GetTransform();
275
276 auto uniform_view = host_buffer.EmplaceUniform(frame_info);
277 VS::BindFrameInfo(cmd, uniform_view);
278
279 return pass.AddCommand(std::move(cmd));
280 }
281
282 // Advanced blends.
283
284 auto sub_atlas = GenerateSubAtlas();
285 auto sub_coverage = Rect::MakeSize(sub_atlas->size);
286
287 auto src_contents = std::make_shared<AtlasTextureContents>(*this);
288 src_contents->SetSubAtlas(sub_atlas);
289 src_contents->SetCoverage(sub_coverage);
290
291 auto dst_contents = std::make_shared<AtlasColorContents>(*this);
292 dst_contents->SetSubAtlas(sub_atlas);
293 dst_contents->SetCoverage(sub_coverage);
294
295 Entity untransformed_entity;
296 auto contents = ColorFilterContents::MakeBlend(
297 blend_mode_,
298 {FilterInput::Make(dst_contents), FilterInput::Make(src_contents)});
299 auto snapshot =
300 contents->RenderToSnapshot(renderer, // renderer
301 untransformed_entity, // entity
302 std::nullopt, // coverage_limit
303 std::nullopt, // sampler_descriptor
304 true, // msaa_enabled
305 "AtlasContents Snapshot"); // label
306 if (!snapshot.has_value()) {
307 return false;
308 }
309
310 auto child_contents = AtlasTextureContents(*this);
311 child_contents.SetAlpha(alpha_);
312 child_contents.SetCoverage(coverage);
313 child_contents.SetTexture(snapshot.value().texture);
314 child_contents.SetUseDestination(true);
315 child_contents.SetSubAtlas(sub_atlas);
316 return child_contents.Render(renderer, entity, pass);
317 }

References impeller::RenderPass::AddCommand(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendVertex(), impeller::Command::BindVertices(), impeller::BlendModeToString(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, GenerateSubAtlas(), impeller::Entity::GetClipDepth(), impeller::ContentContext::GetContext(), impeller::ContentContext::GetDeviceCapabilities(), impeller::RenderPass::GetOrthographicTransform(), impeller::ContentContext::GetPorterDuffBlendPipeline(), impeller::Entity::GetTransform(), impeller::TRect< T >::GetTransformedPoints(), impeller::RenderPass::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::Command::pipeline, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::Reserve(), impeller::SPrintF(), impeller::Command::stencil_reference, 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
DEBUG_COMMAND_INFO
#define DEBUG_COMMAND_INFO(obj, arg)
Definition: command.h:28
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:34
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:264
impeller::InvertPorterDuffBlend
std::optional< BlendMode > InvertPorterDuffBlend(BlendMode blend_mode)
Definition: blend_filter_contents.cc:26
impeller::Vector2
Point Vector2
Definition: point.h:312
impeller::RenderPipelineT::FragmentShader
FragmentShader_ FragmentShader
Definition: pipeline.h:93
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::BlendMode::kModulate
@ kModulate
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:253
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:44
impeller::RenderPipelineT::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:92
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...