Flutter Impeller
impeller::EntityPass Class Reference

#include <entity_pass.h>

Classes

struct  ClipCoverageLayer
 

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)>
 
using ClipCoverageStack = std::vector< ClipCoverageLayer >
 

Public Member Functions

 EntityPass ()
 
 ~EntityPass ()
 
void SetDelegate (std::shared_ptr< EntityPassDelegate > delgate)
 
void SetBoundsLimit (std::optional< Rect > bounds_limit)
 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...
 
size_t GetSubpassesDepth () const
 
std::unique_ptr< EntityPassClone () const
 
void AddEntity (Entity entity)
 Add an entity to the current entity pass. More...
 
void SetElements (std::vector< Element > elements)
 
EntityPassAddSubpass (std::unique_ptr< EntityPass > pass)
 Appends a given pass as a subpass. More...
 
void AddSubpassInline (std::unique_ptr< EntityPass > pass)
 Merges a given pass into this pass. Useful for drawing pre-recorded pictures that don't require rendering into a separate 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 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 SetClipDepth (size_t clip_depth)
 
size_t GetClipDepth ()
 
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)
 
void SetEnableOffscreenCheckerboard (bool enabled)
 
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
 

Static Public Attributes

static const std::string kCaptureDocumentName = "EntityPass"
 

Detailed Description

Definition at line 26 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 44 of file entity_pass.h.

◆ ClipCoverageStack

Definition at line 51 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 37 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)

◆ AddSubpass()

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

Appends a given pass as a subpass.

Definition at line 205 of file entity_pass.cc.

205  {
206  if (!pass) {
207  return nullptr;
208  }
209  FML_DCHECK(pass->superpass_ == nullptr);
210  pass->superpass_ = this;
211 
212  if (pass->backdrop_filter_proc_) {
213  backdrop_filter_reads_from_pass_texture_ += 1;
214  }
215  if (pass->blend_mode_ > Entity::kLastPipelineBlendMode) {
216  advanced_blend_reads_from_pass_texture_ += 1;
217  }
218 
219  auto subpass_pointer = pass.get();
220  elements_.emplace_back(std::move(pass));
221  return subpass_pointer;
222 }

References impeller::Entity::kLastPipelineBlendMode.

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

◆ AddSubpassInline()

void impeller::EntityPass::AddSubpassInline ( std::unique_ptr< EntityPass pass)

Merges a given pass into this pass. Useful for drawing pre-recorded pictures that don't require rendering into a separate subpass.

Definition at line 224 of file entity_pass.cc.

224  {
225  if (!pass) {
226  return;
227  }
228  FML_DCHECK(pass->superpass_ == nullptr);
229 
230  std::vector<Element>& elements = pass->elements_;
231  for (auto i = 0u; i < elements.size(); i++) {
232  elements_.emplace_back(std::move(elements[i]));
233  }
234 
235  backdrop_filter_reads_from_pass_texture_ +=
236  pass->backdrop_filter_reads_from_pass_texture_;
237  advanced_blend_reads_from_pass_texture_ +=
238  pass->advanced_blend_reads_from_pass_texture_;
239 }

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

◆ Clone()

std::unique_ptr< EntityPass > impeller::EntityPass::Clone ( ) const

Definition at line 1084 of file entity_pass.cc.

1084  {
1085  std::vector<Element> new_elements;
1086  new_elements.reserve(elements_.size());
1087 
1088  for (const auto& element : elements_) {
1089  if (auto entity = std::get_if<Entity>(&element)) {
1090  new_elements.push_back(entity->Clone());
1091  continue;
1092  }
1093  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1094  new_elements.push_back(subpass->get()->Clone());
1095  continue;
1096  }
1097  FML_UNREACHABLE();
1098  }
1099 
1100  auto pass = std::make_unique<EntityPass>();
1101  pass->SetElements(std::move(new_elements));
1102  pass->backdrop_filter_reads_from_pass_texture_ =
1103  backdrop_filter_reads_from_pass_texture_;
1104  pass->advanced_blend_reads_from_pass_texture_ =
1105  advanced_blend_reads_from_pass_texture_;
1106  pass->backdrop_filter_proc_ = backdrop_filter_proc_;
1107  pass->blend_mode_ = blend_mode_;
1108  pass->delegate_ = delegate_;
1109  // Note: I tried also adding flood clip and bounds limit but one of the
1110  // two caused rendering in wonderous to break. It's 10:51 PM, and I'm
1111  // ready to move on.
1112  return pass;
1113 }

