| Flutter Impeller |

Classes | Public Types | Public Member Functions | Static Public Attributes | List of all members
impeller::EntityPass Class Reference

`#include <entity_pass.h>`

## Classes
struct | StencilCoverageLayer

## 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 | StencilCoverageStack = std::vector< StencilCoverageLayer >

## 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< Rect > | GetBoundsLimit () const
| Get the bounds limit, which is provided by the user when creating a SaveLayer. More...
size_t | GetSubpassesDepth () const
std::unique_ptr< EntityPass > | Clone () const
void | AddEntity (Entity entity)
void | SetElements (std::vector< Element > elements)
EntityPass * | AddSubpass (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...
EntityPass * | GetSuperpass () 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 | SetTransformation (Matrix xformation)
void | SetStencilDepth (size_t stencil_depth)
size_t | GetStencilDepth ()
void | SetBlendMode (BlendMode blend_mode)
Color | GetClearColor (ISize size=ISize::Infinite()) const
void | SetBackdropFilter (BackdropFilterProc proc)
void | SetEnableOffscreenCheckerboard (bool enabled)
std::optional< Rect > | GetSubpassCoverage (const EntityPass &subpass, std::optional< Rect > coverage_limit) const
| Get the coverage of an unfiltered subpass. More...
std::optional< Rect > | GetElementsCoverage (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.

## ◆ 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.

## ◆ StencilCoverageStack

using impeller::EntityPass::StencilCoverageStack = std::vector<StencilCoverageLayer>

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

Definition at line 77 of file entity_pass.cc.

77 {
78 if (entity.GetBlendMode() == BlendMode::kSourceOver &&
79 entity.GetContents()->IsOpaque()) {
80 entity.SetBlendMode(BlendMode::kSource);
81 }
82
83 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
84 advanced_blend_reads_from_pass_texture_ += 1;
85 }
86 elements_.emplace_back(std::move(entity));
87 }

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

Referenced by impeller::Canvas::DrawAtlas(), impeller::Canvas::DrawImageRect(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawPoints(), impeller::Canvas::DrawRect(), impeller::Canvas::DrawRRect(), impeller::Canvas::DrawTextFrame(), impeller::Canvas::DrawVertices(), and impeller::testing::TEST_P().

## ◆ AddSubpass()

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

Appends a given pass as a subpass.

Definition at line 226 of file entity_pass.cc.

226 {
227 if (!pass) {
228 return nullptr;
229 }
230 FML_DCHECK(pass->superpass_ == nullptr);
231 pass->superpass_ = this;
232
233 if (pass->backdrop_filter_proc_) {
234 backdrop_filter_reads_from_pass_texture_ += 1;
235 }
236 if (pass->blend_mode_ > Entity::kLastPipelineBlendMode) {
237 advanced_blend_reads_from_pass_texture_ += 1;
238 }
239
240 auto subpass_pointer = pass.get();
241 elements_.emplace_back(std::move(pass));
242 return subpass_pointer;
243 }

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

245 {
246 if (!pass) {
247 return;
248 }
249 FML_DCHECK(pass->superpass_ == nullptr);
250
251 elements_.insert(elements_.end(),
252 std::make_move_iterator(pass->elements_.begin()),
253 std::make_move_iterator(pass->elements_.end()));
254
255 backdrop_filter_reads_from_pass_texture_ +=
256 pass->backdrop_filter_reads_from_pass_texture_;
257 advanced_blend_reads_from_pass_texture_ +=
258 pass->advanced_blend_reads_from_pass_texture_;
259 }

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

## ◆ Clone()

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

Definition at line 1095 of file entity_pass.cc.

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

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

73 {
74 return bounds_limit_;
75 }

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

## ◆ GetClearColor()

Color impeller::EntityPass::GetClearColor | ( | ISize | size = `ISize::Infinite()` | ) | const

Definition at line 1143 of file entity_pass.cc.

1143 {
1144 Color result = Color::BlackTransparent();
1145 if (backdrop_filter_proc_) {
1146 return result;
1147 }
1148
1149 for (const Element& element : elements_) {
1150 auto [entity_color, blend_mode] =
1151 ElementAsBackgroundColor(element, target_size);
1152 if (!entity_color.has_value()) {
1153 break;
1154 }
1155 result = result.Blend(entity_color.value(), blend_mode);
1156 }
1157 return result.Premultiply();
1158 }

References impeller::Color::Blend(), and impeller::Color::Premultiply().

## ◆ 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 }

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

## ◆ GetElementsCoverage()

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

Definition at line 104 of file entity_pass.cc.

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

References GetSubpassCoverage(), impeller::Entity::kSubpass, impeller::FilterInput::Make(), impeller::Entity::SetTransformation(), and VALIDATION_LOG.

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

## ◆ GetStencilDepth()

size_t impeller::EntityPass::GetStencilDepth | ( |  | ) |

Definition at line 1134 of file entity_pass.cc.

1134 {
1135 return stencil_depth_;
1136 }

## ◆ GetSubpassCoverage()

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

Get the coverage of an unfiltered subpass.

Definition at line 195 of file entity_pass.cc.

197 {
198 std::shared_ptr<FilterContents> image_filter =
199 subpass.delegate_->WithImageFilter(Rect(), subpass.xformation_);
200
201 // If the filter graph transforms the basis of the subpass, then its space
202 // has deviated too much from the parent pass to safely intersect with the
203 // pass coverage limit.
204 coverage_limit =
205 (image_filter && !image_filter->IsTranslationOnly() ? std::nullopt
206 : coverage_limit);
207
208 auto entities_coverage = subpass.GetElementsCoverage(coverage_limit);
209 // The entities don't cover anything. There is nothing to do.
210 if (!entities_coverage.has_value()) {
211 return std::nullopt;
212 }
213
214 if (!subpass.bounds_limit_.has_value()) {
215 return entities_coverage;
216 }
217 auto user_bounds_coverage =
218 subpass.bounds_limit_->TransformBounds(subpass.xformation_);
219 return entities_coverage->Intersection(user_bounds_coverage);
220 }

References GetElementsCoverage().

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

## ◆ GetSubpassesDepth()

size_t impeller::EntityPass::GetSubpassesDepth | ( |  | ) | const

Definition at line 93 of file entity_pass.cc.

93 {
94 size_t max_subpass_depth = 0u;
95 for (const auto& element : elements_) {
96 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
97 max_subpass_depth =
98 std::max(max_subpass_depth, subpass->get()->GetSubpassesDepth());
99 }
100 }
101 return max_subpass_depth + 1u;
102 }

## ◆ GetSuperpass()

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

Definition at line 222 of file entity_pass.cc.

222 {
223 return superpass_;
224 }

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

1015 {
1016 if (!iterator) {
1017 return;
1018 }
1019
1020 for (auto& element : elements_) {
1021 if (!iterator(element)) {
1022 return;
1023 }
1024 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1025 subpass->get()->IterateAllElements(iterator);
1026 }
1027 }
1028 }

