12#include "flutter/fml/closure.h"
13#include "flutter/fml/logging.h"
14#include "flutter/fml/trace_event.h"
38std::tuple<std::optional<Color>,
BlendMode> ElementAsBackgroundColor(
41 if (
const Entity* entity = std::get_if<Entity>(&element)) {
42 std::optional<Color> entity_color = entity->AsBackgroundColor(target_size);
43 if (entity_color.has_value()) {
44 return {entity_color.value(), entity->GetBlendMode()};
61 delegate_ = std::move(delegate);
66 bounds_limit_ = bounds_limit;
67 bounds_promise_ = bounds_limit.has_value() ? bounds_promise
76 switch (bounds_promise_) {
83 return bounds_limit_.has_value();
95 switch (bounds_promise_) {
113 advanced_blend_reads_from_pass_texture_ =
true;
115 elements_.emplace_back(std::move(entity));
119 elements_.emplace_back(std::move(entity));
120 active_clips_.emplace_back(elements_.size() - 1);
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;
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()]);
137 active_clips_.pop_back();
142 PopClips(active_clips_.size(), depth);
146 elements_ = std::move(elements);
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)) {
154 std::max(max_subpass_depth, subpass->get()->GetSubpassesDepth());
157 return max_subpass_depth + 1u;
161 std::optional<Rect> coverage_limit)
const {
162 std::optional<Rect> accumulated_coverage;
163 for (
const auto& element : elements_) {
164 std::optional<Rect> element_coverage;
166 if (
auto entity = std::get_if<Entity>(&element)) {
167 element_coverage = entity->GetCoverage();
171 if (element_coverage.has_value() && coverage_limit.has_value()) {
172 const auto* filter = entity->GetContents()->AsFilter();
173 if (!filter || filter->IsTranslationOnly()) {
175 element_coverage->Intersection(coverage_limit.value());
178 }
else if (
auto subpass_ptr =
179 std::get_if<std::unique_ptr<EntityPass>>(&element)) {
180 auto& subpass = *subpass_ptr->get();
182 std::optional<Rect> unfiltered_coverage =
188 if (accumulated_coverage.has_value() && subpass.backdrop_filter_proc_) {
189 std::shared_ptr<FilterContents> backdrop_filter =
190 subpass.backdrop_filter_proc_(
193 if (backdrop_filter) {
194 auto backdrop_coverage = backdrop_filter->GetCoverage({});
195 unfiltered_coverage =
196 Rect::Union(unfiltered_coverage, backdrop_coverage);
198 VALIDATION_LOG <<
"The EntityPass backdrop filter proc didn't return "
203 if (!unfiltered_coverage.has_value()) {
215 std::shared_ptr<FilterContents> image_filter =
216 subpass.delegate_->WithImageFilter(*unfiltered_coverage,
221 element_coverage = image_filter->GetCoverage(subpass_entity);
223 element_coverage = unfiltered_coverage;
231 accumulated_coverage =
Rect::Union(accumulated_coverage, element_coverage);
233 return accumulated_coverage;
238 std::optional<Rect> coverage_limit)
const {
240 return subpass.bounds_limit_->TransformBounds(subpass.transform_);
243 std::shared_ptr<FilterContents> image_filter =
244 subpass.delegate_->WithImageFilter(
Rect(), subpass.transform_);
249 if (image_filter && coverage_limit.has_value()) {
250 coverage_limit = image_filter->GetSourceCoverage(subpass.transform_,
251 coverage_limit.value());
256 if (!entities_coverage.has_value()) {
260 if (!subpass.bounds_limit_.has_value()) {
261 return entities_coverage;
263 auto user_bounds_coverage =
264 subpass.bounds_limit_->TransformBounds(subpass.transform_);
265 return entities_coverage->Intersection(user_bounds_coverage);
277 pass->superpass_ =
this;
279 if (pass->backdrop_filter_proc_) {
280 backdrop_filter_reads_from_pass_texture_ =
true;
283 advanced_blend_reads_from_pass_texture_ =
true;
286 auto subpass_pointer = pass.get();
287 elements_.emplace_back(std::move(pass));
288 return subpass_pointer;
301 const Color& clear_color) {
302 const std::shared_ptr<Context>& context = renderer.GetContext();
316 if (context->GetCapabilities()->SupportsOffscreenMSAA()) {
317 target = renderer.GetRenderTargetCache()->CreateOffscreenMSAA(
328 .clear_color = clear_color},
332 target = renderer.GetRenderTargetCache()->CreateOffscreen(
341 .clear_color = clear_color,
348 target, renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
349 renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA());
352bool EntityPass::DoesBackdropGetRead(ContentContext& renderer)
const {
353 return renderer.GetDeviceCapabilities().SupportsFramebufferFetch()
354 ? backdrop_filter_reads_from_pass_texture_
355 : backdrop_filter_reads_from_pass_texture_ ||
356 advanced_blend_reads_from_pass_texture_;
364 renderer.GetRenderTargetCache()->Start();
366 renderer.GetLazyGlyphAtlas()->ResetTextFrames();
367 renderer.GetRenderTargetCache()->End();
370 auto root_render_target = render_target;
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.";
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.";
384 capture.AddRect(
"Coverage",
388 const auto& lazy_glyph_atlas = renderer.GetLazyGlyphAtlas();
391 contents->PopulateGlyphAtlas(lazy_glyph_atlas, entity.DeriveTextScale());
402 if (DoesBackdropGetRead(renderer)) {
404 renderer, root_render_target.GetRenderTargetSize(),
408 if (!OnRender(renderer,
423 auto command_buffer = renderer.GetContext()->CreateCommandBuffer();
424 command_buffer->SetLabel(
"EntityPass Root Command Buffer");
429 if (renderer.GetContext()
431 ->SupportsTextureToTextureBlits()) {
432 auto blit_pass = command_buffer->CreateBlitPass();
435 root_render_target.GetRenderTargetTexture());
436 if (!blit_pass->EncodeCommands(
437 renderer.GetContext()->GetResourceAllocator())) {
441 if (!renderer.GetContext()
443 ->Submit({command_buffer})
448 auto render_pass = command_buffer->CreateRenderPass(root_render_target);
449 render_pass->SetLabel(
"EntityPass Root Render Pass");
455 contents->SetTexture(
457 contents->SetSourceRect(size_rect);
458 contents->SetLabel(
"Root pass blit");
464 if (!entity.
Render(renderer, *render_pass)) {
470 if (!render_pass->EncodeCommands()) {
474 if (!renderer.GetContext()
476 ->Submit({command_buffer})
490 auto color0 = root_render_target.GetColorAttachments().find(0u)->second;
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()) {
497 root_render_target.SetupDepthStencilAttachments(
498 *renderer.GetContext(), *renderer.GetContext()->GetResourceAllocator(),
499 color0.texture->GetSize(),
500 renderer.GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
507 root_render_target.SetColorAttachment(color0, 0);
511 renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
512 renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA());
517 root_render_target.GetRenderTargetSize(),
525EntityPass::EntityResult EntityPass::GetEntityForElement(
530 ISize root_pass_size,
531 Point global_pass_position,
534 size_t clip_height_floor)
const {
538 if (
const auto& entity = std::get_if<Entity>(&element)) {
542 if (!global_pass_position.
IsZero()) {
550 return EntityPass::EntityResult::Success(std::move(element_entity));
556 if (
const auto& subpass_ptr =
557 std::get_if<std::unique_ptr<EntityPass>>(&element)) {
558 auto subpass = subpass_ptr->get();
559 if (subpass->delegate_->CanElide()) {
560 return EntityPass::EntityResult::Skip();
563 if (!subpass->backdrop_filter_proc_ &&
564 subpass->delegate_->CanCollapseIntoParentPass(subpass)) {
565 auto subpass_capture = capture.
CreateChild(
"EntityPass (Collapsed)");
567 if (!subpass->OnRender(
572 global_pass_position,
582 return EntityPass::EntityResult::Failure();
584 return EntityPass::EntityResult::Skip();
587 std::shared_ptr<Contents> subpass_backdrop_filter_contents =
nullptr;
588 if (subpass->backdrop_filter_proc_) {
591 const auto& proc = subpass->backdrop_filter_proc_;
592 subpass_backdrop_filter_contents =
613 capture.
CreateChild(
"Subpass Entity (Skipped: Empty clip A)");
614 return EntityPass::EntityResult::Skip();
617 if (!clip_coverage_back.has_value()) {
618 capture.
CreateChild(
"Subpass Entity (Skipped: Empty clip B)");
619 return EntityPass::EntityResult::Skip();
629 if (!coverage_limit.has_value()) {
630 capture.
CreateChild(
"Subpass Entity (Skipped: Empty coverage limit A)");
631 return EntityPass::EntityResult::Skip();
636 if (!coverage_limit.has_value()) {
637 capture.
CreateChild(
"Subpass Entity (Skipped: Empty coverage limit B)");
638 return EntityPass::EntityResult::Skip();
641 auto subpass_coverage =
642 (subpass->flood_clip_ || subpass_backdrop_filter_contents)
645 if (!subpass_coverage.has_value()) {
646 capture.
CreateChild(
"Subpass Entity (Skipped: Empty subpass coverage A)");
647 return EntityPass::EntityResult::Skip();
650 auto subpass_size =
ISize(subpass_coverage->GetSize());
651 if (subpass_size.IsEmpty()) {
652 capture.
CreateChild(
"Subpass Entity (Skipped: Empty subpass coverage B)");
653 return EntityPass::EntityResult::Skip();
659 subpass->GetRequiredMipCount(),
660 subpass->GetClearColorOrDefault(subpass_size));
662 if (!subpass_target.IsValid()) {
664 return EntityPass::EntityResult::Failure();
667 auto subpass_capture = capture.
CreateChild(
"EntityPass");
668 subpass_capture.AddRect(
"Coverage", *subpass_coverage, {.readonly =
true});
675 clip_coverage_stack.
PushSubpass(subpass_coverage, subpass->clip_height_);
679 if (!subpass->OnRender(
684 subpass_coverage->GetOrigin(),
685 subpass_coverage->GetOrigin() -
686 global_pass_position,
689 subpass->clip_height_,
690 subpass_backdrop_filter_contents
694 return EntityPass::EntityResult::Failure();
700 auto subpass_texture =
701 subpass_target.GetRenderTarget().GetRenderTargetTexture();
703 auto offscreen_texture_contents =
704 subpass->delegate_->CreateContentsForSubpassTarget(
707 subpass->transform_);
709 if (!offscreen_texture_contents) {
718 return EntityPass::EntityResult::Failure();
720 Entity element_entity;
721 Capture subpass_texture_capture =
723 element_entity.SetClipDepth(subpass->clip_depth_);
724 element_entity.SetCapture(subpass_texture_capture);
725 element_entity.SetContents(std::move(offscreen_texture_contents));
726 element_entity.SetBlendMode(subpass->blend_mode_);
727 element_entity.SetTransform(subpass_texture_capture.AddMatrix(
730 Vector3(subpass_coverage->GetOrigin() - global_pass_position))));
732 return EntityPass::EntityResult::Success(std::move(element_entity));
739 Point global_pass_position) {
743 if (clip_coverage.has_value()) {
744 clip_coverage = clip_coverage->
Shift(-global_pass_position);
753bool EntityPass::RenderElement(Entity& element_entity,
754 size_t clip_height_floor,
755 InlinePassContext& pass_context,
757 ContentContext& renderer,
758 EntityPassClipStack& clip_coverage_stack,
759 Point global_pass_position)
const {
760 auto result = pass_context.GetRenderPass(pass_depth);
773 if (
result.backdrop_texture) {
776 msaa_backdrop_contents->SetStencilEnabled(
false);
777 msaa_backdrop_contents->SetLabel(
"MSAA backdrop");
778 msaa_backdrop_contents->SetSourceRect(size_rect);
779 msaa_backdrop_contents->SetTexture(
result.backdrop_texture);
781 Entity msaa_backdrop_entity;
782 msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
784 msaa_backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
785 if (!msaa_backdrop_entity.Render(renderer, *
result.pass)) {
786 VALIDATION_LOG <<
"Failed to render MSAA backdrop filter entity.";
791 if (
result.just_created) {
794 auto& replay_entities = clip_coverage_stack.GetReplayEntities();
795 for (
const auto& replay : replay_entities) {
797 global_pass_position);
798 if (!replay.entity.Render(renderer, *
result.pass)) {
804 auto current_clip_coverage = clip_coverage_stack.CurrentClipCoverage();
805 if (current_clip_coverage.has_value()) {
808 current_clip_coverage = current_clip_coverage->Shift(-global_pass_position);
811 if (!element_entity.ShouldRender(current_clip_coverage)) {
815 auto clip_coverage = element_entity.GetClipCoverage(current_clip_coverage);
816 if (clip_coverage.coverage.has_value()) {
817 clip_coverage.coverage =
818 clip_coverage.coverage->Shift(global_pass_position);
825 auto element_coverage_hint = element_entity.GetContents()->GetCoverageHint();
826 element_entity.GetContents()->SetCoverageHint(
829 EntityPassClipStack::ClipStateResult clip_state_result =
830 clip_coverage_stack.ApplyClipState(clip_coverage, element_entity,
832 global_pass_position);
834 if (clip_state_result.clip_did_change) {
837 global_pass_position);
840 if (!clip_state_result.should_render) {
844 if (!element_entity.Render(renderer, *
result.pass)) {
851bool EntityPass::OnRender(
852 ContentContext& renderer,
854 ISize root_pass_size,
855 EntityPassTarget& pass_target,
856 Point global_pass_position,
857 Point local_pass_position,
859 EntityPassClipStack& clip_coverage_stack,
860 size_t clip_height_floor,
861 std::shared_ptr<Contents> backdrop_filter_contents,
862 const std::optional<InlinePassContext::RenderPassResult>&
863 collapsed_parent_pass)
const {
866 if (!active_clips_.empty()) {
868 "EntityPass (Depth=%d) contains one or more clips with an unresolved "
873 InlinePassContext pass_context(renderer, pass_target,
GetElementCount(),
874 collapsed_parent_pass);
875 if (!pass_context.IsValid()) {
879 auto clear_color_size = pass_target.GetRenderTarget().GetRenderTargetSize();
881 if (!collapsed_parent_pass) {
885 pass_context.GetRenderPass(pass_depth);
888 if (backdrop_filter_proc_) {
889 if (!backdrop_filter_contents) {
891 <<
"EntityPass contains a backdrop filter, but no backdrop filter "
892 "contents was supplied by the parent pass at render time. This is "
893 "a bug in EntityPass. Parent passes are responsible for setting "
894 "up backdrop filters for their children.";
898 Entity backdrop_entity;
899 backdrop_entity.SetContents(std::move(backdrop_filter_contents));
900 backdrop_entity.SetTransform(
902 backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
904 RenderElement(backdrop_entity, clip_height_floor, pass_context, pass_depth,
905 renderer, clip_coverage_stack, global_pass_position);
908 bool is_collapsing_clear_colors = !collapsed_parent_pass &&
911 !backdrop_filter_proc_;
912 for (
const auto& element : elements_) {
914 if (is_collapsing_clear_colors) {
915 auto [entity_color,
_] =
916 ElementAsBackgroundColor(element, clear_color_size);
917 if (entity_color.has_value()) {
920 is_collapsing_clear_colors =
false;
924 GetEntityForElement(element,
929 global_pass_position,
935 case EntityResult::kSuccess:
937 case EntityResult::kFailure:
941 case EntityResult::kSkip:
950 if (
renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) {
951 auto src_contents =
result.entity.GetContents();
952 auto contents = std::make_shared<FramebufferBlendContents>();
953 contents->SetChildContents(src_contents);
954 contents->SetBlendMode(
result.entity.GetBlendMode());
955 result.entity.SetContents(std::move(contents));
968 if (!pass_context.EndPass()) {
970 <<
"Failed to end the current render pass in order to read from "
971 "the backdrop texture and apply an advanced blend.";
977 auto texture = pass_context.GetTexture();
979 VALIDATION_LOG <<
"Failed to fetch the color texture in order to "
980 "apply an advanced blend.";
988 result.entity.GetBlendMode(), inputs);
989 contents->SetCoverageHint(
result.entity.GetCoverage());
990 result.entity.SetContents(std::move(contents));
998 if (!RenderElement(
result.entity, clip_height_floor, pass_context,
999 pass_depth, renderer, clip_coverage_stack,
1000 global_pass_position)) {
1006#ifdef IMPELLER_DEBUG
1013 if (enable_offscreen_debug_checkerboard_ &&
1014 !collapsed_parent_pass.has_value() && pass_depth > 0) {
1015 auto result = pass_context.GetRenderPass(pass_depth);
1022 auto color = ColorHSB(0,
1024 std::max(0.0, 0.6 - pass_depth / 5),
1035 const std::function<
bool(
Element&)>& iterator) {
1040 for (
auto& element : elements_) {
1041 if (!iterator(element)) {
1044 if (
auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1045 subpass->get()->IterateAllElements(iterator);
1051 const std::function<
bool(
const Element&)>& iterator)
const {
1058 for (
auto& element : elements_) {
1059 if (!iterator(element)) {
1062 if (
auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1063 const EntityPass* entity_pass = subpass->get();
1070 const std::function<
bool(
Entity&)>& iterator) {
1075 for (
auto& element : elements_) {
1076 if (
auto entity = std::get_if<Entity>(&element)) {
1077 if (!iterator(*entity)) {
1082 if (
auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1083 subpass->get()->IterateAllEntities(iterator);
1091 const std::function<
bool(
const Entity&)>& iterator)
const {
1096 for (
const auto& element : elements_) {
1097 if (
auto entity = std::get_if<Entity>(&element)) {
1098 if (!iterator(*entity)) {
1103 if (
auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1104 const EntityPass* entity_pass = subpass->get();
1113 const std::function<
bool(
Entity&)>& iterator) {
1118 for (
auto& element : elements_) {
1119 if (
auto entity = std::get_if<Entity>(&element)) {
1120 if (!iterator(*entity)) {
1131 return elements_.size();
1139 clip_height_ = clip_height;
1143 return clip_height_;
1147 clip_depth_ = clip_depth;
1155 blend_mode_ = blend_mode;
1164 if (backdrop_filter_proc_) {
1165 return std::nullopt;
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()) {
1176 .Blend(entity_color.value(), blend_mode);
1178 if (
result.has_value()) {
1179 return result->Premultiply();
1186 VALIDATION_LOG <<
"Backdrop filters cannot be set on EntityPasses that "
1187 "have already been appended to another pass.";
1190 backdrop_filter_proc_ = std::move(proc);
1194 enable_offscreen_debug_checkerboard_ = enabled;
Wraps a closure that is invoked in the destructor unless released by the caller.
Capture CreateChild(std::string_view label)
static std::shared_ptr< ColorFilterContents > MakeBlend(BlendMode blend_mode, FilterInput::Vector inputs, std::optional< Color > foreground_color=std::nullopt)
the [inputs] are expected to be in the order of dst, src.
A class that tracks all clips that have been recorded in the current entity pass stencil.
std::optional< Rect > CurrentClipCoverage() const
void PushSubpass(std::optional< Rect > subpass_coverage, size_t clip_height)
const RenderTarget & GetRenderTarget() const
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-a...
void SetElements(std::vector< Element > elements)
void IterateAllElements(const std::function< bool(Element &)> &iterator)
Iterate all elements (entities and subpasses) in this pass, recursively including elements of child p...
std::variant< Entity, std::unique_ptr< EntityPass > > Element
size_t GetElementCount() const
Return the number of elements on this pass.
bool GetBoundsLimitMightClipContent() const
Indicates if the bounds limit set using |SetBoundsLimit()| might clip the contents of the pass.
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 al...
void SetEnableOffscreenCheckerboard(bool enabled)
Color GetClearColorOrDefault(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities.
void SetClipDepth(size_t clip_depth)
void AddEntity(Entity entity)
Add an entity to the current entity pass.
size_t GetClipHeight() const
void SetBackdropFilter(BackdropFilterProc proc)
bool GetBoundsLimitIsSnug() const
Indicates if the bounds limit set using |SetBoundsLimit()| is a reasonably tight estimate of the boun...
static const std::string kCaptureDocumentName
std::optional< Rect > GetBoundsLimit() const
Get the bounds limit, which is provided by the user when creating a SaveLayer.
EntityPass * GetSuperpass() const
size_t GetSubpassesDepth() const
void PopClips(size_t num_clips, uint64_t depth)
int32_t GetRequiredMipCount() const
void SetClipHeight(size_t clip_height)
std::optional< Color > GetClearColor(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities, if any.
void SetBlendMode(BlendMode blend_mode)
void SetTransform(Matrix transform)
void IterateAllEntities(const std::function< bool(Entity &)> &iterator)
Iterate all entities in this pass, recursively including entities of child passes....
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...
void PopAllClips(uint64_t depth)
EntityPass * AddSubpass(std::unique_ptr< EntityPass > pass)
Appends a given pass as a subpass.
void SetDelegate(std::shared_ptr< EntityPassDelegate > delgate)
bool Render(ContentContext &renderer, const RenderTarget &render_target) const
std::optional< Rect > GetElementsCoverage(std::optional< Rect > coverage_limit) const
void PushClip(Entity entity)
uint32_t GetClipDepth() const
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
void SetCapture(Capture capture) const
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
const std::shared_ptr< Contents > & GetContents() const
void SetClipDepth(uint32_t clip_depth)
BlendMode GetBlendMode() const
void SetContents(std::shared_ptr< Contents > contents)
void SetBlendMode(BlendMode blend_mode)
bool Render(const ContentContext &renderer, RenderPass &parent_pass) const
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
static constexpr BlendMode kLastPipelineBlendMode
static bool IsBlendModeDestructive(BlendMode blend_mode)
Returns true if the blend mode is "destructive", meaning that even fully transparent source colors wo...
EntityPassTarget & GetPassTarget() const
std::shared_ptr< Texture > GetTexture()
RenderPassResult GetRenderPass(uint32_t pass_depth)
Render passes encode render commands directed as one specific render target into an underlying comman...
virtual void SetScissor(IRect scissor)
ISize GetRenderTargetSize() const
std::shared_ptr< Texture > GetRenderTargetTexture() const
ISize GetRenderTargetSize() const
static std::shared_ptr< TextureContents > MakeRect(Rect destination)
A common case factory that marks the texture contents as having a destination rectangle....
#define FML_UNREACHABLE()
#define FML_DCHECK(condition)
static float max(float r, float g, float b)
static void SetClipScissor(std::optional< Rect > clip_coverage, RenderPass &pass, Point global_pass_position)
static std::unique_ptr< EntityPassTarget > CreateRenderTarget(ContentContext &renderer, ISize size, int mip_count, const Color &clear_color)
std::string SPrintF(const char *format,...)
@ 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...
static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
static constexpr Color BlackTransparent()
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
constexpr bool IsZero() const
constexpr std::optional< TRect > Intersection(const TRect &o) const
constexpr TRect Union(const TRect &o) const
RoundOut(const TRect< U > &r)
static constexpr TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
static constexpr TRect MakeSize(const TSize< U > &size)
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
#define TRACE_EVENT0(category_group, name)
static void checkerboard(SkCanvas *canvas, SkColor c1, SkColor c2, int size)