Flutter Impeller
impeller::EntityPass Class Reference

#include <entity_pass.h>

Public Types

using Element = std::variant< Entity, std::unique_ptr< EntityPass > >
 
using BackdropFilterProc = std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)>
 

Public Member Functions

 EntityPass ()
 
 ~EntityPass ()
 
void SetDelegate (std::shared_ptr< EntityPassDelegate > delgate)
 
void SetBoundsLimit (std::optional< Rect > bounds_limit, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown)
 Set the bounds limit, which is provided by the user when creating a SaveLayer. This is a hint that allows the user to communicate that it's OK to not render content outside of the bounds. More...
 
std::optional< RectGetBoundsLimit () const
 Get the bounds limit, which is provided by the user when creating a SaveLayer. More...
 
bool GetBoundsLimitMightClipContent () const
 Indicates if the bounds limit set using |SetBoundsLimit()| might clip the contents of the pass. More...
 
bool GetBoundsLimitIsSnug () const
 Indicates if the bounds limit set using |SetBoundsLimit()| is a reasonably tight estimate of the bounds of the contents. More...
 
size_t GetSubpassesDepth () const
 
void AddEntity (Entity entity)
 Add an entity to the current entity pass. More...
 
void PushClip (Entity entity)
 
void PopClips (size_t num_clips, uint64_t depth)
 
void PopAllClips (uint64_t depth)
 
void SetElements (std::vector< Element > elements)
 
EntityPassAddSubpass (std::unique_ptr< EntityPass > pass)
 Appends a given pass as a subpass. More...
 
EntityPassGetSuperpass () const
 
bool Render (ContentContext &renderer, const RenderTarget &render_target) const
 
void IterateAllElements (const std::function< bool(Element &)> &iterator)
 Iterate all elements (entities and subpasses) in this pass, recursively including elements of child passes. The iteration order is depth-first. Whenever a subpass elements is encountered, it's included in the stream before its children. More...
 
void IterateAllElements (const std::function< bool(const Element &)> &iterator) const
 
void IterateAllEntities (const std::function< bool(Entity &)> &iterator)
 Iterate all entities in this pass, recursively including entities of child passes. The iteration order is depth-first. More...
 
void IterateAllEntities (const std::function< bool(const Entity &)> &iterator) const
 Iterate all entities in this pass, recursively including entities of child passes. The iteration order is depth-first and does not allow modification of the entities. More...
 
bool IterateUntilSubpass (const std::function< bool(Entity &)> &iterator)
 Iterate entities in this pass up until the first subpass is found. This is useful for limiting look-ahead optimizations. More...
 
size_t GetElementCount () const
 Return the number of elements on this pass. More...
 
void SetTransform (Matrix transform)
 
void SetClipHeight (size_t clip_height)
 
size_t GetClipHeight () const
 
void SetClipDepth (size_t clip_depth)
 
uint32_t GetClipDepth () const
 
void SetBlendMode (BlendMode blend_mode)
 
std::optional< ColorGetClearColor (ISize size=ISize::Infinite()) const
 Return the premultiplied clear color of the pass entities, if any. More...
 
Color GetClearColorOrDefault (ISize size=ISize::Infinite()) const
 Return the premultiplied clear color of the pass entities. More...
 
void SetBackdropFilter (BackdropFilterProc proc)
 
int32_t GetRequiredMipCount () const
 
void SetRequiredMipCount (int32_t mip_count)
 
std::optional< RectGetSubpassCoverage (const EntityPass &subpass, std::optional< Rect > coverage_limit) const
 Computes the coverage of a given subpass. This is used to determine the texture size of a given subpass before it's rendered to and passed through the subpass ImageFilter, if any. More...
 
std::optional< RectGetElementsCoverage (std::optional< Rect > coverage_limit) const
 

Detailed Description

Definition at line 43 of file entity_pass.h.

Member Typedef Documentation

◆ BackdropFilterProc

using impeller::EntityPass::BackdropFilterProc = std::function<std::shared_ptr<FilterContents>( FilterInput::Ref, const Matrix& effect_transform, Entity::RenderingMode rendering_mode)>

Definition at line 59 of file entity_pass.h.

◆ Element

using impeller::EntityPass::Element = std::variant<Entity, std::unique_ptr<EntityPass> >

Elements are renderable items in the EntityPass. Each can either be an Entity or a child EntityPass.

When the element is a child EntityPass, it may be rendered to an offscreen texture and converted into an Entity that draws the texture into the current pass, or its children may be collapsed into the current

