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/flow/layers/container_layer.h"
6
7#include "flutter/flow/testing/layer_test.h"
8#include "flutter/flow/testing/mock_layer.h"
9#include "flutter/fml/macros.h"
10#include "flutter/testing/mock_canvas.h"
11
12namespace flutter {
13namespace testing {
14
15using ContainerLayerTest = LayerTest;
16
17#ifndef NDEBUG
18TEST_F(ContainerLayerTest, LayerWithParentHasPlatformView) {
19 auto layer = std::make_shared<ContainerLayer>();
20
21 preroll_context()->has_platform_view = true;
22 EXPECT_DEATH_IF_SUPPORTED(layer->Preroll(preroll_context(), SkMatrix()),
23 "!context->has_platform_view");
24}
25
26TEST_F(ContainerLayerTest, PaintingEmptyLayerDies) {
27 auto layer = std::make_shared<ContainerLayer>();
28
29 layer->Preroll(preroll_context(), SkMatrix());
30 EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
31 EXPECT_FALSE(layer->needs_painting());
32 EXPECT_FALSE(layer->needs_system_composite());
33
34 EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
35 "needs_painting\\(\\)");
36}
37
38TEST_F(ContainerLayerTest, PaintBeforePreollDies) {
39 SkPath child_path;
40 child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
41 auto mock_layer = std::make_shared<MockLayer>(child_path);
42 auto layer = std::make_shared<ContainerLayer>();
43 layer->Add(mock_layer);
44
45 EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
46 EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
47 "needs_painting\\(\\)");
48}
49#endif
50
51TEST_F(ContainerLayerTest, Simple) {
52 SkPath child_path;
53 child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
54 SkPaint child_paint(SkColors::kGreen);
55 SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
56
57 auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
58 auto layer = std::make_shared<ContainerLayer>();
59 layer->Add(mock_layer);
60
61 layer->Preroll(preroll_context(), initial_transform);
62 EXPECT_FALSE(preroll_context()->has_platform_view);
63 EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
64 EXPECT_EQ(layer->paint_bounds(), child_path.getBounds());
65 EXPECT_TRUE(mock_layer->needs_painting());
66 EXPECT_TRUE(layer->needs_painting());
67 EXPECT_FALSE(mock_layer->needs_system_composite());
68 EXPECT_FALSE(layer->needs_system_composite());
69 EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
70 EXPECT_EQ(mock_layer->parent_cull_rect(), kGiantRect);
71
72 layer->Paint(paint_context());
73 EXPECT_EQ(mock_canvas().draw_calls(),
74 std::vector({MockCanvas::DrawCall{
75 0, MockCanvas::DrawPathData{child_path, child_paint}}}));
76}
77
78TEST_F(ContainerLayerTest, Multiple) {
79 SkPath child_path1;
80 child_path1.addRect(5.0f, 6.0f, 20.5f, 21.5f);
81 SkPath child_path2;
82 child_path2.addRect(8.0f, 2.0f, 16.5f, 14.5f);
83 SkPaint child_paint1(SkColors::kGray);
84 SkPaint child_paint2(SkColors::kGreen);
85 SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
86
87 auto mock_layer1 = std::make_shared<MockLayer>(
88 child_path1, child_paint1, true /* fake_has_platform_view */);
89 auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
90 auto layer = std::make_shared<ContainerLayer>();
91 layer->Add(mock_layer1);
92 layer->Add(mock_layer2);
93
94 SkRect expected_total_bounds = child_path1.getBounds();
95 expected_total_bounds.join(child_path2.getBounds());
96 layer->Preroll(preroll_context(), initial_transform);
97 EXPECT_TRUE(preroll_context()->has_platform_view);
98 EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
99 EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
100 EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
101 EXPECT_TRUE(mock_layer1->needs_painting());
102 EXPECT_TRUE(mock_layer2->needs_painting());
103 EXPECT_TRUE(layer->needs_painting());
104 EXPECT_FALSE(mock_layer1->needs_system_composite());
105 EXPECT_FALSE(mock_layer2->needs_system_composite());
106 EXPECT_FALSE(layer->needs_system_composite());
107 EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
108 EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
109 EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
110 EXPECT_EQ(mock_layer2->parent_cull_rect(),
111 kGiantRect); // Siblings are independent
112
113 layer->Paint(paint_context());
114 EXPECT_EQ(
115 mock_canvas().draw_calls(),
116 std::vector({MockCanvas::DrawCall{
117 0, MockCanvas::DrawPathData{child_path1, child_paint1}},
118 MockCanvas::DrawCall{0, MockCanvas::DrawPathData{
119 child_path2, child_paint2}}}));
120}
121
122TEST_F(ContainerLayerTest, MultipleWithEmpty) {
123 SkPath child_path1;
124 child_path1.addRect(5.0f, 6.0f, 20.5f, 21.5f);
125 SkPaint child_paint1(SkColors::kGray);
126 SkPaint child_paint2(SkColors::kGreen);
127 SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
128
129 auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
130 auto mock_layer2 = std::make_shared<MockLayer>(SkPath(), child_paint2);
131 auto layer = std::make_shared<ContainerLayer>();
132 layer->Add(mock_layer1);
133 layer->Add(mock_layer2);
134
135 layer->Preroll(preroll_context(), initial_transform);
136 EXPECT_FALSE(preroll_context()->has_platform_view);
137 EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
138 EXPECT_EQ(mock_layer2->paint_bounds(), SkPath().getBounds());
139 EXPECT_EQ(layer->paint_bounds(), child_path1.getBounds());
140 EXPECT_TRUE(mock_layer1->needs_painting());
141 EXPECT_FALSE(mock_layer2->needs_painting());
142 EXPECT_TRUE(layer->needs_painting());
143 EXPECT_FALSE(mock_layer1->needs_system_composite());
144 EXPECT_FALSE(mock_layer2->needs_system_composite());
145 EXPECT_FALSE(layer->needs_system_composite());
146 EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
147 EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
148 EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
149 EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);
150
151 layer->Paint(paint_context());
152 EXPECT_EQ(mock_canvas().draw_calls(),
153 std::vector({MockCanvas::DrawCall{
154 0, MockCanvas::DrawPathData{child_path1, child_paint1}}}));
155}
156
157TEST_F(ContainerLayerTest, NeedsSystemComposite) {
158 SkPath child_path1;
159 child_path1.addRect(5.0f, 6.0f, 20.5f, 21.5f);
160 SkPath child_path2;
161 child_path2.addRect(8.0f, 2.0f, 16.5f, 14.5f);
162 SkPaint child_paint1(SkColors::kGray);
163 SkPaint child_paint2(SkColors::kGreen);
164 SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
165
166 auto mock_layer1 = std::make_shared<MockLayer>(
167 child_path1, child_paint1, false /* fake_has_platform_view */,
168 true /* fake_needs_system_composite */);
169 auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
170 auto layer = std::make_shared<ContainerLayer>();
171 layer->Add(mock_layer1);
172 layer->Add(mock_layer2);
173
174 SkRect expected_total_bounds = child_path1.getBounds();
175 expected_total_bounds.join(child_path2.getBounds());
176 layer->Preroll(preroll_context(), initial_transform);
177 EXPECT_FALSE(preroll_context()->has_platform_view);
178 EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
179 EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
180 EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
181 EXPECT_TRUE(mock_layer1->needs_painting());
182 EXPECT_TRUE(mock_layer2->needs_painting());
183 EXPECT_TRUE(layer->needs_painting());
184 EXPECT_TRUE(mock_layer1->needs_system_composite());
185 EXPECT_FALSE(mock_layer2->needs_system_composite());
186 EXPECT_TRUE(layer->needs_system_composite());
187 EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
188 EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
189 EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
190 EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);
191
192 layer->Paint(paint_context());
193 EXPECT_EQ(
194 mock_canvas().draw_calls(),
195 std::vector({MockCanvas::DrawCall{
196 0, MockCanvas::DrawPathData{child_path1, child_paint1}},
197 MockCanvas::DrawCall{0, MockCanvas::DrawPathData{
198 child_path2, child_paint2}}}));
199}
200
201TEST_F(ContainerLayerTest, MergedOneChild) {
202 SkPath child_path;
203 child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
204 SkPaint child_paint(SkColors::kGreen);
205 SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
206
207 auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
208 auto layer = std::make_shared<MergedContainerLayer>();
209 layer->Add(mock_layer);
210
211 layer->Preroll(preroll_context(), initial_transform);
212 EXPECT_FALSE(preroll_context()->has_platform_view);
213 EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
214 EXPECT_EQ(layer->paint_bounds(), child_path.getBounds());
215 EXPECT_TRUE(mock_layer->needs_painting());
216 EXPECT_TRUE(layer->needs_painting());
217 EXPECT_FALSE(mock_layer->needs_system_composite());
218 EXPECT_FALSE(layer->needs_system_composite());
219 EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
220 EXPECT_EQ(mock_layer->parent_cull_rect(), kGiantRect);
221
222 layer->Paint(paint_context());
223 EXPECT_EQ(mock_canvas().draw_calls(),
224 std::vector({MockCanvas::DrawCall{
225 0, MockCanvas::DrawPathData{child_path, child_paint}}}));
226}
227
228TEST_F(ContainerLayerTest, MergedMultipleChildren) {
229 SkPath child_path1;
230 child_path1.addRect(5.0f, 6.0f, 20.5f, 21.5f);
231 SkPath child_path2;
232 child_path2.addRect(58.0f, 2.0f, 16.5f, 14.5f);
233 SkPaint child_paint1(SkColors::kGray);
234 SkPaint child_paint2(SkColors::kGreen);
235 SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
236
237 auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
238 auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
239 auto layer = std::make_shared<MergedContainerLayer>();
240 layer->Add(mock_layer1);
241 layer->Add(mock_layer2);
242
243 SkRect expected_total_bounds = child_path1.getBounds();
244 expected_total_bounds.join(child_path2.getBounds());
245 layer->Preroll(preroll_context(), initial_transform);
246 EXPECT_FALSE(preroll_context()->has_platform_view);
247 EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
248 EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
249 EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
250 EXPECT_TRUE(mock_layer1->needs_painting());
251 EXPECT_TRUE(mock_layer2->needs_painting());
252 EXPECT_TRUE(layer->needs_painting());
253 EXPECT_FALSE(mock_layer1->needs_system_composite());
254 EXPECT_FALSE(mock_layer2->needs_system_composite());
255 EXPECT_FALSE(layer->needs_system_composite());
256 EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
257 EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
258 EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
259 EXPECT_EQ(mock_layer2->parent_cull_rect(),
260 kGiantRect); // Siblings are independent
261
262 layer->Paint(paint_context());
263 EXPECT_EQ(
264 mock_canvas().draw_calls(),
265 std::vector({MockCanvas::DrawCall{
266 0, MockCanvas::DrawPathData{child_path1, child_paint1}},
267 MockCanvas::DrawCall{0, MockCanvas::DrawPathData{
268 child_path2, child_paint2}}}));
269}
270
271} // namespace testing
272} // namespace flutter
273