◆ 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 66 of file entity_pass.cc.

66  {
67  return bounds_limit_;
68 }

Referenced by impeller::OpacityPeepholePassDelegate::CanCollapseIntoParentPass().

◆ 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 1136 of file entity_pass.cc.

1136  {
1137  if (backdrop_filter_proc_) {
1138  return std::nullopt;
1139  }
1140 
1141  std::optional<Color> result = std::nullopt;
1142  for (const Element& element : elements_) {
1143  auto [entity_color, blend_mode] =
1144  ElementAsBackgroundColor(element, target_size);
1145  if (!entity_color.has_value()) {
1146  break;
1147  }
1148  result = result.value_or(Color::BlackTransparent())
1149  .Blend(entity_color.value(), blend_mode);
1150  }
1151  if (result.has_value()) {
1152  return result->Premultiply();
1153  }
1154  return result;
1155 }

◆ 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 1132 of file entity_pass.cc.

1132  {
1133  return GetClearColor(size).value_or(Color::BlackTransparent());
1134 }

◆ GetClipDepth()

size_t impeller::EntityPass::GetClipDepth ( )

Definition at line 1123 of file entity_pass.cc.

1123  {
1124  return clip_depth_;
1125 }

◆ GetElementCount()

size_t impeller::EntityPass::GetElementCount ( ) const

Return the number of elements on this pass.

Definition at line 1080 of file entity_pass.cc.

1080  {
1081  return elements_.size();
1082 }

Referenced by impeller::OpacityPeepholePassDelegate::CanCollapseIntoParentPass().

◆ GetElementsCoverage()

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

Definition at line 97 of file entity_pass.cc.

98  {
99  std::optional<Rect> accumulated_coverage;
100  for (const auto& element : elements_) {
101  std::optional<Rect> element_coverage;
102 
103  if (auto entity = std::get_if<Entity>(&element)) {
104  element_coverage = entity->GetCoverage();
105 
106  // When the coverage limit is std::nullopt, that means there is no limit,
107  // as opposed to empty coverage.
108  if (element_coverage.has_value() && coverage_limit.has_value()) {
109  const auto* filter = entity->GetContents()->AsFilter();
110  if (!filter || filter->IsTranslationOnly()) {
111  element_coverage =
112  element_coverage->Intersection(coverage_limit.value());
113  }
114  }
115  } else if (auto subpass_ptr =
116  std::get_if<std::unique_ptr<EntityPass>>(&element)) {
117  auto& subpass = *subpass_ptr->get();
118 
119  std::optional<Rect> unfiltered_coverage =
120  GetSubpassCoverage(subpass, std::nullopt);
121 
122  // If the current pass elements have any coverage so far and there's a
123  // backdrop filter, then incorporate the backdrop filter in the
124  // pre-filtered coverage of the subpass.
125  if (accumulated_coverage.has_value() && subpass.backdrop_filter_proc_) {
126  std::shared_ptr<FilterContents> backdrop_filter =
127  subpass.backdrop_filter_proc_(
128  FilterInput::Make(accumulated_coverage.value()),
129  subpass.transform_, Entity::RenderingMode::kSubpass);
130  if (backdrop_filter) {
131  auto backdrop_coverage = backdrop_filter->GetCoverage({});
132  unfiltered_coverage =
133  Rect::Union(unfiltered_coverage, backdrop_coverage);
134  } else {
135  VALIDATION_LOG << "The EntityPass backdrop filter proc didn't return "
136  "a valid filter.";
137  }
138  }
139 
140  if (!unfiltered_coverage.has_value()) {
141  continue;
142  }
143 
144  // Additionally, subpass textures may be passed through filters, which may
145  // modify the coverage.
146  //
147  // Note that we currently only assume that ImageFilters (such as blurs and
148  // matrix transforms) may modify coverage, although it's technically
149  // possible ColorFilters to affect coverage as well. For example: A
150  // ColorMatrixFilter could output a completely transparent result, and
151  // we could potentially detect this case as zero coverage in the future.
152  std::shared_ptr<FilterContents> image_filter =
153  subpass.delegate_->WithImageFilter(*unfiltered_coverage,
154  subpass.transform_);
155  if (image_filter) {
156  Entity subpass_entity;
157  subpass_entity.SetTransform(subpass.transform_);
158  element_coverage = image_filter->GetCoverage(subpass_entity);
159  } else {
160  element_coverage = unfiltered_coverage;
161  }
162 
163  element_coverage = Rect::Intersection(element_coverage, coverage_limit);
164  } else {
165  FML_UNREACHABLE();
166  }
167 
168  accumulated_coverage = Rect::Union(accumulated_coverage, element_coverage);
169  }
170  return accumulated_coverage;
171 }

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

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

