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/layer_tree.h"
6
7#include "flutter/flow/compositor_context.h"
8#include "flutter/flow/layers/container_layer.h"
9#include "flutter/flow/testing/mock_layer.h"
10#include "flutter/fml/macros.h"
11#include "flutter/testing/canvas_test.h"
12#include "flutter/testing/mock_canvas.h"
13#include "gtest/gtest.h"
14
15namespace flutter {
16namespace testing {
17
18class LayerTreeTest : public CanvasTest {
19 public:
20 LayerTreeTest()
21 : layer_tree_(SkISize::Make(64, 64), 1.0f),
22 compositor_context_(fml::kDefaultFrameBudget),
23 root_transform_(SkMatrix::Translate(1.0f, 1.0f)),
24 scoped_frame_(compositor_context_.AcquireFrame(nullptr,
25 &mock_canvas(),
26 nullptr,
27 root_transform_,
28 false,
29 true,
30 nullptr)) {}
31
32 LayerTree& layer_tree() { return layer_tree_; }
33 CompositorContext::ScopedFrame& frame() { return *scoped_frame_.get(); }
34 const SkMatrix& root_transform() { return root_transform_; }
35
36 private:
37 LayerTree layer_tree_;
38 CompositorContext compositor_context_;
39 SkMatrix root_transform_;
40 std::unique_ptr<CompositorContext::ScopedFrame> scoped_frame_;
41};
42
43TEST_F(LayerTreeTest, PaintingEmptyLayerDies) {
44 auto layer = std::make_shared<ContainerLayer>();
45
46 layer_tree().set_root_layer(layer);
47 layer_tree().Preroll(frame());
48 EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
49 EXPECT_FALSE(layer->needs_painting());
50
51 layer_tree().Paint(frame());
52}
53
54TEST_F(LayerTreeTest, PaintBeforePreollDies) {
55 const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
56 SkPath child_path;
57 child_path.addRect(child_bounds);
58 auto mock_layer = std::make_shared<MockLayer>(child_path);
59 auto layer = std::make_shared<ContainerLayer>();
60 layer->Add(mock_layer);
61
62 layer_tree().set_root_layer(layer);
63 EXPECT_EQ(mock_layer->paint_bounds(), kEmptyRect);
64 EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
65 EXPECT_FALSE(mock_layer->needs_painting());
66 EXPECT_FALSE(layer->needs_painting());
67
68 layer_tree().Paint(frame());
69 EXPECT_EQ(mock_canvas().draw_calls(), std::vector<MockCanvas::DrawCall>());
70}
71
72TEST_F(LayerTreeTest, Simple) {
73 const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
74 const SkPath child_path = SkPath().addRect(child_bounds);
75 const SkPaint child_paint = SkPaint(SkColors::kCyan);
76 auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
77 auto layer = std::make_shared<ContainerLayer>();
78 layer->Add(mock_layer);
79
80 layer_tree().set_root_layer(layer);
81 layer_tree().Preroll(frame());
82 EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
83 EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
84 EXPECT_TRUE(mock_layer->needs_painting());
85 EXPECT_TRUE(layer->needs_painting());
86 EXPECT_EQ(mock_layer->parent_matrix(), root_transform());
87
88 layer_tree().Paint(frame());
89 EXPECT_EQ(mock_canvas().draw_calls(),
90 std::vector({MockCanvas::DrawCall{
91 0, MockCanvas::DrawPathData{child_path, child_paint}}}));
92}
93
94TEST_F(LayerTreeTest, Multiple) {
95 const SkPath child_path1 = SkPath().addRect(5.0f, 6.0f, 20.5f, 21.5f);
96 const SkPath child_path2 = SkPath().addRect(8.0f, 2.0f, 16.5f, 14.5f);
97 const SkPaint child_paint1(SkColors::kGray);
98 const SkPaint child_paint2(SkColors::kGreen);
99 auto mock_layer1 = std::make_shared<MockLayer>(
100 child_path1, child_paint1, true /* fake_has_platform_view */);
101 auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
102 auto layer = std::make_shared<ContainerLayer>();
103 layer->Add(mock_layer1);
104 layer->Add(mock_layer2);
105
106 SkRect expected_total_bounds = child_path1.getBounds();
107 expected_total_bounds.join(child_path2.getBounds());
108 layer_tree().set_root_layer(layer);
109 layer_tree().Preroll(frame());
110 EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
111 EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
112 EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
113 EXPECT_TRUE(mock_layer1->needs_painting());
114 EXPECT_TRUE(mock_layer2->needs_painting());
115 EXPECT_TRUE(layer->needs_painting());
116 EXPECT_FALSE(mock_layer1->needs_system_composite());
117 EXPECT_FALSE(mock_layer2->needs_system_composite());
118 EXPECT_FALSE(layer->needs_system_composite());
119 EXPECT_EQ(mock_layer1->parent_matrix(), root_transform());
120 EXPECT_EQ(mock_layer2->parent_matrix(), root_transform());
121 EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
122 EXPECT_EQ(mock_layer2->parent_cull_rect(),
123 kGiantRect); // Siblings are independent
124
125 layer_tree().Paint(frame());
126 EXPECT_EQ(
127 mock_canvas().draw_calls(),
128 std::vector({MockCanvas::DrawCall{
129 0, MockCanvas::DrawPathData{child_path1, child_paint1}},
130 MockCanvas::DrawCall{0, MockCanvas::DrawPathData{
131 child_path2, child_paint2}}}));
132}
133
134TEST_F(LayerTreeTest, MultipleWithEmpty) {
135 const SkPath child_path1 = SkPath().addRect(5.0f, 6.0f, 20.5f, 21.5f);
136 const SkPaint child_paint1(SkColors::kGray);
137 const SkPaint child_paint2(SkColors::kGreen);
138 auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
139 auto mock_layer2 = std::make_shared<MockLayer>(SkPath(), child_paint2);
140 auto layer = std::make_shared<ContainerLayer>();
141 layer->Add(mock_layer1);
142 layer->Add(mock_layer2);
143
144 layer_tree().set_root_layer(layer);
145 layer_tree().Preroll(frame());
146 EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
147 EXPECT_EQ(mock_layer2->paint_bounds(), SkPath().getBounds());
148 EXPECT_EQ(layer->paint_bounds(), child_path1.getBounds());
149 EXPECT_TRUE(mock_layer1->needs_painting());
150 EXPECT_FALSE(mock_layer2->needs_painting());
151 EXPECT_TRUE(layer->needs_painting());
152 EXPECT_FALSE(mock_layer1->needs_system_composite());
153 EXPECT_FALSE(mock_layer2->needs_system_composite());
154 EXPECT_FALSE(layer->needs_system_composite());
155 EXPECT_EQ(mock_layer1->parent_matrix(), root_transform());
156 EXPECT_EQ(mock_layer2->parent_matrix(), root_transform());
157 EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
158 EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);
159
160 layer_tree().Paint(frame());
161 EXPECT_EQ(mock_canvas().draw_calls(),
162 std::vector({MockCanvas::DrawCall{
163 0, MockCanvas::DrawPathData{child_path1, child_paint1}}}));
164}
165
166TEST_F(LayerTreeTest, NeedsSystemComposite) {
167 const SkPath child_path1 = SkPath().addRect(5.0f, 6.0f, 20.5f, 21.5f);
168 const SkPath child_path2 = SkPath().addRect(8.0f, 2.0f, 16.5f, 14.5f);
169 const SkPaint child_paint1(SkColors::kGray);
170 const SkPaint child_paint2(SkColors::kGreen);
171 auto mock_layer1 = std::make_shared<MockLayer>(
172 child_path1, child_paint1, false /* fake_has_platform_view */,
173 true /* fake_needs_system_composite */);
174 auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
175 auto layer = std::make_shared<ContainerLayer>();
176 layer->Add(mock_layer1);
177 layer->Add(mock_layer2);
178
179 SkRect expected_total_bounds = child_path1.getBounds();
180 expected_total_bounds.join(child_path2.getBounds());
181 layer_tree().set_root_layer(layer);
182 layer_tree().Preroll(frame());
183 EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
184 EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
185 EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
186 EXPECT_TRUE(mock_layer1->needs_painting());
187 EXPECT_TRUE(mock_layer2->needs_painting());
188 EXPECT_TRUE(layer->needs_painting());
189 EXPECT_TRUE(mock_layer1->needs_system_composite());
190 EXPECT_FALSE(mock_layer2->needs_system_composite());
191 EXPECT_TRUE(layer->needs_system_composite());
192 EXPECT_EQ(mock_layer1->parent_matrix(), root_transform());
193 EXPECT_EQ(mock_layer2->parent_matrix(), root_transform());
194 EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
195 EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);
196
197 layer_tree().Paint(frame());
198 EXPECT_EQ(
199 mock_canvas().draw_calls(),
200 std::vector({MockCanvas::DrawCall{
201 0, MockCanvas::DrawPathData{child_path1, child_paint1}},
202 MockCanvas::DrawCall{0, MockCanvas::DrawPathData{
203 child_path2, child_paint2}}}));
204}
205
206} // namespace testing
207} // namespace flutter
208