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