EntityPass. Elements are converted to Entities in GetEntityForElement().

Definition at line 54 of file entity_pass.h.

Constructor & Destructor Documentation

◆ EntityPass()

impeller::EntityPass::EntityPass ( )
default

◆ ~EntityPass()

impeller::EntityPass::~EntityPass ( )
default

Member Function Documentation

◆ AddEntity()

void impeller::EntityPass::AddEntity ( Entity  entity)

Add an entity to the current entity pass.

Definition at line 100 of file entity_pass.cc.

100  {
101  if (entity.GetBlendMode() == BlendMode::kSourceOver &&
102  entity.GetContents()->IsOpaque()) {
103  entity.SetBlendMode(BlendMode::kSource);
104  }
105 
106  if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
107  advanced_blend_reads_from_pass_texture_ = true;
108  }
109  elements_.emplace_back(std::move(entity));
110 }

References impeller::Entity::GetBlendMode(), impeller::Entity::GetContents(), impeller::Entity::kLastPipelineBlendMode, impeller::kSource, impeller::kSourceOver, and impeller::Entity::SetBlendMode().

Referenced by impeller::testing::TEST_P().

◆ AddSubpass()

EntityPass * impeller::EntityPass::AddSubpass ( std::unique_ptr< EntityPass pass)

Appends a given pass as a subpass.

Definition at line 267 of file entity_pass.cc.

267  {
268  if (!pass) {
269  return nullptr;
270  }
271  FML_DCHECK(pass->superpass_ == nullptr);
272  pass->superpass_ = this;
273 
274  if (pass->backdrop_filter_proc_) {
275  backdrop_filter_reads_from_pass_texture_ = true;
276  }
277  if (pass->blend_mode_ > Entity::kLastPipelineBlendMode) {
278  advanced_blend_reads_from_pass_texture_ = true;
279  }
280 
281  auto subpass_pointer = pass.get();
282  elements_.emplace_back(std::move(pass));
283  return subpass_pointer;
284 }

References impeller::Entity::kLastPipelineBlendMode.

Referenced by impeller::testing::TEST_P().

◆ GetBoundsLimit()

std::optional< Rect > impeller::EntityPass::GetBoundsLimit ( ) const

Get the bounds limit, which is provided by the user when creating a SaveLayer.

Definition at line 65 of file entity_pass.cc.

65  {
66  return bounds_limit_;
67 }

◆ GetBoundsLimitIsSnug()

bool impeller::EntityPass::GetBoundsLimitIsSnug ( ) const

Indicates if the bounds limit set using |SetBoundsLimit()| is a reasonably tight estimate of the bounds of the contents.

Definition at line 88 of file entity_pass.cc.

88  {
89  switch (bounds_promise_) {
91  return false;
94  FML_DCHECK(bounds_limit_.has_value());
95  return true;
96  }
97  FML_UNREACHABLE();
98 }

References impeller::kContainsContents, impeller::kMayClipContents, and impeller::kUnknown.

Referenced by GetSubpassCoverage().

◆ GetBoundsLimitMightClipContent()

bool impeller::EntityPass::GetBoundsLimitMightClipContent ( ) const

Indicates if the bounds limit set using |SetBoundsLimit()| might clip the contents of the pass.

Definition at line 69 of file entity_pass.cc.

69  {
70  switch (bounds_promise_) {
72  // If the promise is unknown due to not having a bounds limit,
73  // then no clipping will occur. But if we have a bounds limit
74  // and it is unkown, then we can make no promises about whether
75  // it causes clipping of the entity pass contents and we
76  // conservatively return true.
77  return bounds_limit_.has_value();
79  FML_DCHECK(bounds_limit_.has_value());
80  return false;
82  FML_DCHECK(bounds_limit_.has_value());
83  return true;
84  }
85  FML_UNREACHABLE();
86 }

References impeller::kContainsContents, impeller::kMayClipContents, and impeller::kUnknown.

◆ GetClearColor()

std::optional< Color > impeller::EntityPass::GetClearColor ( ISize  size = ISize::Infinite()) const

Return the premultiplied clear color of the pass entities, if any.

Definition at line 1124 of file entity_pass.cc.

1124  {
1125  if (backdrop_filter_proc_) {
1126  return std::nullopt;
1127  }
1128 
1129  std::optional<Color> result = std::nullopt;
1130  for (const Element& element : elements_) {
1131  auto [entity_color, blend_mode] =
1132  ElementAsBackgroundColor(element, target_size);
1133  if (!entity_color.has_value()) {
1134  break;
1135  }
1136  result = result.value_or(Color::BlackTransparent())
1137  .Blend(entity_color.value(), blend_mode);
1138  }
1139  if (result.has_value()) {
1140  return result->Premultiply();
1141  }
1142  return result;
1143 }

