Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Attributes | 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.
 
std::optional< RectGetBoundsLimit () const
 Get the bounds limit, which is provided by the user when creating a SaveLayer.
 
bool GetBoundsLimitMightClipContent () const
 Indicates if the bounds limit set using |SetBoundsLimit()| might clip the contents of the pass.
 
bool GetBoundsLimitIsSnug () const
 Indicates if the bounds limit set using |SetBoundsLimit()| is a reasonably tight estimate of the bounds of the contents.
 
size_t GetSubpassesDepth () const
 
void AddEntity (Entity entity)
 Add an entity to the current entity pass.
 
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.
 
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.
 
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.
 
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.
 
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.
 
size_t GetElementCount () const
 Return the number of elements on this pass.
 
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.
 
Color GetClearColorOrDefault (ISize size=ISize::Infinite()) const
 Return the premultiplied clear color of the pass entities.
 
void SetBackdropFilter (BackdropFilterProc proc)
 
void SetEnableOffscreenCheckerboard (bool enabled)
 
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.
 
std::optional< RectGetElementsCoverage (std::optional< Rect > coverage_limit) const
 

Static Public Attributes

static const std::string kCaptureDocumentName = "EntityPass"
 

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

106 {
107 if (entity.GetBlendMode() == BlendMode::kSourceOver &&
108 entity.GetContents()->IsOpaque()) {
109 entity.SetBlendMode(BlendMode::kSource);
110 }
111
112 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
113 advanced_blend_reads_from_pass_texture_ = true;
114 }
115 elements_.emplace_back(std::move(entity));
116}
static constexpr BlendMode kLastPipelineBlendMode
Definition entity.h:23

◆ AddSubpass()

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

Appends a given pass as a subpass.

Definition at line 272 of file entity_pass.cc.

272 {
273 if (!pass) {
274 return nullptr;
275 }
276 FML_DCHECK(pass->superpass_ == nullptr);
277 pass->superpass_ = this;
278
279 if (pass->backdrop_filter_proc_) {
280 backdrop_filter_reads_from_pass_texture_ = true;
281 }
282 if (pass->blend_mode_ > Entity::kLastPipelineBlendMode) {
283 advanced_blend_reads_from_pass_texture_ = true;
284 }
285
286 auto subpass_pointer = pass.get();
287 elements_.emplace_back(std::move(pass));
288 return subpass_pointer;
289}
#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 71 of file entity_pass.cc.

71 {
72 return bounds_limit_;
73}

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

94 {
95 switch (bounds_promise_) {
97 return false;
100 FML_DCHECK(bounds_limit_.has_value());
101 return true;
102 }
104}
#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 75 of file entity_pass.cc.

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

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

1163 {
1164 if (backdrop_filter_proc_) {
1165 return std::nullopt;
1166 }
1167
1168 std::optional<Color> result = std::nullopt;
1169 for (const Element& element : elements_) {
1170 auto [entity_color, blend_mode] =
1171 ElementAsBackgroundColor(element, target_size);
1172 if (!entity_color.has_value()) {
1173 break;
1174 }
1176 .Blend(entity_color.value(), blend_mode);
1177 }
1178 if (result.has_value()) {
1179 return result->Premultiply();
1180 }
1181 return result;
1182}
GAsyncResult * result
static constexpr Color BlackTransparent()
Definition color.h:262

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

1159 {
1160 return GetClearColor(size).value_or(Color::BlackTransparent());
1161}
std::optional< Color > GetClearColor(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities, if any.

◆ GetClipDepth()

uint32_t impeller::EntityPass::GetClipDepth ( ) const

Definition at line 1150 of file entity_pass.cc.

1150 {
1151 return clip_depth_;
1152}

◆ GetClipHeight()

size_t impeller::EntityPass::GetClipHeight ( ) const

Definition at line 1142 of file entity_pass.cc.

1142 {
1143 return clip_height_;
1144}

◆ GetElementCount()

size_t impeller::EntityPass::GetElementCount ( ) const

Return the number of elements on this pass.

Definition at line 1130 of file entity_pass.cc.

1130 {
1131 return elements_.size();
1132}

◆ GetElementsCoverage()

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

Definition at line 160 of file entity_pass.cc.

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

◆ GetRequiredMipCount()

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

Definition at line 179 of file entity_pass.h.

179{ 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 236 of file entity_pass.cc.

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

◆ GetSubpassesDepth()

size_t impeller::EntityPass::GetSubpassesDepth ( ) const

Definition at line 149 of file entity_pass.cc.

149 {
150 size_t max_subpass_depth = 0u;
151 for (const auto& element : elements_) {
152 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
153 max_subpass_depth =
154 std::max(max_subpass_depth, subpass->get()->GetSubpassesDepth());
155 }
156 }
157 return max_subpass_depth + 1u;
158}

◆ GetSuperpass()

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

Definition at line 268 of file entity_pass.cc.

268 {
269 return superpass_;
270}

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

1051 {
1052 /// TODO(gaaclarke): Remove duplication here between const and non-const
1053 /// versions.
1054 if (!iterator) {
1055 return;
1056 }
1057
1058 for (auto& element : elements_) {
1059 if (!iterator(element)) {
1060 return;
1061 }
1062 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1063 const EntityPass* entity_pass = subpass->get();
1064 entity_pass->IterateAllElements(iterator);
1065 }
1066 }
1067}

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

