| 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
5 #include "impeller/entity/entity_pass_clip_stack.h"
6 #include "impeller/entity/contents/clip_contents.h"
7 #include "impeller/entity/entity.h"
8
9 namespace impeller {
10
11 EntityPassClipStack::EntityPassClipStack(const Rect& initial_coverage_rect) {
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 }
22
23 std::optional<Rect> EntityPassClipStack::CurrentClipCoverage() const {
24 return subpass_state_.back().clip_coverage.back().coverage;
25 }
26
27 bool EntityPassClipStack::HasCoverage() const {
28 return !subpass_state_.back().clip_coverage.empty();
29 }
30
31 void EntityPassClipStack::PushSubpass(std::optional<Rect> subpass_coverage,
32 size_t clip_height) {
33 subpass_state_.push_back(SubpassState{
34 .clip_coverage =
35 {
36 ClipCoverageLayer{.coverage = subpass_coverage,
37 .clip_height = clip_height},
38 },
39 });
40 }
41
42 void EntityPassClipStack::PopSubpass() {
43 subpass_state_.pop_back();
44 }
45
46 const std::vector<ClipCoverageLayer>
47 EntityPassClipStack::GetClipCoverageLayers() const {
48 return subpass_state_.back().clip_coverage;
49 }
50
51 EntityPassClipStack::ClipStateResult EntityPassClipStack::ApplyClipState(
52 Contents::ClipCoverage global_clip_coverage,
53 Entity& entity,
54 size_t clip_height_floor,
55 Point global_pass_position) {
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 }
132
133 void EntityPassClipStack::RecordEntity(const Entity& entity,
134 Contents::ClipCoverage::Type type,
135 std::optional<Rect> clip_coverage) {
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 }
151
152 EntityPassClipStack::SubpassState&
153 EntityPassClipStack::GetCurrentSubpassState() {
154 return subpass_state_.back();
155 }
156
157 const std::vector<EntityPassClipStack::ReplayResult>&
158 EntityPassClipStack::GetReplayEntities() const {
159 return subpass_state_.back().rendered_clip_entities;
160 }
161
162 } // namespace impeller
impeller::EntityPassClipStack::ClipStateResult::should_render
bool should_render
Definition: entity_pass_clip_stack.h:34
impeller::EntityPassClipStack::PushSubpass
void PushSubpass(std::optional< Rect > subpass_coverage, size_t clip_height)
Definition: entity_pass_clip_stack.cc:31
impeller::Contents::ClipCoverage::Type
Type
Definition: contents.h:38
entity.h
impeller::EntityPassClipStack::GetClipCoverageLayers
const std::vector< ClipCoverageLayer > GetClipCoverageLayers() const
Definition: entity_pass_clip_stack.cc:47
impeller::EntityPassClipStack::HasCoverage
bool HasCoverage() const
Definition: entity_pass_clip_stack.cc:27
impeller::EntityPassClipStack::EntityPassClipStack
EntityPassClipStack(const Rect &initial_coverage_rect)
Create a new [EntityPassClipStack] with an initialized coverage rect.
Definition: entity_pass_clip_stack.cc:11
impeller::ClipRestoreContents::GetRestoreHeight
size_t GetRestoreHeight() const
Definition: clip_contents.cc:198
impeller::Contents::ClipCoverage::Type::kRestore
@ kRestore
impeller::ClipCoverageLayer::coverage
std::optional< Rect > coverage
Definition: entity_pass_clip_stack.h:15
impeller::ClipCoverageLayer
Definition: entity_pass_clip_stack.h:14
impeller::Entity
Definition: entity.h:20
impeller::EntityPassClipStack::ApplyClipState
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,...
Definition: entity_pass_clip_stack.cc:51
impeller::EntityPassClipStack::GetReplayEntities
const std::vector< ReplayResult > & GetReplayEntities() const
Definition: entity_pass_clip_stack.cc:158
impeller::Contents::ClipCoverage::coverage
std::optional< Rect > coverage
Definition: contents.h:41
impeller::EntityPassClipStack::CurrentClipCoverage
std::optional< Rect > CurrentClipCoverage() const
Definition: entity_pass_clip_stack.cc:23
impeller::Contents::ClipCoverage::type
Type type
Definition: contents.h:40
type
GLenum type
Definition: blit_command_gles.cc:126
impeller::Entity::GetContents
const std::shared_ptr< Contents > & GetContents() const
Definition: entity.cc:94
clip_contents.h
impeller::ClipRestoreContents
Definition: clip_contents.h:59
impeller::EntityPassClipStack::PopSubpass
void PopSubpass()
Definition: entity_pass_clip_stack.cc:42
entity_pass_clip_stack.h
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::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:191
impeller::TPoint< Scalar >
impeller::Contents::ClipCoverage
Definition: contents.h:37
impeller::Contents::ClipCoverage::Type::kAppend
@ kAppend
impeller::EntityPassClipStack::ClipStateResult
Definition: entity_pass_clip_stack.h:31
impeller
Definition: aiks_blend_unittests.cc:18
impeller::TRect< Scalar >
impeller::Contents::ClipCoverage::Type::kNoChange
@ kNoChange