◆ 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 173 of file entity_pass.cc.

175  {
176  std::shared_ptr<FilterContents> image_filter =
177  subpass.delegate_->WithImageFilter(Rect(), subpass.transform_);
178 
179  // If the subpass has an image filter, then its coverage space may deviate
180  // from the parent pass and make intersecting with the pass coverage limit
181  // unsafe.
182  if (image_filter && coverage_limit.has_value()) {
183  coverage_limit = image_filter->GetSourceCoverage(subpass.transform_,
184  coverage_limit.value());
185  }
186 
187  auto entities_coverage = subpass.GetElementsCoverage(coverage_limit);
188  // The entities don't cover anything. There is nothing to do.
189  if (!entities_coverage.has_value()) {
190  return std::nullopt;
191  }
192 
193  if (!subpass.bounds_limit_.has_value()) {
194  return entities_coverage;
195  }
196  auto user_bounds_coverage =
197  subpass.bounds_limit_->TransformBounds(subpass.transform_);
198  return entities_coverage->Intersection(user_bounds_coverage);
199 }

References GetElementsCoverage().

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

◆ GetSubpassesDepth()

size_t impeller::EntityPass::GetSubpassesDepth ( ) const

Definition at line 86 of file entity_pass.cc.

86  {
87  size_t max_subpass_depth = 0u;
88  for (const auto& element : elements_) {
89  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
90  max_subpass_depth =
91  std::max(max_subpass_depth, subpass->get()->GetSubpassesDepth());
92  }
93  }
94  return max_subpass_depth + 1u;
95 }

◆ GetSuperpass()

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

Definition at line 201 of file entity_pass.cc.

201  {
202  return superpass_;
203 }

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

◆ IterateAllElements()

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 1003 of file entity_pass.cc.

1004  {
1005  if (!iterator) {
1006  return;
1007  }
1008 
1009  for (auto& element : elements_) {
1010  if (!iterator(element)) {
1011  return;
1012  }
1013  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1014  subpass->get()->IterateAllElements(iterator);
1015  }
1016  }
1017 }

◆ 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 1040 of file entity_pass.cc.

1041  {
1042  if (!iterator) {
1043  return;
1044  }
1045 
1046  for (const auto& element : elements_) {
1047  if (auto entity = std::get_if<Entity>(&element)) {
1048  if (!iterator(*entity)) {
1049  return;
1050  }
1051  continue;
1052  }
1053  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1054  const EntityPass* entity_pass = subpass->get();
1055  entity_pass->IterateAllEntities(iterator);
1056  continue;
1057  }
1058  FML_UNREACHABLE();
1059  }
1060 }

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 1019 of file entity_pass.cc.

