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_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< 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 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) {
61  break;
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;
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) {
139  return;
141  subpass_state.rendered_clip_entities.push_back(
142  {.entity = entity.Clone(), .clip_coverage = clip_coverage});
143  break;
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::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