Flutter Engine
The Flutter Engine
dl_complexity_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/display_list/benchmarking/dl_complexity.h"
6#include "flutter/display_list/benchmarking/dl_complexity_gl.h"
7#include "flutter/display_list/benchmarking/dl_complexity_metal.h"
8#include "flutter/display_list/display_list.h"
9#include "flutter/display_list/dl_builder.h"
10#include "flutter/display_list/dl_sampling_options.h"
11#include "flutter/display_list/testing/dl_test_snippets.h"
12#include "flutter/testing/testing.h"
13
17
18namespace flutter {
19namespace testing {
20
21namespace {
22
23std::vector<DisplayListComplexityCalculator*> Calculators() {
27}
28
29std::vector<DisplayListComplexityCalculator*> AccumulatorCalculators() {
32}
33
34std::vector<SkPoint> GetTestPoints() {
35 std::vector<SkPoint> points;
36 points.push_back(SkPoint::Make(0, 0));
37 points.push_back(SkPoint::Make(10, 0));
38 points.push_back(SkPoint::Make(10, 10));
39 points.push_back(SkPoint::Make(20, 10));
40 points.push_back(SkPoint::Make(20, 20));
41
42 return points;
43}
44
45} // namespace
46
47TEST(DisplayListComplexity, EmptyDisplayList) {
48 auto display_list = GetSampleDisplayList(0);
49
50 auto calculators = Calculators();
51 for (auto calculator : calculators) {
52 ASSERT_EQ(calculator->Compute(display_list.get()), 0u);
53 }
54}
55
56TEST(DisplayListComplexity, DisplayListCeiling) {
57 auto display_list = GetSampleDisplayList();
58
59 auto calculators = AccumulatorCalculators();
60 for (auto calculator : calculators) {
61 calculator->SetComplexityCeiling(10u);
62 ASSERT_EQ(calculator->Compute(display_list.get()), 10u);
63 calculator->SetComplexityCeiling(std::numeric_limits<unsigned int>::max());
64 }
65}
66
67TEST(DisplayListComplexity, NestedDisplayList) {
68 auto display_list = GetSampleNestedDisplayList();
69
70 auto calculators = Calculators();
71 for (auto calculator : calculators) {
72 // There's only one draw call in the "outer" DisplayList, which calls
73 // drawDisplayList with the "inner" DisplayList. To ensure we are
74 // recursing correctly into the inner DisplayList, check that we aren't
75 // returning 0 (if the function is a no-op) or 1 (as the op_count is 1)
76 ASSERT_GT(calculator->Compute(display_list.get()), 1u);
77 }
78}
79
80TEST(DisplayListComplexity, AntiAliasing) {
81 DisplayListBuilder builder_no_aa;
82 builder_no_aa.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
83 DlPaint());
84 auto display_list_no_aa = builder_no_aa.Build();
85
86 DisplayListBuilder builder_aa;
87 builder_aa.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
88 DlPaint().setAntiAlias(true));
89 auto display_list_aa = builder_aa.Build();
90
91 auto calculators = AccumulatorCalculators();
92 for (auto calculator : calculators) {
93 ASSERT_NE(calculator->Compute(display_list_no_aa.get()),
94 calculator->Compute(display_list_aa.get()));
95 }
96}
97
98TEST(DisplayListComplexity, StrokeWidth) {
99 DisplayListBuilder builder_stroke_0;
100 builder_stroke_0.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
101 DlPaint().setStrokeWidth(0.0f));
102 auto display_list_stroke_0 = builder_stroke_0.Build();
103
104 DisplayListBuilder builder_stroke_1;
105 builder_stroke_1.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
106 DlPaint().setStrokeWidth(1.0f));
107 auto display_list_stroke_1 = builder_stroke_1.Build();
108
109 auto calculators = AccumulatorCalculators();
110 for (auto calculator : calculators) {
111 ASSERT_NE(calculator->Compute(display_list_stroke_0.get()),
112 calculator->Compute(display_list_stroke_1.get()));
113 }
114}
115
116TEST(DisplayListComplexity, Style) {
117 DisplayListBuilder builder_filled;
118 builder_filled.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80),
119 DlPaint().setDrawStyle(DlDrawStyle::kFill));
120 auto display_list_filled = builder_filled.Build();
121
122 DisplayListBuilder builder_stroked;
123 builder_stroked.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80),
124 DlPaint().setDrawStyle(DlDrawStyle::kStroke));
125 auto display_list_stroked = builder_stroked.Build();
126
127 auto calculators = AccumulatorCalculators();
128 for (auto calculator : calculators) {
129 ASSERT_NE(calculator->Compute(display_list_filled.get()),
130 calculator->Compute(display_list_stroked.get()));
131 }
132}
133
134TEST(DisplayListComplexity, SaveLayers) {
136 builder.SaveLayer(nullptr, nullptr);
137 auto display_list = builder.Build();
138
139 auto calculators = AccumulatorCalculators();
140 for (auto calculator : calculators) {
141 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
142 }
143}
144
145TEST(DisplayListComplexity, DrawPath) {
146 DisplayListBuilder builder_line;
147 SkPath line_path;
148 line_path.moveTo(SkPoint::Make(0, 0));
149 line_path.lineTo(SkPoint::Make(10, 10));
150 line_path.close();
151 builder_line.DrawPath(line_path, DlPaint());
152 auto display_list_line = builder_line.Build();
153
154 DisplayListBuilder builder_quad;
159 builder_quad.DrawPath(quad_path, DlPaint());
160 auto display_list_quad = builder_quad.Build();
161
162 DisplayListBuilder builder_conic;
163 SkPath conic_path;
164 conic_path.moveTo(SkPoint::Make(0, 0));
165 conic_path.conicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), 1.5f);
166 conic_path.close();
167 builder_conic.DrawPath(conic_path, DlPaint());
168 auto display_list_conic = builder_conic.Build();
169
170 DisplayListBuilder builder_cubic;
174 SkPoint::Make(20, 20));
175 builder_cubic.DrawPath(cubic_path, DlPaint());
176 auto display_list_cubic = builder_cubic.Build();
177
178 auto calculators = AccumulatorCalculators();
179 for (auto calculator : calculators) {
180 ASSERT_NE(calculator->Compute(display_list_line.get()), 0u);
181 ASSERT_NE(calculator->Compute(display_list_quad.get()), 0u);
182 ASSERT_NE(calculator->Compute(display_list_conic.get()), 0u);
183 ASSERT_NE(calculator->Compute(display_list_cubic.get()), 0u);
184 }
185}
186
187TEST(DisplayListComplexity, DrawShadow) {
188 DisplayListBuilder builder_line;
189 SkPath line_path;
190 line_path.moveTo(SkPoint::Make(0, 0));
191 line_path.lineTo(SkPoint::Make(10, 10));
192 line_path.close();
193 builder_line.DrawShadow(line_path, DlColor(SK_ColorRED), 10.0f, false, 1.0f);
194 auto display_list_line = builder_line.Build();
195
196 DisplayListBuilder builder_quad;
201 builder_quad.DrawShadow(quad_path, DlColor(SK_ColorRED), 10.0f, false, 1.0f);
202 auto display_list_quad = builder_quad.Build();
203
204 DisplayListBuilder builder_conic;
205 SkPath conic_path;
206 conic_path.moveTo(SkPoint::Make(0, 0));
207 conic_path.conicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), 1.5f);
208 conic_path.close();
209 builder_conic.DrawShadow(conic_path, DlColor(SK_ColorRED), 10.0f, false,
210 1.0f);
211 auto display_list_conic = builder_conic.Build();
212
213 DisplayListBuilder builder_cubic;
217 SkPoint::Make(20, 20));
218 builder_cubic.DrawShadow(cubic_path, DlColor(SK_ColorRED), 10.0f, false,
219 1.0f);
220 auto display_list_cubic = builder_cubic.Build();
221
222 auto calculators = AccumulatorCalculators();
223 for (auto calculator : calculators) {
224 ASSERT_NE(calculator->Compute(display_list_line.get()), 0u);
225 ASSERT_NE(calculator->Compute(display_list_quad.get()), 0u);
226 ASSERT_NE(calculator->Compute(display_list_conic.get()), 0u);
227 ASSERT_NE(calculator->Compute(display_list_cubic.get()), 0u);
228 }
229}
230
231TEST(DisplayListComplexity, DrawOval) {
233 builder.DrawOval(SkRect::MakeXYWH(10, 10, 100, 80), DlPaint());
234 auto display_list = builder.Build();
235
236 auto calculators = AccumulatorCalculators();
237 for (auto calculator : calculators) {
238 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
239 }
240}
241
242TEST(DisplayListComplexity, DrawCircle) {
244 builder.DrawCircle(SkPoint::Make(50, 50), 10.0f, DlPaint());
245 auto display_list = builder.Build();
246
247 auto calculators = AccumulatorCalculators();
248 for (auto calculator : calculators) {
249 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
250 }
251}
252
253TEST(DisplayListComplexity, DrawRRect) {
255 builder.DrawRRect(
256 SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f),
257 DlPaint());
258 auto display_list = builder.Build();
259
260 auto calculators = AccumulatorCalculators();
261 for (auto calculator : calculators) {
262 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
263 }
264}
265
266TEST(DisplayListComplexity, DrawDRRect) {
268 SkRRect outer =
269 SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f);
270 SkRRect inner =
271 SkRRect::MakeRectXY(SkRect::MakeXYWH(15, 15, 70, 70), 1.5f, 1.5f);
272 builder.DrawDRRect(outer, inner, DlPaint());
273 auto display_list = builder.Build();
274
275 auto calculators = AccumulatorCalculators();
276 for (auto calculator : calculators) {
277 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
278 }
279}
280
281TEST(DisplayListComplexity, DrawArc) {
283 builder.DrawArc(SkRect::MakeXYWH(10, 10, 100, 80), 0.0f, 10.0f, true,
284 DlPaint());
285 auto display_list = builder.Build();
286
287 auto calculators = AccumulatorCalculators();
288 for (auto calculator : calculators) {
289 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
290 }
291}
292
293TEST(DisplayListComplexity, DrawVertices) {
294 auto points = GetTestPoints();
295 auto vertices = DlVertices::Make(DlVertexMode::kTriangles, points.size(),
296 points.data(), nullptr, nullptr);
298 builder.DrawVertices(vertices.get(), DlBlendMode::kSrc, DlPaint());
299 auto display_list = builder.Build();
300
301 auto calculators = AccumulatorCalculators();
302 for (auto calculator : calculators) {
303 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
304 }
305}
306
307TEST(DisplayListComplexity, DrawTextBlob) {
308 auto text_blob = SkTextBlob::MakeFromString(
309 "The quick brown fox jumps over the lazy dog.", CreateTestFontOfSize(20));
310
312 builder.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint());
313 auto display_list = builder.Build();
314
315 DisplayListBuilder builder_multiple;
316 builder_multiple.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint());
317 builder_multiple.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint());
318 auto display_list_multiple = builder_multiple.Build();
319
320 auto calculators = AccumulatorCalculators();
321 for (auto calculator : calculators) {
322 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
323 ASSERT_GT(calculator->Compute(display_list_multiple.get()),
324 calculator->Compute(display_list.get()));
325 }
326}
327
328TEST(DisplayListComplexity, DrawPoints) {
329 auto points = GetTestPoints();
330 DisplayListBuilder builder_lines;
331 builder_lines.DrawPoints(DlCanvas::PointMode::kLines, points.size(),
332 points.data(), DlPaint());
333 auto display_list_lines = builder_lines.Build();
334
335 DisplayListBuilder builder_points;
336 builder_points.DrawPoints(DlCanvas::PointMode::kPoints, points.size(),
337 points.data(), DlPaint());
338 auto display_list_points = builder_points.Build();
339
340 DisplayListBuilder builder_polygon;
341 builder_polygon.DrawPoints(DlCanvas::PointMode::kPolygon, points.size(),
342 points.data(), DlPaint());
343 auto display_list_polygon = builder_polygon.Build();
344
345 auto calculators = AccumulatorCalculators();
346 for (auto calculator : calculators) {
347 ASSERT_NE(calculator->Compute(display_list_lines.get()), 0u);
348 ASSERT_NE(calculator->Compute(display_list_points.get()), 0u);
349 ASSERT_NE(calculator->Compute(display_list_polygon.get()), 0u);
350 }
351}
352
353TEST(DisplayListComplexity, DrawImage) {
358 bitmap.allocPixels(info, 0);
360
362 builder.DrawImage(DlImage::Make(image), SkPoint::Make(0, 0),
364 auto display_list = builder.Build();
365
366 auto calculators = AccumulatorCalculators();
367 for (auto calculator : calculators) {
368 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
369 }
370}
371
372TEST(DisplayListComplexity, DrawImageNine) {
377 bitmap.allocPixels(info, 0);
379
380 SkIRect center = SkIRect::MakeXYWH(5, 5, 20, 20);
381 SkRect dest = SkRect::MakeXYWH(0, 0, 50, 50);
382
384 builder.DrawImageNine(DlImage::Make(image), center, dest,
385 DlFilterMode::kNearest, nullptr);
386 auto display_list = builder.Build();
387
388 auto calculators = AccumulatorCalculators();
389 for (auto calculator : calculators) {
390 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
391 }
392}
393
394TEST(DisplayListComplexity, DrawImageRect) {
399 bitmap.allocPixels(info, 0);
401
402 SkRect src = SkRect::MakeXYWH(0, 0, 50, 50);
403 SkRect dest = SkRect::MakeXYWH(0, 0, 50, 50);
404
406 builder.DrawImageRect(DlImage::Make(image), src, dest,
408 auto display_list = builder.Build();
409
410 auto calculators = AccumulatorCalculators();
411 for (auto calculator : calculators) {
412 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
413 }
414}
415
416TEST(DisplayListComplexity, DrawAtlas) {
421 bitmap.allocPixels(info, 0);
423
424 std::vector<SkRect> rects;
425 std::vector<SkRSXform> xforms;
426 for (int i = 0; i < 10; i++) {
427 rects.push_back(SkRect::MakeXYWH(0, 0, 10, 10));
428 xforms.push_back(SkRSXform::Make(1, 0, 0, 0));
429 }
430
432 builder.DrawAtlas(DlImage::Make(image), xforms.data(), rects.data(), nullptr,
434 nullptr, nullptr);
435 auto display_list = builder.Build();
436
437 auto calculators = AccumulatorCalculators();
438 for (auto calculator : calculators) {
439 ASSERT_NE(calculator->Compute(display_list.get()), 0u);
440 }
441}
442
443} // namespace testing
444} // namespace flutter
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static const int points[]
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
Definition: SkPath.h:59
SkPath & moveTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:688
SkPath & lineTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:728
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
Definition: SkPath.cpp:746
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
Definition: SkPath.cpp:799
SkPath & conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
Definition: SkPath.cpp:766
SkPath & close()
Definition: SkPath.cpp:823
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.h:180
static sk_sp< SkTextBlob > MakeFromString(const char *string, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
Definition: SkTextBlob.h:115
void DrawLine(const SkPoint &p0, const SkPoint &p1, const DlPaint &paint) override
Definition: dl_builder.cc:1077
void DrawRect(const SkRect &rect, const DlPaint &paint) override
Definition: dl_builder.cc:1116
void DrawPath(const SkPath &path, const DlPaint &paint) override
Definition: dl_builder.cc:1204
void DrawPoints(PointMode mode, uint32_t count, const SkPoint pts[], const DlPaint &paint) override
Definition: dl_builder.cc:1305
void DrawTextBlob(const sk_sp< SkTextBlob > &blob, SkScalar x, SkScalar y, const DlPaint &paint) override
Definition: dl_builder.cc:1630
void DrawShadow(const SkPath &path, const DlColor color, const SkScalar elevation, bool transparent_occluder, SkScalar dpr) override
Definition: dl_builder.cc:1679
sk_sp< DisplayList > Build()
Definition: dl_builder.cc:67
static DisplayListGLComplexityCalculator * GetInstance()
static DisplayListMetalComplexityCalculator * GetInstance()
static DisplayListComplexityCalculator * GetInstance()
@ kLines
draw each separate pair of points as a line segment
@ kPolygon
draw each pair of overlapping points as a line segment
@ kPoints
draw each point separately
static sk_sp< DlImage > Make(const SkImage *image)
Definition: dl_image.cc:11
static std::shared_ptr< DlVertices > Make(DlVertexMode mode, int vertex_count, const SkPoint vertices[], const SkPoint texture_coordinates[], const DlColor colors[], int index_count=0, const uint16_t indices[]=nullptr)
Constructs a DlVector with compact inline storage for all of its required and optional lists of data.
Definition: dl_vertices.cc:39
static float max(float r, float g, float b)
Definition: hsl.cpp:49
SK_API sk_sp< SkImage > RasterFromBitmap(const SkBitmap &bitmap)
sk_sp< const SkImage > image
Definition: SkRecords.h:269
PODArray< SkRSXform > xforms
Definition: SkRecords.h:332
void DrawImage(SkCanvas *canvas, const SkImage *image, SkScalar x, SkScalar y, const SkSamplingOptions &sampling={}, const SkPaint *paint=nullptr, SkCanvas::SrcRectConstraint constraint=SkCanvas::kFast_SrcRectConstraint)
SK_API void DrawImageRect(SkCanvas *canvas, const SkImage *image, const SkRect &src, const SkRect &dst, const SkSamplingOptions &sampling={}, const SkPaint *paint=nullptr, SkCanvas::SrcRectConstraint constraint=SkCanvas::kFast_SrcRectConstraint)
Definition: bitmap.py:1
SkFont CreateTestFontOfSize(SkScalar scalar)
sk_sp< DisplayList > GetSampleDisplayList()
std::vector< SkPoint > GetTestPoints(size_t count, SkISize canvas_size)
sk_sp< DisplayList > GetSampleNestedDisplayList()
TEST(DisplayListComplexity, EmptyDisplayList)
@ kTriangles
The vertices are taken 3 at a time to form a triangle.
@ kStroke
strokes boundary of shapes
@ kFill
fills interior of shapes
skgpu::graphite::DrawAtlas DrawAtlas
flutter::DlColor DlColor
flutter::DlPaint DlPaint
dest
Definition: zip.py:79
SkPath quad_path()
Definition: overstroke.cpp:60
SkPath cubic_path()
Definition: overstroke.cpp:68
Definition: SkRect.h:32
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
static SkRSXform Make(SkScalar scos, SkScalar ssin, SkScalar tx, SkScalar ty)
Definition: SkRSXform.h:24
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659