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(paint_context()));
26 
27  EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
28  "needs_painting\\(context\\)");
29 }
30 
31 TEST_F(ColorFilterLayerTest, PaintBeforePrerollDies) {
32  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
33  const SkPath child_path = SkPath().addRect(child_bounds);
34  auto mock_layer = std::make_shared<MockLayer>(child_path);
35  auto layer = std::make_shared<ColorFilterLayer>(sk_sp<SkColorFilter>());
36  layer->Add(mock_layer);
37 
38  EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
39  EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
40  "needs_painting\\(context\\)");
41 }
42 #endif
43 
44 TEST_F(ColorFilterLayerTest, EmptyFilter) {
45  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
46  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
47  const SkPath child_path = SkPath().addRect(child_bounds);
48  const SkPaint child_paint = SkPaint(SkColors::kYellow);
49  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
50  auto layer = std::make_shared<ColorFilterLayer>(nullptr);
51  layer->Add(mock_layer);
52 
53  layer->Preroll(preroll_context(), initial_transform);
54  EXPECT_EQ(layer->paint_bounds(), child_bounds);
55  EXPECT_TRUE(layer->needs_painting(paint_context()));
56  EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
57 
58  SkPaint filter_paint;
59  filter_paint.setColorFilter(nullptr);
60  layer->Paint(paint_context());
61  EXPECT_EQ(
62  mock_canvas().draw_calls(),
63  std::vector({MockCanvas::DrawCall{
64  0, MockCanvas::SaveLayerData{child_bounds, filter_paint,
65  nullptr, 1}},
67  1, MockCanvas::DrawPathData{child_path, child_paint}},
69 }
70 
71 TEST_F(ColorFilterLayerTest, SimpleFilter) {
72  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
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::kYellow);
76  auto layer_filter =
77  SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW);
78  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
79  auto layer = std::make_shared<ColorFilterLayer>(layer_filter);
80  layer->Add(mock_layer);
81 
82  layer->Preroll(preroll_context(), initial_transform);
83  EXPECT_EQ(layer->paint_bounds(), child_bounds);
84  EXPECT_TRUE(layer->needs_painting(paint_context()));
85  EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
86 
87  SkPaint filter_paint;
88  filter_paint.setColorFilter(layer_filter);
89  layer->Paint(paint_context());
90  EXPECT_EQ(
91  mock_canvas().draw_calls(),
92  std::vector({MockCanvas::DrawCall{
93  0, MockCanvas::SaveLayerData{child_bounds, filter_paint,
94  nullptr, 1}},
96  1, MockCanvas::DrawPathData{child_path, child_paint}},
98 }
99 
100 TEST_F(ColorFilterLayerTest, MultipleChildren) {
101  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
102  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 2.5f, 3.5f);
103  const SkPath child_path1 = SkPath().addRect(child_bounds);
104  const SkPath child_path2 =
105  SkPath().addRect(child_bounds.makeOffset(3.0f, 0.0f));
106  const SkPaint child_paint1 = SkPaint(SkColors::kYellow);
107  const SkPaint child_paint2 = SkPaint(SkColors::kCyan);
108  auto layer_filter =
109  SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW);
110  auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
111  auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
112  auto layer = std::make_shared<ColorFilterLayer>(layer_filter);
113  layer->Add(mock_layer1);
114  layer->Add(mock_layer2);
115 
116  SkRect children_bounds = child_path1.getBounds();
117  children_bounds.join(child_path2.getBounds());
118  layer->Preroll(preroll_context(), initial_transform);
119  EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
120  EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
121  EXPECT_EQ(layer->paint_bounds(), children_bounds);
122  EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
123  EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
124  EXPECT_TRUE(layer->needs_painting(paint_context()));
125  EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
126  EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
127 
128  SkPaint filter_paint;
129  filter_paint.setColorFilter(layer_filter);
130  layer->Paint(paint_context());
131  EXPECT_EQ(
132  mock_canvas().draw_calls(),
133  std::vector({MockCanvas::DrawCall{
134  0, MockCanvas::SaveLayerData{children_bounds,
135  filter_paint, nullptr, 1}},
137  1, MockCanvas::DrawPathData{child_path1, child_paint1}},
139  1, MockCanvas::DrawPathData{child_path2, child_paint2}},
141 }
142 
143 TEST_F(ColorFilterLayerTest, Nested) {
144  const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
145  const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 2.5f, 3.5f);
146  const SkPath child_path1 = SkPath().addRect(child_bounds);
147  const SkPath child_path2 =
148  SkPath().addRect(child_bounds.makeOffset(3.0f, 0.0f));
149  const SkPaint child_paint1 = SkPaint(SkColors::kYellow);
150  const SkPaint child_paint2 = SkPaint(SkColors::kCyan);
151  auto layer_filter1 =
152  SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW);
153  auto layer_filter2 =
154  SkColorMatrixFilter::MakeLightingFilter(SK_ColorMAGENTA, SK_ColorBLUE);
155  auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
156  auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
157  auto layer1 = std::make_shared<ColorFilterLayer>(layer_filter1);
158  auto layer2 = std::make_shared<ColorFilterLayer>(layer_filter2);
159  layer2->Add(mock_layer2);
160  layer1->Add(mock_layer1);
161  layer1->Add(layer2);
162 
163  SkRect children_bounds = child_path1.getBounds();
164  children_bounds.join(child_path2.getBounds());
165  layer1->Preroll(preroll_context(), initial_transform);
166  EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
167  EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
168  EXPECT_EQ(layer1->paint_bounds(), children_bounds);
169  EXPECT_EQ(layer2->paint_bounds(), mock_layer2->paint_bounds());
170  EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
171  EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
172  EXPECT_TRUE(layer1->needs_painting(paint_context()));
173  EXPECT_TRUE(layer2->needs_painting(paint_context()));
174  EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
175  EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
176 
177  SkPaint filter_paint1, filter_paint2;
178  filter_paint1.setColorFilter(layer_filter1);
179  filter_paint2.setColorFilter(layer_filter2);
180  layer1->Paint(paint_context());
181  EXPECT_EQ(
182  mock_canvas().draw_calls(),
183  std::vector({MockCanvas::DrawCall{
184  0, MockCanvas::SaveLayerData{children_bounds,
185  filter_paint1, nullptr, 1}},
187  1, MockCanvas::DrawPathData{child_path1, child_paint1}},
189  1, MockCanvas::SaveLayerData{child_path2.getBounds(),
190  filter_paint2, nullptr, 2}},
192  2, MockCanvas::DrawPathData{child_path2, child_paint2}},
195 }
196 
197 TEST_F(ColorFilterLayerTest, Readback) {
198  auto layer_filter = SkColorFilters::LinearToSRGBGamma();
199  auto initial_transform = SkMatrix();
200 
201  // ColorFilterLayer does not read from surface
202  auto layer = std::make_shared<ColorFilterLayer>(layer_filter);
203  preroll_context()->surface_needs_readback = false;
204  layer->Preroll(preroll_context(), initial_transform);
205  EXPECT_FALSE(preroll_context()->surface_needs_readback);
206 
207  // ColorFilterLayer blocks child with readback
208  auto mock_layer =
209  std::make_shared<MockLayer>(SkPath(), SkPaint(), false, true);
210  layer->Add(mock_layer);
211  preroll_context()->surface_needs_readback = false;
212  layer->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