Flutter Impeller
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< RectCurrentClipCoverage () 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< ClipCoverageLayerGetClipCoverageLayers () 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) {
62  break;
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;
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 
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) {
150  return;
152  subpass_state.rendered_clip_entities.push_back(
153  {.entity = entity.Clone(), .clip_coverage = clip_coverage});
154  break;
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::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