Flutter Impeller
impeller::AtlasContents Class Referencefinal

#include <atlas_contents.h>

Inheritance diagram for impeller::AtlasContents:
impeller::Contents

Public Member Functions

 AtlasContents ()
 
 ~AtlasContents () override
 
void SetTexture (std::shared_ptr< Texture > texture)
 
std::shared_ptr< TextureGetTexture () 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 SamplerDescriptorGetSamplerDescriptor () const
 
const std::vector< Matrix > & GetTransforms () const
 
const std::vector< Rect > & GetTextureCoordinates () const
 
const std::vector< Color > & GetColors () const
 
std::shared_ptr< SubAtlasResultGenerateSubAtlas () 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< RectGetCoverage (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< SnapshotRenderToSnapshot (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< SizeGetColorSourceSize () 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< ColorAsBackgroundColor (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 FilterContentsAsFilter () 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< ContentsMakeAnonymous (RenderProc render_proc, CoverageProc coverage_proc)
 

Detailed Description

Definition at line 33 of file atlas_contents.h.

Constructor & Destructor Documentation

◆ AtlasContents()

impeller::AtlasContents::AtlasContents ( )
explicitdefault

◆ ~AtlasContents()

impeller::AtlasContents::~AtlasContents ( )
overridedefault

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
overridevirtual

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
overridevirtual

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