| Flutter Impeller |

Classes | Public Member Functions | List of all members
impeller::EntityPassClipStack Class Reference

A class that tracks all clips that have been recorded in the current entity pass stencil. More...

`#include <entity_pass_clip_stack.h>`

## Classes
struct | ClipStateResult
struct | ReplayResult

## Public Member Functions
| EntityPassClipStack (const Rect &initial_coverage_rect)
| Create a new [EntityPassClipStack] with an initialized coverage rect. More...
| ~EntityPassClipStack ()=default
std::optional< Rect > | CurrentClipCoverage () const
void | PushSubpass (std::optional< Rect > subpass_coverage, size_t clip_depth)
void | PopSubpass ()
bool | HasCoverage () const
ClipStateResult | ApplyClipState (Contents::ClipCoverage global_clip_coverage, Entity &entity, size_t clip_depth_floor, Point global_pass_position)
| Applies the current clip state to an Entity. If the given Entity is a clip operation, then the clip state is updated accordingly. More...
void | RecordEntity (const Entity &entity, Contents::ClipCoverage::Type type, std::optional< Rect > clip_coverage)
const std::vector< ReplayResult > & | GetReplayEntities () const
const std::vector< ClipCoverageLayer > | GetClipCoverageLayers () const

## Detailed Description

A class that tracks all clips that have been recorded in the current entity pass stencil.

These clips are replayed when restoring the backdrop so that the stencil buffer is left in an identical state.

Definition at line 24 of file entity_pass_clip_stack.h.

## Constructor & Destructor Documentation

## ◆ EntityPassClipStack()

impeller::EntityPassClipStack::EntityPassClipStack | ( | const Rect & | initial_coverage_rect | ) |
| explicit

Create a new [EntityPassClipStack] with an initialized coverage rect.

Definition at line 12 of file entity_pass_clip_stack.cc.

12 {
13 subpass_state_.push_back(SubpassState{
14 .clip_coverage =
15 {
16 {ClipCoverageLayer{
17 .coverage = initial_coverage_rect,
18 .clip_depth = 0,
19 }},
20 },
21 });
22 }

References impeller::ClipCoverageLayer::coverage.

## ◆ ~EntityPassClipStack()

impeller::EntityPassClipStack::~EntityPassClipStack | ( |  | ) |
| default

## Member Function Documentation

## ◆ ApplyClipState()

EntityPassClipStack::ClipStateResult impeller::EntityPassClipStack::ApplyClipState | ( | Contents::ClipCoverage | global_clip_coverage,
|  | Entity & | entity,
|  | size_t | clip_depth_floor,
|  | Point | global_pass_position
| ) |  |

Applies the current clip state to an Entity. If the given Entity is a clip operation, then the clip state is updated accordingly.

Definition at line 52 of file entity_pass_clip_stack.cc.

