| 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 | 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< 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)
| Add an entity to the current entity pass. More...
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 | SetTransform (Matrix transform)
void | SetClipDepth (size_t clip_depth)
size_t | GetClipDepth ()
void | SetBlendMode (BlendMode blend_mode)
std::optional< Color > | GetClearColor (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< 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 subpass before it's rendered to and passed through the subpass ImageFilter, if any. 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.

## ◆ ClipCoverageStack

using impeller::EntityPass::ClipCoverageStack = std::vector<ClipCoverageLayer>

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 | ) |

Add an entity to the current entity pass.

Definition at line 70 of file entity_pass.cc.

70 {
71 if (entity.GetBlendMode() == BlendMode::kSourceOver &&
72 entity.GetContents()->IsOpaque()) {
73 entity.SetBlendMode(BlendMode::kSource);
74 }
75
76 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
77 advanced_blend_reads_from_pass_texture_ += 1;
78 }
79 elements_.emplace_back(std::move(entity));
80 }

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::DrawCircle(), impeller::Canvas::DrawImageRect(), impeller::Canvas::DrawLine(), impeller::Canvas::DrawOval(), 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 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] | subpass | The EntityPass for which to compute pre-filteredcoverage.
  [in] | coverage_limit | Confines 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/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: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