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 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< 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, 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< 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 32 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 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
overridevirtual

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
overridevirtual

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