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 25 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 43 of file entity_pass.h.

◆ ClipCoverageStack

Definition at line 50 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 36 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 1080 of file entity_pass.cc.

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

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

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

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

1128  {
1129  return GetClearColor(size).value_or(Color::BlackTransparent());
1130 }

◆ GetClipDepth()

size_t impeller::EntityPass::GetClipDepth ( )

Definition at line 1119 of file entity_pass.cc.

1119  {
1120  return clip_depth_;
1121 }

◆ GetElementCount()

size_t impeller::EntityPass::GetElementCount ( ) const

Return the number of elements on this pass.

Definition at line 1076 of file entity_pass.cc.

1076  {
1077  return elements_.size();
1078 }

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

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

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

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

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

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

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

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

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

◆ Render()

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

Definition at line 304 of file entity_pass.cc.

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

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

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

References VALIDATION_LOG.

◆ SetBlendMode()

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

Definition at line 1123 of file entity_pass.cc.

1123  {
1124  blend_mode_ = blend_mode;
1125  flood_clip_ = Entity::IsBlendModeDestructive(blend_mode);
1126 }

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

1115  {
1116  clip_depth_ = clip_depth;
1117 }

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

1162  {
1163  enable_offscreen_debug_checkerboard_ = enabled;
1164 }

◆ SetTransform()

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

Definition at line 1111 of file entity_pass.cc.

1111  {
1112  transform_ = transform;
1113 }

Member Data Documentation

◆ kCaptureDocumentName

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

Definition at line 38 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:1015
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::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:50
impeller::CreateRenderTarget
static EntityPassTarget CreateRenderTarget(ContentContext &renderer, ISize size, bool readable, const Color &clear_color)
Definition: entity_pass.cc:250
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:36
impeller::GetDefaultStencilConfig
static RenderTarget::AttachmentConfig GetDefaultStencilConfig(bool readable)
Definition: entity_pass.cc:241
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:38
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:1132
impeller::EntityPass::GetClearColorOrDefault
Color GetClearColorOrDefault(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities.
Definition: entity_pass.cc:1128