References impeller::Color::BlackTransparent().

Referenced by GetClearColorOrDefault().

◆ GetClearColorOrDefault()

Color impeller::EntityPass::GetClearColorOrDefault ( ISize  size = ISize::Infinite()) const

Return the premultiplied clear color of the pass entities.

If the entity pass has no clear color, this will return transparent black.

Definition at line 1120 of file entity_pass.cc.

1120  {
1121  return GetClearColor(size).value_or(Color::BlackTransparent());
1122 }

References impeller::Color::BlackTransparent(), and GetClearColor().

Referenced by Render().

◆ GetClipDepth()

uint32_t impeller::EntityPass::GetClipDepth ( ) const

Definition at line 1111 of file entity_pass.cc.

1111  {
1112  return clip_depth_;
1113 }

◆ GetClipHeight()

size_t impeller::EntityPass::GetClipHeight ( ) const

Definition at line 1103 of file entity_pass.cc.

1103  {
1104  return clip_height_;
1105 }

◆ GetElementCount()

size_t impeller::EntityPass::GetElementCount ( ) const

Return the number of elements on this pass.

Definition at line 1091 of file entity_pass.cc.

1091  {
1092  return elements_.size();
1093 }

◆ GetElementsCoverage()

std::optional< Rect > impeller::EntityPass::GetElementsCoverage ( std::optional< Rect coverage_limit) const

Definition at line 154 of file entity_pass.cc.