1020  {
1021  if (!iterator) {
1022  return;
1023  }
1024 
1025  for (auto& element : elements_) {
1026  if (auto entity = std::get_if<Entity>(&element)) {
1027  if (!iterator(*entity)) {
1028  return;
1029  }
1030  continue;
1031  }
1032  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1033  subpass->get()->IterateAllEntities(iterator);
1034  continue;
1035  }
1036  FML_UNREACHABLE();
1037  }
1038 }

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 1062 of file entity_pass.cc.

1063  {
1064  if (!iterator) {
1065  return true;
1066  }
1067 
1068  for (auto& element : elements_) {
1069  if (auto entity = std::get_if<Entity>(&element)) {
1070  if (!iterator(*entity)) {
1071  return false;
1072  }
1073  continue;
1074  }
1075  return true;
1076  }
1077  return false;
1078 }

Referenced by impeller::OpacityPeepholePassDelegate::CanCollapseIntoParentPass().

◆ Render()

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

Definition at line 301 of file entity_pass.cc.

302  {
303  auto capture =
304  renderer.GetContext()->capture.GetDocument(kCaptureDocumentName);
305 
306  renderer.GetRenderTargetCache()->Start();
307 
308  auto root_render_target = render_target;
309 
310  if (root_render_target.GetColorAttachments().find(0u) ==
311  root_render_target.GetColorAttachments().end()) {
312  VALIDATION_LOG << "The root RenderTarget must have a color attachment.";
313  return false;
314  }
315 
316  capture.AddRect("Coverage",
317  Rect::MakeSize(root_render_target.GetRenderTargetSize()),
318  {.readonly = true});
319 
320  fml::ScopedCleanupClosure reset_state([&renderer]() {
321  renderer.GetLazyGlyphAtlas()->ResetTextFrames();
322  renderer.GetRenderTargetCache()->End();
323  });
324 
325  IterateAllEntities([lazy_glyph_atlas =
326  renderer.GetLazyGlyphAtlas()](const Entity& entity) {
327  if (const auto& contents = entity.GetContents()) {
328  contents->PopulateGlyphAtlas(lazy_glyph_atlas, entity.DeriveTextScale());
329  }
330  return true;
331  });
332 
333  ClipCoverageStack clip_coverage_stack = {ClipCoverageLayer{
334  .coverage = Rect::MakeSize(root_render_target.GetRenderTargetSize()),
335  .clip_depth = 0}};
336 
337  bool reads_from_onscreen_backdrop = GetTotalPassReads(renderer) > 0;
338  // In this branch path, we need to render everything to an offscreen texture
339  // and then blit the results onto the onscreen texture. If using this branch,
340  // there's no need to set up a stencil attachment on the root render target.
341  if (reads_from_onscreen_backdrop) {
342  auto offscreen_target = CreateRenderTarget(
343  renderer, root_render_target.GetRenderTargetSize(),
344  GetClearColorOrDefault(render_target.GetRenderTargetSize()));
345 
346  if (!OnRender(renderer, // renderer
347  capture, // capture
348  offscreen_target.GetRenderTarget()
349  .GetRenderTargetSize(), // root_pass_size
350  offscreen_target, // pass_target
351  Point(), // global_pass_position
352  Point(), // local_pass_position
353  0, // pass_depth
354  clip_coverage_stack // clip_coverage_stack
355  )) {
356  // Validation error messages are triggered for all `OnRender()` failure
357  // cases.
358  return false;
359  }
360 
361  auto command_buffer = renderer.GetContext()->CreateCommandBuffer();
362  command_buffer->SetLabel("EntityPass Root Command Buffer");
363 
364  // If the context supports blitting, blit the offscreen texture to the
365  // onscreen texture. Otherwise, draw it to the parent texture using a
366  // pipeline (slower).
367  if (renderer.GetContext()
368  ->GetCapabilities()
369  ->SupportsTextureToTextureBlits()) {
370  auto blit_pass = command_buffer->CreateBlitPass();
371  blit_pass->AddCopy(
372  offscreen_target.GetRenderTarget().GetRenderTargetTexture(),
373  root_render_target.GetRenderTargetTexture());
374 
375  if (!command_buffer->EncodeAndSubmit(
376  blit_pass, renderer.GetContext()->GetResourceAllocator())) {
377  VALIDATION_LOG << "Failed to encode root pass blit command.";
378  return false;
379  }
380  } else {
381  auto render_pass = command_buffer->CreateRenderPass(root_render_target);
382  render_pass->SetLabel("EntityPass Root Render Pass");
383 
384  {
385  auto size_rect = Rect::MakeSize(
386  offscreen_target.GetRenderTarget().GetRenderTargetSize());
387  auto contents = TextureContents::MakeRect(size_rect);
388  contents->SetTexture(
389  offscreen_target.GetRenderTarget().GetRenderTargetTexture());
390  contents->SetSourceRect(size_rect);
391  contents->SetLabel("Root pass blit");
392 
393  Entity entity;
394  entity.SetContents(contents);
395  entity.SetBlendMode(BlendMode::kSource);
396 
397  if (!entity.Render(renderer, *render_pass)) {
398  VALIDATION_LOG << "Failed to render EntityPass root blit.";
399  return false;
400  }
401  }
402 
403  if (!command_buffer->EncodeAndSubmit(render_pass)) {
404  VALIDATION_LOG << "Failed to encode root pass command buffer.";
405  return false;
406  }
407  }
408 
409  return true;
410  }
411 
412  // If we make it this far, that means the context is capable of rendering
413  // everything directly to the onscreen texture.
414 
415  // The safety check for fetching this color attachment is at the beginning of
416  // this method.
417  auto color0 = root_render_target.GetColorAttachments().find(0u)->second;
418 
419  // If a root stencil was provided by the caller, then verify that it has a
420  // configuration which can be used to render this pass.
421  auto stencil_attachment = root_render_target.GetStencilAttachment();
422  if (stencil_attachment.has_value()) {
423  auto stencil_texture = stencil_attachment->texture;
424  if (!stencil_texture) {
425  VALIDATION_LOG << "The root RenderTarget must have a stencil texture.";
426  return false;
427  }
428 
429  auto stencil_storage_mode =
430  stencil_texture->GetTextureDescriptor().storage_mode;
431  if (reads_from_onscreen_backdrop &&
432  stencil_storage_mode == StorageMode::kDeviceTransient) {
433  VALIDATION_LOG << "The given root RenderTarget stencil needs to be read, "
434  "but it's marked as transient.";
435  return false;
436  }
437  }
438  // Setup a new root stencil with an optimal configuration if one wasn't
439  // provided by the caller.
440  else {
441  root_render_target.SetupStencilAttachment(
442  *renderer.GetContext(), *renderer.GetRenderTargetCache(),
443  color0.texture->GetSize(),
444  renderer.GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
445  "ImpellerOnscreen", kDefaultStencilConfig);
446  }
447 
448  // Set up the clear color of the root pass.
449  color0.clear_color =
450  GetClearColorOrDefault(render_target.GetRenderTargetSize());
451  root_render_target.SetColorAttachment(color0, 0);
452 
453  EntityPassTarget pass_target(
454  root_render_target,
455  renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
456  renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA());
457 
458  return OnRender( //
459  renderer, // renderer
460  capture, // capture
461  root_render_target.GetRenderTargetSize(), // root_pass_size
462  pass_target, // pass_target
463  Point(), // global_pass_position
464  Point(), // local_pass_position
465  0, // pass_depth
466  clip_coverage_stack); // clip_coverage_stack
467 }

