Flutter Engine
The Flutter Engine
dl_complexity_gl.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_gl.h"
6
7// The numbers and weightings used in this file stem from taking the
8// data from the DisplayListBenchmarks suite run on an Pixel 4 and
9// applying very rough analysis on them to identify the approximate
10// trends.
11//
12// See the comments in display_list_complexity_helper.h for details on the
13// process and rationale behind coming up with these numbers.
14
15namespace flutter {
16
17DisplayListGLComplexityCalculator*
18 DisplayListGLComplexityCalculator::instance_ = nullptr;
19
20DisplayListGLComplexityCalculator*
22 if (instance_ == nullptr) {
23 instance_ = new DisplayListGLComplexityCalculator();
24 }
25 return instance_;
26}
27
28unsigned int DisplayListGLComplexityCalculator::GLHelper::BatchedComplexity() {
29 // Calculate the impact of saveLayer.
30 unsigned int save_layer_complexity;
31 if (save_layer_count_ == 0) {
32 save_layer_complexity = 0;
33 } else {
34 // m = 1/5
35 // c = 10
36 save_layer_complexity = (save_layer_count_ + 50) * 40000;
37 }
38
39 unsigned int draw_text_blob_complexity;
40 if (draw_text_blob_count_ == 0) {
41 draw_text_blob_complexity = 0;
42 } else {
43 // m = 1/240
44 // c = 0.25
45 draw_text_blob_complexity = (draw_text_blob_count_ + 60) * 2500 / 3;
46 }
47
48 return save_layer_complexity + draw_text_blob_complexity;
49}
50
51void DisplayListGLComplexityCalculator::GLHelper::saveLayer(
52 const SkRect& bounds,
54 const DlImageFilter* backdrop) {
55 if (IsComplex()) {
56 return;
57 }
58 if (backdrop) {
59 // Flutter does not offer this operation so this value can only ever be
60 // non-null for a frame-wide builder which is not currently evaluated for
61 // complexity.
62 AccumulateComplexity(Ceiling());
63 }
64 save_layer_count_++;
65}
66
67void DisplayListGLComplexityCalculator::GLHelper::drawLine(const SkPoint& p0,
68 const SkPoint& p1) {
69 if (IsComplex()) {
70 return;
71 }
72
73 // There is a relatively high fixed overhead cost for drawLine on OpenGL.
74 // Further, there is a strange bump where the cost of drawing a line of
75 // length ~500px is actually more costly than drawing a line of length
76 // ~1000px. The calculations here will be for a linear graph that
77 // approximate the overall trend.
78
79 float non_hairline_penalty = 1.0f;
80 unsigned int aa_penalty = 1;
81
82 // The non-hairline penalty is insignificant when AA is on.
83 if (!IsHairline() && !IsAntiAliased()) {
84 non_hairline_penalty = 1.15f;
85 }
86 if (IsAntiAliased()) {
87 aa_penalty = 2;
88 }
89
90 // Use an approximation for the distance to avoid floating point or
91 // sqrt() calls.
92 SkScalar distance = abs(p0.x() - p1.x()) + abs(p0.y() - p1.y());
93
94 // The baseline complexity is for a hairline stroke with no AA.
95 // m = 1/40
96 // c = 13
97 unsigned int complexity =
98 ((distance + 520) / 2) * non_hairline_penalty * aa_penalty;
99
100 AccumulateComplexity(complexity);
101}
102
103void DisplayListGLComplexityCalculator::GLHelper::drawDashedLine(
104 const DlPoint& p0,
105 const DlPoint& p1,
106 DlScalar on_length,
107 DlScalar off_length) {
108 // Dashing is slightly more complex than a regular drawLine, but this
109 // op is so rare it is not worth measuring the difference.
110 drawLine(ToSkPoint(p0), ToSkPoint(p1));
111}
112
113void DisplayListGLComplexityCalculator::GLHelper::drawRect(const SkRect& rect) {
114 if (IsComplex()) {
115 return;
116 }
117
118 unsigned int complexity;
119
120 // If stroked, cost scales linearly with the rectangle width/height.
121 // If filled, it scales with the area.
122 //
123 // Hairline stroke vs non hairline has no significant penalty.
124 //
125 // There is also a kStrokeAndFill_Style that Skia exposes, but we do not
126 // currently use it anywhere in Flutter.
127 if (DrawStyle() == DlDrawStyle::kFill) {
128 // No real difference for AA with filled styles
129 unsigned int area = rect.width() * rect.height();
130
131 // m = 1/3500
132 // c = 0
133 complexity = area * 2 / 175;
134 } else {
135 // Take the average of the width and height.
136 unsigned int length = (rect.width() + rect.height()) / 2;
137
138 if (IsAntiAliased()) {
139 // m = 1/30
140 // c = 0
141 complexity = length * 4 / 3;
142 } else {
143 // If AA is disabled, the data shows that at larger sizes the overall
144 // cost comes down, peaking at around 1000px. As we don't anticipate
145 // rasterising rects with AA disabled to be all that frequent, just treat
146 // it as a straight line that peaks at 1000px, beyond which it stays
147 // constant. The rationale here is that it makes more sense to
148 // overestimate than to start decreasing the cost as the length goes up.
149 //
150 // This should be a reasonable approximation as it doesn't decrease by
151 // much from 1000px to 2000px.
152 //
153 // m = 1/20
154 // c = 0
155 complexity = std::min(length, 1000u) * 2;
156 }
157 }
158
159 AccumulateComplexity(complexity);
160}
161
162void DisplayListGLComplexityCalculator::GLHelper::drawOval(
163 const SkRect& bounds) {
164 if (IsComplex()) {
165 return;
166 }
167 // DrawOval scales very roughly linearly with the bounding box width/height
168 // (not area) for stroked styles without AA.
169 //
170 // Filled styles and stroked styles with AA scale linearly with the bounding
171 // box area.
172 unsigned int area = bounds.width() * bounds.height();
173
174 unsigned int complexity;
175
176 // There is also a kStrokeAndFill_Style that Skia exposes, but we do not
177 // currently use it anywhere in Flutter.
178 if (DrawStyle() == DlDrawStyle::kFill) {
179 // With filled styles, there is no significant AA penalty.
180 // m = 1/6000
181 // c = 0
182 complexity = area / 30;
183 } else {
184 if (IsAntiAliased()) {
185 // m = 1/4000
186 // c = 0
187 complexity = area / 20;
188 } else {
189 // Take the average of the width and height.
190 unsigned int length = (bounds.width() + bounds.height()) / 2;
191
192 // m = 1/75
193 // c = 0
194 complexity = length * 8 / 3;
195 }
196 }
197
198 AccumulateComplexity(complexity);
199}
200
201void DisplayListGLComplexityCalculator::GLHelper::drawCircle(
202 const SkPoint& center,
203 SkScalar radius) {
204 if (IsComplex()) {
205 return;
206 }
207
208 unsigned int complexity;
209
210 // There is also a kStrokeAndFill_Style that Skia exposes, but we do not
211 // currently use it anywhere in Flutter.
212 if (DrawStyle() == DlDrawStyle::kFill) {
213 // We can ignore pi here
214 unsigned int area = radius * radius;
215 // m = 1/525
216 // c = 50
217 complexity = (area + 26250) * 8 / 105;
218
219 // Penalty of around 8% when AA is disabled.
220 if (!IsAntiAliased()) {
221 complexity *= 1.08f;
222 }
223 } else {
224 // Hairline vs non-hairline has no significant performance difference.
225 if (IsAntiAliased()) {
226 // m = 1/3
227 // c = 10
228 complexity = (radius + 30) * 40 / 3;
229 } else {
230 // m = 1/10
231 // c = 20
232 complexity = (radius + 200) * 4;
233 }
234 }
235
236 AccumulateComplexity(complexity);
237}
238
239void DisplayListGLComplexityCalculator::GLHelper::drawRRect(
240 const SkRRect& rrect) {
241 if (IsComplex()) {
242 return;
243 }
244
245 // Drawing RRects is split into three performance tiers:
246 //
247 // 1) All stroked styles without AA *except* simple/symmetric RRects.
248 // 2) All filled styles and symmetric stroked styles w/AA.
249 // 3) Remaining stroked styles with AA.
250 //
251 // 1) and 3) scale linearly with length, 2) scales with area.
252
253 unsigned int complexity;
254
255 // These values were worked out by creating a straight line graph (y=mx+c)
256 // approximately matching the measured data, normalising the data so that
257 // 0.0005ms resulted in a score of 100 then simplifying down the formula.
258 if (DrawStyle() == DlDrawStyle::kFill ||
259 ((rrect.getType() == SkRRect::Type::kSimple_Type) && IsAntiAliased())) {
260 unsigned int area = rrect.width() * rrect.height();
261 // m = 1/3200
262 // c = 0.5
263 complexity = (area + 1600) / 80;
264 } else {
265 // Take the average of the width and height.
266 unsigned int length = (rrect.width() + rrect.height()) / 2;
267
268 // There is some difference between hairline and non-hairline performance
269 // but the spread is relatively inconsistent and it's pretty much a wash.
270 if (IsAntiAliased()) {
271 // m = 1/25
272 // c = 1
273 complexity = (length + 25) * 8 / 5;
274 } else {
275 // m = 1/50
276 // c = 0.75
277 complexity = ((length * 2) + 75) * 2 / 5;
278 }
279 }
280
281 AccumulateComplexity(complexity);
282}
283
284void DisplayListGLComplexityCalculator::GLHelper::drawDRRect(
285 const SkRRect& outer,
286 const SkRRect& inner) {
287 if (IsComplex()) {
288 return;
289 }
290 // There are roughly four classes here:
291 // a) Filled style.
292 // b) Complex RRect type with AA enabled and filled style.
293 // c) Stroked style with AA enabled.
294 // d) Stroked style with AA disabled.
295 //
296 // a) and b) scale linearly with the area, c) and d) scale linearly with
297 // a single dimension (length). In all cases, the dimensions refer to
298 // the outer RRect.
299
300 unsigned int complexity;
301
302 // These values were worked out by creating a straight line graph (y=mx+c)
303 // approximately matching the measured data, normalising the data so that
304 // 0.0005ms resulted in a score of 100 then simplifying down the formula.
305 //
306 // There is also a kStrokeAndFill_Style that Skia exposes, but we do not
307 // currently use it anywhere in Flutter.
308 if (DrawStyle() == DlDrawStyle::kFill) {
309 unsigned int area = outer.width() * outer.height();
310 if (outer.getType() == SkRRect::Type::kComplex_Type) {
311 // m = 1/500
312 // c = 0.5
313 complexity = (area + 250) / 5;
314 } else {
315 // m = 1/1600
316 // c = 2
317 complexity = (area + 3200) / 16;
318 }
319 } else {
320 unsigned int length = (outer.width() + outer.height()) / 2;
321 if (IsAntiAliased()) {
322 // m = 1/15
323 // c = 1
324 complexity = (length + 15) * 20 / 3;
325 } else {
326 // m = 1/27
327 // c = 0.5
328 complexity = ((length * 2) + 27) * 50 / 27;
329 }
330 }
331
332 AccumulateComplexity(complexity);
333}
334
336 if (IsComplex()) {
337 return;
338 }
339 // There is negligible effect on the performance for hairline vs. non-hairline
340 // stroke widths.
341 //
342 // The data for filled styles is currently suspicious, so for now we are going
343 // to assign scores based on stroked styles.
344
345 unsigned int line_verb_cost, quad_verb_cost, conic_verb_cost, cubic_verb_cost;
346 unsigned int complexity;
347
348 if (IsAntiAliased()) {
349 // There seems to be a fixed cost of around 1ms for calling drawPath with
350 // AA.
351 complexity = 200000;
352
353 line_verb_cost = 235;
354 quad_verb_cost = 365;
355 conic_verb_cost = 365;
356 cubic_verb_cost = 725;
357 } else {
358 // There seems to be a fixed cost of around 0.25ms for calling drawPath.
359 // without AA
360 complexity = 50000;
361
362 line_verb_cost = 135;
363 quad_verb_cost = 150;
364 conic_verb_cost = 200;
365 cubic_verb_cost = 235;
366 }
367
368 complexity += CalculatePathComplexity(path, line_verb_cost, quad_verb_cost,
369 conic_verb_cost, cubic_verb_cost);
370
371 AccumulateComplexity(complexity);
372}
373
374void DisplayListGLComplexityCalculator::GLHelper::drawArc(
375 const SkRect& oval_bounds,
376 SkScalar start_degrees,
377 SkScalar sweep_degrees,
378 bool use_center) {
379 if (IsComplex()) {
380 return;
381 }
382 // Hairline vs non-hairline makes no difference to the performance.
383 // Stroked styles without AA scale linearly with the log of the diameter.
384 // Stroked styles with AA scale linearly with the area.
385 // Filled styles scale lienarly with the area.
386 unsigned int area = oval_bounds.width() * oval_bounds.height();
387 unsigned int complexity;
388
389 // These values were worked out by creating a straight line graph (y=mx+c)
390 // approximately matching the measured data, normalising the data so that
391 // 0.0005ms resulted in a score of 100 then simplifying down the formula.
392 //
393 // There is also a kStrokeAndFill_Style that Skia exposes, but we do not
394 // currently use it anywhere in Flutter.
395 if (DrawStyle() == DlDrawStyle::kStroke) {
396 if (IsAntiAliased()) {
397 // m = 1/3800
398 // c = 12
399 complexity = (area + 45600) / 171;
400 } else {
401 unsigned int diameter = (oval_bounds.width() + oval_bounds.height()) / 2;
402 // m = 15
403 // c = -100
404 // This should never go negative though, so use std::max to ensure
405 // c is never larger than 15*log_diameter.
406 //
407 // Pre-multiply by 15 here so we get a little bit more precision.
408 unsigned int log_diameter = 15 * log(diameter);
409 complexity = (log_diameter - std::max(log_diameter, 100u)) * 200 / 9;
410 }
411 } else {
412 if (IsAntiAliased()) {
413 // m = 1/1000
414 // c = 10
415 complexity = (area + 10000) / 45;
416 } else {
417 // m = 1/6500
418 // c = 12
419 complexity = (area + 52000) * 2 / 585;
420 }
421 }
422
423 AccumulateComplexity(complexity);
424}
425
426void DisplayListGLComplexityCalculator::GLHelper::drawPoints(
428 uint32_t count,
429 const SkPoint points[]) {
430 if (IsComplex()) {
431 return;
432 }
433 unsigned int complexity;
434
435 if (IsAntiAliased()) {
437 if (IsHairline()) {
438 // This is a special case, it triggers an extremely fast path.
439 // m = 1/4500
440 // c = 0
441 complexity = count * 400 / 9;
442 } else {
443 // m = 1/500
444 // c = 0
445 complexity = count * 400;
446 }
447 } else if (mode == DlCanvas::PointMode::kLines) {
448 if (IsHairline()) {
449 // m = 1/750
450 // c = 0
451 complexity = count * 800 / 3;
452 } else {
453 // m = 1/500
454 // c = 0
455 complexity = count * 400;
456 }
457 } else {
458 if (IsHairline()) {
459 // m = 1/350
460 // c = 0
461 complexity = count * 4000 / 7;
462 } else {
463 // m = 1/250
464 // c = 0
465 complexity = count * 800;
466 }
467 }
468 } else {
470 // Hairline vs non hairline makes no difference for points without AA.
471 // m = 1/18000
472 // c = 0.25
473 complexity = (count + 4500) * 100 / 9;
474 } else if (mode == DlCanvas::PointMode::kLines) {
475 if (IsHairline()) {
476 // m = 1/8500
477 // c = 0.25
478 complexity = (count + 2125) * 400 / 17;
479 } else {
480 // m = 1/9000
481 // c = 0.25
482 complexity = (count + 2250) * 200 / 9;
483 }
484 } else {
485 // Polygon only really diverges for hairline vs non hairline at large
486 // point counts, and only by a few %.
487 // m = 1/7500
488 // c = 0.25
489 complexity = (count + 1875) * 80 / 3;
490 }
491 }
492
493 AccumulateComplexity(complexity);
494}
495
496void DisplayListGLComplexityCalculator::GLHelper::drawVertices(
497 const DlVertices* vertices,
499 // There is currently no way for us to get the VertexMode from the SkVertices
500 // object, but for future reference:
501 //
502 // TriangleStrip is roughly 25% more expensive than TriangleFan.
503 // TriangleFan is roughly 5% more expensive than Triangles.
504
505 // For the baseline, it's hard to identify the trend. It might be O(n^1/2)
506 // For now, treat it as linear as an approximation.
507 //
508 // m = 1/1600
509 // c = 1
510 unsigned int complexity = (vertices->vertex_count() + 1600) * 250 / 2;
511
512 AccumulateComplexity(complexity);
513}
514
515void DisplayListGLComplexityCalculator::GLHelper::drawImage(
516 const sk_sp<DlImage> image,
517 const SkPoint point,
519 bool render_with_attributes) {
520 if (IsComplex()) {
521 return;
522 }
523 // AA vs non-AA has a cost but it's dwarfed by the overall cost of the
524 // drawImage call.
525 //
526 // The main difference is if the image is backed by a texture already or not
527 // If we don't need to upload, then the cost scales linearly with the
528 // length of the image. If it needs uploading, the cost scales linearly
529 // with the square of the area (!!!).
530 SkISize dimensions = image->dimensions();
531 unsigned int length = (dimensions.width() + dimensions.height()) / 2;
532 unsigned int area = dimensions.width() * dimensions.height();
533
534 // m = 1/13
535 // c = 0
536 unsigned int complexity = length * 400 / 13;
537
538 if (!image->isTextureBacked()) {
539 // We can't square the area here as we'll overflow, so let's approximate
540 // by taking the calculated complexity score and applying a multiplier to
541 // it.
542 //
543 // (complexity * area / 60000) + 4000 gives a reasonable approximation with
544 // AA (complexity * area / 19000) gives a reasonable approximation without
545 // AA.
546 float multiplier;
547 if (IsAntiAliased()) {
548 multiplier = area / 60000.0f;
549 complexity = complexity * multiplier + 4000;
550 } else {
551 multiplier = area / 19000.0f;
552 complexity = complexity * multiplier;
553 }
554 }
555
556 AccumulateComplexity(complexity);
557}
558
559void DisplayListGLComplexityCalculator::GLHelper::ImageRect(
560 const SkISize& size,
561 bool texture_backed,
562 bool render_with_attributes,
563 bool enforce_src_edges) {
564 if (IsComplex()) {
565 return;
566 }
567 // Two main groups here - texture-backed and non-texture-backed images.
568 //
569 // Within each group, they all perform within a few % of each other *except*
570 // when we have a strict constraint and anti-aliasing enabled.
571
572 // These values were worked out by creating a straight line graph (y=mx+c)
573 // approximately matching the measured data, normalising the data so that
574 // 0.0005ms resulted in a score of 100 then simplifying down the formula.
575 unsigned int complexity;
576 if (!texture_backed || (texture_backed && render_with_attributes &&
577 enforce_src_edges && IsAntiAliased())) {
578 unsigned int area = size.width() * size.height();
579 // m = 1/4000
580 // c = 5
581 complexity = (area + 20000) / 10;
582 } else {
583 unsigned int length = (size.width() + size.height()) / 2;
584 // There's a little bit of spread here but the numbers are pretty large
585 // anyway.
586 //
587 // m = 1/22
588 // c = 0
589 complexity = length * 200 / 11;
590 }
591
592 AccumulateComplexity(complexity);
593}
594
595void DisplayListGLComplexityCalculator::GLHelper::drawImageNine(
596 const sk_sp<DlImage> image,
597 const SkIRect& center,
598 const SkRect& dst,
599 DlFilterMode filter,
600 bool render_with_attributes) {
601 if (IsComplex()) {
602 return;
603 }
604
605 SkISize dimensions = image->dimensions();
606 unsigned int area = dimensions.width() * dimensions.height();
607
608 // m = 1/3600
609 // c = 3
610 unsigned int complexity = (area + 10800) / 9;
611
612 // Uploading incurs about a 40% performance penalty.
613 if (!image->isTextureBacked()) {
614 complexity *= 1.4f;
615 }
616
617 AccumulateComplexity(complexity);
618}
619
620void DisplayListGLComplexityCalculator::GLHelper::drawDisplayList(
621 const sk_sp<DisplayList> display_list,
622 SkScalar opacity) {
623 if (IsComplex()) {
624 return;
625 }
626 GLHelper helper(Ceiling() - CurrentComplexityScore());
627 if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) {
628 auto bounds = display_list->bounds();
629 helper.saveLayer(bounds, SaveLayerOptions::kWithAttributes, nullptr);
630 }
631 display_list->Dispatch(helper);
632 AccumulateComplexity(helper.ComplexityScore());
633}
634
636 const sk_sp<SkTextBlob> blob,
637 SkScalar x,
638 SkScalar y) {
639 if (IsComplex()) {
640 return;
641 }
642
643 // DrawTextBlob has a high fixed cost, but if we call it multiple times
644 // per frame, that fixed cost is greatly reduced per subsequent call. This
645 // is likely because there is batching being done in SkCanvas.
646
647 // Increment draw_text_blob_count_ and calculate the cost at the end.
648 draw_text_blob_count_++;
649}
650
651void DisplayListGLComplexityCalculator::GLHelper::drawTextFrame(
652 const std::shared_ptr<impeller::TextFrame>& text_frame,
653 SkScalar x,
654 SkScalar y) {}
655
656void DisplayListGLComplexityCalculator::GLHelper::drawShadow(
657 const SkPath& path,
658 const DlColor color,
659 const SkScalar elevation,
660 bool transparent_occluder,
661 SkScalar dpr) {
662 if (IsComplex()) {
663 return;
664 }
665
666 // Elevation has no significant effect on the timings. Whether the shadow
667 // is cast by a transparent occluder or not has a small impact of around 5%.
668 //
669 // The path verbs do have an effect but only if the verb type is cubic; line,
670 // quad and conic all perform similarly.
671 float occluder_penalty = 1.0f;
672 if (transparent_occluder) {
673 occluder_penalty = 1.20f;
674 }
675
676 // The benchmark uses a test path of around 10 path elements. This is likely
677 // to be similar to what we see in real world usage, but we should benchmark
678 // different path lengths to see how much impact there is from varying the
679 // path length.
680 //
681 // For now, we will assume that there is no fixed overhead and that the time
682 // spent rendering the shadow for a path is split evenly amongst all the verbs
683 // enumerated.
684 unsigned int line_verb_cost = 17000; // 0.085ms
685 unsigned int quad_verb_cost = 20000; // 0.1ms
686 unsigned int conic_verb_cost = 20000; // 0.1ms
687 unsigned int cubic_verb_cost = 120000; // 0.6ms
688
689 unsigned int complexity = CalculatePathComplexity(
690 path, line_verb_cost, quad_verb_cost, conic_verb_cost, cubic_verb_cost);
691
692 AccumulateComplexity(complexity * occluder_penalty);
693}
694
695} // namespace flutter
const char * options
int count
Definition: FontMgrTest.cpp:50
static const int points[]
SkISize dimensions() const
Definition: SkImage.h:297
virtual bool isTextureBacked() const =0
Definition: SkPath.h:59
Type getType() const
Definition: SkRRect.h:76
SkScalar width() const
Definition: SkRRect.h:95
SkScalar height() const
Definition: SkRRect.h:102
static DisplayListGLComplexityCalculator * GetInstance()
@ kLines
draw each separate pair of points as a line segment
@ kPoints
draw each point separately
static const SaveLayerOptions kWithAttributes
Definition: display_list.h:154
DlColor color
float SkScalar
Definition: extension.cpp:12
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
size_t length
static void drawPath(SkPath &path, SkCanvas *canvas, SkColor color, const SkRect &clip, SkPaint::Cap cap, SkPaint::Join join, SkPaint::Style style, SkPathFillType fill, SkScalar strokeWidth)
Definition: linepaths.cpp:22
double y
double x
drawTextBlob(r.blob.get(), r.x, r.y, r.paint)) DRAW(DrawSlug
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< const SkImage > image
Definition: SkRecords.h:269
sk_sp< const SkImageFilter > backdrop
Definition: SkRecords.h:191
SkRRect rrect
Definition: SkRecords.h:232
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
SkSamplingOptions sampling
Definition: SkRecords.h:337
impeller::Scalar DlScalar
const SkPoint & ToSkPoint(const DlPoint &point)
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
@ 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
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 keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
impeller::Point DlPoint
dst
Definition: cp.py:12
SIN Vec< N, float > abs(const Vec< N, float > &x)
Definition: SkVx.h:707
flutter::DlColor DlColor
flutter::SaveLayerOptions SaveLayerOptions
Definition: SkRect.h:32
Definition: SkSize.h:16
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37
constexpr float y() const
Definition: SkPoint_impl.h:187
constexpr float x() const
Definition: SkPoint_impl.h:181
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762