155  {
156  std::optional<Rect> accumulated_coverage;
157  for (const auto& element : elements_) {
158  std::optional<Rect> element_coverage;
159 
160  if (auto entity = std::get_if<Entity>(&element)) {
161  element_coverage = entity->GetCoverage();
162 
163  // When the coverage limit is std::nullopt, that means there is no limit,
164  // as opposed to empty coverage.
165  if (element_coverage.has_value() && coverage_limit.has_value()) {
166  const auto* filter = entity->GetContents()->AsFilter();
167  if (!filter || filter->IsTranslationOnly()) {
168  element_coverage =
169  element_coverage->Intersection(coverage_limit.value());
170  }
171  }
172  } else if (auto subpass_ptr =
173  std::get_if<std::unique_ptr<EntityPass>>(&element)) {
174  auto& subpass = *subpass_ptr->get();
175 
176  std::optional<Rect> unfiltered_coverage =
177  GetSubpassCoverage(subpass, std::nullopt);
178 
179  // If the current pass elements have any coverage so far and there's a
180  // backdrop filter, then incorporate the backdrop filter in the
181  // pre-filtered coverage of the subpass.
182  if (accumulated_coverage.has_value() && subpass.backdrop_filter_proc_) {
183  std::shared_ptr<FilterContents> backdrop_filter =
184  subpass.backdrop_filter_proc_(
185  FilterInput::Make(accumulated_coverage.value()),
186  subpass.transform_,
188  if (backdrop_filter) {
189  auto backdrop_coverage = backdrop_filter->GetCoverage({});
190  unfiltered_coverage =
191  Rect::Union(unfiltered_coverage, backdrop_coverage);
192  } else {
193  VALIDATION_LOG << "The EntityPass backdrop filter proc didn't return "
194  "a valid filter.";
195  }
196  }
197 
198  if (!unfiltered_coverage.has_value()) {
199  continue;
200  }
201 
202  // Additionally, subpass textures may be passed through filters, which may
203  // modify the coverage.
204  //
205  // Note that we currently only assume that ImageFilters (such as blurs and
206  // matrix transforms) may modify coverage, although it's technically
207  // possible ColorFilters to affect coverage as well. For example: A
208  // ColorMatrixFilter could output a completely transparent result, and
209  // we could potentially detect this case as zero coverage in the future.
210  std::shared_ptr<FilterContents> image_filter =
211  subpass.delegate_->WithImageFilter(*unfiltered_coverage,
212  subpass.transform_);
213  if (image_filter) {
214  Entity subpass_entity;
215  subpass_entity.SetTransform(subpass.transform_);
216  element_coverage = image_filter->GetCoverage(subpass_entity);
217  } else {
218  element_coverage = unfiltered_coverage;
219  }
220 
221  element_coverage = Rect::Intersection(element_coverage, coverage_limit);
222  } else {
223  FML_UNREACHABLE();
224  }
225 
226  accumulated_coverage = Rect::Union(accumulated_coverage, element_coverage);
227  }
228  return accumulated_coverage;
229 }

References GetSubpassCoverage(), impeller::TRect< Scalar >::Intersection(), impeller::Entity::kSubpassAppendSnapshotTransform, impeller::FilterInput::Make(), impeller::Entity::SetTransform(), impeller::TRect< Scalar >::Union(), and VALIDATION_LOG.

Referenced by GetSubpassCoverage(), and impeller::testing::TEST_P().

◆ GetRequiredMipCount()

int32_t impeller::EntityPass::GetRequiredMipCount ( ) const
inline

Definition at line 175 of file entity_pass.h.

175 { return required_mip_count_; }

Referenced by Render().

◆ GetSubpassCoverage()

std::optional< Rect > impeller::EntityPass::GetSubpassCoverage ( const EntityPass subpass,
std::optional< Rect coverage_limit 
) const

Computes the coverage of a given subpass. This is used to determine the texture size of a given subpass before it's rendered to and passed through the subpass ImageFilter, if any.

Parameters
[in]subpassThe EntityPass for which to compute pre-filteredcoverage.
[in]coverage_limitConfines coverage to a specified area. This hint is used to trim coverage to the root framebuffer area. std::nullopt means there is no limit.
Returns
The screen space pixel area that the subpass contents will render into, prior to being transformed by the subpass ImageFilter, if any. std::nullopt means rendering the subpass will have no effect on the color attachment.

Definition at line 231 of file entity_pass.cc.

233  {
234  if (subpass.bounds_limit_.has_value() && subpass.GetBoundsLimitIsSnug()) {
235  return subpass.bounds_limit_->TransformBounds(subpass.transform_);
236  }
237 
238  std::shared_ptr<FilterContents> image_filter =
239  subpass.delegate_->WithImageFilter(Rect(), subpass.transform_);
240 
241  // If the subpass has an image filter, then its coverage space may deviate
242  // from the parent pass and make intersecting with the pass coverage limit
243  // unsafe.
244  if (image_filter && coverage_limit.has_value()) {
245  coverage_limit = image_filter->GetSourceCoverage(subpass.transform_,
246  coverage_limit.value());
247  }
248 
249  auto entities_coverage = subpass.GetElementsCoverage(coverage_limit);
250  // The entities don't cover anything. There is nothing to do.
251  if (!entities_coverage.has_value()) {
252  return std::nullopt;
253  }
254 
255  if (!subpass.bounds_limit_.has_value()) {
256  return entities_coverage;
257  }
258  auto user_bounds_coverage =
259  subpass.bounds_limit_->TransformBounds(subpass.transform_);
260  return entities_coverage->Intersection(user_bounds_coverage);
261 }

References GetBoundsLimitIsSnug(), and GetElementsCoverage().

Referenced by GetElementsCoverage(), and impeller::testing::TEST_P().

◆ GetSubpassesDepth()

size_t impeller::EntityPass::GetSubpassesDepth ( ) const

Definition at line 143 of file entity_pass.cc.

143  {
144  size_t max_subpass_depth = 0u;
145  for (const auto& element : elements_) {
146  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
147  max_subpass_depth =
148  std::max(max_subpass_depth, subpass->get()->GetSubpassesDepth());
149  }
150  }
151  return max_subpass_depth + 1u;
152 }

◆ GetSuperpass()

EntityPass * impeller::EntityPass::GetSuperpass ( ) const

Definition at line 263 of file entity_pass.cc.

263  {
264  return superpass_;
265 }

Referenced by impeller::Canvas::Restore().

◆ IterateAllElements() [1/2]

void impeller::EntityPass::IterateAllElements ( const std::function< bool(const Element &)> &  iterator) const

TODO(gaaclarke): Remove duplication here between const and non-const versions.

Definition at line 1011 of file entity_pass.cc.

1012  {
1013  /// TODO(gaaclarke): Remove duplication here between const and non-const
1014  /// versions.
1015  if (!iterator) {
1016  return;
1017  }
1018 
1019  for (auto& element : elements_) {
1020  if (!iterator(element)) {
1021  return;
1022  }
1023  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1024  const EntityPass* entity_pass = subpass->get();
1025  entity_pass->IterateAllElements(iterator);
1026  }
1027  }
1028 }

References IterateAllElements().

◆ IterateAllElements() [2/2]

void impeller::EntityPass::IterateAllElements ( const std::function< bool(Element &)> &  iterator)