56 {
57 ClipStateResult result = {.should_render = false, .clip_did_change = false};
58
59 auto& subpass_state = GetCurrentSubpassState();
60 switch (global_clip_coverage.type) {
61 case Contents::ClipCoverage::Type::kNoChange:
62 break;
63 case Contents::ClipCoverage::Type::kAppend: {
64 auto op = CurrentClipCoverage();
65 subpass_state.clip_coverage.push_back(
66 ClipCoverageLayer{.coverage = global_clip_coverage.coverage,
67 .clip_depth = entity.GetClipDepth() + 1});
68 result.clip_did_change = true;
69
70 FML_DCHECK(subpass_state.clip_coverage.back().clip_depth ==
71 subpass_state.clip_coverage.front().clip_depth +
72 subpass_state.clip_coverage.size() - 1);
73
74 if (!op.has_value()) {
75 // Running this append op won't impact the clip buffer because the
76 // whole screen is already being clipped, so skip it.
77 return result;
78 }
79 } break;
80 case Contents::ClipCoverage::Type::kRestore: {
81 if (subpass_state.clip_coverage.back().clip_depth <=
82 entity.GetClipDepth()) {
83 // Drop clip restores that will do nothing.
84 return result;
85 }
86
87 auto restoration_index = entity.GetClipDepth() -
88 subpass_state.clip_coverage.front().clip_depth;
89 FML_DCHECK(restoration_index < subpass_state.clip_coverage.size());
90
91 // We only need to restore the area that covers the coverage of the
92 // clip rect at target depth + 1.
93 std::optional<Rect> restore_coverage =
94 (restoration_index + 1 < subpass_state.clip_coverage.size())
95 ? subpass_state.clip_coverage[restoration_index + 1].coverage
96 : std::nullopt;
97 if (restore_coverage.has_value()) {
98 // Make the coverage rectangle relative to the current pass.
99 restore_coverage = restore_coverage->Shift(-global_pass_position);
100 }
101 subpass_state.clip_coverage.resize(restoration_index + 1);
102 result.clip_did_change = true;
103
104 if constexpr (ContentContext::kEnableStencilThenCover) {
105 // Skip all clip restores when stencil-then-cover is enabled.
106 if (subpass_state.clip_coverage.back().coverage.has_value()) {
107 RecordEntity(entity, global_clip_coverage.type, Rect());
108 }
109 return result;
110 }
111
112 if (!subpass_state.clip_coverage.back().coverage.has_value()) {
113 // Running this restore op won't make anything renderable, so skip it.
114 return result;
115 }
116
117 auto restore_contents =
118 static_cast<ClipRestoreContents*>(entity.GetContents().get());
119 restore_contents->SetRestoreCoverage(restore_coverage);
120
121 } break;
122 }
123
124 #ifdef IMPELLER_ENABLE_CAPTURE
125 {
126 auto element_entity_coverage = entity.GetCoverage();
127 if (element_entity_coverage.has_value()) {
128 element_entity_coverage =
129 element_entity_coverage->Shift(global_pass_position);
130 entity.GetCapture().AddRect("Coverage", *element_entity_coverage,
131 {.readonly = true});
132 }
133 }
134 #endif
135
136 entity.SetClipDepth(entity.GetClipDepth() - clip_depth_floor);
137 RecordEntity(entity, global_clip_coverage.type,
138 subpass_state.clip_coverage.back().coverage);
139
140 result.should_render = true;
141 return result;
142 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::ClipCoverageLayer::coverage, impeller::Contents::ClipCoverage::coverage, CurrentClipCoverage(), impeller::Entity::GetCapture(), impeller::Entity::GetClipDepth(), impeller::Entity::GetContents(), impeller::Entity::GetCoverage(), impeller::Contents::ClipCoverage::kAppend, impeller::ContentContext::kEnableStencilThenCover, impeller::Contents::ClipCoverage::kNoChange, impeller::Contents::ClipCoverage::kRestore, RecordEntity(), impeller::Entity::SetClipDepth(), impeller::ClipRestoreContents::SetRestoreCoverage(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Contents::ClipCoverage::type.

Referenced by impeller::testing::TEST().

## ◆ CurrentClipCoverage()

std::optional< Rect > impeller::EntityPassClipStack::CurrentClipCoverage | ( |  | ) | const

Definition at line 24 of file entity_pass_clip_stack.cc.

24 {
25 return subpass_state_.back().clip_coverage.back().coverage;
26 }

Referenced by ApplyClipState().

## ◆ GetClipCoverageLayers()

const std::vector< ClipCoverageLayer > impeller::EntityPassClipStack::GetClipCoverageLayers | ( |  | ) | const

Definition at line 48 of file entity_pass_clip_stack.cc.

48 {
49 return subpass_state_.back().clip_coverage;
50 }

Referenced by impeller::testing::TEST().

## ◆ GetReplayEntities()

const std::vector< EntityPassClipStack::ReplayResult > & impeller::EntityPassClipStack::GetReplayEntities | ( |  | ) | const

Definition at line 169 of file entity_pass_clip_stack.cc.

169 {
170 return subpass_state_.back().rendered_clip_entities;
171 }

Referenced by impeller::testing::TEST().

## ◆ HasCoverage()

bool impeller::EntityPassClipStack::HasCoverage | ( |  | ) | const

Definition at line 28 of file entity_pass_clip_stack.cc.

28 {
29 return !subpass_state_.back().clip_coverage.empty();
30 }

## ◆ PopSubpass()

void impeller::EntityPassClipStack::PopSubpass | ( |  | ) |

Definition at line 43 of file entity_pass_clip_stack.cc.

43 {
44 subpass_state_.pop_back();
45 }

Referenced by impeller::testing::TEST().

## ◆ PushSubpass()

void impeller::EntityPassClipStack::PushSubpass | ( | std::optional< Rect > | subpass_coverage,
|  | size_t | clip_depth
| ) |  |

Definition at line 32 of file entity_pass_clip_stack.cc.

33 {
34 subpass_state_.push_back(SubpassState{
35 .clip_coverage =
36 {
37 ClipCoverageLayer{.coverage = subpass_coverage,
38 .clip_depth = clip_depth},
39 },
40 });
41 }

References impeller::ClipCoverageLayer::coverage.

Referenced by impeller::testing::TEST().

## ◆ RecordEntity()

void impeller::EntityPassClipStack::RecordEntity | ( | const Entity & | entity,
|  | Contents::ClipCoverage::Type | type,
|  | std::optional< Rect > | clip_coverage
| ) |  |

Definition at line 144 of file entity_pass_clip_stack.cc.

146 {
147 auto& subpass_state = GetCurrentSubpassState();
148 switch (type) {
149 case Contents::ClipCoverage::Type::kNoChange:
150 return;
151 case Contents::ClipCoverage::Type::kAppend:
152 subpass_state.rendered_clip_entities.push_back(
153 {.entity = entity.Clone(), .clip_coverage = clip_coverage});
154 break;
155 case Contents::ClipCoverage::Type::kRestore:
156 if (!subpass_state.rendered_clip_entities.empty()) {
157 subpass_state.rendered_clip_entities.pop_back();
158 }
159 break;
160 }
161 }

References impeller::Entity::Clone(), impeller::Contents::ClipCoverage::kAppend, impeller::Contents::ClipCoverage::kNoChange, and impeller::Contents::ClipCoverage::kRestore.

Referenced by ApplyClipState(), and impeller::testing::TEST().

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

- impeller/entity/entity_pass_clip_stack.h
- impeller/entity/entity_pass_clip_stack.cc

impeller::Contents::ClipCoverage::Type::kRestore
@ kRestore
impeller::ContentContext::kEnableStencilThenCover
static constexpr bool kEnableStencilThenCover
Definition: content_context.h:411
impeller::EntityPassClipStack::CurrentClipCoverage
std::optional< Rect > CurrentClipCoverage() const
Definition: entity_pass_clip_stack.cc:24
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:661
impeller::EntityPassClipStack::RecordEntity
void RecordEntity(const Entity &entity, Contents::ClipCoverage::Type type, std::optional< Rect > clip_coverage)
Definition: entity_pass_clip_stack.cc:144
impeller::Contents::ClipCoverage::Type::kAppend
@ kAppend
impeller::Contents::ClipCoverage::Type::kNoChange
@ kNoChange