References impeller::ContentContext::GetContext(), impeller::ContentContext::GetLazyGlyphAtlas(), impeller::ContentContext::GetRenderTargetCache(), IterateAllEntities(), kCaptureDocumentName, impeller::TRect< Scalar >::MakeSize(), and VALIDATION_LOG.

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

◆ SetBackdropFilter()

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

Definition at line 1157 of file entity_pass.cc.

1157  {
1158  if (superpass_) {
1159  VALIDATION_LOG << "Backdrop filters cannot be set on EntityPasses that "
1160  "have already been appended to another pass.";
1161  }
1162 
1163  backdrop_filter_proc_ = std::move(proc);
1164 }

References VALIDATION_LOG.

◆ SetBlendMode()

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

Definition at line 1127 of file entity_pass.cc.

1127  {
1128  blend_mode_ = blend_mode;
1129  flood_clip_ = Entity::IsBlendModeDestructive(blend_mode);
1130 }

◆ SetBoundsLimit()

void impeller::EntityPass::SetBoundsLimit ( std::optional< Rect bounds_limit)

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.

Definition at line 62 of file entity_pass.cc.

62  {
63  bounds_limit_ = bounds_limit;
64 }

◆ SetClipDepth()

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

Definition at line 1119 of file entity_pass.cc.