Iterate all elements (entities and subpasses) in this pass, recursively including elements of child passes. The iteration order is depth-first. Whenever a subpass elements is encountered, it's included in the stream before its children.

Definition at line 995 of file entity_pass.cc.

996  {
997  if (!iterator) {
998  return;
999  }
1000 
1001  for (auto& element : elements_) {
1002  if (!iterator(element)) {
1003  return;
1004  }
1005  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1006  subpass->get()->IterateAllElements(iterator);
1007  }
1008  }
1009 }

Referenced by IterateAllElements().

◆ IterateAllEntities() [1/2]

void impeller::EntityPass::IterateAllEntities ( const std::function< bool(const Entity &)> &  iterator) const

Iterate all entities in this pass, recursively including entities of child passes. The iteration order is depth-first and does not allow modification of the entities.

Definition at line 1051 of file entity_pass.cc.

1052  {
1053  if (!iterator) {
1054  return;
1055  }
1056 
1057  for (const auto& element : elements_) {
1058  if (auto entity = std::get_if<Entity>(&element)) {
1059  if (!iterator(*entity)) {
1060  return;
1061  }
1062  continue;
1063  }
1064  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1065  const EntityPass* entity_pass = subpass->get();
1066  entity_pass->IterateAllEntities(iterator);
1067  continue;
1068  }
1069  FML_UNREACHABLE();
1070  }
1071 }

References IterateAllEntities().

◆ IterateAllEntities() [2/2]

void impeller::EntityPass::IterateAllEntities ( const std::function< bool(Entity &)> &  iterator)

Iterate all entities in this pass, recursively including entities of child passes. The iteration order is depth-first.

Definition at line 1030 of file entity_pass.cc.

1031  {
1032  if (!iterator) {
1033  return;
1034  }
1035 
1036  for (auto& element : elements_) {
1037  if (auto entity = std::get_if<Entity>(&element)) {
1038  if (!iterator(*entity)) {
1039  return;
1040  }
1041  continue;
1042  }
1043  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1044  subpass->get()->IterateAllEntities(iterator);
1045  continue;
1046  }
1047  FML_UNREACHABLE();
1048  }
1049 }

Referenced by IterateAllEntities(), and Render().

◆ IterateUntilSubpass()

bool impeller::EntityPass::IterateUntilSubpass ( const std::function< bool(Entity &)> &  iterator)

Iterate entities in this pass up until the first subpass is found. This is useful for limiting look-ahead optimizations.

Returns
Returns whether a subpass was encountered.

Definition at line 1073 of file entity_pass.cc.

1074  {
1075  if (!iterator) {
1076  return true;
1077  }
1078 
1079  for (auto& element : elements_) {
1080  if (auto entity = std::get_if<Entity>(&element)) {
1081  if (!iterator(*entity)) {
1082  return false;
1083  }
1084  continue;
1085  }
1086  return true;
1087  }
1088  return false;
1089 }

◆ PopAllClips()

void impeller::EntityPass::PopAllClips ( uint64_t  depth)

Definition at line 135 of file entity_pass.cc.

135  {
136  PopClips(active_clips_.size(), depth);
137 }

References PopClips().

Referenced by impeller::EntityPlayground::OpenPlaygroundHere().

◆ PopClips()

void impeller::EntityPass::PopClips ( size_t  num_clips,
uint64_t  depth 
)

Definition at line 117 of file entity_pass.cc.

117  {
118  if (num_clips > active_clips_.size()) {
120  << "Attempted to pop more clips than are currently active. Active: "
121  << active_clips_.size() << ", Popped: " << num_clips
122  << ", Depth: " << depth;
123  }
124 
125  size_t max = std::min(num_clips, active_clips_.size());
126  for (size_t i = 0; i < max; i++) {
127  FML_DCHECK(active_clips_.back() < elements_.size());
128  Entity* element = std::get_if<Entity>(&elements_[active_clips_.back()]);
129  FML_DCHECK(element);
130  element->SetClipDepth(depth);
131  active_clips_.pop_back();
132  }
133 }

References impeller::Entity::SetClipDepth(), and VALIDATION_LOG.

Referenced by PopAllClips(), and impeller::Canvas::Restore().

◆ PushClip()

void impeller::EntityPass::PushClip ( Entity  entity)

Definition at line 112 of file entity_pass.cc.

112  {
113  elements_.emplace_back(std::move(entity));
114  active_clips_.emplace_back(elements_.size() - 1);
115 }

◆ Render()

