Flutter Engine
The Flutter Engine
blurcircles2.cpp
Go to the documentation of this file.
1/*
2* Copyright 2016 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
8#include "gm/gm.h"
15#include "include/core/SkRect.h"
18#include "include/core/SkSize.h"
20#include "src/base/SkRandom.h"
21#include "src/core/SkBlurMask.h"
23
24/**
25 * In GM mode this draws an array of circles with different radii and different blur radii. Below
26 * each circle an almost-circle path is drawn with the same blur filter for comparison.
27 *
28 * In Sample mode this draws a single circle and almost-circle with animating radius and blur
29 * radius.
30 *
31 * Bench mode draws the same as GM mode but without the comparison almost-circle paths. It also
32 * slightly perturbs the blur and circle radii to stress caching of blurred profiles in GPU mode.
33 */
34class BlurCircles2GM : public skiagm::GM {
35public:
37 fAnimRadius = TimeUtils::PingPong(
38 0, kRadiusPingPoingPeriod, kRadiusPingPoingShift, kMinRadius, kMaxRadius);
39 fAnimBlurRadius = TimeUtils::PingPong(0,
40 kBlurRadiusPingPoingPeriod,
41 kBlurRadiusPingPoingShift,
42 kMinBlurRadius,
43 kMaxBlurRadius);
44 }
45
46protected:
47 bool runAsBench() const override { return true; }
48
49 SkString getName() const override { return SkString("blurcircles2"); }
50
51 SkISize getISize() override { return SkISize::Make(730, 1350); }
52
53 void onDraw(SkCanvas* canvas) override {
54 constexpr SkScalar kMaxR = kMaxRadius + kMaxBlurRadius;
55
56 auto almostCircleMaker = [] (SkScalar radius) {
57 return SkPathBuilder().addArc(SkRect::MakeXYWH(-radius, -radius, 2 * radius, 2 * radius), 0, 355)
58 .setIsVolatile(true)
59 .close()
60 .detach();
61 };
62
63 auto blurMaker = [] (SkScalar radius) ->sk_sp<SkMaskFilter> {
66 };
67
69 paint.setColor(SK_ColorBLACK);
70
71 if (this->getMode() == kSample_Mode) {
72 paint.setMaskFilter(blurMaker(fAnimBlurRadius));
73 SkISize size = canvas->getBaseLayerSize();
74 SkPath almostCircle = almostCircleMaker(fAnimRadius);
75 canvas->save();
76 canvas->translate(size.fWidth / 2.f, size.fHeight / 4.f);
77 canvas->drawCircle(0, 0, fAnimRadius, paint);
78 canvas->translate(0, 2 * kMaxR);
79 canvas->drawPath(almostCircle, paint);
80 canvas->restore();
81 } else {
82 bool benchMode = this->getMode() == kBench_Mode;
83 canvas->save();
84 constexpr SkScalar kPad = 5;
85 constexpr SkScalar kRadiusSteps = 5;
86 constexpr SkScalar kBlurRadiusSteps = 5;
87 canvas->translate(kPad + kMinRadius + kMaxBlurRadius,
88 kPad + kMinRadius + kMaxBlurRadius);
89 constexpr SkScalar kDeltaRadius = (kMaxRadius - kMinRadius) / kRadiusSteps;
90 constexpr SkScalar kDeltaBlurRadius = (kMaxBlurRadius - kMinBlurRadius) /
91 kBlurRadiusSteps;
92 SkScalar lineWidth = 0;
93 if (!benchMode) {
94 for (int r = 0; r < kRadiusSteps - 1; ++r) {
95 const SkScalar radius = r * kDeltaRadius + kMinRadius;
96 lineWidth += 2 * (radius + kMaxBlurRadius) + kPad;
97 }
98 }
99 for (int br = 0; br < kBlurRadiusSteps; ++br) {
100 SkScalar blurRadius = br * kDeltaBlurRadius + kMinBlurRadius;
101 if (benchMode) {
102 blurRadius += fRandom.nextSScalar1() * kDeltaBlurRadius;
103 }
104 const SkScalar maxRowR = blurRadius + kMaxRadius;
105 paint.setMaskFilter(blurMaker(blurRadius));
106 canvas->save();
107 for (int r = 0; r < kRadiusSteps; ++r) {
108 SkScalar radius = r * kDeltaRadius + kMinRadius;
109 if (benchMode) {
110 radius += fRandom.nextSScalar1() * kDeltaRadius;
111 }
112 SkPath almostCircle;
113 if (!benchMode) {
114 almostCircle = almostCircleMaker(radius);
115 }
116 canvas->save();
117 canvas->drawCircle(0, 0, radius, paint);
118 canvas->translate(0, 2 * maxRowR + kPad);
119 if (!benchMode) {
120 canvas->drawPath(almostCircle, paint);
121 }
122 canvas->restore();
123 const SkScalar maxColR = radius + kMaxBlurRadius;
124 canvas->translate(maxColR * 2 + kPad, 0);
125 }
126 canvas->restore();
127 if (!benchMode) {
128 SkPaint blackPaint;
129 blackPaint.setColor(SK_ColorBLACK);
130 const SkScalar lineY = 3 * maxRowR + 1.5f * kPad;
131 if (br != kBlurRadiusSteps - 1) {
132 canvas->drawLine(0, lineY, lineWidth, lineY, blackPaint);
133 }
134 }
135 canvas->translate(0, maxRowR * 4 + 2 * kPad);
136 }
137 canvas->restore();
138 }
139 }
140
141 bool onAnimate(double nanos) override {
142 fAnimRadius = TimeUtils::PingPong(1e-9 * nanos, kRadiusPingPoingPeriod, kRadiusPingPoingShift, kMinRadius,
143 kMaxRadius);
144 fAnimBlurRadius = TimeUtils::PingPong(1e-9 * nanos, kBlurRadiusPingPoingPeriod, kBlurRadiusPingPoingShift,
145 kMinBlurRadius, kMaxBlurRadius);
146 return true;
147 }
148
149private:
150 inline static constexpr SkScalar kMinRadius = 15;
151 inline static constexpr SkScalar kMaxRadius = 45;
152 inline static constexpr SkScalar kRadiusPingPoingPeriod = 8;
153 inline static constexpr SkScalar kRadiusPingPoingShift = 3;
154
155 inline static constexpr SkScalar kMinBlurRadius = 5;
156 inline static constexpr SkScalar kMaxBlurRadius = 45;
157 inline static constexpr SkScalar kBlurRadiusPingPoingPeriod = 3;
158 inline static constexpr SkScalar kBlurRadiusPingPoingShift = 1.5;
159
160 SkScalar fAnimRadius;
161 SkScalar fAnimBlurRadius;
162
163 SkRandom fRandom;
164
165 using INHERITED = skiagm::GM;
166};
167
168DEF_GM(return new BlurCircles2GM();)
@ kNormal_SkBlurStyle
fuzzy inside and outside
Definition: SkBlurTypes.h:12
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr int kPad
bool runAsBench() const override
SkISize getISize() override
bool onAnimate(double nanos) override
SkString getName() const override
void onDraw(SkCanvas *canvas) override
static SkScalar SK_SPI ConvertRadiusToSigma(SkScalar radius)
Definition: SkBlurMask.cpp:39
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
Definition: SkCanvas.cpp:2700
virtual SkISize getBaseLayerSize() const
Definition: SkCanvas.cpp:369
int save()
Definition: SkCanvas.cpp:447
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint &paint)
Definition: SkCanvas.cpp:2707
static sk_sp< SkMaskFilter > MakeBlur(SkBlurStyle style, SkScalar sigma, bool respectCTM=true)
void setColor(SkColor color)
Definition: SkPaint.cpp:119
void setMaskFilter(sk_sp< SkMaskFilter > maskFilter)
SkPathBuilder & close()
SkPathBuilder & addArc(const SkRect &oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg)
SkPathBuilder & setIsVolatile(bool isVolatile)
Definition: SkPathBuilder.h:43
Definition: SkPath.h:59
SkScalar nextSScalar1()
Definition: SkRandom.h:113
Definition: gm.h:110
@ kBench_Mode
Definition: gm.h:121
@ kSample_Mode
Definition: gm.h:120
Mode getMode() const
Definition: gm.h:125
const Paint & paint
Definition: color_source.cc:38
float SkScalar
Definition: extension.cpp:12
#define DEF_GM(CODE)
Definition: gm.h:40
static float PingPong(double time, float period, float phase, float ends, float mid)
Definition: TimeUtils.h:37
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
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659