Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
layer_tree_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 <stddef.h>
6#include "flutter/flow/layers/layer_tree.h"
7
8#include "flutter/flow/compositor_context.h"
9#include "flutter/flow/layers/container_layer.h"
10#include "flutter/flow/raster_cache.h"
11#include "flutter/flow/testing/mock_layer.h"
12#include "flutter/fml/macros.h"
13#include "flutter/testing/canvas_test.h"
14#include "flutter/testing/mock_canvas.h"
15#include "gtest/gtest.h"
16
17namespace flutter {
18namespace testing {
19class LayerTreeTest : public CanvasTest {
20 public:
22 : root_transform_(SkMatrix::Translate(1.0f, 1.0f)),
23 scoped_frame_(compositor_context_.AcquireFrame(nullptr,
24 &mock_canvas(),
25 nullptr,
26 root_transform_,
27 false,
28 true,
29 nullptr,
30 nullptr)) {}
31
32 CompositorContext::ScopedFrame& frame() { return *scoped_frame_.get(); }
33 const SkMatrix& root_transform() { return root_transform_; }
34
35 std::unique_ptr<LayerTree> BuildLayerTree(const LayerTree::Config& config) {
36 return std::make_unique<LayerTree>(config, SkISize::Make(64, 64));
37 }
38
39 private:
40 CompositorContext compositor_context_;
41 SkMatrix root_transform_;
42 std::unique_ptr<CompositorContext::ScopedFrame> scoped_frame_;
43};
44
45TEST_F(LayerTreeTest, PaintingEmptyLayerDies) {
46 auto layer = std::make_shared<ContainerLayer>();
47
48 auto layer_tree = BuildLayerTree(LayerTree::Config{
49 .root_layer = layer,
50 });
51 layer_tree->Preroll(frame());
52 EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
53 EXPECT_TRUE(layer->is_empty());
54
55 layer_tree->Paint(frame());
56}
57
58TEST_F(LayerTreeTest, PaintBeforePrerollDies) {
59 const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
60 SkPath child_path;
61 child_path.addRect(child_bounds);
62 auto mock_layer = std::make_shared<MockLayer>(child_path);
63 auto layer = std::make_shared<ContainerLayer>();
64 layer->Add(mock_layer);
65
66 auto layer_tree = BuildLayerTree(LayerTree::Config{
67 .root_layer = layer,
68 });
69 EXPECT_EQ(mock_layer->paint_bounds(), kEmptyRect);
70 EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
71 EXPECT_TRUE(mock_layer->is_empty());
72 EXPECT_TRUE(layer->is_empty());
73
74 layer_tree->Paint(frame());
75 EXPECT_EQ(mock_canvas().draw_calls(), std::vector<MockCanvas::DrawCall>());
76}
77
79 const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
80 const SkPath child_path = SkPath().addRect(child_bounds);
81 const DlPaint child_paint = DlPaint(DlColor::kCyan());
82 auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
83 auto layer = std::make_shared<ContainerLayer>();
84 layer->Add(mock_layer);
85
86 auto layer_tree = BuildLayerTree(LayerTree::Config{
87 .root_layer = layer,
88 });
89 layer_tree->Preroll(frame());
90 EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
91 EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
92 EXPECT_FALSE(mock_layer->is_empty());
93 EXPECT_FALSE(layer->is_empty());
94 EXPECT_EQ(mock_layer->parent_matrix(), root_transform());
95
96 layer_tree->Paint(frame());
97 EXPECT_EQ(mock_canvas().draw_calls(),
98 std::vector({MockCanvas::DrawCall{
99 0, MockCanvas::DrawPathData{child_path, child_paint}}}));
100}
101
103 const SkPath child_path1 = SkPath().addRect(5.0f, 6.0f, 20.5f, 21.5f);
104 const SkPath child_path2 = SkPath().addRect(8.0f, 2.0f, 16.5f, 14.5f);
105 const DlPaint child_paint1 = DlPaint(DlColor::kMidGrey());
106 const DlPaint child_paint2 = DlPaint(DlColor::kGreen());
107 auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
108 mock_layer1->set_fake_has_platform_view(true);
109 auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
110 auto layer = std::make_shared<ContainerLayer>();
111 layer->Add(mock_layer1);
112 layer->Add(mock_layer2);
113
114 SkRect expected_total_bounds = child_path1.getBounds();
115 expected_total_bounds.join(child_path2.getBounds());
116 auto layer_tree = BuildLayerTree(LayerTree::Config{
117 .root_layer = layer,
118 });
119 layer_tree->Preroll(frame());
120 EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
121 EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
122 EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
123 EXPECT_FALSE(mock_layer1->is_empty());
124 EXPECT_FALSE(mock_layer2->is_empty());
125 EXPECT_FALSE(layer->is_empty());
126 EXPECT_EQ(mock_layer1->parent_matrix(), root_transform());
127 EXPECT_EQ(mock_layer2->parent_matrix(), root_transform());
128 EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
129 EXPECT_EQ(mock_layer2->parent_cull_rect(),
130 kGiantRect); // Siblings are independent
131
132 layer_tree->Paint(frame());
133 EXPECT_EQ(
134 mock_canvas().draw_calls(),
135 std::vector({MockCanvas::DrawCall{
136 0, MockCanvas::DrawPathData{child_path1, child_paint1}},
138 child_path2, child_paint2}}}));
139}
140
141TEST_F(LayerTreeTest, MultipleWithEmpty) {
142 const SkPath child_path1 = SkPath().addRect(5.0f, 6.0f, 20.5f, 21.5f);
143 const DlPaint child_paint1 = DlPaint(DlColor::kMidGrey());
144 const DlPaint child_paint2 = DlPaint(DlColor::kGreen());
145 auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
146 auto mock_layer2 = std::make_shared<MockLayer>(SkPath(), child_paint2);
147 auto layer = std::make_shared<ContainerLayer>();
148 layer->Add(mock_layer1);
149 layer->Add(mock_layer2);
150
151 auto layer_tree = BuildLayerTree(LayerTree::Config{
152 .root_layer = layer,
153 });
154 layer_tree->Preroll(frame());
155 EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
156 EXPECT_EQ(mock_layer2->paint_bounds(), SkPath().getBounds());
157 EXPECT_EQ(layer->paint_bounds(), child_path1.getBounds());
158 EXPECT_FALSE(mock_layer1->is_empty());
159 EXPECT_TRUE(mock_layer2->is_empty());
160 EXPECT_FALSE(layer->is_empty());
161 EXPECT_EQ(mock_layer1->parent_matrix(), root_transform());
162 EXPECT_EQ(mock_layer2->parent_matrix(), root_transform());
163 EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
164 EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);
165
166 layer_tree->Paint(frame());
167 EXPECT_EQ(mock_canvas().draw_calls(),
168 std::vector({MockCanvas::DrawCall{
169 0, MockCanvas::DrawPathData{child_path1, child_paint1}}}));
170}
171
172TEST_F(LayerTreeTest, NeedsSystemComposite) {
173 const SkPath child_path1 = SkPath().addRect(5.0f, 6.0f, 20.5f, 21.5f);
174 const SkPath child_path2 = SkPath().addRect(8.0f, 2.0f, 16.5f, 14.5f);
175 const DlPaint child_paint1 = DlPaint(DlColor::kMidGrey());
176 const DlPaint child_paint2 = DlPaint(DlColor::kGreen());
177 auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
178 auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
179 auto layer = std::make_shared<ContainerLayer>();
180 layer->Add(mock_layer1);
181 layer->Add(mock_layer2);
182
183 SkRect expected_total_bounds = child_path1.getBounds();
184 expected_total_bounds.join(child_path2.getBounds());
185 auto layer_tree = BuildLayerTree(LayerTree::Config{
186 .root_layer = layer,
187 });
188 layer_tree->Preroll(frame());
189 EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
190 EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
191 EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
192 EXPECT_FALSE(mock_layer1->is_empty());
193 EXPECT_FALSE(mock_layer2->is_empty());
194 EXPECT_FALSE(layer->is_empty());
195 EXPECT_EQ(mock_layer1->parent_matrix(), root_transform());
196 EXPECT_EQ(mock_layer2->parent_matrix(), root_transform());
197 EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
198 EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);
199
200 layer_tree->Paint(frame());
201 EXPECT_EQ(
202 mock_canvas().draw_calls(),
203 std::vector({MockCanvas::DrawCall{
204 0, MockCanvas::DrawPathData{child_path1, child_paint1}},
206 child_path2, child_paint2}}}));
207}
208
209TEST_F(LayerTreeTest, PrerollContextInitialization) {
210 LayerStateStack state_stack;
212 FixedRefreshRateStopwatch mock_raster_time;
213 FixedRefreshRateStopwatch mock_ui_time;
214 std::shared_ptr<TextureRegistry> mock_registry;
215
216 auto expect_defaults = [&state_stack, &mock_raster_time, &mock_ui_time,
217 &mock_registry](const PrerollContext& context) {
218 EXPECT_EQ(context.raster_cache, nullptr);
219 EXPECT_EQ(context.gr_context, nullptr);
220 EXPECT_EQ(context.view_embedder, nullptr);
221 EXPECT_EQ(&context.state_stack, &state_stack);
222 EXPECT_EQ(context.dst_color_space, nullptr);
223 EXPECT_EQ(context.state_stack.device_cull_rect(), kGiantRect);
224 EXPECT_EQ(context.state_stack.transform_3x3(), SkMatrix::I());
225 EXPECT_EQ(context.state_stack.transform_4x4(), SkM44());
226 EXPECT_EQ(context.surface_needs_readback, false);
227
228 EXPECT_EQ(&context.raster_time, &mock_raster_time);
229 EXPECT_EQ(&context.ui_time, &mock_ui_time);
230 EXPECT_EQ(context.texture_registry.get(), mock_registry.get());
231
232 EXPECT_EQ(context.has_platform_view, false);
233 EXPECT_EQ(context.has_texture_layer, false);
234
235 EXPECT_EQ(context.renderable_state_flags, 0);
236 EXPECT_EQ(context.raster_cached_entries, nullptr);
237 };
238
239 // These 4 initializers are required because they are handled by reference
240 PrerollContext context{
241 .state_stack = state_stack,
242 .raster_time = mock_raster_time,
243 .ui_time = mock_ui_time,
244 .texture_registry = mock_registry,
245 };
246 expect_defaults(context);
247}
248
249TEST_F(LayerTreeTest, PaintContextInitialization) {
250 LayerStateStack state_stack;
251 FixedRefreshRateStopwatch mock_raster_time;
252 FixedRefreshRateStopwatch mock_ui_time;
253 std::shared_ptr<TextureRegistry> mock_registry;
254
255 auto expect_defaults = [&state_stack, &mock_raster_time, &mock_ui_time,
256 &mock_registry](const PaintContext& context) {
257 EXPECT_EQ(&context.state_stack, &state_stack);
258 EXPECT_EQ(context.canvas, nullptr);
259 EXPECT_EQ(context.gr_context, nullptr);
260 EXPECT_EQ(context.view_embedder, nullptr);
261 EXPECT_EQ(&context.raster_time, &mock_raster_time);
262 EXPECT_EQ(&context.ui_time, &mock_ui_time);
263 EXPECT_EQ(context.texture_registry.get(), mock_registry.get());
264 EXPECT_EQ(context.raster_cache, nullptr);
265 EXPECT_EQ(context.state_stack.checkerboard_func(), nullptr);
266
267 EXPECT_EQ(context.enable_leaf_layer_tracing, false);
268 EXPECT_EQ(context.layer_snapshot_store, nullptr);
269 };
270
271 // These 4 initializers are required because they are handled by reference
272 PaintContext context{
273 .state_stack = state_stack,
274 .raster_time = mock_raster_time,
275 .ui_time = mock_ui_time,
276 .texture_registry = mock_registry,
277 };
278 expect_defaults(context);
279}
280
281} // namespace testing
282} // namespace flutter
Definition SkM44.h:150
static const SkMatrix & I()
const SkRect & getBounds() const
Definition SkPath.cpp:420
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
Definition SkPath.cpp:854
Used for fixed refresh rate cases.
Definition stopwatch.h:77
void set_preroll_delegate(const SkRect &cull_rect, const SkMatrix &matrix)
std::unique_ptr< LayerTree > BuildLayerTree(const LayerTree::Config &config)
CompositorContext::ScopedFrame & frame()
double frame
Definition examples.cpp:31
TEST_F(DisplayListTest, Defaults)
static constexpr SkRect kEmptyRect
Definition mock_canvas.h:30
static constexpr SkRect kGiantRect
Definition layer.h:49
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
static constexpr SkRect MakeEmpty()
Definition SkRect.h:595
void join(const SkRect &r)
Definition SkRect.cpp:126
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646
static constexpr DlColor kMidGrey()
Definition dl_color.h:31
static constexpr DlColor kGreen()
Definition dl_color.h:25
static constexpr DlColor kCyan()
Definition dl_color.h:27
std::shared_ptr< Layer > root_layer
Definition layer_tree.h:25
LayerStateStack & state_stack
Definition layer.h:100
LayerStateStack & state_stack
Definition layer.h:58
#define EXPECT_TRUE(handle)
Definition unit_test.h:685