bool impeller::EntityPass::Render ( ContentContext renderer,
const RenderTarget render_target 
) const

Definition at line 354 of file entity_pass.cc.

355  {
356  renderer.GetRenderTargetCache()->Start();
357  fml::ScopedCleanupClosure reset_state([&renderer]() {
358  renderer.GetLazyGlyphAtlas()->ResetTextFrames();
359  renderer.GetRenderTargetCache()->End();
360  });
361 
362  auto root_render_target = render_target;
363 
364  if (root_render_target.GetColorAttachments().find(0u) ==
365  root_render_target.GetColorAttachments().end()) {
366  VALIDATION_LOG << "The root RenderTarget must have a color attachment.";
367  return false;
368  }
369  if (root_render_target.GetDepthAttachment().has_value() !=
370  root_render_target.GetStencilAttachment().has_value()) {
371  VALIDATION_LOG << "The root RenderTarget should have a stencil attachment "
372  "iff it has a depth attachment.";
373  return false;
374  }
375 
376  const auto& lazy_glyph_atlas = renderer.GetLazyGlyphAtlas();
377  IterateAllEntities([&lazy_glyph_atlas](const Entity& entity) {
378  if (const auto& contents = entity.GetContents()) {
379  contents->PopulateGlyphAtlas(lazy_glyph_atlas, entity.DeriveTextScale());
380  }
381  return true;
382  });
383 
384  EntityPassClipStack clip_stack = EntityPassClipStack(
385  Rect::MakeSize(root_render_target.GetRenderTargetSize()));
386 
387  // In this branch path, we need to render everything to an offscreen texture
388  // and then blit the results onto the onscreen texture. If using this branch,
389  // there's no need to set up a stencil attachment on the root render target.
390  if (DoesBackdropGetRead(renderer)) {
391  EntityPassTarget offscreen_target = CreateRenderTarget(
392  renderer, root_render_target.GetRenderTargetSize(),
394  GetClearColorOrDefault(render_target.GetRenderTargetSize()));
395 
396  if (!OnRender(renderer, // renderer
397  offscreen_target.GetRenderTarget()
398  .GetRenderTargetSize(), // root_pass_size
399  offscreen_target, // pass_target
400  Point(), // global_pass_position
401  Point(), // local_pass_position
402  0, // pass_depth
403  clip_stack // clip_coverage_stack
404  )) {
405  // Validation error messages are triggered for all `OnRender()` failure
406  // cases.
407  return false;
408  }
409 
410  auto command_buffer = renderer.GetContext()->CreateCommandBuffer();
411  command_buffer->SetLabel("EntityPass Root Command Buffer");
412 
413  // If the context supports blitting, blit the offscreen texture to the
414  // onscreen texture. Otherwise, draw it to the parent texture using a
415  // pipeline (slower).
416  if (renderer.GetContext()
417  ->GetCapabilities()
418  ->SupportsTextureToTextureBlits()) {
419  auto blit_pass = command_buffer->CreateBlitPass();
420  blit_pass->AddCopy(
421  offscreen_target.GetRenderTarget().GetRenderTargetTexture(),
422  root_render_target.GetRenderTargetTexture());
423  if (!blit_pass->EncodeCommands(
424  renderer.GetContext()->GetResourceAllocator())) {
425  VALIDATION_LOG << "Failed to encode root pass blit command.";
426  return false;
427  }
428  if (!renderer.GetContext()
429  ->GetCommandQueue()
430  ->Submit({command_buffer})
431  .ok()) {
432  return false;
433  }
434  } else {
435  auto render_pass = command_buffer->CreateRenderPass(root_render_target);
436  render_pass->SetLabel("EntityPass Root Render Pass");
437 
438  {
439  auto size_rect = Rect::MakeSize(
440  offscreen_target.GetRenderTarget().GetRenderTargetSize());
441  auto contents = TextureContents::MakeRect(size_rect);
442  contents->SetTexture(
443  offscreen_target.GetRenderTarget().GetRenderTargetTexture());
444  contents->SetSourceRect(size_rect);
445  contents->SetLabel("Root pass blit");
446 
447  Entity entity;
448  entity.SetContents(contents);
449  entity.SetBlendMode(BlendMode::kSource);
450 
451  if (!entity.Render(renderer, *render_pass)) {
452  VALIDATION_LOG << "Failed to render EntityPass root blit.";
453  return false;
454  }
455  }
456 
457  if (!render_pass->EncodeCommands()) {
458  VALIDATION_LOG << "Failed to encode root pass command buffer.";
459  return false;
460  }
461  if (!renderer.GetContext()
462  ->GetCommandQueue()
463  ->Submit({command_buffer})
464  .ok()) {
465  return false;
466  }
467  }
468 
469  return true;
470  }
471 
472  // If we make it this far, that means the context is capable of rendering
473  // everything directly to the onscreen texture.
474 
475  // The safety check for fetching this color attachment is at the beginning of
476  // this method.
477  auto color0 = root_render_target.GetColorAttachments().find(0u)->second;
478 
479  auto stencil_attachment = root_render_target.GetStencilAttachment();
480  auto depth_attachment = root_render_target.GetDepthAttachment();
481  if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
482  // Setup a new root stencil with an optimal configuration if one wasn't
483  // provided by the caller.
484  root_render_target.SetupDepthStencilAttachments(
485  *renderer.GetContext(), *renderer.GetContext()->GetResourceAllocator(),
486  color0.texture->GetSize(),
487  renderer.GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
488  "ImpellerOnscreen", kDefaultStencilConfig);
489  }
490 
491  // Set up the clear color of the root pass.
492  color0.clear_color =
493  GetClearColorOrDefault(render_target.GetRenderTargetSize());
494  root_render_target.SetColorAttachment(color0, 0);
495 
496  EntityPassTarget pass_target(
497  root_render_target,
498  renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
499  renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA());
500 
501  return OnRender( //
502  renderer, // renderer
503  root_render_target.GetRenderTargetSize(), // root_pass_size
504  pass_target, // pass_target
505  Point(), // global_pass_position
506  Point(), // local_pass_position
507  0, // pass_depth
508  clip_stack); // clip_coverage_stack
509 }