1119  {
1120  clip_depth_ = clip_depth;
1121 }

◆ SetDelegate()

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

Definition at line 55 of file entity_pass.cc.

55  {
56  if (!delegate) {
57  return;
58  }
59  delegate_ = std::move(delegate);
60 }

◆ SetElements()

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

Definition at line 82 of file entity_pass.cc.

82  {
83  elements_ = std::move(elements);
84 }

◆ SetEnableOffscreenCheckerboard()

void impeller::EntityPass::SetEnableOffscreenCheckerboard ( bool  enabled)

Definition at line 1166 of file entity_pass.cc.

1166  {
1167  enable_offscreen_debug_checkerboard_ = enabled;
1168 }

◆ SetTransform()

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

Definition at line 1115 of file entity_pass.cc.

1115  {
1116  transform_ = transform;
1117 }

Member Data Documentation

◆ kCaptureDocumentName

const std::string impeller::EntityPass::kCaptureDocumentName = "EntityPass"
static

Definition at line 39 of file entity_pass.h.

Referenced by Render().


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:1019
impeller::Entity::kLastPipelineBlendMode
static constexpr BlendMode kLastPipelineBlendMode
Definition: entity.h:23
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:173
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::CreateRenderTarget
static EntityPassTarget CreateRenderTarget(ContentContext &renderer, ISize size, const Color &clear_color)
Definition: entity_pass.cc:248
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:142
impeller::EntityPass::ClipCoverageStack
std::vector< ClipCoverageLayer > ClipCoverageStack
Definition: entity_pass.h:51
impeller::kDefaultStencilConfig
static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig
Definition: entity_pass.cc:241
impeller::StorageMode::kDeviceTransient
@ kDeviceTransient
impeller::Point
TPoint< Scalar > Point
Definition: point.h:308
impeller::TRect< Scalar >::Intersection
constexpr std::optional< TRect< Scalar > > Intersection(const TRect &o) const
Definition: rect.h:312
impeller::EntityPass::Element
std::variant< Entity, std::unique_ptr< EntityPass > > Element
Definition: entity_pass.h:37
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:488
impeller::Entity::RenderingMode::kSubpass
@ kSubpass
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:67
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:44
impeller::Color::BlackTransparent
static constexpr Color BlackTransparent()
Definition: color.h:262
impeller::TRect< Scalar >::Union
constexpr TRect Union(const TRect &o) const
Definition: rect.h:302
impeller::EntityPass::kCaptureDocumentName
static const std::string kCaptureDocumentName
Definition: entity_pass.h:39
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::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:1136
impeller::EntityPass::GetClearColorOrDefault
Color GetClearColorOrDefault(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities.
Definition: entity_pass.cc:1132