| 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 screen space bounding rectangle that this contents affects. 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 StencilCoverage | GetStencilCoverage (const Entity &entity, const std::optional< Rect > &current_stencil_coverage) const
| Given the current screen space bounding rectangle of the stencil, return the expected stencil coverage after this draw call. This should only be implemented for contents that may write to the stencil 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, stencil 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 > stencil_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 32 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 89 of file atlas_contents.cc.

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

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 186 of file atlas_contents.cc.

186 {
187 return colors_;
188 }

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

## ◆ GetCoverage()

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

Get the screen space bounding rectangle that this contents affects.

Implements impeller::Contents.

Definition at line 149 of file atlas_contents.cc.

149 {
150 if (cull_rect_.has_value()) {
151 return cull_rect_.value().TransformBounds(entity.GetTransformation());
152 }
153 return ComputeBoundingBox().TransformBounds(entity.GetTransformation());
154 }

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

## ◆ GetSamplerDescriptor()

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

Definition at line 174 of file atlas_contents.cc.

174 {
175 return sampler_descriptor_;
176 }

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

## ◆ GetTexture()

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

Definition at line 38 of file atlas_contents.cc.

38 {
39 return texture_;
40 }

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

## ◆ GetTextureCoordinates()

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

Definition at line 182 of file atlas_contents.cc.

182 {
183 return texture_coords_;
184 }

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

## ◆ GetTransforms()

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

Definition at line 178 of file atlas_contents.cc.

178 {
179 return transforms_;
180 }

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 190 of file atlas_contents.cc.

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

References impeller::RenderPass::AddCommand(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendVertex(), impeller::Command::BindVertices(), impeller::BlendModeToString(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, GenerateSubAtlas(), impeller::ContentContext::GetContext(), impeller::ContentContext::GetDeviceCapabilities(), impeller::ContentContext::GetPorterDuffBlendPipeline(), impeller::RenderPass::GetRenderTargetSize(), impeller::Entity::GetStencilDepth(), impeller::Entity::GetTransformation(), 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::Matrix::MakeOrthographic(), 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 56 of file atlas_contents.cc.

56 {
57 alpha_ = alpha;
58 }

## ◆ SetBlendMode()

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

Definition at line 60 of file atlas_contents.cc.

60 {
61 blend_mode_ = blend_mode;
62 }

## ◆ SetColors()

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

Definition at line 52 of file atlas_contents.cc.

52 {
53 colors_ = std::move(colors);
54 }

## ◆ SetCullRect()

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

Definition at line 64 of file atlas_contents.cc.

64 {
65 cull_rect_ = cull_rect;
66 }

## ◆ SetSamplerDescriptor()

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

Definition at line 170 of file atlas_contents.cc.

170 {
171 sampler_descriptor_ = std::move(desc);
172 }

## ◆ SetTexture()

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

Definition at line 34 of file atlas_contents.cc.

34 {
35 texture_ = std::move(texture);
36 }

## ◆ SetTextureCoordinates()

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

Definition at line 47 of file atlas_contents.cc.

47 {
48 texture_coords_ = std::move(texture_coords);
49 bounding_box_cache_.reset();
50 }

## ◆ SetTransforms()

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

Definition at line 42 of file atlas_contents.cc.

42 {
43 transforms_ = std::move(transforms);
44 bounding_box_cache_.reset();
45 }

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:31
impeller::BlendModeToString
const char * BlendModeToString(BlendMode blend_mode)
Definition: color.cc:47
impeller::Scalar
float Scalar
Definition: scalar.h:15
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:47
impeller::FilterInput::Make
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
impeller::TRect::TransformBounds
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:204
impeller::InvertPorterDuffBlend
std::optional< BlendMode > InvertPorterDuffBlend(BlendMode blend_mode)
Definition: blend_filter_contents.cc:28
impeller::Vector2
Point Vector2
Definition: point.h:310
impeller::RenderPipelineT::FragmentShader
FragmentShader_ FragmentShader
Definition: pipeline.h:91
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:94
impeller::Point
TPoint< Scalar > Point
Definition: point.h:306
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:89
impeller::Color::ToIColor
static constexpr uint32_t ToIColor(Color color)
Convert this color to a 32-bit representation.
Definition: color.h:159
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
impeller::BlendMode::kDestination
@ kDestination
impeller::TRect::GetTransformedPoints
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
Definition: rect.h:193
impeller::SamplerDescriptor::width_address_mode
SamplerAddressMode width_address_mode
Definition: sampler_descriptor.h:23
impeller::kPorterDuffCoefficients
constexpr std::array< std::array< Scalar, 5 >, 15 > kPorterDuffCoefficients
Definition: blend_filter_contents.h:14
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:136
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:52
impeller::BlendMode::kClear
@ kClear
impeller::Matrix::MakeOrthographic
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:448
impeller::BlendMode::kModulate
@ kModulate
impeller::RenderPipelineT::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:90
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::BlendMode::kSource
@ kSource
impeller::SamplerAddressMode::kDecal
@ kDecal
decal sampling mode is only supported on devices that pass the Capabilities.SupportsDecalSamplerAddre...