Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
dl_benchmarks.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_benchmarks.h"
6#include "flutter/display_list/dl_builder.h"
7#include "flutter/display_list/dl_op_flags.h"
8#include "flutter/display_list/skia/dl_sk_canvas.h"
9#include "flutter/display_list/testing/dl_test_snippets.h"
10
19
20namespace flutter {
21namespace testing {
22
23DlPaint GetPaintForRun(unsigned attributes) {
25
26 if (attributes & kStrokedStyle && attributes & kFilledStyle) {
27 // Not currently exposed by Flutter, but we can probably benchmark this in
28 // the future
30 } else if (attributes & kStrokedStyle) {
31 paint.setDrawStyle(DlDrawStyle::kStroke);
32 } else if (attributes & kFilledStyle) {
33 paint.setDrawStyle(DlDrawStyle::kFill);
34 }
35
36 if (attributes & kHairlineStroke) {
37 paint.setStrokeWidth(0.0f);
38 } else {
39 paint.setStrokeWidth(1.0f);
40 }
41
42 paint.setAntiAlias(attributes & kAntiAliasing);
43 return paint;
44}
45
47 if (!surface) {
48 return;
49 }
50 if (GrDirectContext* dContext =
51 GrAsDirectContext(surface->recordingContext())) {
52 dContext->flushAndSubmit(surface.get(), GrSyncCpu::kYes);
53 }
54}
55
56void AnnotateAttributes(unsigned attributes,
57 benchmark::State& state,
59 if (flags.always_stroked()) {
60 state.counters["HairlineStroke"] = attributes & kHairlineStroke ? 1 : 0;
61 }
62 if (flags.applies_style()) {
63 state.counters["HairlineStroke"] = attributes & kHairlineStroke ? 1 : 0;
64 state.counters["StrokedStyle"] = attributes & kStrokedStyle ? 1 : 0;
65 state.counters["FilledStyle"] = attributes & kFilledStyle ? 1 : 0;
66 }
67 if (flags.applies_anti_alias()) {
68 state.counters["AntiAliasing"] = attributes & kAntiAliasing ? 1 : 0;
69 }
70}
71
72// Constants chosen to produce benchmark results in the region of 1-50ms
73constexpr size_t kLinesToDraw = 10000;
74constexpr size_t kRectsToDraw = 5000;
75constexpr size_t kOvalsToDraw = 1000;
76constexpr size_t kCirclesToDraw = 5000;
77constexpr size_t kRRectsToDraw = 5000;
78constexpr size_t kDRRectsToDraw = 2000;
79constexpr size_t kArcSweepSetsToDraw = 1000;
80constexpr size_t kImagesToDraw = 500;
81constexpr size_t kFixedCanvasSize = 1024;
82
83// Draw a series of diagonal lines across a square canvas of width/height of
84// the length requested. The lines will start from the top left corner to the
85// bottom right corner, and move from left to right (at the top) and from right
86// to left (at the bottom) until 10,000 lines are drawn.
87//
88// The resulting image will be an hourglass shape.
89void BM_DrawLine(benchmark::State& state,
90 BackendType backend_type,
91 unsigned attributes) {
92 auto surface_provider = DlSurfaceProvider::Create(backend_type);
93 DisplayListBuilder builder;
94 DlPaint paint = GetPaintForRun(attributes);
95
97
98 size_t length = state.range(0);
99
100 surface_provider->InitializeSurface(length, length);
101 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
102 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
103
104 state.counters["DrawCallCount"] = kLinesToDraw;
105 for (size_t i = 0; i < kLinesToDraw; i++) {
106 builder.DrawLine(SkPoint::Make(i % length, 0),
108 }
109
110 auto display_list = builder.Build();
111
112 // We only want to time the actual rasterization.
113 for ([[maybe_unused]] auto _ : state) {
114 canvas.DrawDisplayList(display_list);
116 }
117
118 auto filename = surface_provider->backend_name() + "-DrawLine-" +
119 std::to_string(state.range(0)) + ".png";
120 surface_provider->Snapshot(filename);
121}
122
123// Draws a series of square rects of the requested width across
124// the canvas and repeats until `kRectsToDraw` rects have been drawn.
125//
126// Half the drawn rects will not have an integral offset.
127void BM_DrawRect(benchmark::State& state,
128 BackendType backend_type,
129 unsigned attributes) {
130 auto surface_provider = DlSurfaceProvider::Create(backend_type);
131 DisplayListBuilder builder;
132 DlPaint paint = GetPaintForRun(attributes);
133
135
136 size_t length = state.range(0);
137 size_t canvas_size = length * 2;
138 surface_provider->InitializeSurface(canvas_size, canvas_size);
139 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
140 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
141
142 // As rects have SkScalar dimensions, we want to ensure that we also
143 // draw rects with non-integer position and size
144 const SkScalar offset = 0.5f;
145 SkRect rect = SkRect::MakeLTRB(0, 0, length, length);
146
147 state.counters["DrawCallCount"] = kRectsToDraw;
148 for (size_t i = 0; i < kRectsToDraw; i++) {
149 builder.DrawRect(rect, paint);
150 rect.offset(offset, offset);
151 if (rect.right() > canvas_size) {
152 rect.offset(-canvas_size, 0);
153 }
154 if (rect.bottom() > canvas_size) {
155 rect.offset(0, -canvas_size);
156 }
157 }
158
159 auto display_list = builder.Build();
160
161 // We only want to time the actual rasterization.
162 for ([[maybe_unused]] auto _ : state) {
163 canvas.DrawDisplayList(display_list);
165 }
166
167 auto filename = surface_provider->backend_name() + "-DrawRect-" +
168 std::to_string(state.range(0)) + ".png";
169 surface_provider->Snapshot(filename);
170}
171
172// Draws a series of ovals of the requested height with aspect ratio 3:2 across
173// the canvas and repeats until `kOvalsToDraw` ovals have been drawn.
174//
175// Half the drawn ovals will not have an integral offset.
176void BM_DrawOval(benchmark::State& state,
177 BackendType backend_type,
178 unsigned attributes) {
179 auto surface_provider = DlSurfaceProvider::Create(backend_type);
180 DisplayListBuilder builder;
181 DlPaint paint = GetPaintForRun(attributes);
182
184
185 size_t length = state.range(0);
186 size_t canvas_size = length * 2;
187 surface_provider->InitializeSurface(canvas_size, canvas_size);
188 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
189 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
190
191 SkRect rect = SkRect::MakeXYWH(0, 0, length * 1.5f, length);
192 const SkScalar offset = 0.5f;
193
194 state.counters["DrawCallCount"] = kOvalsToDraw;
195 for (size_t i = 0; i < kOvalsToDraw; i++) {
196 builder.DrawOval(rect, paint);
197 rect.offset(offset, offset);
198 if (rect.right() > canvas_size) {
199 rect.offset(-canvas_size, 0);
200 }
201 if (rect.bottom() > canvas_size) {
202 rect.offset(0, -canvas_size);
203 }
204 }
205 auto display_list = builder.Build();
206
207 // We only want to time the actual rasterization.
208 for ([[maybe_unused]] auto _ : state) {
209 canvas.DrawDisplayList(display_list);
211 }
212
213 auto filename = surface_provider->backend_name() + "-DrawOval-" +
214 std::to_string(state.range(0)) + ".png";
215 surface_provider->Snapshot(filename);
216}
217
218// Draws a series of circles of the requested radius across
219// the canvas and repeats until `kCirclesToDraw` circles have been drawn.
220//
221// Half the drawn circles will not have an integral center point.
222void BM_DrawCircle(benchmark::State& state,
223 BackendType backend_type,
224 unsigned attributes) {
225 auto surface_provider = DlSurfaceProvider::Create(backend_type);
226 DisplayListBuilder builder;
227 DlPaint paint = GetPaintForRun(attributes);
228
230
231 size_t length = state.range(0);
232 size_t canvas_size = length * 2;
233 surface_provider->InitializeSurface(canvas_size, canvas_size);
234 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
235 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
236
237 SkScalar radius = length / 2.0f;
238 const SkScalar offset = 0.5f;
239
240 SkPoint center = SkPoint::Make(radius, radius);
241
242 state.counters["DrawCallCount"] = kCirclesToDraw;
243 for (size_t i = 0; i < kCirclesToDraw; i++) {
244 builder.DrawCircle(center, radius, paint);
245 center.offset(offset, offset);
246 if (center.x() + radius > canvas_size) {
247 center.set(radius, center.y());
248 }
249 if (center.y() + radius > canvas_size) {
250 center.set(center.x(), radius);
251 }
252 }
253 auto display_list = builder.Build();
254
255 // We only want to time the actual rasterization.
256 for ([[maybe_unused]] auto _ : state) {
257 canvas.DrawDisplayList(display_list);
259 }
260
261 auto filename = surface_provider->backend_name() + "-DrawCircle-" +
262 std::to_string(state.range(0)) + ".png";
263 surface_provider->Snapshot(filename);
264}
265
266// Draws a series of rounded rects of the requested width across
267// the canvas and repeats until `kRRectsToDraw` rects have been drawn.
268//
269// Half the drawn rounded rects will not have an integral offset.
270void BM_DrawRRect(benchmark::State& state,
271 BackendType backend_type,
272 unsigned attributes,
274 auto surface_provider = DlSurfaceProvider::Create(backend_type);
275 DisplayListBuilder builder;
276 DlPaint paint = GetPaintForRun(attributes);
277
279
280 size_t length = state.range(0);
281 size_t canvas_size = length * 2;
282 surface_provider->InitializeSurface(canvas_size, canvas_size);
283 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
284 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
285
286 SkVector radii[4] = {};
287 switch (type) {
289 radii[0] = SkVector::Make(5.0f, 5.0f);
290 radii[1] = SkVector::Make(5.0f, 5.0f);
291 radii[2] = SkVector::Make(5.0f, 5.0f);
292 radii[3] = SkVector::Make(5.0f, 5.0f);
293 break;
295 radii[0] = SkVector::Make(5.0f, 2.0f);
296 radii[1] = SkVector::Make(3.0f, 2.0f);
297 radii[2] = SkVector::Make(3.0f, 4.0f);
298 radii[3] = SkVector::Make(5.0f, 4.0f);
299 break;
301 radii[0] = SkVector::Make(5.0f, 4.0f);
302 radii[1] = SkVector::Make(4.0f, 5.0f);
303 radii[2] = SkVector::Make(3.0f, 6.0f);
304 radii[3] = SkVector::Make(2.0f, 7.0f);
305 break;
306 default:
307 break;
308 }
309
310 const SkScalar offset = 0.5f;
311 const SkScalar multiplier = length / 16.0f;
312 SkRRect rrect;
313
315 for (size_t i = 0; i < 4; i++) {
316 set_radii[i] = radii[i] * multiplier;
317 }
319
320 state.counters["DrawCallCount"] = kRRectsToDraw;
321 for (size_t i = 0; i < kRRectsToDraw; i++) {
322 builder.DrawRRect(rrect, paint);
323 rrect.offset(offset, offset);
324 if (rrect.rect().right() > canvas_size) {
325 rrect.offset(-canvas_size, 0);
326 }
327 if (rrect.rect().bottom() > canvas_size) {
328 rrect.offset(0, -canvas_size);
329 }
330 }
331 auto display_list = builder.Build();
332
333 // We only want to time the actual rasterization.
334 for ([[maybe_unused]] auto _ : state) {
335 canvas.DrawDisplayList(display_list);
337 }
338
339 auto filename = surface_provider->backend_name() + "-DrawRRect-" +
340 std::to_string(state.range(0)) + ".png";
341 surface_provider->Snapshot(filename);
342}
343
344// Draws a series of "DR" rects of the requested width across
345// the canvas and repeats until `kRRectsToDraw` rects have been drawn.
346//
347// A "DR" rect is a shape consisting of the difference between two
348// rounded rects.
349//
350// Half the drawn DR rects will not have an integral offset.
351void BM_DrawDRRect(benchmark::State& state,
352 BackendType backend_type,
353 unsigned attributes,
355 auto surface_provider = DlSurfaceProvider::Create(backend_type);
356 DisplayListBuilder builder;
357 DlPaint paint = GetPaintForRun(attributes);
358
360
361 size_t length = state.range(0);
362 size_t canvas_size = length * 2;
363 surface_provider->InitializeSurface(canvas_size, canvas_size);
364 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
365 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
366
367 SkVector radii[4] = {};
368 switch (type) {
370 radii[0] = SkVector::Make(5.0f, 5.0f);
371 radii[1] = SkVector::Make(5.0f, 5.0f);
372 radii[2] = SkVector::Make(5.0f, 5.0f);
373 radii[3] = SkVector::Make(5.0f, 5.0f);
374 break;
376 radii[0] = SkVector::Make(5.0f, 7.0f);
377 radii[1] = SkVector::Make(3.0f, 7.0f);
378 radii[2] = SkVector::Make(3.0f, 4.0f);
379 radii[3] = SkVector::Make(5.0f, 4.0f);
380 break;
382 radii[0] = SkVector::Make(5.0f, 4.0f);
383 radii[1] = SkVector::Make(4.0f, 5.0f);
384 radii[2] = SkVector::Make(3.0f, 6.0f);
385 radii[3] = SkVector::Make(8.0f, 7.0f);
386 break;
387 default:
388 break;
389 }
390
391 const SkScalar offset = 0.5f;
392 const SkScalar multiplier = length / 16.0f;
393 SkRRect rrect, rrect_2;
394
396 for (size_t i = 0; i < 4; i++) {
397 set_radii[i] = radii[i] * multiplier;
398 }
400
401 state.counters["DrawCallCount"] = kDRRectsToDraw;
402 for (size_t i = 0; i < kDRRectsToDraw; i++) {
403 rrect.inset(0.1f * length, 0.1f * length, &rrect_2);
404 builder.DrawDRRect(rrect, rrect_2, paint);
405 rrect.offset(offset, offset);
406 if (rrect.rect().right() > canvas_size) {
407 rrect.offset(-canvas_size, 0);
408 }
409 if (rrect.rect().bottom() > canvas_size) {
410 rrect.offset(0, -canvas_size);
411 }
412 }
413 auto display_list = builder.Build();
414
415 // We only want to time the actual rasterization.
416 for ([[maybe_unused]] auto _ : state) {
417 canvas.DrawDisplayList(display_list);
419 }
420
421 auto filename = surface_provider->backend_name() + "-DrawDRRect-" +
422 std::to_string(state.range(0)) + ".png";
423 surface_provider->Snapshot(filename);
424}
425
426void BM_DrawArc(benchmark::State& state,
427 BackendType backend_type,
428 unsigned attributes) {
429 auto surface_provider = DlSurfaceProvider::Create(backend_type);
430 DisplayListBuilder builder;
431 DlPaint paint = GetPaintForRun(attributes);
432
433 AnnotateAttributes(attributes, state,
435
436 size_t length = state.range(0);
437 size_t canvas_size = length * 2;
438 surface_provider->InitializeSurface(canvas_size, canvas_size);
439 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
440 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
441
442 SkScalar starting_angle = 0.0f;
443 SkScalar offset = 0.5f;
444
445 // Just some random sweeps that will mostly circumnavigate the circle
446 std::vector<SkScalar> segment_sweeps = {5.5f, -10.0f, 42.0f, 71.7f, 90.0f,
447 37.5f, 17.9f, 32.0f, 379.4f};
448
449 SkRect bounds = SkRect::MakeLTRB(0, 0, length, length);
450
451 state.counters["DrawCallCount"] = kArcSweepSetsToDraw * segment_sweeps.size();
452 for (size_t i = 0; i < kArcSweepSetsToDraw; i++) {
453 for (SkScalar sweep : segment_sweeps) {
454 builder.DrawArc(bounds, starting_angle, sweep, false, paint);
455 starting_angle += sweep + 5.0f;
456 }
457 bounds.offset(offset, offset);
458 if (bounds.right() > canvas_size) {
459 bounds.offset(-canvas_size, 0);
460 }
461 if (bounds.bottom() > canvas_size) {
462 bounds.offset(0, -canvas_size);
463 }
464 }
465
466 auto display_list = builder.Build();
467
468 // We only want to time the actual rasterization.
469 for ([[maybe_unused]] auto _ : state) {
470 canvas.DrawDisplayList(display_list);
472 }
473
474 auto filename = surface_provider->backend_name() + "-DrawArc-" +
475 std::to_string(state.range(0)) + ".png";
476 surface_provider->Snapshot(filename);
477}
478
479// Returns a list of SkPoints that represent `n` points equally spaced out
480// along the circumference of a circle with radius `r` and centered on `center`.
481std::vector<SkPoint> GetPolygonPoints(size_t n, SkPoint center, SkScalar r) {
482 std::vector<SkPoint> points;
483 SkScalar x, y;
484 float angle;
485 float full_circle = 2.0f * M_PI;
486 for (size_t i = 0; i < n; i++) {
487 angle = (full_circle / static_cast<float>(n)) * static_cast<float>(i);
488 x = center.x() + r * std::cosf(angle);
489 y = center.y() + r * std::sinf(angle);
490 points.push_back(SkPoint::Make(x, y));
491 }
492 return points;
493}
494
495// Creates a path that represents a regular polygon with `sides` sides,
496// centered on `center` with a radius of `radius`. The control points are
497// equally spaced out along the circumference of the circle described by
498// `radius` and `center`.
499//
500// The path segment connecting each control point is a line segment.
501void GetLinesPath(SkPath& path, size_t sides, SkPoint center, float radius) {
502 std::vector<SkPoint> points = GetPolygonPoints(sides, center, radius);
503 path.moveTo(points[0]);
504 for (size_t i = 1; i < sides; i++) {
505 path.lineTo(points[i]);
506 }
507 path.lineTo(points[0]);
508 path.close();
509}
510
511// Creates a path that represents a regular polygon with `sides` sides,
512// centered on `center` with a radius of `radius`. The control points are
513// equally spaced out along the circumference of the circle described by
514// `radius` and `center`.
515//
516// The path segment connecting each control point is a quad bezier, with the
517// bezier control point being on a circle with 80% of `radius` and with the
518// control point angle half way between the start and end point angles for the
519// polygon segment.
520void GetQuadsPath(SkPath& path, size_t sides, SkPoint center, float radius) {
521 std::vector<SkPoint> points = GetPolygonPoints(sides, center, radius);
522 std::vector<SkPoint> control_points =
523 GetPolygonPoints(sides * 2, center, radius * 0.8f);
524
525 path.moveTo(points[0]);
526 for (size_t i = 1; i < sides; i++) {
527 path.quadTo(control_points[2 * i - 1], points[i]);
528 }
529 path.quadTo(control_points[2 * sides - 1], points[0]);
530 path.close();
531}
532
533// Creates a path that represents a regular polygon with `sides` sides,
534// centered on `center` with a radius of `radius`. The control points are
535// equally spaced out along the circumference of the circle described by
536// `radius` and `center`.
537//
538// The path segment connecting each control point is a conic, with the
539// control point being on a circle with 80% of `radius` and with the
540// control point angle half way between the start and end point angles for the
541// polygon segment, and the conic weight set to 3.7f.
542void GetConicsPath(SkPath& path, size_t sides, SkPoint center, float radius) {
543 std::vector<SkPoint> points = GetPolygonPoints(sides, center, radius);
544 std::vector<SkPoint> control_points =
545 GetPolygonPoints(sides * 2, center, radius * 0.8f);
546
547 path.moveTo(points[0]);
548 for (size_t i = 1; i < sides; i++) {
549 path.conicTo(control_points[2 * i - 1], points[i], 3.7f);
550 }
551 path.conicTo(control_points[2 * sides - 1], points[0], 3.7f);
552 path.close();
553}
554
555// Creates a path that represents a regular polygon with `sides` sides,
556// centered on `center` with a radius of `radius`. The control points are
557// equally spaced out along the circumference of the circle described by
558// `radius` and `center`.
559//
560// The path segment connecting each control point is a cubic, with the first
561// control point being on a circle with 80% of `radius` and with the second
562// control point being on a circle with 120% of `radius`. The first
563// control point is 1/3, and the second control point is 2/3, of the angle
564// between the start and end point angles for the polygon segment.
565void GetCubicsPath(SkPath& path, size_t sides, SkPoint center, float radius) {
566 std::vector<SkPoint> points = GetPolygonPoints(sides, center, radius);
567 std::vector<SkPoint> inner_control_points =
568 GetPolygonPoints(sides * 3, center, radius * 0.8f);
569 std::vector<SkPoint> outer_control_points =
570 GetPolygonPoints(sides * 3, center, radius * 1.2f);
571
572 path.moveTo(points[0]);
573 for (size_t i = 1; i < sides; i++) {
574 path.cubicTo(inner_control_points[3 * i - 2],
575 outer_control_points[3 * i - 1], points[i]);
576 }
577 path.cubicTo(inner_control_points[3 * sides - 2],
578 outer_control_points[3 * sides - 1], points[0]);
579 path.close();
580}
581
582// Returns a path generated by one of the above path generators
583// which is multiplied `number` times centered on each of the `number` control
584// points along the circumference of a circle centered on `center` with radius
585// `radius`.
586//
587// Each of the polygons will have `sides` sides, and the resulting path will be
588// bounded by a circle with radius of 150% of `radius` (or another 20% on top of
589// that for cubics)
593 size_t sides,
594 size_t number,
595 float radius) {
596 std::vector<SkPoint> center_points =
597 GetPolygonPoints(number, center, radius / 2.0f);
598
599 for (SkPoint p : center_points) {
600 switch (type) {
602 GetLinesPath(path, sides, p, radius);
603 break;
605 GetQuadsPath(path, sides, p, radius);
606 break;
608 GetConicsPath(path, sides, p, radius);
609 break;
611 GetCubicsPath(path, sides, p, radius);
612 break;
613 default:
614 break;
615 }
616 }
617}
618
620 switch (type) {
622 return "Lines";
624 return "Quads";
626 return "Conics";
628 return "Cubics";
629 default:
630 return "Unknown";
631 }
632}
633
634// Draws a series of overlapping 20-sided polygons where the path segment
635// between each point is one of the verb types defined in SkPath.
636//
637// The number of polygons drawn will be varied to get an overall path
638// with approximately 20*N verbs, so we can get an idea of the fixed
639// cost of using drawPath as well as an idea of how the cost varies according
640// to the verb count.
641void BM_DrawPath(benchmark::State& state,
642 BackendType backend_type,
643 unsigned attributes,
645 auto surface_provider = DlSurfaceProvider::Create(backend_type);
646 DisplayListBuilder builder;
647 DlPaint paint = GetPaintForRun(attributes);
648
650
651 size_t length = kFixedCanvasSize;
652 surface_provider->InitializeSurface(length, length);
653 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
654 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
655
656 SkPath path;
657
658 std::string label = VerbToString(type);
659 SkPoint center = SkPoint::Make(length / 2.0f, length / 2.0f);
660 float radius = length * 0.25f;
661 state.SetComplexityN(state.range(0));
662
663 MultiplyPath(path, type, center, 20, state.range(0), radius);
664
665 state.counters["VerbCount"] = path.countVerbs();
666 state.counters["DrawCallCount"] = 1;
667
668 builder.DrawPath(path, paint);
669 auto display_list = builder.Build();
670
671 // We only want to time the actual rasterization.
672 for ([[maybe_unused]] auto _ : state) {
673 canvas.DrawDisplayList(display_list);
675 }
676
677 auto filename = surface_provider->backend_name() + "-DrawPath-" + label +
678 "-" + std::to_string(state.range(0)) + ".png";
679 surface_provider->Snapshot(filename);
680}
681
682// Returns a set of vertices that describe a circle that has a
683// radius of `radius` and outer vertex count of approximately
684// `vertex_count`. The final number of vertices will differ as we
685// need to ensure the correct usage of vertices to ensure we do not
686// request degenerate triangles be drawn. This final count is output
687// through `final_vertex_count`.
688//
689// The resulting vertices will describe a disc consisting of a series
690// of triangles with two vertices on the circumference of the disc,
691// and the final vertex being the center point of the disc.
692//
693// Each vertex colour will alternate through Red, Green, Blue and Cyan.
694std::shared_ptr<DlVertices> GetTestVertices(SkPoint center,
695 float radius,
696 size_t vertex_count,
698 size_t& final_vertex_count) {
699 size_t outer_vertex_count = vertex_count / 2;
700 std::vector<SkPoint> outer_points =
701 GetPolygonPoints(outer_vertex_count, center, radius);
702
703 std::vector<SkPoint> vertices;
704 std::vector<DlColor> colors;
705
706 switch (mode) {
708 // Calling the points on the outer circle O_0, O_1, O_2, ..., and
709 // the center point C, this should create a triangle fan with vertices
710 // C, O_0, O_1, O_2, O_3, ...
711 vertices.push_back(center);
712 colors.push_back(DlColor(SK_ColorCYAN));
713 for (size_t i = 0; i <= outer_points.size(); i++) {
714 vertices.push_back(outer_points[i % outer_points.size()]);
715 if (i % 3 == 0) {
716 colors.push_back(DlColor(SK_ColorRED));
717 } else if (i % 3 == 1) {
718 colors.push_back(DlColor(SK_ColorGREEN));
719 } else {
720 colors.push_back(DlColor(SK_ColorBLUE));
721 }
722 }
723 break;
725 // Calling the points on the outer circle O_0, O_1, O_2, ..., and
726 // the center point C, this should create a series of triangles with
727 // vertices O_0, O_1, C, O_1, O_2, C, O_2, O_3, C, ...
728 for (size_t i = 0; i < outer_vertex_count; i++) {
729 vertices.push_back(outer_points[i % outer_points.size()]);
730 colors.push_back(DlColor(SK_ColorRED));
731 vertices.push_back(outer_points[(i + 1) % outer_points.size()]);
732 colors.push_back(DlColor(SK_ColorGREEN));
733 vertices.push_back(center);
734 colors.push_back(DlColor(SK_ColorBLUE));
735 }
736 break;
738 // Calling the points on the outer circle O_0, O_1, O_2, ..., and
739 // the center point C, this should create a strip with vertices
740 // O_0, O_1, C, O_2, O_3, C, O_4, O_5, C, ...
741 for (size_t i = 0; i <= outer_vertex_count; i++) {
742 vertices.push_back(outer_points[i % outer_points.size()]);
743 colors.push_back(i % 2 ? DlColor(SK_ColorRED) : DlColor(SK_ColorGREEN));
744 if (i % 2 == 1) {
745 vertices.push_back(center);
746 colors.push_back(DlColor(SK_ColorBLUE));
747 }
748 }
749 break;
750 default:
751 break;
752 }
753
754 final_vertex_count = vertices.size();
755 return DlVertices::Make(mode, vertices.size(), vertices.data(), nullptr,
756 colors.data());
757}
758
760 switch (mode) {
762 return "TriangleStrip";
764 return "TriangleFan";
766 return "Triangles";
767 }
768 return "Unknown";
769}
770
771// Draws a series of discs generated by `GetTestVertices()` with
772// 50 vertices in each disc. The number of discs drawn will vary according
773// to the benchmark input, and the benchmark will automatically calculate
774// the Big-O complexity of `DrawVertices` with N being the number of vertices
775// being drawn.
776//
777// The discs drawn will be centered on points along a circle with radius of 25%
778// of the canvas width/height, with each point being equally spaced out.
779void BM_DrawVertices(benchmark::State& state,
780 BackendType backend_type,
781 unsigned attributes,
783 auto surface_provider = DlSurfaceProvider::Create(backend_type);
784 DisplayListBuilder builder;
785 DlPaint paint = GetPaintForRun(attributes);
786
788
789 size_t length = kFixedCanvasSize;
790 surface_provider->InitializeSurface(length, length);
791 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
792 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
793
794 SkPoint center = SkPoint::Make(length / 2.0f, length / 2.0f);
795
796 float radius = length / 4.0f;
797
798 size_t vertex_count, total_vertex_count = 0;
799 size_t disc_count = state.range(0);
800
801 std::vector<SkPoint> center_points =
802 GetPolygonPoints(disc_count, center, radius / 4.0f);
803
804 state.counters["DrawCallCount"] = center_points.size();
805 for (SkPoint p : center_points) {
806 std::shared_ptr<DlVertices> vertices =
807 GetTestVertices(p, radius, 50, mode, vertex_count);
808 total_vertex_count += vertex_count;
809 builder.DrawVertices(vertices.get(), DlBlendMode::kSrc, paint);
810 }
811
812 state.counters["VertexCount"] = total_vertex_count;
813 state.SetComplexityN(total_vertex_count);
814
815 auto display_list = builder.Build();
816
817 // We only want to time the actual rasterization.
818 for ([[maybe_unused]] auto _ : state) {
819 canvas.DrawDisplayList(display_list);
821 }
822
823 auto filename = surface_provider->backend_name() + "-DrawVertices-" +
824 std::to_string(disc_count) + "-" + VertexModeToString(mode) +
825 ".png";
826 surface_provider->Snapshot(filename);
827}
828
829// Generate `count` test points.
830//
831// The points are distributed using some fixed constant offsets that were
832// chosen to appear somewhat random.
833//
834// The points generated will wrap in x and y for the bounds of `canvas_size`.
835std::vector<SkPoint> GetTestPoints(size_t count, SkISize canvas_size) {
836 std::vector<SkPoint> points;
837
838 // Some arbitrary offsets to use when building the list of points
839 std::vector<SkScalar> delta_x = {10.0f, 6.3f, 15.0f, 3.5f, 22.6f, 4.7f};
840 std::vector<SkScalar> delta_y = {9.3f, -5.4f, 8.5f, -12.0f, 19.2f, -19.6f};
841
842 SkPoint current = SkPoint::Make(0.0f, 0.0f);
843 for (size_t i = 0; i < count; i++) {
844 points.push_back(current);
845 current.offset(delta_x[i % delta_x.size()], delta_y[i % delta_y.size()]);
846 if (current.x() > canvas_size.width()) {
847 current.offset(-canvas_size.width(), 25.0f);
848 }
849 if (current.y() > canvas_size.height()) {
850 current.offset(0.0f, -canvas_size.height());
851 }
852 }
853
854 return points;
855}
856
858 switch (mode) {
860 return "Lines";
862 return "Polygon";
864 default:
865 return "Points";
866 }
867}
868
869// Draws a series of points generated by `GetTestPoints()` above to
870// a fixed-size canvas. The benchmark will vary the number of points drawn,
871// and they can be drawn in one of three modes - Lines, Polygon or Points mode.
872//
873// This benchmark will automatically calculate the Big-O complexity of
874// `DrawPoints` with N being the number of points being drawn.
875void BM_DrawPoints(benchmark::State& state,
876 BackendType backend_type,
877 unsigned attributes,
879 auto surface_provider = DlSurfaceProvider::Create(backend_type);
880 DisplayListBuilder builder;
881 DlPaint paint = GetPaintForRun(attributes);
882
883 switch (mode) {
885 AnnotateAttributes(attributes, state,
887 break;
889 AnnotateAttributes(attributes, state,
891 break;
893 AnnotateAttributes(attributes, state,
895 break;
896 }
897
898 size_t length = kFixedCanvasSize;
899 surface_provider->InitializeSurface(length, length);
900 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
901 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
902
903 size_t point_count = state.range(0);
904 state.SetComplexityN(point_count);
905 state.counters["PointCount"] = point_count;
906 state.counters["DrawCallCount"] = 1;
907
908 std::vector<SkPoint> points =
910 builder.DrawPoints(mode, points.size(), points.data(), paint);
911
912 auto display_list = builder.Build();
913
914 for ([[maybe_unused]] auto _ : state) {
915 canvas.DrawDisplayList(display_list);
917 }
918
919 auto filename = surface_provider->backend_name() + "-DrawPoints-" +
920 PointModeToString(mode) + "-" + std::to_string(point_count) +
921 ".png";
922 surface_provider->Snapshot(filename);
923}
924
926 // If we create an SkPixmap with a ref to the SkBitmap's pixel data,
927 // then create an SkImage from that, we always get a new generation ID,
928 // so we will avoid hitting the cache.
929 SkPixmap pixmap;
930 bitmap.peekPixels(&pixmap);
931 return SkImages::RasterFromPixmap(pixmap, nullptr, nullptr);
932}
933
934// Draws `kImagesToDraw` bitmaps to a canvas, either with texture-backed
935// bitmaps or bitmaps that need to be uploaded to the GPU first.
936void BM_DrawImage(benchmark::State& state,
937 BackendType backend_type,
938 unsigned attributes,
940 bool upload_bitmap) {
941 auto surface_provider = DlSurfaceProvider::Create(backend_type);
942 DisplayListBuilder builder;
943 DlPaint paint = GetPaintForRun(attributes);
944
945 AnnotateAttributes(attributes, state,
947
948 size_t bitmap_size = state.range(0);
949 size_t canvas_size = 2 * bitmap_size;
950 surface_provider->InitializeSurface(canvas_size, canvas_size);
951 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
952 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
953
955 std::shared_ptr<DlSurfaceInstance> offscreen_instance;
956 sk_sp<SkSurface> offscreen;
958
959 if (upload_bitmap) {
960 SkImageInfo info = SkImageInfo::Make(bitmap_size, bitmap_size,
963 bitmap.allocPixels(info, 0);
964 bitmap.eraseColor(SK_ColorBLUE);
965 } else {
966 offscreen_instance =
967 surface_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
968 offscreen = offscreen_instance->sk_surface();
969 offscreen->getCanvas()->clear(SK_ColorRED);
970 }
971
972 SkScalar offset = 0.5f;
973 SkPoint dst = SkPoint::Make(0, 0);
974
975 state.counters["DrawCallCount"] = kImagesToDraw;
976 for (size_t i = 0; i < kImagesToDraw; i++) {
977 image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
978 : offscreen->makeImageSnapshot();
979 builder.DrawImage(DlImage::Make(image), dst, options, &paint);
980
981 dst.offset(offset, offset);
982 if (dst.x() + bitmap_size > canvas_size) {
983 dst.set(0, dst.y());
984 }
985 if (dst.y() + bitmap_size > canvas_size) {
986 dst.set(dst.x(), 0);
987 }
988 }
989
990 auto display_list = builder.Build();
991
992 for ([[maybe_unused]] auto _ : state) {
993 canvas.DrawDisplayList(display_list);
995 }
996
997 auto filename = surface_provider->backend_name() + "-DrawImage-" +
998 (upload_bitmap ? "Upload-" : "Texture-") +
999 std::to_string(bitmap_size) + ".png";
1000 surface_provider->Snapshot(filename);
1001}
1002
1004 switch (constraint) {
1006 return "Strict";
1008 return "Fast";
1009 default:
1010 return "Unknown";
1011 }
1012}
1013
1014// Draws `kImagesToDraw` bitmaps to a canvas, either with texture-backed
1015// bitmaps or bitmaps that need to be uploaded to the GPU first.
1016//
1017// The bitmaps are shrunk down to 75% of their size when rendered to the canvas.
1018void BM_DrawImageRect(benchmark::State& state,
1019 BackendType backend_type,
1020 unsigned attributes,
1022 DlCanvas::SrcRectConstraint constraint,
1023 bool upload_bitmap) {
1024 auto surface_provider = DlSurfaceProvider::Create(backend_type);
1025 DisplayListBuilder builder;
1026 DlPaint paint = GetPaintForRun(attributes);
1027
1028 AnnotateAttributes(attributes, state,
1030
1031 size_t bitmap_size = state.range(0);
1032 size_t canvas_size = 2 * bitmap_size;
1033 surface_provider->InitializeSurface(canvas_size, canvas_size);
1034 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
1035 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
1036
1038 std::shared_ptr<DlSurfaceInstance> offscreen_instance;
1039 sk_sp<SkSurface> offscreen;
1041
1042 if (upload_bitmap) {
1043 SkImageInfo info = SkImageInfo::Make(bitmap_size, bitmap_size,
1046 bitmap.allocPixels(info, 0);
1047 bitmap.eraseColor(SK_ColorBLUE);
1048 } else {
1049 offscreen_instance =
1050 surface_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
1051 offscreen = offscreen_instance->sk_surface();
1052 offscreen->getCanvas()->clear(SK_ColorRED);
1053 }
1054
1055 SkScalar offset = 0.5f;
1056 SkRect src = SkRect::MakeXYWH(bitmap_size / 4.0f, bitmap_size / 4.0f,
1057 bitmap_size / 2.0f, bitmap_size / 2.0f);
1058 SkRect dst =
1059 SkRect::MakeXYWH(0.0f, 0.0f, bitmap_size * 0.75f, bitmap_size * 0.75f);
1060
1061 state.counters["DrawCallCount"] = kImagesToDraw;
1062 for (size_t i = 0; i < kImagesToDraw; i++) {
1063 image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
1064 : offscreen->makeImageSnapshot();
1065 builder.DrawImageRect(DlImage::Make(image), src, dst, options, &paint,
1066 constraint);
1067 dst.offset(offset, offset);
1068 if (dst.right() > canvas_size) {
1069 dst.offsetTo(0, dst.y());
1070 }
1071 if (dst.bottom() > canvas_size) {
1072 dst.offsetTo(dst.x(), 0);
1073 }
1074 }
1075
1076 auto display_list = builder.Build();
1077
1078 for ([[maybe_unused]] auto _ : state) {
1079 canvas.DrawDisplayList(display_list);
1081 }
1082
1083 auto filename = surface_provider->backend_name() + "-DrawImageRect-" +
1084 (upload_bitmap ? "Upload-" : "Texture-") +
1085 ConstraintToString(constraint) + "-" +
1086 std::to_string(bitmap_size) + ".png";
1087 surface_provider->Snapshot(filename);
1088}
1089
1091 switch (mode) {
1093 return "Nearest";
1095 return "Linear";
1096 default:
1097 return "Unknown";
1098 }
1099}
1100
1101// Draws `kImagesToDraw` bitmaps to a canvas, either with texture-backed
1102// bitmaps or bitmaps that need to be uploaded to the GPU first.
1103//
1104// The image is split into 9 sub-rects and stretched proportionally for final
1105// rendering.
1106void BM_DrawImageNine(benchmark::State& state,
1107 BackendType backend_type,
1108 unsigned attributes,
1109 const DlFilterMode filter,
1110 bool upload_bitmap) {
1111 auto surface_provider = DlSurfaceProvider::Create(backend_type);
1112 DisplayListBuilder builder;
1113 DlPaint paint = GetPaintForRun(attributes);
1114
1115 AnnotateAttributes(attributes, state,
1117
1118 size_t bitmap_size = state.range(0);
1119 size_t canvas_size = 2 * bitmap_size;
1120 surface_provider->InitializeSurface(canvas_size, canvas_size);
1121 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
1122 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
1123
1124 SkIRect center = SkIRect::MakeXYWH(bitmap_size / 4, bitmap_size / 4,
1125 bitmap_size / 2, bitmap_size / 2);
1126
1128 std::shared_ptr<DlSurfaceInstance> offscreen_instance;
1129 sk_sp<SkSurface> offscreen;
1131
1132 if (upload_bitmap) {
1133 SkImageInfo info = SkImageInfo::Make(bitmap_size, bitmap_size,
1136 bitmap.allocPixels(info, 0);
1137 bitmap.eraseColor(SK_ColorBLUE);
1138 } else {
1139 offscreen_instance =
1140 surface_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
1141 offscreen = offscreen_instance->sk_surface();
1142 offscreen->getCanvas()->clear(SK_ColorRED);
1143 }
1144
1145 SkScalar offset = 0.5f;
1146 SkRect dst =
1147 SkRect::MakeXYWH(0.0f, 0.0f, bitmap_size * 0.75f, bitmap_size * 0.75f);
1148
1149 state.counters["DrawCallCount"] = kImagesToDraw;
1150 for (size_t i = 0; i < kImagesToDraw; i++) {
1151 image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
1152 : offscreen->makeImageSnapshot();
1153 builder.DrawImageNine(DlImage::Make(image), center, dst, filter, &paint);
1154 dst.offset(offset, offset);
1155 if (dst.right() > canvas_size) {
1156 dst.offsetTo(0, dst.y());
1157 }
1158 if (dst.bottom() > canvas_size) {
1159 dst.offsetTo(dst.x(), 0);
1160 }
1161 }
1162
1163 auto display_list = builder.Build();
1164
1165 for ([[maybe_unused]] auto _ : state) {
1166 canvas.DrawDisplayList(display_list);
1168 }
1169
1170 auto filename = surface_provider->backend_name() + "-DrawImageNine-" +
1171 (upload_bitmap ? "Upload-" : "Texture-") +
1172 FilterModeToString(filter) + "-" +
1173 std::to_string(bitmap_size) + ".png";
1174 surface_provider->Snapshot(filename);
1175}
1176
1177// Draws a series of glyph runs with 32 glyphs in each run. The number of runs
1178// may vary according to the benchmark parameters. The text will start in the
1179// upper left corner of the canvas and advance from left to right and wrap at
1180// the canvas boundaries in both x and y.
1181//
1182// This benchmark will automatically calculate the Big-O complexity of
1183// `DrawTextBlob` with N being the number of glyphs being drawn.
1184void BM_DrawTextBlob(benchmark::State& state,
1185 BackendType backend_type,
1186 unsigned attributes) {
1187 auto surface_provider = DlSurfaceProvider::Create(backend_type);
1188 DisplayListBuilder builder;
1189 DlPaint paint = GetPaintForRun(attributes);
1190
1192
1193 size_t draw_calls = state.range(0);
1194 size_t canvas_size = kFixedCanvasSize;
1195 surface_provider->InitializeSurface(canvas_size, canvas_size);
1196 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
1197 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
1198
1199 state.counters["DrawCallCount_Varies"] = draw_calls;
1200 state.counters["GlyphCount"] = draw_calls;
1201 char character[2] = {'A', '\0'};
1202
1203 for (size_t i = 0; i < draw_calls; i++) {
1204 character[0] = 'A' + (i % 26);
1206 builder.DrawTextBlob(blob, 50.0f, 50.0f, paint);
1207 }
1208
1209 auto display_list = builder.Build();
1210
1211 for ([[maybe_unused]] auto _ : state) {
1212 canvas.DrawDisplayList(display_list);
1214 }
1215
1216 auto filename = surface_provider->backend_name() + "-DrawTextBlob-" +
1217 std::to_string(draw_calls) + ".png";
1218 surface_provider->Snapshot(filename);
1219}
1220
1221// Draw the shadow for a 10-sided regular polygon where the polygon's
1222// sides are denoted by one of a Line, Quad, Conic or Cubic path segment.
1223//
1224// The elevation of the light source will vary according to the benchmark
1225// paremeters.
1226//
1227// The benchmark can be run with either a transparent occluder or an opaque
1228// occluder.
1229void BM_DrawShadow(benchmark::State& state,
1230 BackendType backend_type,
1231 unsigned attributes,
1232 bool transparent_occluder,
1234 auto surface_provider = DlSurfaceProvider::Create(backend_type);
1235 DisplayListBuilder builder;
1236 DlPaint paint = GetPaintForRun(attributes);
1237
1239
1240 size_t length = kFixedCanvasSize;
1241 surface_provider->InitializeSurface(length, length);
1242 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
1243 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
1244
1245 SkPath path;
1246
1247 SkPoint center = SkPoint::Make(length / 2.0f, length / 2.0f);
1248 float radius = length * 0.25f;
1249
1250 switch (type) {
1252 GetLinesPath(path, 10, center, radius);
1253 break;
1255 GetQuadsPath(path, 10, center, radius);
1256 break;
1258 GetConicsPath(path, 10, center, radius);
1259 break;
1261 GetCubicsPath(path, 10, center, radius);
1262 break;
1263 default:
1264 break;
1265 }
1266
1267 float elevation = state.range(0);
1268 state.counters["DrawCallCount"] = 1;
1269
1270 // We can hardcode dpr to 1.0f as we're varying elevation, and dpr is only
1271 // ever used in conjunction with elevation.
1272 builder.DrawShadow(path, DlColor(SK_ColorBLUE), elevation,
1273 transparent_occluder, 1.0f);
1274 auto display_list = builder.Build();
1275
1276 // We only want to time the actual rasterization.
1277 for ([[maybe_unused]] auto _ : state) {
1278 canvas.DrawDisplayList(display_list);
1280 }
1281
1282 auto filename = surface_provider->backend_name() + "-DrawShadow-" +
1283 VerbToString(type) + "-" +
1284 (transparent_occluder ? "Transparent-" : "Opaque-") +
1285 std::to_string(elevation) + "-" + ".png";
1286 surface_provider->Snapshot(filename);
1287}
1288
1289// Calls saveLayer N times from the root canvas layer, and optionally calls
1290// saveLayer a further M times nested inside that top saveLayer call.
1291//
1292// The total number of saveLayer calls will be N * (M+1).
1293//
1294// In each saveLayer call, simply draw the colour red with no clip rect.
1295void BM_SaveLayer(benchmark::State& state,
1296 BackendType backend_type,
1297 unsigned attributes,
1298 size_t save_depth) {
1299 auto surface_provider = DlSurfaceProvider::Create(backend_type);
1300 DisplayListBuilder builder;
1301 DlPaint paint = GetPaintForRun(attributes);
1302
1304
1305 size_t length = kFixedCanvasSize;
1306 surface_provider->InitializeSurface(length, length);
1307 auto surface = surface_provider->GetPrimarySurface()->sk_surface();
1308 auto canvas = DlSkCanvasAdapter(surface->getCanvas());
1309
1310 size_t save_layer_calls = state.range(0);
1311
1312 // Ensure we draw two overlapping rects to avoid any peephole optimisations
1313 SkRect rect1 = SkRect::MakeLTRB(0, 0, 0.75f * length, 0.75f * length);
1314 SkRect rect2 =
1315 SkRect::MakeLTRB(0.25f * length, 0.25f * length, length, length);
1316
1317 state.counters["DrawCallCount_Varies"] = save_layer_calls * save_depth;
1318 for (size_t i = 0; i < save_layer_calls; i++) {
1319 for (size_t j = 0; j < save_depth; j++) {
1320 builder.SaveLayer(nullptr, nullptr);
1321 builder.DrawRect(rect1, paint);
1322 builder.DrawRect(rect2, paint);
1323 }
1324 for (size_t j = 0; j < save_depth; j++) {
1325 builder.Restore();
1326 }
1327 }
1328 auto display_list = builder.Build();
1329
1330 // We only want to time the actual rasterization.
1331 for ([[maybe_unused]] auto _ : state) {
1332 canvas.DrawDisplayList(display_list);
1334 }
1335
1336 auto filename = surface_provider->backend_name() + "-SaveLayer-" +
1337 std::to_string(save_depth) + "-" +
1338 std::to_string(save_layer_calls) + ".png";
1339 surface_provider->Snapshot(filename);
1340}
1341
1342#ifdef ENABLE_SOFTWARE_BENCHMARKS
1344#endif
1345
1346#ifdef ENABLE_OPENGL_BENCHMARKS
1348#endif
1349
1350#ifdef ENABLE_METAL_BENCHMARKS
1352#endif
1353
1354} // namespace testing
1355} // namespace flutter
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
#define M_PI
int count
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
static const int points[]
static void set_radii(SkVector radii[4], int index, float rad)
Definition PathTest.cpp:62
@ 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_ColorCYAN
Definition SkColor.h:143
constexpr SkColor SK_ColorBLUE
Definition SkColor.h:135
constexpr SkColor SK_ColorRED
Definition SkColor.h:126
constexpr SkColor SK_ColorGREEN
Definition SkColor.h:131
static SkScalar center(float pos0, float pos1)
@ kConic_Verb
Definition SkPath.h:1461
@ kCubic_Verb
Definition SkPath.h:1462
@ kQuad_Verb
Definition SkPath.h:1460
@ kLine_Verb
Definition SkPath.h:1459
const SkRect & rect() const
Definition SkRRect.h:264
@ kSimple_Type
non-zero width and height with equal radii
Definition SkRRect.h:70
@ kNinePatch_Type
non-zero width and height with axis-aligned radii
Definition SkRRect.h:71
@ kComplex_Type
non-zero width and height with arbitrary radii
Definition SkRRect.h:72
void inset(SkScalar dx, SkScalar dy, SkRRect *dst) const
Definition SkRRect.cpp:562
void offset(SkScalar dx, SkScalar dy)
Definition SkRRect.h:387
void setRectRadii(const SkRect &rect, const SkVector radii[4])
Definition SkRRect.cpp:189
static sk_sp< SkTextBlob > MakeFromString(const char *string, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
Definition SkTextBlob.h:115
static constexpr DisplayListAttributeFlags kDrawVerticesFlags
static constexpr DisplayListAttributeFlags kDrawArcNoCenterFlags
static constexpr DisplayListAttributeFlags kDrawImageRectWithPaintFlags
static constexpr DisplayListAttributeFlags kSaveLayerFlags
static constexpr DisplayListAttributeFlags kDrawOvalFlags
static constexpr DisplayListAttributeFlags kDrawTextBlobFlags
static constexpr DisplayListAttributeFlags kDrawPointsAsLinesFlags
static constexpr DisplayListAttributeFlags kDrawPointsAsPolygonFlags
static constexpr DisplayListAttributeFlags kDrawCircleFlags
static constexpr DisplayListAttributeFlags kDrawPathFlags
static constexpr DisplayListAttributeFlags kDrawLineFlags
static constexpr DisplayListAttributeFlags kDrawPointsAsPointsFlags
static constexpr DisplayListAttributeFlags kDrawImageWithPaintFlags
static constexpr DisplayListAttributeFlags kDrawImageNineWithPaintFlags
static constexpr DisplayListAttributeFlags kDrawShadowFlags
static constexpr DisplayListAttributeFlags kDrawRRectFlags
static constexpr DisplayListAttributeFlags kDrawDRRectFlags
static constexpr DisplayListAttributeFlags kDrawRectFlags
@ 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
Backend implementation of |DlCanvas| for |SkCanvas|.
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.
static std::unique_ptr< DlSurfaceProvider > Create(BackendType backend_type)
const Paint & paint
#define RUN_DISPLAYLIST_BENCHMARKS(BACKEND)
VkSurfaceKHR surface
Definition main.cc:49
sk_sp< SkImage > image
Definition examples.cpp:29
float SkScalar
Definition extension.cpp:12
AtkStateType state
FlutterSemanticsFlag flags
size_t length
double y
double x
SK_API sk_sp< SkImage > RasterFromPixmap(const SkPixmap &pixmap, RasterReleaseProc rasterReleaseProc, ReleaseContext releaseContext)
std::string VertexModeToString(DlVertexMode mode)
void BM_DrawVertices(benchmark::State &state, BackendType backend_type, unsigned attributes, DlVertexMode mode)
std::string PointModeToString(DlCanvas::PointMode mode)
static void FlushSubmitCpuSync(const sk_sp< SkSurface > &surface)
void BM_DrawRRect(benchmark::State &state, BackendType backend_type, unsigned attributes, SkRRect::Type type)
void BM_DrawPath(benchmark::State &state, BackendType backend_type, unsigned attributes, SkPath::Verb type)
void BM_DrawShadow(benchmark::State &state, BackendType backend_type, unsigned attributes, bool transparent_occluder, SkPath::Verb type)
std::vector< SkPoint > GetPolygonPoints(size_t n, SkPoint center, SkScalar r)
void BM_DrawImageRect(benchmark::State &state, BackendType backend_type, unsigned attributes, DlImageSampling options, DlCanvas::SrcRectConstraint constraint, bool upload_bitmap)
SkFont CreateTestFontOfSize(SkScalar scalar)
constexpr size_t kRectsToDraw
void GetLinesPath(SkPath &path, size_t sides, SkPoint center, float radius)
std::shared_ptr< DlVertices > GetTestVertices(SkPoint center, float radius, size_t vertex_count, DlVertexMode mode, size_t &final_vertex_count)
void BM_DrawOval(benchmark::State &state, BackendType backend_type, unsigned attributes)
void AnnotateAttributes(unsigned attributes, benchmark::State &state, const DisplayListAttributeFlags flags)
constexpr size_t kFixedCanvasSize
constexpr size_t kImagesToDraw
void BM_DrawImage(benchmark::State &state, BackendType backend_type, unsigned attributes, DlImageSampling options, bool upload_bitmap)
void BM_DrawLine(benchmark::State &state, BackendType backend_type, unsigned attributes)
void BM_DrawCircle(benchmark::State &state, BackendType backend_type, unsigned attributes)
void BM_DrawRect(benchmark::State &state, BackendType backend_type, unsigned attributes)
constexpr size_t kDRRectsToDraw
std::string VerbToString(SkPath::Verb type)
std::string FilterModeToString(const DlFilterMode mode)
void BM_DrawDRRect(benchmark::State &state, BackendType backend_type, unsigned attributes, SkRRect::Type type)
std::vector< SkPoint > GetTestPoints(size_t count, SkISize canvas_size)
sk_sp< SkImage > ImageFromBitmapWithNewID(const SkBitmap &bitmap)
void MultiplyPath(SkPath &path, SkPath::Verb type, SkPoint center, size_t sides, size_t number, float radius)
void BM_DrawTextBlob(benchmark::State &state, BackendType backend_type, unsigned attributes)
void BM_DrawArc(benchmark::State &state, BackendType backend_type, unsigned attributes)
void GetQuadsPath(SkPath &path, size_t sides, SkPoint center, float radius)
constexpr size_t kRRectsToDraw
void GetConicsPath(SkPath &path, size_t sides, SkPoint center, float radius)
constexpr size_t kArcSweepSetsToDraw
void BM_DrawImageNine(benchmark::State &state, BackendType backend_type, unsigned attributes, const DlFilterMode filter, bool upload_bitmap)
void BM_DrawPoints(benchmark::State &state, BackendType backend_type, unsigned attributes, DlCanvas::PointMode mode)
void BM_SaveLayer(benchmark::State &state, BackendType backend_type, unsigned attributes, size_t save_depth)
constexpr size_t kCirclesToDraw
constexpr size_t kLinesToDraw
constexpr size_t kOvalsToDraw
void GetCubicsPath(SkPath &path, size_t sides, SkPoint center, float radius)
std::string ConstraintToString(DlCanvas::SrcRectConstraint constraint)
DlPaint GetPaintForRun(unsigned attributes)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switches.h:57
DlVertexMode
Defines the way in which the vertices of a DlVertices object are separated into triangles into which ...
Definition dl_vertices.h:20
@ kTriangles
The vertices are taken 3 at a time to form a triangle.
@ kStrokeAndFill
both strokes and fills shapes
@ kStroke
strokes boundary of shapes
@ kFill
fills interior of shapes
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition switches.h:228
Point offset
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition SkRect.h:104
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
void offset(float dx, float dy)
static constexpr SkPoint Make(float x, float y)
constexpr float y() const
constexpr float x() const
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659
constexpr float right() const
Definition SkRect.h:748
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646
constexpr float bottom() const
Definition SkRect.h:755