blob: 809314815f773ee88003d57c5f3899dc8f7b269a [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"
Mike Reedd16d6542020-08-22 15:08:27 -040014#include "include/core/SkPathBuilder.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"
Kevin Lubick0d4d1142023-02-13 09:13:10 -050020#include "src/base/SkRandom.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#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
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000049 SkString getName() const override { return SkString("blurcircles2"); }
bsalomonc67bb572016-05-13 13:48:48 -070050
Leandro Lovisolo8f023882023-08-15 21:13:52 +000051 SkISize getISize() override { return SkISize::Make(730, 1350); }
bsalomonc67bb572016-05-13 13:48:48 -070052
53 void onDraw(SkCanvas* canvas) override {
mtkleindbfd7ab2016-09-01 11:24:54 -070054 constexpr SkScalar kMaxR = kMaxRadius + kMaxBlurRadius;
bsalomonc67bb572016-05-13 13:48:48 -070055
Mike Reedd16d6542020-08-22 15:08:27 -040056 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();
bsalomonc67bb572016-05-13 13:48:48 -070061 };
62
63 auto blurMaker = [] (SkScalar radius) ->sk_sp<SkMaskFilter> {
Mike Reed1be1f8d2018-03-14 13:01:17 -040064 return SkMaskFilter::MakeBlur(kNormal_SkBlurStyle,
65 SkBlurMask::ConvertRadiusToSigma(radius));
bsalomonc67bb572016-05-13 13:48:48 -070066 };
67
68 SkPaint paint;
69 paint.setColor(SK_ColorBLACK);
70
71 if (this->getMode() == kSample_Mode) {
72 paint.setMaskFilter(blurMaker(fAnimBlurRadius));
73 SkISize size = canvas->getBaseLayerSize();
Mike Reedd16d6542020-08-22 15:08:27 -040074 SkPath almostCircle = almostCircleMaker(fAnimRadius);
bsalomonc67bb572016-05-13 13:48:48 -070075 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 {
bsalomon29965532016-05-16 09:36:44 -070082 bool benchMode = this->getMode() == kBench_Mode;
bsalomonc67bb572016-05-13 13:48:48 -070083 canvas->save();
mtkleindbfd7ab2016-09-01 11:24:54 -070084 constexpr SkScalar kPad = 5;
85 constexpr SkScalar kRadiusSteps = 5;
86 constexpr SkScalar kBlurRadiusSteps = 5;
bsalomonc67bb572016-05-13 13:48:48 -070087 canvas->translate(kPad + kMinRadius + kMaxBlurRadius,
88 kPad + kMinRadius + kMaxBlurRadius);
mtkleindbfd7ab2016-09-01 11:24:54 -070089 constexpr SkScalar kDeltaRadius = (kMaxRadius - kMinRadius) / kRadiusSteps;
90 constexpr SkScalar kDeltaBlurRadius = (kMaxBlurRadius - kMinBlurRadius) /
bsalomon29965532016-05-16 09:36:44 -070091 kBlurRadiusSteps;
bsalomonc67bb572016-05-13 13:48:48 -070092 SkScalar lineWidth = 0;
bsalomon29965532016-05-16 09:36:44 -070093 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 }
bsalomonc67bb572016-05-13 13:48:48 -070098 }
99 for (int br = 0; br < kBlurRadiusSteps; ++br) {
bsalomon29965532016-05-16 09:36:44 -0700100 SkScalar blurRadius = br * kDeltaBlurRadius + kMinBlurRadius;
101 if (benchMode) {
102 blurRadius += fRandom.nextSScalar1() * kDeltaBlurRadius;
103 }
bsalomonc67bb572016-05-13 13:48:48 -0700104 const SkScalar maxRowR = blurRadius + kMaxRadius;
105 paint.setMaskFilter(blurMaker(blurRadius));
106 canvas->save();
107 for (int r = 0; r < kRadiusSteps; ++r) {
bsalomon29965532016-05-16 09:36:44 -0700108 SkScalar radius = r * kDeltaRadius + kMinRadius;
109 if (benchMode) {
110 radius += fRandom.nextSScalar1() * kDeltaRadius;
111 }
bsalomonc67bb572016-05-13 13:48:48 -0700112 SkPath almostCircle;
bsalomon29965532016-05-16 09:36:44 -0700113 if (!benchMode) {
Mike Reedd16d6542020-08-22 15:08:27 -0400114 almostCircle = almostCircleMaker(radius);
bsalomon29965532016-05-16 09:36:44 -0700115 }
bsalomonc67bb572016-05-13 13:48:48 -0700116 canvas->save();
117 canvas->drawCircle(0, 0, radius, paint);
118 canvas->translate(0, 2 * maxRowR + kPad);
bsalomon29965532016-05-16 09:36:44 -0700119 if (!benchMode) {
bsalomonc67bb572016-05-13 13:48:48 -0700120 canvas->drawPath(almostCircle, paint);
bsalomon29965532016-05-16 09:36:44 -0700121 }
bsalomonc67bb572016-05-13 13:48:48 -0700122 canvas->restore();
123 const SkScalar maxColR = radius + kMaxBlurRadius;
124 canvas->translate(maxColR * 2 + kPad, 0);
125 }
126 canvas->restore();
bsalomon29965532016-05-16 09:36:44 -0700127 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 }
bsalomonc67bb572016-05-13 13:48:48 -0700134 }
135 canvas->translate(0, maxRowR * 4 + 2 * kPad);
136 }
137 canvas->restore();
138 }
139 }
140
Hal Canary41248072019-07-11 16:32:53 -0400141 bool onAnimate(double nanos) override {
142 fAnimRadius = TimeUtils::PingPong(1e-9 * nanos, kRadiusPingPoingPeriod, kRadiusPingPoingShift, kMinRadius,
bsalomonc67bb572016-05-13 13:48:48 -0700143 kMaxRadius);
Hal Canary41248072019-07-11 16:32:53 -0400144 fAnimBlurRadius = TimeUtils::PingPong(1e-9 * nanos, kBlurRadiusPingPoingPeriod, kBlurRadiusPingPoingShift,
bsalomonc67bb572016-05-13 13:48:48 -0700145 kMinBlurRadius, kMaxBlurRadius);
146 return true;
147 }
148
149private:
Brian Salomon9fa47cc2021-10-08 18:48:26 -0400150 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;
bsalomonc67bb572016-05-13 13:48:48 -0700154
Brian Salomon9fa47cc2021-10-08 18:48:26 -0400155 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;
bsalomonc67bb572016-05-13 13:48:48 -0700159
160 SkScalar fAnimRadius;
161 SkScalar fAnimBlurRadius;
162
bsalomon29965532016-05-16 09:36:44 -0700163 SkRandom fRandom;
164
John Stiles7571f9e2020-09-02 22:42:33 -0400165 using INHERITED = skiagm::GM;
bsalomonc67bb572016-05-13 13:48:48 -0700166};
167
168DEF_GM(return new BlurCircles2GM();)