| 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_height)
void | PopSubpass ()
bool | HasCoverage () const
ClipStateResult | ApplyClipState (Contents::ClipCoverage global_clip_coverage, Entity &entity, size_t clip_height_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 11 of file entity_pass_clip_stack.cc.

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

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_height_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 51 of file entity_pass_clip_stack.cc.

55 {
56 ClipStateResult result = {.should_render = false, .clip_did_change = false};
57
58 auto& subpass_state = GetCurrentSubpassState();
59 switch (global_clip_coverage.type) {
60 case Contents::ClipCoverage::Type::kNoChange:
61 break;
62 case Contents::ClipCoverage::Type::kAppend: {
63 auto op = CurrentClipCoverage();
64
65 // Compute the previous clip height.
66 size_t previous_clip_height = 0;
67 if (!subpass_state.clip_coverage.empty()) {
68 previous_clip_height = subpass_state.clip_coverage.back().clip_height;
69 } else {
70 // If there is no clip coverage, then the previous clip height is the
71 // clip height floor.
72 previous_clip_height = clip_height_floor;
73 }
74
75 subpass_state.clip_coverage.push_back(
76 ClipCoverageLayer{.coverage = global_clip_coverage.coverage,
77 .clip_height = previous_clip_height + 1});
78 result.clip_did_change = true;
79
80 FML_DCHECK(subpass_state.clip_coverage.back().clip_height ==
81 subpass_state.clip_coverage.front().clip_height +
82 subpass_state.clip_coverage.size() - 1);
83
84 if (!op.has_value()) {
85 // Running this append op won't impact the clip buffer because the
86 // whole screen is already being clipped, so skip it.
87 return result;
88 }
89 } break;
90 case Contents::ClipCoverage::Type::kRestore: {
91 ClipRestoreContents* restore_contents =
92 reinterpret_cast<ClipRestoreContents*>(entity.GetContents().get());
93 size_t restore_height = restore_contents->GetRestoreHeight();
94
95 if (subpass_state.clip_coverage.back().clip_height <= restore_height) {
96 // Drop clip restores that will do nothing.
97 return result;
98 }
99
100 auto restoration_index =
101 restore_height - subpass_state.clip_coverage.front().clip_height;
102 FML_DCHECK(restoration_index < subpass_state.clip_coverage.size());
103
104 // We only need to restore the area that covers the coverage of the
105 // clip rect at target height + 1.
106 std::optional<Rect> restore_coverage =
107 (restoration_index + 1 < subpass_state.clip_coverage.size())
108 ? subpass_state.clip_coverage[restoration_index + 1].coverage
109 : std::nullopt;
110 if (restore_coverage.has_value()) {
111 // Make the coverage rectangle relative to the current pass.
112 restore_coverage = restore_coverage->Shift(-global_pass_position);
113 }
114 subpass_state.clip_coverage.resize(restoration_index + 1);
115 result.clip_did_change = true;
116
117 // Skip all clip restores when stencil-then-cover is enabled.
118 if (subpass_state.clip_coverage.back().coverage.has_value()) {
119 RecordEntity(entity, global_clip_coverage.type, Rect());
120 }
121 return result;
122
123 } break;
124 }
125
126 RecordEntity(entity, global_clip_coverage.type,
127 subpass_state.clip_coverage.back().coverage);
128
129 result.should_render = true;
130 return result;
131 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::ClipCoverageLayer::coverage, impeller::Contents::ClipCoverage::coverage, CurrentClipCoverage(), impeller::Entity::GetContents(), impeller::ClipRestoreContents::GetRestoreHeight(), impeller::Contents::ClipCoverage::kAppend, impeller::Contents::ClipCoverage::kNoChange, impeller::Contents::ClipCoverage::kRestore, RecordEntity(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Contents::ClipCoverage::type.

Referenced by impeller::ExperimentalCanvas::Restore(), and impeller::testing::TEST().

## ◆ CurrentClipCoverage()

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

Definition at line 23 of file entity_pass_clip_stack.cc.

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

Referenced by ApplyClipState(), impeller::ExperimentalCanvas::Restore(), and impeller::ExperimentalCanvas::SaveLayer().

## ◆ GetClipCoverageLayers()

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

Definition at line 47 of file entity_pass_clip_stack.cc.

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

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

## ◆ GetReplayEntities()

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

Definition at line 158 of file entity_pass_clip_stack.cc.

158 {
159 return subpass_state_.back().rendered_clip_entities;
160 }

Referenced by impeller::ExperimentalCanvas::SaveLayer(), and impeller::testing::TEST().

## ◆ HasCoverage()

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

Definition at line 27 of file entity_pass_clip_stack.cc.

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

Referenced by impeller::ExperimentalCanvas::SaveLayer().

## ◆ PopSubpass()

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

Definition at line 42 of file entity_pass_clip_stack.cc.

42 {
43 subpass_state_.pop_back();
44 }

Referenced by impeller::ExperimentalCanvas::Restore(), and impeller::testing::TEST().

## ◆ PushSubpass()

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

Definition at line 31 of file entity_pass_clip_stack.cc.

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

References impeller::ClipCoverageLayer::coverage.

Referenced by impeller::ExperimentalCanvas::SaveLayer(), and impeller::testing::TEST().

## ◆ RecordEntity()

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

Definition at line 133 of file entity_pass_clip_stack.cc.

135 {
136 auto& subpass_state = GetCurrentSubpassState();
137 switch (type) {
138 case Contents::ClipCoverage::Type::kNoChange:
139 return;
140 case Contents::ClipCoverage::Type::kAppend:
141 subpass_state.rendered_clip_entities.push_back(
142 {.entity = entity.Clone(), .clip_coverage = clip_coverage});
143 break;
144 case Contents::ClipCoverage::Type::kRestore:
145 if (!subpass_state.rendered_clip_entities.empty()) {
146 subpass_state.rendered_clip_entities.pop_back();
147 }
148 break;
149 }
150 }

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

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::EntityPassClipStack::CurrentClipCoverage
std::optional< Rect > CurrentClipCoverage() const
Definition: entity_pass_clip_stack.cc:23
type
GLenum type
Definition: blit_command_gles.cc:126
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:769
impeller::EntityPassClipStack::RecordEntity
void RecordEntity(const Entity &entity, Contents::ClipCoverage::Type type, std::optional< Rect > clip_coverage)
Definition: entity_pass_clip_stack.cc:133
impeller::Contents::ClipCoverage::Type::kAppend
@ kAppend
impeller::Contents::ClipCoverage::Type::kNoChange
@ kNoChange