blob: c399d563621d96eb7afc518b247df716e989cde2 [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"
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
Mike Reedd16d6542020-08-22 15:08:27 -040058 auto almostCircleMaker = [] (SkScalar radius) {
59 return SkPathBuilder().addArc(SkRect::MakeXYWH(-radius, -radius, 2 * radius, 2 * radius), 0, 355)
60 .setIsVolatile(true)
61 .close()
62 .detach();
bsalomonc67bb572016-05-13 13:48:48 -070063 };
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();
Mike Reedd16d6542020-08-22 15:08:27 -040076 SkPath almostCircle = almostCircleMaker(fAnimRadius);
bsalomonc67bb572016-05-13 13:48:48 -070077 canvas->save();
78 canvas->translate(size.fWidth / 2.f, size.fHeight / 4.f);
79 canvas->drawCircle(0, 0, fAnimRadius, paint);
80 canvas->translate(0, 2 * kMaxR);
81 canvas->drawPath(almostCircle, paint);
82 canvas->restore();
83 } else {
bsalomon29965532016-05-16 09:36:44 -070084 bool benchMode = this->getMode() == kBench_Mode;
bsalomonc67bb572016-05-13 13:48:48 -070085 canvas->save();
mtkleindbfd7ab2016-09-01 11:24:54 -070086 constexpr SkScalar kPad = 5;
87 constexpr SkScalar kRadiusSteps = 5;
88 constexpr SkScalar kBlurRadiusSteps = 5;
bsalomonc67bb572016-05-13 13:48:48 -070089 canvas->translate(kPad + kMinRadius + kMaxBlurRadius,
90 kPad + kMinRadius + kMaxBlurRadius);
mtkleindbfd7ab2016-09-01 11:24:54 -070091 constexpr SkScalar kDeltaRadius = (kMaxRadius - kMinRadius) / kRadiusSteps;
92 constexpr SkScalar kDeltaBlurRadius = (kMaxBlurRadius - kMinBlurRadius) /
bsalomon29965532016-05-16 09:36:44 -070093 kBlurRadiusSteps;
bsalomonc67bb572016-05-13 13:48:48 -070094 SkScalar lineWidth = 0;
bsalomon29965532016-05-16 09:36:44 -070095 if (!benchMode) {
96 for (int r = 0; r < kRadiusSteps - 1; ++r) {
97 const SkScalar radius = r * kDeltaRadius + kMinRadius;
98 lineWidth += 2 * (radius + kMaxBlurRadius) + kPad;
99 }
bsalomonc67bb572016-05-13 13:48:48 -0700100 }
101 for (int br = 0; br < kBlurRadiusSteps; ++br) {
bsalomon29965532016-05-16 09:36:44 -0700102 SkScalar blurRadius = br * kDeltaBlurRadius + kMinBlurRadius;
103 if (benchMode) {
104 blurRadius += fRandom.nextSScalar1() * kDeltaBlurRadius;
105 }
bsalomonc67bb572016-05-13 13:48:48 -0700106 const SkScalar maxRowR = blurRadius + kMaxRadius;
107 paint.setMaskFilter(blurMaker(blurRadius));
108 canvas->save();
109 for (int r = 0; r < kRadiusSteps; ++r) {
bsalomon29965532016-05-16 09:36:44 -0700110 SkScalar radius = r * kDeltaRadius + kMinRadius;
111 if (benchMode) {
112 radius += fRandom.nextSScalar1() * kDeltaRadius;
113 }
bsalomonc67bb572016-05-13 13:48:48 -0700114 SkPath almostCircle;
bsalomon29965532016-05-16 09:36:44 -0700115 if (!benchMode) {
Mike Reedd16d6542020-08-22 15:08:27 -0400116 almostCircle = almostCircleMaker(radius);
bsalomon29965532016-05-16 09:36:44 -0700117 }
bsalomonc67bb572016-05-13 13:48:48 -0700118 canvas->save();
119 canvas->drawCircle(0, 0, radius, paint);
120 canvas->translate(0, 2 * maxRowR + kPad);
bsalomon29965532016-05-16 09:36:44 -0700121 if (!benchMode) {
bsalomonc67bb572016-05-13 13:48:48 -0700122 canvas->drawPath(almostCircle, paint);
bsalomon29965532016-05-16 09:36:44 -0700123 }
bsalomonc67bb572016-05-13 13:48:48 -0700124 canvas->restore();
125 const SkScalar maxColR = radius + kMaxBlurRadius;
126 canvas->translate(maxColR * 2 + kPad, 0);
127 }
128 canvas->restore();
bsalomon29965532016-05-16 09:36:44 -0700129 if (!benchMode) {
130 SkPaint blackPaint;
131 blackPaint.setColor(SK_ColorBLACK);
132 const SkScalar lineY = 3 * maxRowR + 1.5f * kPad;
133 if (br != kBlurRadiusSteps - 1) {
134 canvas->drawLine(0, lineY, lineWidth, lineY, blackPaint);
135 }
bsalomonc67bb572016-05-13 13:48:48 -0700136 }
137 canvas->translate(0, maxRowR * 4 + 2 * kPad);
138 }
139 canvas->restore();
140 }
141 }
142
Hal Canary41248072019-07-11 16:32:53 -0400143 bool onAnimate(double nanos) override {
144 fAnimRadius = TimeUtils::PingPong(1e-9 * nanos, kRadiusPingPoingPeriod, kRadiusPingPoingShift, kMinRadius,
bsalomonc67bb572016-05-13 13:48:48 -0700145 kMaxRadius);
Hal Canary41248072019-07-11 16:32:53 -0400146 fAnimBlurRadius = TimeUtils::PingPong(1e-9 * nanos, kBlurRadiusPingPoingPeriod, kBlurRadiusPingPoingShift,
bsalomonc67bb572016-05-13 13:48:48 -0700147 kMinBlurRadius, kMaxBlurRadius);
148 return true;
149 }
150
151private:
152 static constexpr SkScalar kMinRadius = 15;
153 static constexpr SkScalar kMaxRadius = 45;
154 static constexpr SkScalar kRadiusPingPoingPeriod = 8;
155 static constexpr SkScalar kRadiusPingPoingShift = 3;
156
157 static constexpr SkScalar kMinBlurRadius = 5;
158 static constexpr SkScalar kMaxBlurRadius = 45;
159 static constexpr SkScalar kBlurRadiusPingPoingPeriod = 3;
160 static constexpr SkScalar kBlurRadiusPingPoingShift = 1.5;
161
162 SkScalar fAnimRadius;
163 SkScalar fAnimBlurRadius;
164
bsalomon29965532016-05-16 09:36:44 -0700165 SkRandom fRandom;
166
John Stiles7571f9e2020-09-02 22:42:33 -0400167 using INHERITED = skiagm::GM;
bsalomonc67bb572016-05-13 13:48:48 -0700168};
169
170DEF_GM(return new BlurCircles2GM();)