1035 {
1036 if (!iterator) {
1037 return;
1038 }
1039
1040 for (auto& element : elements_) {
1041 if (!iterator(element)) {
1042 return;
1043 }
1044 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1045 subpass->get()->IterateAllElements(iterator);
1046 }
1047 }
1048}

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

1091 {
1092 if (!iterator) {
1093 return;
1094 }
1095
1096 for (const auto& element : elements_) {
1097 if (auto entity = std::get_if<Entity>(&element)) {
1098 if (!iterator(*entity)) {
1099 return;
1100 }
1101 continue;
1102 }
1103 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1104 const EntityPass* entity_pass = subpass->get();
1105 entity_pass->IterateAllEntities(iterator);
1106 continue;
1107 }
1109 }
1110}

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

1070 {
1071 if (!iterator) {
1072 return;
1073 }
1074
1075 for (auto& element : elements_) {
1076 if (auto entity = std::get_if<Entity>(&element)) {
1077 if (!iterator(*entity)) {
1078 return;
1079 }
1080 continue;
1081 }
1082 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1083 subpass->get()->IterateAllEntities(iterator);
1084 continue;
1085 }
1087 }
1088}

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

1113 {
1114 if (!iterator) {
1115 return true;
1116 }
1117
1118 for (auto& element : elements_) {
1119 if (auto entity = std::get_if<Entity>(&element)) {
1120 if (!iterator(*entity)) {
1121 return false;
1122 }
1123 continue;
1124 }
1125 return true;
1126 }
1127 return false;
1128}

◆ PopAllClips()

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

Definition at line 141 of file entity_pass.cc.

141 {
142 PopClips(active_clips_.size(), depth);
143}
void PopClips(size_t num_clips, uint64_t depth)

◆ PopClips()

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

Definition at line 123 of file entity_pass.cc.

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

◆ PushClip()

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

Definition at line 118 of file entity_pass.cc.

118 {
119 elements_.emplace_back(std::move(entity));
120 active_clips_.emplace_back(elements_.size() - 1);
121}

◆ Render()

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

Definition at line 359 of file entity_pass.cc.

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

1184 {
1185 if (superpass_) {
1186 VALIDATION_LOG << "Backdrop filters cannot be set on EntityPasses that "
1187 "have already been appended to another pass.";
1188 }
1189
1190 backdrop_filter_proc_ = std::move(proc);
1191}

◆ SetBlendMode()

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

Definition at line 1154 of file entity_pass.cc.

1154 {
1155 blend_mode_ = blend_mode;
1156 flood_clip_ = Entity::IsBlendModeDestructive(blend_mode);
1157}
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 64 of file entity_pass.cc.

65 {
66 bounds_limit_ = bounds_limit;
67 bounds_promise_ = bounds_limit.has_value() ? bounds_promise
69}

◆ SetClipDepth()

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

Definition at line 1146 of file entity_pass.cc.

1146 {
1147 clip_depth_ = clip_depth;
1148}

◆ SetClipHeight()

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

Definition at line 1138 of file entity_pass.cc.

1138 {
1139 clip_height_ = clip_height;
1140}

◆ SetDelegate()

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

Definition at line 57 of file entity_pass.cc.

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

◆ SetElements()

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

Definition at line 145 of file entity_pass.cc.

145 {
146 elements_ = std::move(elements);
147}

◆ SetEnableOffscreenCheckerboard()

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

Definition at line 1193 of file entity_pass.cc.

1193 {
1194 enable_offscreen_debug_checkerboard_ = enabled;
1195}

◆ SetRequiredMipCount()

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

Definition at line 181 of file entity_pass.h.

181 {
182 required_mip_count_ = mip_count;
183 }

◆ SetTransform()

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

Definition at line 1134 of file entity_pass.cc.

1134 {
1135 transform_ = transform;
1136}
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47

Member Data Documentation

◆ kCaptureDocumentName

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

Definition at line 56 of file entity_pass.h.


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