Flutter Engine
color_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/color_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/SkColorFilter.h"
12 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
13 
14 namespace flutter {
15 namespace testing {
16 
18 
19 #ifndef NDEBUG
20 TEST_F(ColorFilterLayerTest, PaintingEmptyLayerDies) {
21  auto layer = std::make_shared<ColorFilterLayer>(sk_sp<SkColorFilter>());
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(ColorFilterLayerTest, 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<ColorFilterLayer>(sk_sp<SkColorFilter>());
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 
45 TEST_F(ColorFilterLayerTest, EmptyFilter) {
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<ColorFilterLayer>(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  SkPaint filter_paint;
60  filter_paint.setColorFilter(nullptr);
61  layer->Paint(paint_context());
62  EXPECT_EQ(
63  mock_canvas().draw_calls(),
64  std::vector({MockCanvas::DrawCall{
65  0, MockCanvas::SaveLayerData{child_bounds, filter_paint,
66  nullptr, 1}},
68  1, MockCanvas::DrawPathData{child_path, child_paint}},
70 }
71 
72 TEST_F(ColorFilterLayerTest, SimpleFilter) {
73  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
74  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
75  const SkPath child_path = SkPath().addRect(child_bounds);
76  const SkPaint child_paint = SkPaint(SkColors::kYellow);
77  auto layer_filter =
78  SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW);
79  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
80  auto layer = std::make_shared<ColorFilterLayer>(layer_filter);
81  layer->Add(mock_layer);
82 
83  layer->Preroll(preroll_context(), initial_transform);
84  EXPECT_EQ(layer->paint_bounds(), child_bounds);
85  EXPECT_TRUE(layer->needs_painting());
86  EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
87 
88  SkPaint filter_paint;
89  filter_paint.setColorFilter(layer_filter);
90  layer->Paint(paint_context());
91  EXPECT_EQ(
92  mock_canvas().draw_calls(),
93  std::vector({MockCanvas::DrawCall{
94  0, MockCanvas::SaveLayerData{child_bounds, filter_paint,
95  nullptr, 1}},
97  1, MockCanvas::DrawPathData{child_path, child_paint}},
99 }
100 
101 TEST_F(ColorFilterLayerTest, MultipleChildren) {
102  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
103  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 2.5f, 3.5f);
104  const SkPath child_path1 = SkPath().addRect(child_bounds);
105  const SkPath child_path2 =
106  SkPath().addRect(child_bounds.makeOffset(3.0f, 0.0f));
107  const SkPaint child_paint1 = SkPaint(SkColors::kYellow);
108  const SkPaint child_paint2 = SkPaint(SkColors::kCyan);
109  auto layer_filter =
110  SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW);
111  auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
112  auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
113  auto layer = std::make_shared<ColorFilterLayer>(layer_filter);
114  layer->Add(mock_layer1);
115  layer->Add(mock_layer2);
116 
117  SkRect children_bounds = child_path1.getBounds();
118  children_bounds.join(child_path2.getBounds());
119  layer->Preroll(preroll_context(), initial_transform);
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(), children_bounds);
123  EXPECT_TRUE(mock_layer1->needs_painting());
124  EXPECT_TRUE(mock_layer2->needs_painting());
125  EXPECT_TRUE(layer->needs_painting());
126  EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
127  EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
128 
129  SkPaint filter_paint;
130  filter_paint.setColorFilter(layer_filter);
131  layer->Paint(paint_context());
132  EXPECT_EQ(
133  mock_canvas().draw_calls(),
134  std::vector({MockCanvas::DrawCall{
135  0, MockCanvas::SaveLayerData{children_bounds,
136  filter_paint, nullptr, 1}},
138  1, MockCanvas::DrawPathData{child_path1, child_paint1}},
140  1, MockCanvas::DrawPathData{child_path2, child_paint2}},
142 }
143 
144 TEST_F(ColorFilterLayerTest, Nested) {
145  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
146  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 2.5f, 3.5f);
147  const SkPath child_path1 = SkPath().addRect(child_bounds);
148  const SkPath child_path2 =
149  SkPath().addRect(child_bounds.makeOffset(3.0f, 0.0f));
150  const SkPaint child_paint1 = SkPaint(SkColors::kYellow);
151  const SkPaint child_paint2 = SkPaint(SkColors::kCyan);
152  auto layer_filter1 =
153  SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW);
154  auto layer_filter2 =
155  SkColorMatrixFilter::MakeLightingFilter(SK_ColorMAGENTA, SK_ColorBLUE);
156  auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
157  auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
158  auto layer1 = std::make_shared<ColorFilterLayer>(layer_filter1);
159  auto layer2 = std::make_shared<ColorFilterLayer>(layer_filter2);
160  layer2->Add(mock_layer2);
161  layer1->Add(mock_layer1);
162  layer1->Add(layer2);
163 
164  SkRect children_bounds = child_path1.getBounds();
165  children_bounds.join(child_path2.getBounds());
166  layer1->Preroll(preroll_context(), initial_transform);
167  EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
168  EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
169  EXPECT_EQ(layer1->paint_bounds(), children_bounds);
170  EXPECT_EQ(layer2->paint_bounds(), mock_layer2->paint_bounds());
171  EXPECT_TRUE(mock_layer1->needs_painting());
172  EXPECT_TRUE(mock_layer2->needs_painting());
173  EXPECT_TRUE(layer1->needs_painting());
174  EXPECT_TRUE(layer2->needs_painting());
175  EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
176  EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
177 
178  SkPaint filter_paint1, filter_paint2;
179  filter_paint1.setColorFilter(layer_filter1);
180  filter_paint2.setColorFilter(layer_filter2);
181  layer1->Paint(paint_context());
182  EXPECT_EQ(
183  mock_canvas().draw_calls(),
184  std::vector({MockCanvas::DrawCall{
185  0, MockCanvas::SaveLayerData{children_bounds,
186  filter_paint1, nullptr, 1}},
188  1, MockCanvas::DrawPathData{child_path1, child_paint1}},
190  1, MockCanvas::SaveLayerData{child_path2.getBounds(),
191  filter_paint2, nullptr, 2}},
193  2, MockCanvas::DrawPathData{child_path2, child_paint2}},
196 }
197 
198 TEST_F(ColorFilterLayerTest, Readback) {
199  auto layer_filter = SkColorFilters::LinearToSRGBGamma();
200  auto initial_transform = SkMatrix();
201 
202  // ColorFilterLayer does not read from surface
203  auto layer = std::make_shared<ColorFilterLayer>(layer_filter);
204  preroll_context()->surface_needs_readback = false;
205  layer->Preroll(preroll_context(), initial_transform);
206  EXPECT_FALSE(preroll_context()->surface_needs_readback);
207 
208  // ColorFilterLayer blocks child with readback
209  auto mock_layer =
210  std::make_shared<MockLayer>(SkPath(), SkPaint(), false, false, true);
211  layer->Add(mock_layer);
212  preroll_context()->surface_needs_readback = false;
213  layer->Preroll(preroll_context(), initial_transform);
214  EXPECT_FALSE(preroll_context()->surface_needs_readback);
215 }
216 
217 } // namespace testing
218 } // namespace flutter
LayerTestBase<::testing::Test > LayerTest
Definition: layer_test.h:151
TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies)
static constexpr SkRect kEmptyRect
Definition: mock_canvas.h:28