Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 8dbffe5

Browse files
authored
switch from MockCanvas to DisplayListBuilder in layer unit tests (#41889)
Part of an ongoing set of efforts to address flutter/flutter#106448 The layer unittests have been using a MockCanvas class to record the painting of trees of layers and then testing for the expected output. A while back a similar mechanism was created to compare DisplayList output and to print out a human-friendly version of the differences found, but it was only used in a few tests written at the time it was created and a few since then. This is the first in a series of PRs that will move all the rest of the unit tests onto the new DL comparison mechanism, starting with the layer types that just do basic drawing. Some of the remaining layers will require creating new hooks in, for instance, the Texture registry, the performance overlay TextBlob generation, etc.
1 parent 892f88d commit 8dbffe5

17 files changed

+781
-562
lines changed

display_list/display_list_unittests.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,22 @@ class DisplayListTestBase : public BaseT {
9292
};
9393
using DisplayListTest = DisplayListTestBase<::testing::Test>;
9494

95+
TEST_F(DisplayListTest, EmptyBuild) {
96+
DisplayListBuilder builder;
97+
auto dl = builder.Build();
98+
EXPECT_EQ(dl->op_count(), 0u);
99+
EXPECT_EQ(dl->bytes(), sizeof(DisplayList));
100+
}
101+
102+
TEST_F(DisplayListTest, EmptyRebuild) {
103+
DisplayListBuilder builder;
104+
auto dl1 = builder.Build();
105+
auto dl2 = builder.Build();
106+
auto dl3 = builder.Build();
107+
ASSERT_TRUE(dl1->Equals(dl2));
108+
ASSERT_TRUE(dl2->Equals(dl3));
109+
}
110+
95111
TEST_F(DisplayListTest, BuilderCanBeReused) {
96112
DisplayListBuilder builder(kTestBounds);
97113
builder.DrawRect(kTestBounds, DlPaint());

display_list/dl_builder.cc

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -578,15 +578,18 @@ void DisplayListBuilder::Transform2DAffine(
578578
SkScalar myx, SkScalar myy, SkScalar myt) {
579579
if (SkScalarsAreFinite(mxx, myx) &&
580580
SkScalarsAreFinite(mxy, myy) &&
581-
SkScalarsAreFinite(mxt, myt) &&
582-
!(mxx == 1 && mxy == 0 && mxt == 0 &&
583-
myx == 0 && myy == 1 && myt == 0)) {
584-
checkForDeferredSave();
585-
Push<Transform2DAffineOp>(0, 1,
586-
mxx, mxy, mxt,
587-
myx, myy, myt);
588-
tracker_.transform2DAffine(mxx, mxy, mxt,
589-
myx, myy, myt);
581+
SkScalarsAreFinite(mxt, myt)) {
582+
if (mxx == 1 && mxy == 0 &&
583+
myx == 0 && myy == 1) {
584+
Translate(mxt, myt);
585+
} else {
586+
checkForDeferredSave();
587+
Push<Transform2DAffineOp>(0, 1,
588+
mxx, mxy, mxt,
589+
myx, myy, myt);
590+
tracker_.transform2DAffine(mxx, mxy, mxt,
591+
myx, myy, myt);
592+
}
590593
}
591594
}
592595
// full 4x4 transform in row major order

display_list/dl_builder.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,17 @@ class DisplayListBuilder final : public virtual DlCanvas,
113113
SkMatrix GetTransform() const override { return tracker_.matrix_3x3(); }
114114

115115
// |DlCanvas|
116-
void ClipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override;
116+
void ClipRect(const SkRect& rect,
117+
ClipOp clip_op = ClipOp::kIntersect,
118+
bool is_aa = false) override;
117119
// |DlCanvas|
118-
void ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
120+
void ClipRRect(const SkRRect& rrect,
121+
ClipOp clip_op = ClipOp::kIntersect,
122+
bool is_aa = false) override;
119123
// |DlCanvas|
120-
void ClipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
124+
void ClipPath(const SkPath& path,
125+
ClipOp clip_op = ClipOp::kIntersect,
126+
bool is_aa = false) override;
121127

122128
/// Conservative estimate of the bounds of all outstanding clip operations
123129
/// measured in the coordinate space within which this DisplayList will

flow/layers/backdrop_filter_layer_unittests.cc

Lines changed: 142 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@
1111
#include "flutter/flow/testing/layer_test.h"
1212
#include "flutter/flow/testing/mock_layer.h"
1313
#include "flutter/fml/macros.h"
14-
#include "flutter/testing/mock_canvas.h"
15-
#include "third_party/skia/include/core/SkImageFilter.h"
16-
#include "third_party/skia/include/effects/SkImageFilters.h"
1714

1815
namespace flutter {
1916
namespace testing {
@@ -72,15 +69,30 @@ TEST_F(BackdropFilterLayerTest, EmptyFilter) {
7269
EXPECT_TRUE(layer->needs_painting(paint_context()));
7370
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
7471

75-
layer->Paint(paint_context());
76-
EXPECT_EQ(
77-
mock_canvas().draw_calls(),
78-
std::vector({MockCanvas::DrawCall{
79-
0, MockCanvas::SaveLayerData{child_bounds, DlPaint(),
80-
nullptr, 1}},
81-
MockCanvas::DrawCall{
82-
1, MockCanvas::DrawPathData{child_path, child_paint}},
83-
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
72+
parent->Paint(display_list_paint_context());
73+
DisplayListBuilder expected_builder;
74+
/* (ClipRect)parent::Paint */ {
75+
expected_builder.Save();
76+
{
77+
expected_builder.ClipRect(child_bounds, DlCanvas::ClipOp::kIntersect,
78+
false);
79+
/* (BackdropFilter)layer::Paint */ {
80+
expected_builder.Save();
81+
{
82+
expected_builder.SaveLayer(&child_bounds, nullptr, nullptr);
83+
{
84+
/* mock_layer::Paint */ {
85+
expected_builder.DrawPath(child_path, child_paint);
86+
}
87+
}
88+
expected_builder.Restore();
89+
}
90+
expected_builder.Restore();
91+
}
92+
}
93+
expected_builder.Restore();
94+
}
95+
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
8496
}
8597

8698
TEST_F(BackdropFilterLayerTest, SimpleFilter) {
@@ -104,15 +116,31 @@ TEST_F(BackdropFilterLayerTest, SimpleFilter) {
104116
EXPECT_TRUE(layer->needs_painting(paint_context()));
105117
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
106118

107-
layer->Paint(paint_context());
108-
EXPECT_EQ(
109-
mock_canvas().draw_calls(),
110-
std::vector({MockCanvas::DrawCall{
111-
0, MockCanvas::SaveLayerData{child_bounds, DlPaint(),
112-
layer_filter, 1}},
113-
MockCanvas::DrawCall{
114-
1, MockCanvas::DrawPathData{child_path, child_paint}},
115-
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
119+
parent->Paint(display_list_paint_context());
120+
DisplayListBuilder expected_builder;
121+
/* (ClipRect)parent::Paint */ {
122+
expected_builder.Save();
123+
{
124+
expected_builder.ClipRect(child_bounds, DlCanvas::ClipOp::kIntersect,
125+
false);
126+
/* (BackdropFilter)layer::Paint */ {
127+
expected_builder.Save();
128+
{
129+
expected_builder.SaveLayer(&child_bounds, nullptr,
130+
layer_filter.get());
131+
{
132+
/* mock_layer::Paint */ {
133+
expected_builder.DrawPath(child_path, child_paint);
134+
}
135+
}
136+
expected_builder.Restore();
137+
}
138+
expected_builder.Restore();
139+
}
140+
}
141+
expected_builder.Restore();
142+
}
143+
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
116144
}
117145

118146
TEST_F(BackdropFilterLayerTest, NonSrcOverBlend) {
@@ -139,15 +167,32 @@ TEST_F(BackdropFilterLayerTest, NonSrcOverBlend) {
139167
DlPaint filter_paint = DlPaint();
140168
filter_paint.setBlendMode(DlBlendMode::kSrc);
141169

142-
layer->Paint(paint_context());
143-
EXPECT_EQ(
144-
mock_canvas().draw_calls(),
145-
std::vector({MockCanvas::DrawCall{
146-
0, MockCanvas::SaveLayerData{child_bounds, filter_paint,
147-
layer_filter, 1}},
148-
MockCanvas::DrawCall{
149-
1, MockCanvas::DrawPathData{child_path, child_paint}},
150-
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
170+
parent->Paint(display_list_paint_context());
171+
DisplayListBuilder expected_builder;
172+
/* (ClipRect)parent::Paint */ {
173+
expected_builder.Save();
174+
{
175+
expected_builder.ClipRect(child_bounds, DlCanvas::ClipOp::kIntersect,
176+
false);
177+
/* (BackdropFilter)layer::Paint */ {
178+
expected_builder.Save();
179+
{
180+
DlPaint save_paint = DlPaint().setBlendMode(DlBlendMode::kSrc);
181+
expected_builder.SaveLayer(&child_bounds, &save_paint,
182+
layer_filter.get());
183+
{
184+
/* mock_layer::Paint */ {
185+
expected_builder.DrawPath(child_path, child_paint);
186+
}
187+
}
188+
expected_builder.Restore();
189+
}
190+
expected_builder.Restore();
191+
}
192+
}
193+
expected_builder.Restore();
194+
}
195+
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
151196
}
152197

153198
TEST_F(BackdropFilterLayerTest, MultipleChildren) {
@@ -184,17 +229,34 @@ TEST_F(BackdropFilterLayerTest, MultipleChildren) {
184229
EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
185230
EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
186231

187-
layer->Paint(paint_context());
188-
EXPECT_EQ(
189-
mock_canvas().draw_calls(),
190-
std::vector({MockCanvas::DrawCall{
191-
0, MockCanvas::SaveLayerData{children_bounds, DlPaint(),
192-
layer_filter, 1}},
193-
MockCanvas::DrawCall{
194-
1, MockCanvas::DrawPathData{child_path1, child_paint1}},
195-
MockCanvas::DrawCall{
196-
1, MockCanvas::DrawPathData{child_path2, child_paint2}},
197-
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
232+
parent->Paint(display_list_paint_context());
233+
DisplayListBuilder expected_builder;
234+
/* (ClipRect)parent::Paint */ {
235+
expected_builder.Save();
236+
{
237+
expected_builder.ClipRect(children_bounds, DlCanvas::ClipOp::kIntersect,
238+
false);
239+
/* (BackdropFilter)layer::Paint */ {
240+
expected_builder.Save();
241+
{
242+
expected_builder.SaveLayer(&children_bounds, nullptr,
243+
layer_filter.get());
244+
{
245+
/* mock_layer1::Paint */ {
246+
expected_builder.DrawPath(child_path1, child_paint1);
247+
}
248+
/* mock_layer2::Paint */ {
249+
expected_builder.DrawPath(child_path2, child_paint2);
250+
}
251+
}
252+
expected_builder.Restore();
253+
}
254+
expected_builder.Restore();
255+
}
256+
}
257+
expected_builder.Restore();
258+
}
259+
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
198260
}
199261

200262
TEST_F(BackdropFilterLayerTest, Nested) {
@@ -238,21 +300,45 @@ TEST_F(BackdropFilterLayerTest, Nested) {
238300
EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
239301
EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
240302

241-
layer1->Paint(paint_context());
242-
EXPECT_EQ(
243-
mock_canvas().draw_calls(),
244-
std::vector({MockCanvas::DrawCall{
245-
0, MockCanvas::SaveLayerData{children_bounds, DlPaint(),
246-
layer_filter1, 1}},
247-
MockCanvas::DrawCall{
248-
1, MockCanvas::DrawPathData{child_path1, child_paint1}},
249-
MockCanvas::DrawCall{
250-
1, MockCanvas::SaveLayerData{children_bounds, DlPaint(),
251-
layer_filter2, 2}},
252-
MockCanvas::DrawCall{
253-
2, MockCanvas::DrawPathData{child_path2, child_paint2}},
254-
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
255-
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
303+
parent->Paint(display_list_paint_context());
304+
DisplayListBuilder expected_builder;
305+
/* (ClipRect)parent::Paint */ {
306+
expected_builder.Save();
307+
{
308+
expected_builder.ClipRect(children_bounds, DlCanvas::ClipOp::kIntersect,
309+
false);
310+
/* (BackdropFilter)layer1::Paint */ {
311+
expected_builder.Save();
312+
{
313+
expected_builder.SaveLayer(&children_bounds, nullptr,
314+
layer_filter1.get());
315+
{
316+
/* mock_layer1::Paint */ {
317+
expected_builder.DrawPath(child_path1, child_paint1);
318+
}
319+
/* (BackdropFilter)layer2::Paint */ {
320+
expected_builder.Save();
321+
{
322+
expected_builder.SaveLayer(&children_bounds, nullptr,
323+
layer_filter2.get());
324+
{
325+
/* mock_layer2::Paint */ {
326+
expected_builder.DrawPath(child_path2, child_paint2);
327+
}
328+
}
329+
expected_builder.Restore();
330+
}
331+
expected_builder.Restore();
332+
}
333+
}
334+
expected_builder.Restore();
335+
}
336+
expected_builder.Restore();
337+
}
338+
}
339+
expected_builder.Restore();
340+
}
341+
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
256342
}
257343

258344
TEST_F(BackdropFilterLayerTest, Readback) {

flow/layers/clip_path_layer_unittests.cc

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include "flutter/flow/testing/mock_embedder.h"
1313
#include "flutter/flow/testing/mock_layer.h"
1414
#include "flutter/fml/macros.h"
15-
#include "flutter/testing/mock_canvas.h"
1615
#include "gtest/gtest.h"
1716

1817
namespace flutter {
@@ -170,17 +169,19 @@ TEST_F(ClipPathLayerTest, FullyContainedChild) {
170169
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
171170
EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)}));
172171

173-
layer->Paint(paint_context());
174-
EXPECT_EQ(
175-
mock_canvas().draw_calls(),
176-
std::vector(
177-
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
178-
MockCanvas::DrawCall{
179-
1, MockCanvas::ClipPathData{layer_path, ClipOp::kIntersect,
180-
MockCanvas::kHard_ClipEdgeStyle}},
181-
MockCanvas::DrawCall{
182-
1, MockCanvas::DrawPathData{child_path, child_paint}},
183-
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
172+
layer->Paint(display_list_paint_context());
173+
DisplayListBuilder expected_builder;
174+
/* (ClipPath)layer::Paint */ {
175+
expected_builder.Save();
176+
{
177+
expected_builder.ClipPath(layer_path);
178+
/* mock_layer::Paint */ {
179+
expected_builder.DrawPath(child_path, child_paint);
180+
}
181+
}
182+
expected_builder.Restore();
183+
}
184+
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
184185
}
185186

186187
TEST_F(ClipPathLayerTest, PartiallyContainedChild) {
@@ -224,17 +225,19 @@ TEST_F(ClipPathLayerTest, PartiallyContainedChild) {
224225
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
225226
EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(clip_path)}));
226227

227-
layer->Paint(paint_context());
228-
EXPECT_EQ(
229-
mock_canvas().draw_calls(),
230-
std::vector(
231-
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
232-
MockCanvas::DrawCall{
233-
1, MockCanvas::ClipPathData{clip_path, ClipOp::kIntersect,
234-
MockCanvas::kHard_ClipEdgeStyle}},
235-
MockCanvas::DrawCall{
236-
1, MockCanvas::DrawPathData{child_path, child_paint}},
237-
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
228+
layer->Paint(display_list_paint_context());
229+
DisplayListBuilder expected_builder;
230+
/* (ClipPath)layer::Paint */ {
231+
expected_builder.Save();
232+
{
233+
expected_builder.ClipPath(clip_path);
234+
/* mock_layer::Paint */ {
235+
expected_builder.DrawPath(child_path, child_paint);
236+
}
237+
}
238+
expected_builder.Restore();
239+
}
240+
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
238241
}
239242

240243
static bool ReadbackResult(PrerollContext* context,

0 commit comments

Comments
 (0)