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, 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 = 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;
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::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...