Flutter Impeller
save_layer_utils_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"
8 
9 // TODO(zanderso): https://github.com/flutter/flutter/issues/127701
10 // NOLINTBEGIN(bugprone-unchecked-optional-access)
11 
12 namespace impeller {
13 namespace testing {
14 
15 using SaveLayerUtilsTest = ::testing::Test;
16 
17 TEST(SaveLayerUtilsTest, SimplePaintComputedCoverage) {
18  // Basic Case, simple paint, computed coverage
19  auto coverage = ComputeSaveLayerCoverage(
20  /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
21  /*effect_transform=*/{}, //
22  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
23  /*image_filter=*/nullptr //
24  );
25  ASSERT_TRUE(coverage.has_value());
26  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
27 }
28 
29 TEST(SaveLayerUtilsTest, BackdropFiterComputedCoverage) {
30  // Backdrop Filter, computed coverage
31  auto coverage = ComputeSaveLayerCoverage(
32  /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
33  /*effect_transform=*/{}, //
34  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
35  /*image_filter=*/nullptr,
36  /*flood_output_coverage=*/false, //
37  /*flood_input_coverage=*/true //
38  );
39 
40  ASSERT_TRUE(coverage.has_value());
41  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
42 }
43 
44 TEST(SaveLayerUtilsTest, ImageFiterComputedCoverage) {
45  // Image Filter, computed coverage
46  auto image_filter = FilterContents::MakeMatrixFilter(
47  FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
48 
49  auto coverage = ComputeSaveLayerCoverage(
50  /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
51  /*effect_transform=*/{}, //
52  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
53  /*image_filter=*/image_filter //
54  );
55 
56  ASSERT_TRUE(coverage.has_value());
57  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
58 }
59 
61  ImageFiterSmallScaleComputedCoverageLargerThanBoundsLimit) {
62  // Image Filter scaling large, computed coverage is larger than bounds limit.
63  auto image_filter = FilterContents::MakeMatrixFilter(
64  FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
65 
66  auto coverage = ComputeSaveLayerCoverage(
67  /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
68  /*effect_transform=*/{}, //
69  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 5, 5), //
70  /*image_filter=*/image_filter //
71  );
72 
73  ASSERT_TRUE(coverage.has_value());
74  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2.5, 2.5));
75 }
76 
78  ImageFiterLargeScaleComputedCoverageLargerThanBoundsLimit) {
79  // Image Filter scaling small, computed coverage is larger than bounds limit.
80  auto image_filter = FilterContents::MakeMatrixFilter(
81  FilterInput::Make(Rect()), Matrix::MakeScale({0.5, 0.5, 1}), {});
82 
83  auto coverage = ComputeSaveLayerCoverage(
84  /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
85  /*effect_transform=*/{}, //
86  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 5, 5), //
87  /*image_filter=*/image_filter //
88  );
89 
90  ASSERT_TRUE(coverage.has_value());
91  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
92 }
93 
94 TEST(SaveLayerUtilsTest, DisjointCoverage) {
95  // No intersection in coverage
96  auto coverage = ComputeSaveLayerCoverage(
97  /*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
98  /*effect_transform=*/{}, //
99  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
100  /*image_filter=*/nullptr //
101  );
102 
103  EXPECT_FALSE(coverage.has_value());
104 }
105 
106 TEST(SaveLayerUtilsTest, DisjointCoverageTransformedByImageFilter) {
107  // Coverage disjoint from parent coverage but transformed into parent space
108  // with image filter.
109  auto image_filter = FilterContents::MakeMatrixFilter(
110  FilterInput::Make(Rect()), Matrix::MakeTranslation({-200, -200, 0}), {});
111 
112  auto coverage = ComputeSaveLayerCoverage(
113  /*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
114  /*effect_transform=*/{}, //
115  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
116  /*image_filter=*/image_filter //
117  );
118 
119  ASSERT_TRUE(coverage.has_value());
120  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(200, 200, 210, 210));
121 }
122 
123 TEST(SaveLayerUtilsTest, DisjointCoveragTransformedByCTM) {
124  // Coverage disjoint from parent coverage.
125  Matrix ctm = Matrix::MakeTranslation({-200, -200, 0});
126  auto coverage = ComputeSaveLayerCoverage(
127  /*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
128  /*effect_transform=*/ctm, //
129  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
130  /*image_filter=*/nullptr //
131  );
132 
133  ASSERT_TRUE(coverage.has_value());
134  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
135 }
136 
137 TEST(SaveLayerUtilsTest, BasicEmptyCoverage) {
138  auto coverage = ComputeSaveLayerCoverage(
139  /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
140  /*effect_transform=*/{}, //
141  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
142  /*image_filter=*/nullptr //
143  );
144 
145  ASSERT_FALSE(coverage.has_value());
146 }
147 
148 TEST(SaveLayerUtilsTest, ImageFilterEmptyCoverage) {
149  // Empty coverage with Image Filter
150  auto image_filter = FilterContents::MakeMatrixFilter(
151  FilterInput::Make(Rect()), Matrix::MakeTranslation({-200, -200, 0}), {});
152 
153  auto coverage = ComputeSaveLayerCoverage(
154  /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
155  /*effect_transform=*/{}, //
156  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
157  /*image_filter=*/image_filter //
158  );
159 
160  ASSERT_FALSE(coverage.has_value());
161 }
162 
163 TEST(SaveLayerUtilsTest, BackdropFilterEmptyCoverage) {
164  // Empty coverage with backdrop filter.
165  auto coverage = ComputeSaveLayerCoverage(
166  /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
167  /*effect_transform=*/{}, //
168  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
169  /*image_filter=*/nullptr, //
170  /*flood_output_coverage=*/true //
171  );
172 
173  ASSERT_TRUE(coverage.has_value());
174  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
175 }
176 
177 TEST(SaveLayerUtilsTest, FloodInputCoverage) {
178  auto coverage = ComputeSaveLayerCoverage(
179  /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
180  /*effect_transform=*/{}, //
181  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
182  /*image_filter=*/nullptr, //
183  /*flood_output_coverage=*/false, //
184  /*flood_input_coverage=*/true //
185  );
186 
187  ASSERT_TRUE(coverage.has_value());
188  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
189 }
190 
191 TEST(SaveLayerUtilsTest, FloodInputCoverageWithImageFilter) {
192  auto image_filter = FilterContents::MakeMatrixFilter(
193  FilterInput::Make(Rect()), Matrix::MakeScale({0.5, 0.5, 1}), {});
194 
195  auto coverage = ComputeSaveLayerCoverage(
196  /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
197  /*effect_transform=*/{}, //
198  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
199  /*image_filter=*/image_filter, //
200  /*flood_output_coverage=*/false, //
201  /*flood_input_coverage=*/true //
202  );
203 
204  ASSERT_TRUE(coverage.has_value());
205  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 4800, 3600));
206 }
207 
209  FloodInputCoverageWithImageFilterWithNoCoverageProducesNoCoverage) {
210  // Even if we flood the input coverage due to a bdf, we can still cull out the
211  // layer if the image filter results in no coverage.
212  auto image_filter = FilterContents::MakeMatrixFilter(
213  FilterInput::Make(Rect()), Matrix::MakeScale({1, 1, 0}), {});
214 
215  auto coverage = ComputeSaveLayerCoverage(
216  /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
217  /*effect_transform=*/{}, //
218  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
219  /*image_filter=*/image_filter, //
220  /*flood_output_coverage=*/false, //
221  /*flood_input_coverage=*/true //
222  );
223 
224  ASSERT_FALSE(coverage.has_value());
225 }
226 
229  CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageSmallerWithImageFilter) {
230  // Create an image filter that slightly shrinks the coverage limit
231  auto image_filter = FilterContents::MakeMatrixFilter(
232  FilterInput::Make(Rect()), Matrix::MakeScale({1.1, 1.1, 1}), {});
233 
234  auto coverage = ComputeSaveLayerCoverage(
235  /*content_coverage=*/Rect::MakeLTRB(0, 0, 100, 100), //
236  /*effect_transform=*/{}, //
237  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
238  /*image_filter=*/image_filter //
239  );
240 
241  ASSERT_TRUE(coverage.has_value());
242  // The transfomed coverage limit is ((0, 0), (90.9091, 90.9091)).
243  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
244 }
245 
248  CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageLargerWithImageFilter) {
249  // Create an image filter that slightly stretches the coverage limit. Even
250  // without the special logic for using the original content coverage, we
251  // verify that we don't introduce any artifacts from the intersection.
252  auto image_filter = FilterContents::MakeMatrixFilter(
253  FilterInput::Make(Rect()), Matrix::MakeScale({0.9, 0.9, 1}), {});
254 
255  auto coverage = ComputeSaveLayerCoverage(
256  /*content_coverage=*/Rect::MakeLTRB(0, 0, 100, 100), //
257  /*effect_transform=*/{}, //
258  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
259  /*image_filter=*/image_filter //
260  );
261 
262  ASSERT_TRUE(coverage.has_value());
263  // The transfomed coverage limit is ((0, 0), (111.111, 111.111)).
264  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
265 }
266 
268  CoverageLimitRespectedIfSubstantiallyDifferentFromContentCoverage) {
269  auto image_filter = FilterContents::MakeMatrixFilter(
270  FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
271 
272  auto coverage = ComputeSaveLayerCoverage(
273  /*content_coverage=*/Rect::MakeLTRB(0, 0, 1000, 1000), //
274  /*effect_transform=*/{}, //
275  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
276  /*image_filter=*/image_filter //
277  );
278 
279  ASSERT_TRUE(coverage.has_value());
280  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
281 }
282 
283 TEST(SaveLayerUtilsTest, RoundUpCoverageWhenCloseToCoverageLimit) {
284  // X varies, translation is performed on coverage.
285  auto coverage = ComputeSaveLayerCoverage(
286  /*content_coverage=*/Rect::MakeLTRB(0, 0, 90, 90), //
287  /*effect_transform=*/{}, //
288  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
289  /*image_filter=*/nullptr //
290  );
291 
292  ASSERT_TRUE(coverage.has_value());
293  // Size that matches coverage limit
294  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
295 }
296 
297 TEST(SaveLayerUtilsTest, DontRoundUpCoverageWhenNotCloseToCoverageLimitWidth) {
298  // X varies, translation is performed on coverage.
299  auto coverage = ComputeSaveLayerCoverage(
300  /*content_coverage=*/Rect::MakeLTRB(0, 0, 50, 90), //
301  /*effect_transform=*/{}, //
302  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
303  /*image_filter=*/nullptr //
304  );
305 
306  ASSERT_TRUE(coverage.has_value());
307  // Size that matches coverage limit
308  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 90));
309 }
310 
311 TEST(SaveLayerUtilsTest, DontRoundUpCoverageWhenNotCloseToCoverageLimitHeight) {
312  // X varies, translation is performed on coverage.
313  auto coverage = ComputeSaveLayerCoverage(
314  /*content_coverage=*/Rect::MakeLTRB(0, 0, 90, 50), //
315  /*effect_transform=*/{}, //
316  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
317  /*image_filter=*/nullptr //
318  );
319 
320  ASSERT_TRUE(coverage.has_value());
321  // Size that matches coverage limit
322  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 90, 50));
323 }
324 
326  DontRoundUpCoverageWhenNotCloseToCoverageLimitWidthHeight) {
327  // X varies, translation is performed on coverage.
328  auto coverage = ComputeSaveLayerCoverage(
329  /*content_coverage=*/Rect::MakeLTRB(0, 0, 50, 50), //
330  /*effect_transform=*/{}, //
331  /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
332  /*image_filter=*/nullptr //
333  );
334 
335  ASSERT_TRUE(coverage.has_value());
336  // Size that matches coverage limit
337  EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
338 }
339 
340 } // namespace testing
341 } // namespace impeller
342 
343 // NOLINTEND(bugprone-unchecked-optional-access)
static std::shared_ptr< FilterContents > MakeMatrixFilter(FilterInput::Ref input, const Matrix &matrix, const SamplerDescriptor &desc)
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
::testing::Test SaveLayerUtilsTest
TEST(AllocationSizeTest, CanCreateTypedAllocations)
TRect< Scalar > Rect
Definition: rect.h:792
std::optional< Rect > ComputeSaveLayerCoverage(const Rect &content_coverage, const Matrix &effect_transform, const Rect &coverage_limit, const std::shared_ptr< FilterContents > &image_filter, bool flood_output_coverage, bool flood_input_coverage)
Compute the coverage of a subpass in the global coordinate space.
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129