References impeller::CreateRenderTarget(), GetClearColorOrDefault(), impeller::Entity::GetContents(), impeller::ContentContext::GetContext(), impeller::ContentContext::GetDeviceCapabilities(), impeller::ContentContext::GetLazyGlyphAtlas(), impeller::EntityPassTarget::GetRenderTarget(), impeller::ContentContext::GetRenderTargetCache(), impeller::RenderTarget::GetRenderTargetSize(), impeller::RenderTarget::GetRenderTargetTexture(), GetRequiredMipCount(), IterateAllEntities(), impeller::kDefaultStencilConfig, impeller::kSource, impeller::TextureContents::MakeRect(), impeller::TRect< Scalar >::MakeSize(), impeller::Entity::Render(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Capabilities::SupportsImplicitResolvingMSAA(), impeller::Capabilities::SupportsReadFromResolve(), and VALIDATION_LOG.

Referenced by impeller::EntityPlayground::OpenPlaygroundHere().

◆ SetBackdropFilter()

void impeller::EntityPass::SetBackdropFilter ( BackdropFilterProc  proc)

Definition at line 1145 of file entity_pass.cc.

1145  {
1146  if (superpass_) {
1147  VALIDATION_LOG << "Backdrop filters cannot be set on EntityPasses that "
1148  "have already been appended to another pass.";
1149  }
1150 
1151  backdrop_filter_proc_ = std::move(proc);
1152 }

References VALIDATION_LOG.

◆ SetBlendMode()

void impeller::EntityPass::SetBlendMode ( BlendMode  blend_mode)

Definition at line 1115 of file entity_pass.cc.

1115  {
1116  blend_mode_ = blend_mode;
1117  flood_clip_ = Entity::IsBlendModeDestructive(blend_mode);
1118 }

References impeller::Entity::IsBlendModeDestructive().

◆ SetBoundsLimit()

void impeller::EntityPass::SetBoundsLimit ( std::optional< Rect bounds_limit,
ContentBoundsPromise  bounds_promise = ContentBoundsPromise::kUnknown 
)

Set the bounds limit, which is provided by the user when creating a SaveLayer. This is a hint that allows the user to communicate that it's OK to not render content outside of the bounds.

For consistency with Skia, we effectively treat this like a rectangle clip by forcing the subpass texture size to never exceed it.

The entity pass will assume that these bounds cause a clipping effect on the layer unless this call is followed up with a call to |SetBoundsClipsContent()| specifying otherwise.

Definition at line 58 of file entity_pass.cc.

59  {
60  bounds_limit_ = bounds_limit;
61  bounds_promise_ = bounds_limit.has_value() ? bounds_promise
63 }

References impeller::kUnknown.

◆ SetClipDepth()

void impeller::EntityPass::SetClipDepth ( size_t  clip_depth)

Definition at line 1107 of file entity_pass.cc.

1107  {
1108  clip_depth_ = clip_depth;
1109 }

Referenced by impeller::Canvas::Restore().

◆ SetClipHeight()

void impeller::EntityPass::SetClipHeight ( size_t  clip_height)

Definition at line 1099 of file entity_pass.cc.

1099  {
1100  clip_height_ = clip_height;
1101 }

◆ SetDelegate()

void impeller::EntityPass::SetDelegate ( std::shared_ptr< EntityPassDelegate delgate)

Definition at line 51 of file entity_pass.cc.

51  {
52  if (!delegate) {
53  return;
54  }
55  delegate_ = std::move(delegate);
56 }

◆ SetElements()

void impeller::EntityPass::SetElements ( std::vector< Element elements)

Definition at line 139 of file entity_pass.cc.

139  {
140  elements_ = std::move(elements);
141 }

◆ SetRequiredMipCount()

void impeller::EntityPass::SetRequiredMipCount ( int32_t  mip_count)
inline

Definition at line 177 of file entity_pass.h.

177  {
178  required_mip_count_ = mip_count;
179  }

◆ SetTransform()

void impeller::EntityPass::SetTransform ( Matrix  transform)

Definition at line 1095 of file entity_pass.cc.

1095  {
1096  transform_ = transform;
1097 }

References transform.


The documentation for this class was generated from the following files:
impeller::EntityPass::IterateAllEntities
void IterateAllEntities(const std::function< bool(Entity &)> &iterator)
Iterate all entities in this pass, recursively including entities of child passes....
Definition: entity_pass.cc:1030
impeller::Entity::kLastPipelineBlendMode
static constexpr BlendMode kLastPipelineBlendMode
Definition: entity.h:22
impeller::EntityPass::GetSubpassCoverage
std::optional< Rect > GetSubpassCoverage(const EntityPass &subpass, std::optional< Rect > coverage_limit) const
Computes the coverage of a given subpass. This is used to determine the texture size of a given subpa...
Definition: entity_pass.cc:231
impeller::ContentBoundsPromise::kMayClipContents
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
impeller::EntityPass::EntityPass
EntityPass()
impeller::FilterInput::Make
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
impeller::BlendMode::kSource
@ kSource
impeller::Entity::IsBlendModeDestructive
static bool IsBlendModeDestructive(BlendMode blend_mode)
Returns true if the blend mode is "destructive", meaning that even fully transparent source colors wo...
Definition: entity.cc:156
impeller::Entity::RenderingMode::kSubpassAppendSnapshotTransform
@ kSubpassAppendSnapshotTransform
impeller::TRect< Scalar >::Intersection
constexpr std::optional< TRect > Intersection(const TRect &o) const
Definition: rect.h:519
impeller::ContentBoundsPromise::kUnknown
@ kUnknown
The caller makes no claims related to the size of the bounds.
impeller::kDefaultStencilConfig
static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig
Definition: experimental_canvas.cc:48
impeller::Point
TPoint< Scalar > Point
Definition: point.h:322
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:231
impeller::EntityPass::Element
std::variant< Entity, std::unique_ptr< EntityPass > > Element
Definition: entity_pass.h:54
impeller::EntityPass::GetRequiredMipCount
int32_t GetRequiredMipCount() const
Definition: entity_pass.h:175
impeller::CreateRenderTarget
static std::unique_ptr< EntityPassTarget > CreateRenderTarget(ContentContext &renderer, ISize size, int mip_count, const Color &clear_color)
Definition: experimental_canvas.cc:55
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:769
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:146
impeller::EntityPass::PopClips
void PopClips(size_t num_clips, uint64_t depth)
Definition: entity_pass.cc:117
impeller::Color::BlackTransparent
static constexpr Color BlackTransparent()
Definition: color.h:272
impeller::TRect< Scalar >::Union
constexpr TRect Union(const TRect &o) const
Definition: rect.h:504
impeller::TextureContents::MakeRect
static std::shared_ptr< TextureContents > MakeRect(Rect destination)
A common case factory that marks the texture contents as having a destination rectangle....
Definition: texture_contents.cc:27
impeller::ContentBoundsPromise::kContainsContents
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
impeller::BlendMode::kSourceOver
@ kSourceOver
impeller::EntityPass::GetClearColor
std::optional< Color > GetClearColor(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities, if any.
Definition: entity_pass.cc:1124
impeller::EntityPass::GetClearColorOrDefault
Color GetClearColorOrDefault(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities.
Definition: entity_pass.cc:1120