blurcircles2.cpp 6.8 KB

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