Flutter Engine
The Flutter Engine
Classes | Public Types | Public Member Functions | List of all members
impeller::EntityPass Class Reference

#include <entity_pass.h>

Public Types

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

Public Member Functions

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

Detailed Description

Definition at line 43 of file entity_pass.h.

Member Typedef Documentation

◆ BackdropFilterProc

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

Definition at line 56 of file entity_pass.h.

◆ Element

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

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

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

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

Definition at line 54 of file entity_pass.h.

Constructor & Destructor Documentation

◆ EntityPass()

impeller::EntityPass::EntityPass ( )
default

◆ ~EntityPass()

impeller::EntityPass::~EntityPass ( )
default

Member Function Documentation

◆ AddEntity()

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

Add an entity to the current entity pass.

Definition at line 100 of file entity_pass.cc.

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

◆ AddSubpass()

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

Appends a given pass as a subpass.

Definition at line 267 of file entity_pass.cc.

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

◆ GetBoundsLimit()

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

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

Definition at line 65 of file entity_pass.cc.

65 {
66 return bounds_limit_;
67}

◆ GetBoundsLimitIsSnug()

bool impeller::EntityPass::GetBoundsLimitIsSnug ( ) const

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

Definition at line 88 of file entity_pass.cc.

88 {
89 switch (bounds_promise_) {
91 return false;
94 FML_DCHECK(bounds_limit_.has_value());
95 return true;
96 }
98}
#define FML_UNREACHABLE()
Definition: logging.h:109
@ kUnknown
The caller makes no claims related to the size of the bounds.
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...

◆ GetBoundsLimitMightClipContent()

bool impeller::EntityPass::GetBoundsLimitMightClipContent ( ) const

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

Definition at line 69 of file entity_pass.cc.

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

◆ GetClearColor()

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

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

Definition at line 1124 of file entity_pass.cc.

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

◆ GetClearColorOrDefault()

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

Return the premultiplied clear color of the pass entities.

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

Definition at line 1120 of file entity_pass.cc.

1120 {
1121 return GetClearColor(size).value_or(Color::BlackTransparent());
1122}
std::optional< Color > GetClearColor(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities, if any.
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259

◆ GetClipDepth()

uint32_t impeller::EntityPass::GetClipDepth ( ) const

Definition at line 1111 of file entity_pass.cc.

1111 {
1112 return clip_depth_;
1113}

◆ GetClipHeight()

size_t impeller::EntityPass::GetClipHeight ( ) const

Definition at line 1103 of file entity_pass.cc.

1103 {
1104 return clip_height_;
1105}

◆ GetElementCount()

size_t impeller::EntityPass::GetElementCount ( ) const

Return the number of elements on this pass.

Definition at line 1091 of file entity_pass.cc.

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

◆ GetElementsCoverage()

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

Definition at line 154 of file entity_pass.cc.

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

◆ GetRequiredMipCount()

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

Definition at line 175 of file entity_pass.h.

175{ return required_mip_count_; }

◆ GetSubpassCoverage()

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

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

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

Definition at line 231 of file entity_pass.cc.

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

◆ GetSubpassesDepth()

size_t impeller::EntityPass::GetSubpassesDepth ( ) const

Definition at line 143 of file entity_pass.cc.

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

◆ GetSuperpass()

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

Definition at line 263 of file entity_pass.cc.

263 {
264 return superpass_;
265}

◆ IterateAllElements() [1/2]

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

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

Definition at line 1011 of file entity_pass.cc.

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

◆ IterateAllElements() [2/2]

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

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

Definition at line 995 of file entity_pass.cc.

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

◆ 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 }
1070 }
1071}

◆ 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 }
1048 }
1049}

◆ IterateUntilSubpass()

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

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

Returns
Returns whether a subpass was encountered.

Definition at line 1073 of file entity_pass.cc.

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

◆ PopAllClips()

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

Definition at line 135 of file entity_pass.cc.

135 {
136 PopClips(active_clips_.size(), depth);
137}
void PopClips(size_t num_clips, uint64_t depth)
Definition: entity_pass.cc:117

◆ PopClips()

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

Definition at line 117 of file entity_pass.cc.

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

◆ PushClip()

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

Definition at line 112 of file entity_pass.cc.

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

◆ Render()

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

Definition at line 354 of file entity_pass.cc.

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

◆ SetBackdropFilter()

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

Definition at line 1145 of file entity_pass.cc.

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

◆ SetBlendMode()

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

Definition at line 1115 of file entity_pass.cc.

1115 {
1116 blend_mode_ = blend_mode;
1117 flood_clip_ = Entity::IsBlendModeDestructive(blend_mode);
1118}
static bool IsBlendModeDestructive(BlendMode blend_mode)
Returns true if the blend mode is "destructive", meaning that even fully transparent source colors wo...
Definition: entity.cc:156

◆ SetBoundsLimit()

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

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

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

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

Definition at line 58 of file entity_pass.cc.

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

◆ SetClipDepth()

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

Definition at line 1107 of file entity_pass.cc.

1107 {
1108 clip_depth_ = clip_depth;
1109}

◆ SetClipHeight()

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

Definition at line 1099 of file entity_pass.cc.

1099 {
1100 clip_height_ = clip_height;
1101}

◆ SetDelegate()

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

Definition at line 51 of file entity_pass.cc.

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

◆ SetElements()

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

Definition at line 139 of file entity_pass.cc.

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

◆ SetRequiredMipCount()

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

Definition at line 177 of file entity_pass.h.

177 {
178 required_mip_count_ = mip_count;
179 }

◆ SetTransform()

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

Definition at line 1095 of file entity_pass.cc.

1095 {
1096 transform_ = transform;
1097}
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition: p3.cpp:47

The documentation for this class was generated from the following files: