blob: 82cadf1a79308bc351260566f5a2814f23709b7e [file] [log] [blame]
bsalomonc67bb572016-05-13 13:48:48 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -04009#include "include/core/SkBlurTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkCanvas.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040011#include "include/core/SkColor.h"
12#include "include/core/SkMaskFilter.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkPaint.h"
14#include "include/core/SkPath.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040015#include "include/core/SkRect.h"
16#include "include/core/SkRefCnt.h"
17#include "include/core/SkScalar.h"
18#include "include/core/SkSize.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "include/utils/SkRandom.h"
21#include "src/core/SkBlurMask.h"
Hal Canary41248072019-07-11 16:32:53 -040022#include "tools/timer/TimeUtils.h"
bsalomonc67bb572016-05-13 13:48:48 -070023
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.
bsalomon29965532016-05-16 09:36:44 -070030 *
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.
bsalomonc67bb572016-05-13 13:48:48 -070033 */
34class BlurCircles2GM : public skiagm::GM {
35public:
36 BlurCircles2GM() {
Hal Canary41248072019-07-11 16:32:53 -040037 fAnimRadius = TimeUtils::PingPong(
Mike Kleincd5104e2019-03-20 11:55:08 -050038 0, kRadiusPingPoingPeriod, kRadiusPingPoingShift, kMinRadius, kMaxRadius);
Hal Canary41248072019-07-11 16:32:53 -040039 fAnimBlurRadius = TimeUtils::PingPong(0,
Mike Kleincd5104e2019-03-20 11:55:08 -050040 kBlurRadiusPingPoingPeriod,
41 kBlurRadiusPingPoingShift,
42 kMinBlurRadius,
43 kMaxBlurRadius);
bsalomonc67bb572016-05-13 13:48:48 -070044 }
45
46protected:
bsalomon29965532016-05-16 09:36:44 -070047 bool runAsBench() const override { return true; }
48
bsalomonc67bb572016-05-13 13:48:48 -070049 SkString onShortName() override { return SkString("blurcircles2"); }
50
51 SkISize onISize() override {
52 return SkISize::Make(730, 1350);
53 }
54
55 void onDraw(SkCanvas* canvas) override {
mtkleindbfd7ab2016-09-01 11:24:54 -070056 constexpr SkScalar kMaxR = kMaxRadius + kMaxBlurRadius;
bsalomonc67bb572016-05-13 13:48:48 -070057
58 auto almostCircleMaker = [] (SkScalar radius, SkPath* dst) {
59 dst->reset();
60 dst->addArc(SkRect::MakeXYWH(-radius, -radius, 2 * radius, 2 * radius), 0, 355);
61 dst->setIsVolatile(true);
62 dst->close();
63 };
64
65 auto blurMaker = [] (SkScalar radius) ->sk_sp<SkMaskFilter> {
Mike Reed1be1f8d2018-03-14 13:01:17 -040066 return SkMaskFilter::MakeBlur(kNormal_SkBlurStyle,
67 SkBlurMask::ConvertRadiusToSigma(radius));
bsalomonc67bb572016-05-13 13:48:48 -070068 };
69
70 SkPaint paint;
71 paint.setColor(SK_ColorBLACK);
72
73 if (this->getMode() == kSample_Mode) {
74 paint.setMaskFilter(blurMaker(fAnimBlurRadius));
75 SkISize size = canvas->getBaseLayerSize();
76 SkPath almostCircle;
77 almostCircleMaker(fAnimRadius, &almostCircle);
78 canvas->save();
79 canvas->translate(size.fWidth / 2.f, size.fHeight / 4.f);
80 canvas->drawCircle(0, 0, fAnimRadius, paint);
81 canvas->translate(0, 2 * kMaxR);
82 canvas->drawPath(almostCircle, paint);
83 canvas->restore();
84 } else {
bsalomon29965532016-05-16 09:36:44 -070085 bool benchMode = this->getMode() == kBench_Mode;
bsalomonc67bb572016-05-13 13:48:48 -070086 canvas->save();
mtkleindbfd7ab2016-09-01 11:24:54 -070087 constexpr SkScalar kPad = 5;
88 constexpr SkScalar kRadiusSteps = 5;
89 constexpr SkScalar kBlurRadiusSteps = 5;
bsalomonc67bb572016-05-13 13:48:48 -070090 canvas->translate(kPad + kMinRadius + kMaxBlurRadius,
91 kPad + kMinRadius + kMaxBlurRadius);
mtkleindbfd7ab2016-09-01 11:24:54 -070092 constexpr SkScalar kDeltaRadius = (kMaxRadius - kMinRadius) / kRadiusSteps;
93 constexpr SkScalar kDeltaBlurRadius = (kMaxBlurRadius - kMinBlurRadius) /
bsalomon29965532016-05-16 09:36:44 -070094 kBlurRadiusSteps;
bsalomonc67bb572016-05-13 13:48:48 -070095 SkScalar lineWidth = 0;
bsalomon29965532016-05-16 09:36:44 -070096 if (!benchMode) {
97 for (int r = 0; r < kRadiusSteps - 1; ++r) {
98 const SkScalar radius = r * kDeltaRadius + kMinRadius;
99 lineWidth += 2 * (radius + kMaxBlurRadius) + kPad;
100 }
bsalomonc67bb572016-05-13 13:48:48 -0700101 }
102 for (int br = 0; br < kBlurRadiusSteps; ++br) {
bsalomon29965532016-05-16 09:36:44 -0700103 SkScalar blurRadius = br * kDeltaBlurRadius + kMinBlurRadius;
104 if (benchMode) {
105 blurRadius += fRandom.nextSScalar1() * kDeltaBlurRadius;
106 }
bsalomonc67bb572016-05-13 13:48:48 -0700107 const SkScalar maxRowR = blurRadius + kMaxRadius;
108 paint.setMaskFilter(blurMaker(blurRadius));
109 canvas->save();
110 for (int r = 0; r < kRadiusSteps; ++r) {
bsalomon29965532016-05-16 09:36:44 -0700111 SkScalar radius = r * kDeltaRadius + kMinRadius;
112 if (benchMode) {
113 radius += fRandom.nextSScalar1() * kDeltaRadius;
114 }
bsalomonc67bb572016-05-13 13:48:48 -0700115 SkPath almostCircle;
bsalomon29965532016-05-16 09:36:44 -0700116 if (!benchMode) {
117 almostCircleMaker(radius, &almostCircle);
118 }
bsalomonc67bb572016-05-13 13:48:48 -0700119 canvas->save();
120 canvas->drawCircle(0, 0, radius, paint);
121 canvas->translate(0, 2 * maxRowR + kPad);
bsalomon29965532016-05-16 09:36:44 -0700122 if (!benchMode) {
bsalomonc67bb572016-05-13 13:48:48 -0700123 canvas->drawPath(almostCircle, paint);
bsalomon29965532016-05-16 09:36:44 -0700124 }
bsalomonc67bb572016-05-13 13:48:48 -0700125 canvas->restore();
126 const SkScalar maxColR = radius + kMaxBlurRadius;
127 canvas->translate(maxColR * 2 + kPad, 0);
128 }
129 canvas->restore();
bsalomon29965532016-05-16 09:36:44 -0700130 if (!benchMode) {
131 SkPaint blackPaint;
132 blackPaint.setColor(SK_ColorBLACK);
133 const SkScalar lineY = 3 * maxRowR + 1.5f * kPad;
134 if (br != kBlurRadiusSteps - 1) {
135 canvas->drawLine(0, lineY, lineWidth, lineY, blackPaint);
136 }
bsalomonc67bb572016-05-13 13:48:48 -0700137 }
138 canvas->translate(0, maxRowR * 4 + 2 * kPad);
139 }
140 canvas->restore();
141 }
142 }
143
Hal Canary41248072019-07-11 16:32:53 -0400144 bool onAnimate(double nanos) override {
145 fAnimRadius = TimeUtils::PingPong(1e-9 * nanos, kRadiusPingPoingPeriod, kRadiusPingPoingShift, kMinRadius,
bsalomonc67bb572016-05-13 13:48:48 -0700146 kMaxRadius);
Hal Canary41248072019-07-11 16:32:53 -0400147 fAnimBlurRadius = TimeUtils::PingPong(1e-9 * nanos, kBlurRadiusPingPoingPeriod, kBlurRadiusPingPoingShift,
bsalomonc67bb572016-05-13 13:48:48 -0700148 kMinBlurRadius, kMaxBlurRadius);
149 return true;
150 }
151
152private:
153 static constexpr SkScalar kMinRadius = 15;
154 static constexpr SkScalar kMaxRadius = 45;
155 static constexpr SkScalar kRadiusPingPoingPeriod = 8;
156 static constexpr SkScalar kRadiusPingPoingShift = 3;
157
158 static constexpr SkScalar kMinBlurRadius = 5;
159 static constexpr SkScalar kMaxBlurRadius = 45;
160 static constexpr SkScalar kBlurRadiusPingPoingPeriod = 3;
161 static constexpr SkScalar kBlurRadiusPingPoingShift = 1.5;
162
163 SkScalar fAnimRadius;
164 SkScalar fAnimBlurRadius;
165
bsalomon29965532016-05-16 09:36:44 -0700166 SkRandom fRandom;
167
bsalomonc67bb572016-05-13 13:48:48 -0700168 typedef skiagm::GM INHERITED;
169};
170
171DEF_GM(return new BlurCircles2GM();)