Flutter Engine
backdrop_filter_layer_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/flow/layers/backdrop_filter_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 #include "third_party/skia/include/core/SkImageFilter.h"
12 #include "third_party/skia/include/effects/SkImageFilters.h"
13 
14 namespace flutter {
15 namespace testing {
16 
18 
19 #ifndef NDEBUG
20 TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies) {
21  auto layer = std::make_shared<BackdropFilterLayer>(sk_sp<SkImageFilter>());
22 
23  layer->Preroll(preroll_context(), SkMatrix());
24  EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
25  EXPECT_FALSE(layer->needs_painting());
26  EXPECT_FALSE(layer->needs_system_composite());
27 
28  EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
29  "needs_painting\\(\\)");
30 }
31 
32 TEST_F(BackdropFilterLayerTest, PaintBeforePrerollDies) {
33  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
34  const SkPath child_path = SkPath().addRect(child_bounds);
35  auto mock_layer = std::make_shared<MockLayer>(child_path);
36  auto layer = std::make_shared<BackdropFilterLayer>(sk_sp<SkImageFilter>());
37  layer->Add(mock_layer);
38 
39  EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
40  EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
41  "needs_painting\\(\\)");
42 }
43 #endif
44 
46  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
47  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
48  const SkPath child_path = SkPath().addRect(child_bounds);
49  const SkPaint child_paint = SkPaint(SkColors::kYellow);
50  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
51  auto layer = std::make_shared<BackdropFilterLayer>(nullptr);
52  layer->Add(mock_layer);
53 
54  layer->Preroll(preroll_context(), initial_transform);
55  EXPECT_EQ(layer->paint_bounds(), child_bounds);
56  EXPECT_TRUE(layer->needs_painting());
57  EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
58 
59  layer->Paint(paint_context());
60  EXPECT_EQ(
61  mock_canvas().draw_calls(),
62  std::vector({MockCanvas::DrawCall{
63  0, MockCanvas::SaveLayerData{child_bounds, SkPaint(),
64  nullptr, 1}},
66  1, MockCanvas::DrawPathData{child_path, child_paint}},
68 }
69 
71  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
72  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
73  const SkPath child_path = SkPath().addRect(child_bounds);
74  const SkPaint child_paint = SkPaint(SkColors::kYellow);
75  auto layer_filter = SkImageFilters::Paint(SkPaint(SkColors::kMagenta));
76  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
77  auto layer = std::make_shared<BackdropFilterLayer>(layer_filter);
78  layer->Add(mock_layer);
79 
80  layer->Preroll(preroll_context(), initial_transform);
81  EXPECT_EQ(layer->paint_bounds(), child_bounds);
82  EXPECT_TRUE(layer->needs_painting());
83  EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
84 
85  layer->Paint(paint_context());
86  EXPECT_EQ(
87  mock_canvas().draw_calls(),
88  std::vector({MockCanvas::DrawCall{
89  0, MockCanvas::SaveLayerData{child_bounds, SkPaint(),
90  layer_filter, 1}},
92  1, MockCanvas::DrawPathData{child_path, child_paint}},
94 }
95 
96 TEST_F(BackdropFilterLayerTest, MultipleChildren) {
97  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
98  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 2.5f, 3.5f);
99  const SkPath child_path1 = SkPath().addRect(child_bounds);
100  const SkPath child_path2 =
101  SkPath().addRect(child_bounds.makeOffset(3.0f, 0.0f));
102  const SkPaint child_paint1 = SkPaint(SkColors::kYellow);
103  const SkPaint child_paint2 = SkPaint(SkColors::kCyan);
104  auto layer_filter = SkImageFilters::Paint(SkPaint(SkColors::kMagenta));
105  auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
106  auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
107  auto layer = std::make_shared<BackdropFilterLayer>(layer_filter);
108  layer->Add(mock_layer1);
109  layer->Add(mock_layer2);
110 
111  SkRect children_bounds = child_path1.getBounds();
112  children_bounds.join(child_path2.getBounds());
113  layer->Preroll(preroll_context(), initial_transform);
114  EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
115  EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
116  EXPECT_EQ(layer->paint_bounds(), children_bounds);
117  EXPECT_TRUE(mock_layer1->needs_painting());
118  EXPECT_TRUE(mock_layer2->needs_painting());
119  EXPECT_TRUE(layer->needs_painting());
120  EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
121  EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
122 
123  layer->Paint(paint_context());
124  EXPECT_EQ(
125  mock_canvas().draw_calls(),
126  std::vector({MockCanvas::DrawCall{
127  0, MockCanvas::SaveLayerData{children_bounds, SkPaint(),
128  layer_filter, 1}},
130  1, MockCanvas::DrawPathData{child_path1, child_paint1}},
132  1, MockCanvas::DrawPathData{child_path2, child_paint2}},
134 }
135 
137  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
138  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 2.5f, 3.5f);
139  const SkPath child_path1 = SkPath().addRect(child_bounds);
140  const SkPath child_path2 =
141  SkPath().addRect(child_bounds.makeOffset(3.0f, 0.0f));
142  const SkPaint child_paint1 = SkPaint(SkColors::kYellow);
143  const SkPaint child_paint2 = SkPaint(SkColors::kCyan);
144  auto layer_filter1 = SkImageFilters::Paint(SkPaint(SkColors::kMagenta));
145  auto layer_filter2 = SkImageFilters::Paint(SkPaint(SkColors::kDkGray));
146  auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
147  auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
148  auto layer1 = std::make_shared<BackdropFilterLayer>(layer_filter1);
149  auto layer2 = std::make_shared<BackdropFilterLayer>(layer_filter2);
150  layer2->Add(mock_layer2);
151  layer1->Add(mock_layer1);
152  layer1->Add(layer2);
153 
154  SkRect children_bounds = child_path1.getBounds();
155  children_bounds.join(child_path2.getBounds());
156  layer1->Preroll(preroll_context(), initial_transform);
157  EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
158  EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
159  EXPECT_EQ(layer1->paint_bounds(), children_bounds);
160  EXPECT_EQ(layer2->paint_bounds(), mock_layer2->paint_bounds());
161  EXPECT_TRUE(mock_layer1->needs_painting());
162  EXPECT_TRUE(mock_layer2->needs_painting());
163  EXPECT_TRUE(layer1->needs_painting());
164  EXPECT_TRUE(layer2->needs_painting());
165  EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
166  EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
167 
168  layer1->Paint(paint_context());
169  EXPECT_EQ(mock_canvas().draw_calls(),
170  std::vector(
172  0, MockCanvas::SaveLayerData{children_bounds, SkPaint(),
173  layer_filter1, 1}},
175  1, MockCanvas::DrawPathData{child_path1, child_paint1}},
177  1, MockCanvas::SaveLayerData{child_path2.getBounds(),
178  SkPaint(), layer_filter2, 2}},
180  2, MockCanvas::DrawPathData{child_path2, child_paint2}},
183 }
184 
186  sk_sp<SkImageFilter> no_filter;
187  auto layer_filter = SkImageFilters::Paint(SkPaint(SkColors::kMagenta));
188  auto initial_transform = SkMatrix();
189 
190  // BDF with filter always reads from surface
191  auto layer1 = std::make_shared<BackdropFilterLayer>(layer_filter);
192  preroll_context()->surface_needs_readback = false;
193  layer1->Preroll(preroll_context(), initial_transform);
194  EXPECT_TRUE(preroll_context()->surface_needs_readback);
195 
196  // BDF with no filter does not read from surface itself
197  auto layer2 = std::make_shared<BackdropFilterLayer>(no_filter);
198  preroll_context()->surface_needs_readback = false;
199  layer2->Preroll(preroll_context(), initial_transform);
200  EXPECT_FALSE(preroll_context()->surface_needs_readback);
201 
202  // BDF with no filter does not block prior readback value
203  preroll_context()->surface_needs_readback = true;
204  layer2->Preroll(preroll_context(), initial_transform);
205  EXPECT_TRUE(preroll_context()->surface_needs_readback);
206 
207  // BDF with no filter blocks child with readback
208  auto mock_layer =
209  std::make_shared<MockLayer>(SkPath(), SkPaint(), false, false, true);
210  layer2->Add(mock_layer);
211  preroll_context()->surface_needs_readback = false;
212  layer2->Preroll(preroll_context(), initial_transform);
213  EXPECT_FALSE(preroll_context()->surface_needs_readback);
214 }
215 
216 } // namespace testing
217 } // namespace flutter
LayerTestBase<::testing::Test > LayerTest
Definition: layer_test.h:151
TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies)
static constexpr SkRect kEmptyRect
Definition: mock_canvas.h:28