| Flutter Impeller |

entity_pass_unittests.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 "flutter/testing/testing.h"
6 #include "gtest/gtest.h"
7 #include "impeller/entity/entity.h"
8 #include "impeller/entity/entity_pass_clip_stack.h"
9
10 namespace impeller {
11 namespace testing {
12
13 TEST(EntityPassClipStackTest, CanPushAndPopEntities) {
14 EntityPassClipStack recorder =
15 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
16
17 EXPECT_TRUE(recorder.GetReplayEntities().empty());
18
19 Entity entity;
20 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kAppend,
21 Rect::MakeLTRB(0, 0, 100, 100));
22 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
23
24 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kAppend,
25 Rect::MakeLTRB(0, 0, 50, 50));
26 EXPECT_EQ(recorder.GetReplayEntities().size(), 2u);
27 ASSERT_TRUE(recorder.GetReplayEntities()[0].clip_coverage.has_value());
28 ASSERT_TRUE(recorder.GetReplayEntities()[1].clip_coverage.has_value());
29 // NOLINTBEGIN(bugprone-unchecked-optional-access)
30 EXPECT_EQ(recorder.GetReplayEntities()[0].clip_coverage.value(),
31 Rect::MakeLTRB(0, 0, 100, 100));
32 EXPECT_EQ(recorder.GetReplayEntities()[1].clip_coverage.value(),
33 Rect::MakeLTRB(0, 0, 50, 50));
34 // NOLINTEND(bugprone-unchecked-optional-access)
35
36 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
37 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
38
39 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
40 EXPECT_TRUE(recorder.GetReplayEntities().empty());
41 }
42
43 TEST(EntityPassClipStackTest, CanPopEntitiesSafely) {
44 EntityPassClipStack recorder =
45 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
46
47 EXPECT_TRUE(recorder.GetReplayEntities().empty());
48
49 Entity entity;
50 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
51 EXPECT_TRUE(recorder.GetReplayEntities().empty());
52 }
53
54 TEST(EntityPassClipStackTest, CanAppendNoChange) {
55 EntityPassClipStack recorder =
56 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
57
58 EXPECT_TRUE(recorder.GetReplayEntities().empty());
59
60 Entity entity;
61 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kNoChange,
62 Rect());
63 EXPECT_TRUE(recorder.GetReplayEntities().empty());
64 }
65
66 TEST(EntityPassClipStackTest, AppendCoverageNoChange) {
67 EntityPassClipStack recorder =
68 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
69
70 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
71 Rect::MakeSize(Size::MakeWH(100, 100)));
72 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_depth, 0u);
73
74 Entity entity;
75 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
76 Contents::ClipCoverage{
77 .type = Contents::ClipCoverage::Type::kNoChange,
78 .coverage = std::nullopt,
79 },
80 entity, 0, Point(0, 0));
81 EXPECT_TRUE(result.should_render);
82 EXPECT_FALSE(result.clip_did_change);
83
84 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
85 Rect::MakeSize(Size::MakeWH(100, 100)));
86 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_depth, 0u);
87 }
88
89 TEST(EntityPassClipStackTest, AppendAndRestoreClipCoverage) {
90 EntityPassClipStack recorder =
91 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
92
93 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
94
95 // Push a clip.
96 Entity entity;
97 entity.SetClipDepth(0);
98 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
99 Contents::ClipCoverage{
100 .type = Contents::ClipCoverage::Type::kAppend,
101 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
102 },
103 entity, 0, Point(0, 0));
104 EXPECT_TRUE(result.should_render);
105 EXPECT_TRUE(result.clip_did_change);
106
107 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
108 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
109 Rect::MakeLTRB(50, 50, 55, 55));
110 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_depth, 1u);
111 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
112
113 // Restore the clip.
114 entity.SetClipDepth(0);
115 recorder.ApplyClipState(
116 Contents::ClipCoverage{
117 .type = Contents::ClipCoverage::Type::kRestore,
118 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
119 },
120 entity, 0, Point(0, 0));
121
122 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
123 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
124 Rect::MakeSize(Size::MakeWH(100, 100)));
125 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_depth, 0u);
126 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
127 }
128
129 TEST(EntityPassClipStackTest, UnbalancedRestore) {
130 EntityPassClipStack recorder =
131 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
132
133 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
134
135 // Restore the clip.
136 Entity entity;
137 entity.SetClipDepth(0);
138 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
139 Contents::ClipCoverage{
140 .type = Contents::ClipCoverage::Type::kRestore,
141 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
142 },
143 entity, 0, Point(0, 0));
144 EXPECT_FALSE(result.should_render);
145 EXPECT_FALSE(result.clip_did_change);
146
147 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
148 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
149 Rect::MakeSize(Size::MakeWH(100, 100)));
150 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_depth, 0u);
151 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
152 }
153
154 TEST(EntityPassClipStackTest, ClipAndRestoreWithSubpasses) {
155 EntityPassClipStack recorder =
156 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
157
158 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
159
160 // Push a clip.
161 Entity entity;
162 entity.SetClipDepth(0u);
163 {
164 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
165 Contents::ClipCoverage{
166 .type = Contents::ClipCoverage::Type::kAppend,
167 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
168 },
169 entity, 0, Point(0, 0));
170 EXPECT_TRUE(result.should_render);
171 EXPECT_TRUE(result.clip_did_change);
172 }
173
174 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
175 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
176 Rect::MakeLTRB(50, 50, 55, 55));
177 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_depth, 1u);
178 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
179
180 // Begin a subpass.
181 recorder.PushSubpass(Rect::MakeLTRB(50, 50, 55, 55), 1);
182 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
183 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
184 Rect::MakeLTRB(50, 50, 55, 55));
185
186 entity.SetClipDepth(1);
187 {
188 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
189 Contents::ClipCoverage{
190 .type = Contents::ClipCoverage::Type::kAppend,
191 .coverage = Rect::MakeLTRB(54, 54, 55, 55),
192 },
193 entity, 0, Point(0, 0));
194 EXPECT_TRUE(result.should_render);
195 EXPECT_TRUE(result.clip_did_change);
196 }
197
198 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
199 Rect::MakeLTRB(54, 54, 55, 55));
200
201 // End subpass.
202 recorder.PopSubpass();
203
204 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
205 Rect::MakeLTRB(50, 50, 55, 55));
206 }
207
208 } // namespace testing
209 } // 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
entity.h
impeller::EntityPassClipStack::GetClipCoverageLayers
const std::vector< ClipCoverageLayer > GetClipCoverageLayers() const
Definition: entity_pass_clip_stack.cc:48
impeller::Contents::ClipCoverage::Type::kRestore
@ kRestore
impeller::Entity
Definition: entity.h:21
impeller::EntityPassClipStack::GetReplayEntities
const std::vector< ReplayResult > & GetReplayEntities() const
Definition: entity_pass_clip_stack.cc:169
impeller::Point
TPoint< Scalar > Point
Definition: point.h:316
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::type
Type type
Definition: contents.h:43
impeller::testing::TEST
TEST(CanvasRecorder, Save)
Definition: canvas_recorder_unittests.cc:65
impeller::EntityPassClipStack::PushSubpass
void PushSubpass(std::optional< Rect > subpass_coverage, size_t clip_depth)
Definition: entity_pass_clip_stack.cc:32
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:661
impeller::EntityPassClipStack::PopSubpass
void PopSubpass()
Definition: entity_pass_clip_stack.cc:43
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:144
impeller::EntityPassClipStack::ClipStateResult::clip_did_change
bool clip_did_change
Definition: entity_pass_clip_stack.h:37
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:146
impeller::Contents::ClipCoverage
Definition: contents.h:40
impeller::Contents::ClipCoverage::Type::kAppend
@ kAppend
impeller::EntityPassClipStack
A class that tracks all clips that have been recorded in the current entity pass stencil.
Definition: entity_pass_clip_stack.h:24
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::TSize< Scalar >::MakeWH
static constexpr TSize MakeWH(Type width, Type height)
Definition: size.h:34
impeller::EntityPassClipStack::ClipStateResult
Definition: entity_pass_clip_stack.h:31
impeller
Definition: aiks_blur_unittests.cc:20
impeller::Contents::ClipCoverage::Type::kNoChange
@ kNoChange