Flutter Impeller
entity_pass_clip_stack.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
9 
10 namespace impeller {
11 
12 EntityPassClipStack::EntityPassClipStack(const Rect& initial_coverage_rect) {
13  subpass_state_.push_back(SubpassState{
14  .clip_coverage =
15  {
17  .coverage = initial_coverage_rect,
18  .clip_depth = 0,
19  }},
20  },
21  });
22 }
23 
24 std::optional<Rect> EntityPassClipStack::CurrentClipCoverage() const {
25  return subpass_state_.back().clip_coverage.back().coverage;
26 }
27 
29  return !subpass_state_.back().clip_coverage.empty();
30 }
31 
32 void EntityPassClipStack::PushSubpass(std::optional<Rect> subpass_coverage,
33  size_t clip_depth) {
34  subpass_state_.push_back(SubpassState{
35  .clip_coverage =
36  {
37  ClipCoverageLayer{.coverage = subpass_coverage,
38  .clip_depth = clip_depth},
39  },
40  });
41 }
42 
44  subpass_state_.pop_back();
45 }
46 
47 const std::vector<ClipCoverageLayer>
49  return subpass_state_.back().clip_coverage;
50 }
51 
53  Contents::ClipCoverage global_clip_coverage,
54  Entity& entity,
55  size_t clip_depth_floor,
56  Point global_pass_position) {
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 }
143 
146  std::optional<Rect> clip_coverage) {
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 }
162 
163 EntityPassClipStack::SubpassState&
164 EntityPassClipStack::GetCurrentSubpassState() {
165  return subpass_state_.back();
166 }
167 
168 const std::vector<EntityPassClipStack::ReplayResult>&
170  return subpass_state_.back().rendered_clip_entities;
171 }
172 
173 } // namespace impeller
impeller::Entity::SetClipDepth
void SetClipDepth(uint32_t clip_depth)
Definition: entity.cc:101
impeller::EntityPassClipStack::ClipStateResult::should_render
bool should_render
Definition: entity_pass_clip_stack.h:34
impeller::Entity::GetCapture
Capture & GetCapture() const
Definition: entity.cc:206
impeller::Contents::ClipCoverage::Type
Type
Definition: contents.h:41
entity.h
impeller::EntityPassClipStack::GetClipCoverageLayers
const std::vector< ClipCoverageLayer > GetClipCoverageLayers() const
Definition: entity_pass_clip_stack.cc:48
impeller::EntityPassClipStack::HasCoverage
bool HasCoverage() const
Definition: entity_pass_clip_stack.cc:28
impeller::EntityPassClipStack::EntityPassClipStack
EntityPassClipStack(const Rect &initial_coverage_rect)
Create a new [EntityPassClipStack] with an initialized coverage rect.
Definition: entity_pass_clip_stack.cc:12
impeller::ClipRestoreContents::SetRestoreCoverage
void SetRestoreCoverage(std::optional< Rect > coverage)
The area on the pass texture where this clip restore will be applied. If unset, the entire pass textu...
Definition: clip_contents.cc:256
impeller::Contents::ClipCoverage::Type::kRestore
@ kRestore
impeller::ClipCoverageLayer::coverage
std::optional< Rect > coverage
Definition: entity_pass_clip_stack.h:15
impeller::ContentContext::kEnableStencilThenCover
static constexpr bool kEnableStencilThenCover
Definition: content_context.h:411
impeller::ClipCoverageLayer
Definition: entity_pass_clip_stack.h:14
impeller::Entity
Definition: entity.h:21
impeller::EntityPassClipStack::GetReplayEntities
const std::vector< ReplayResult > & GetReplayEntities() const
Definition: entity_pass_clip_stack.cc:169
impeller::EntityPassClipStack::ApplyClipState
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,...
Definition: entity_pass_clip_stack.cc:52
impeller::Contents::ClipCoverage::coverage
std::optional< Rect > coverage
Definition: contents.h:44
impeller::EntityPassClipStack::CurrentClipCoverage
std::optional< Rect > CurrentClipCoverage() const
Definition: entity_pass_clip_stack.cc:24
impeller::Contents::ClipCoverage::type
Type type
Definition: contents.h:43
impeller::Entity::GetContents
const std::shared_ptr< Contents > & GetContents() const
Definition: entity.cc:97
impeller::EntityPassClipStack::PushSubpass
void PushSubpass(std::optional< Rect > subpass_coverage, size_t clip_depth)
Definition: entity_pass_clip_stack.cc:32
clip_contents.h
impeller::ClipRestoreContents
Definition: clip_contents.h:71
impeller::EntityPassClipStack::PopSubpass
void PopSubpass()
Definition: entity_pass_clip_stack.cc:43
entity_pass_clip_stack.h
impeller::Entity::GetClipDepth
uint32_t GetClipDepth() const
Definition: entity.cc:105
content_context.h
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::Entity::GetCoverage
std::optional< Rect > GetCoverage() const
Definition: entity.cc:69
impeller::EntityPassClipStack::ClipStateResult::clip_did_change
bool clip_did_change
Definition: entity_pass_clip_stack.h:37
impeller::Entity::Clone
Entity Clone() const
Definition: entity.cc:210
impeller::TPoint< Scalar >
impeller::Contents::ClipCoverage
Definition: contents.h:40
impeller::Contents::ClipCoverage::Type::kAppend
@ kAppend
impeller::EntityPassClipStack::ClipStateResult
Definition: entity_pass_clip_stack.h:31
impeller
Definition: aiks_blur_unittests.cc:20
impeller::TRect< Scalar >
impeller::Contents::ClipCoverage::Type::kNoChange
@ kNoChange