## ◆ 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 }

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

## ◆ Render()

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

Definition at line 323 of file entity_pass.cc.

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

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

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

References VALIDATION_LOG.

## ◆ SetBlendMode()

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

Definition at line 1138 of file entity_pass.cc.

1138 {
1139 blend_mode_ = blend_mode;
1140 flood_clip_ = Entity::IsBlendModeDestructive(blend_mode);
1141 }

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

69 {
70 bounds_limit_ = bounds_limit;
71 }

## ◆ SetDelegate()

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

Definition at line 62 of file entity_pass.cc.

62 {
63 if (!delegate) {
64 return;
65 }
66 delegate_ = std::move(delegate);
67 }

## ◆ SetElements()

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

Definition at line 89 of file entity_pass.cc.

89 {
90 elements_ = std::move(elements);
91 }

## ◆ SetEnableOffscreenCheckerboard()

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

Definition at line 1169 of file entity_pass.cc.

1169 {
1170 enable_offscreen_debug_checkerboard_ = enabled;
1171 }

## ◆ SetStencilDepth()

void impeller::EntityPass::SetStencilDepth | ( | size_t | stencil_depth | ) |

Definition at line 1130 of file entity_pass.cc.

1130 {
1131 stencil_depth_ = stencil_depth;
1132 }

## ◆ SetTransformation()

void impeller::EntityPass::SetTransformation | ( | Matrix | xformation | ) |

Definition at line 1126 of file entity_pass.cc.

1126 {
1127 xformation_ = xformation;
1128 }

## 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/entity/entity_pass.h
- impeller/entity/entity_pass.cc

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:23
impeller::EntityPass::GetSubpassCoverage
std::optional< Rect > GetSubpassCoverage(const EntityPass &subpass, std::optional< Rect > coverage_limit) const
Get the coverage of an unfiltered subpass.
Definition: entity_pass.cc:195
impeller::EntityPass::EntityPass
EntityPass()
impeller::FilterInput::Make
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
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:138
impeller::CreateRenderTarget
static EntityPassTarget CreateRenderTarget(ContentContext &renderer, ISize size, bool readable, const Color &clear_color)
Definition: entity_pass.cc:270
impeller::StorageMode::kDeviceTransient
@ kDeviceTransient
impeller::Point
TPoint< Scalar > Point
Definition: point.h:306
impeller::EntityPass::StencilCoverageStack
std::vector< StencilCoverageLayer > StencilCoverageStack
Definition: entity_pass.h:51
impeller::BlendMode::kSourceOver
@ kSourceOver
impeller::EntityPass::Element
std::variant< Entity, std::unique_ptr< EntityPass > > Element
Definition: entity_pass.h:37
impeller::GetDefaultStencilConfig
static RenderTarget::AttachmentConfig GetDefaultStencilConfig(bool readable)
Definition: entity_pass.cc:261
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:306
impeller::Entity::RenderingMode::kSubpass
@ kSubpass
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:52
impeller::EntityPass::GetClearColor
Color GetClearColor(ISize size=ISize::Infinite()) const
Definition: entity_pass.cc:1143
impeller::Color::BlackTransparent
static constexpr Color BlackTransparent()
Definition: color.h:260
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:28
impeller::BlendMode::kSource
@ kSource