1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* Copyright 2016 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*/ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gm.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAnimTimer.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBlurMask.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBlurMaskFilter.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaint.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPath.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRandom.h" 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * In GM mode this draws an array of circles with different radii and different blur radii. Below 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * each circle an almost-circle path is drawn with the same blur filter for comparison. 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * In Sample mode this draws a single circle and almost-circle with animating radius and blur 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * radius. 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Bench mode draws the same as GM mode but without the comparison almost-circle paths. It also 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * slightly perturbs the blur and circle radii to stress caching of blurred profiles in GPU mode. 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass BlurCircles2GM : public skiagm::GM { 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot BlurCircles2GM() { 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAnimRadius = SkAnimTimer::PingPong(0, kRadiusPingPoingPeriod, kRadiusPingPoingShift, 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kMinRadius, kMaxRadius); 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAnimBlurRadius = SkAnimTimer::PingPong(0, kBlurRadiusPingPoingPeriod, 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kBlurRadiusPingPoingShift, kMinBlurRadius, 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kMaxBlurRadius); 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected: 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool runAsBench() const override { return true; } 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkString onShortName() override { return SkString("blurcircles2"); } 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkISize onISize() override { 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkISize::Make(730, 1350); 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void onDraw(SkCanvas* canvas) override { 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr SkScalar kMaxR = kMaxRadius + kMaxBlurRadius; 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto almostCircleMaker = [] (SkScalar radius, SkPath* dst) { 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dst->reset(); 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dst->addArc(SkRect::MakeXYWH(-radius, -radius, 2 * radius, 2 * radius), 0, 355); 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dst->setIsVolatile(true); 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dst->close(); 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto blurMaker = [] (SkScalar radius) ->sk_sp<SkMaskFilter> { 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlurMask::ConvertRadiusToSigma(radius), 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlurMaskFilter::kHighQuality_BlurFlag); 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint paint; 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setColor(SK_ColorBLACK); 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->getMode() == kSample_Mode) { 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setMaskFilter(blurMaker(fAnimBlurRadius)); 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkISize size = canvas->getBaseLayerSize(); 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath almostCircle; 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot almostCircleMaker(fAnimRadius, &almostCircle); 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->save(); 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(size.fWidth / 2.f, size.fHeight / 4.f); 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->drawCircle(0, 0, fAnimRadius, paint); 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(0, 2 * kMaxR); 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->drawPath(almostCircle, paint); 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool benchMode = this->getMode() == kBench_Mode; 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->save(); 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr SkScalar kPad = 5; 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr SkScalar kRadiusSteps = 5; 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr SkScalar kBlurRadiusSteps = 5; 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(kPad + kMinRadius + kMaxBlurRadius, 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kPad + kMinRadius + kMaxBlurRadius); 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr SkScalar kDeltaRadius = (kMaxRadius - kMinRadius) / kRadiusSteps; 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr SkScalar kDeltaBlurRadius = (kMaxBlurRadius - kMinBlurRadius) / 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kBlurRadiusSteps; 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar lineWidth = 0; 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!benchMode) { 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int r = 0; r < kRadiusSteps - 1; ++r) { 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar radius = r * kDeltaRadius + kMinRadius; 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lineWidth += 2 * (radius + kMaxBlurRadius) + kPad; 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int br = 0; br < kBlurRadiusSteps; ++br) { 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar blurRadius = br * kDeltaBlurRadius + kMinBlurRadius; 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (benchMode) { 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot blurRadius += fRandom.nextSScalar1() * kDeltaBlurRadius; 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar maxRowR = blurRadius + kMaxRadius; 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setMaskFilter(blurMaker(blurRadius)); 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->save(); 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int r = 0; r < kRadiusSteps; ++r) { 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar radius = r * kDeltaRadius + kMinRadius; 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (benchMode) { 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot radius += fRandom.nextSScalar1() * kDeltaRadius; 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath almostCircle; 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!benchMode) { 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot almostCircleMaker(radius, &almostCircle); 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->save(); 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->drawCircle(0, 0, radius, paint); 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(0, 2 * maxRowR + kPad); 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!benchMode) { 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->drawPath(almostCircle, paint); 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar maxColR = radius + kMaxBlurRadius; 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(maxColR * 2 + kPad, 0); 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!benchMode) { 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint blackPaint; 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot blackPaint.setColor(SK_ColorBLACK); 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar lineY = 3 * maxRowR + 1.5f * kPad; 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (br != kBlurRadiusSteps - 1) { 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->drawLine(0, lineY, lineWidth, lineY, blackPaint); 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(0, maxRowR * 4 + 2 * kPad); 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool onAnimate(const SkAnimTimer& timer) override { 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAnimRadius = timer.pingPong(kRadiusPingPoingPeriod, kRadiusPingPoingShift, kMinRadius, 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kMaxRadius); 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAnimBlurRadius = timer.pingPong(kBlurRadiusPingPoingPeriod, kBlurRadiusPingPoingShift, 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kMinBlurRadius, kMaxBlurRadius); 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr SkScalar kMinRadius = 15; 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr SkScalar kMaxRadius = 45; 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr SkScalar kRadiusPingPoingPeriod = 8; 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr SkScalar kRadiusPingPoingShift = 3; 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr SkScalar kMinBlurRadius = 5; 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr SkScalar kMaxBlurRadius = 45; 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr SkScalar kBlurRadiusPingPoingPeriod = 3; 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr SkScalar kBlurRadiusPingPoingShift = 1.5; 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar fAnimRadius; 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar fAnimBlurRadius; 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRandom fRandom; 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot typedef skiagm::GM INHERITED; 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM(return new BlurCircles2GM();) 165