RotatedRectBench.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * Copyright 2014 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 "bench/Benchmark.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkPaint.h"
  10. #include "include/effects/SkGradientShader.h"
  11. #include "src/core/SkBlendModePriv.h"
  12. #include <ctype.h>
  13. /** This benchmark tests rendering rotated rectangles. It can optionally apply AA and/or change the
  14. paint color between each rect in different ways using the ColorType enum. The xfermode used can
  15. be specified as well.
  16. */
  17. enum ColorType {
  18. kConstantOpaque_ColorType,
  19. kConstantTransparent_ColorType,
  20. kChangingOpaque_ColorType,
  21. kChangingTransparent_ColorType,
  22. kAlternatingOpaqueAndTransparent_ColorType,
  23. kShaderOpaque_ColorType
  24. };
  25. static inline SkColor start_color(ColorType ct) {
  26. switch (ct) {
  27. case kConstantOpaque_ColorType:
  28. case kChangingOpaque_ColorType:
  29. case kAlternatingOpaqueAndTransparent_ColorType:
  30. return 0xFFA07040;
  31. case kConstantTransparent_ColorType:
  32. case kChangingTransparent_ColorType:
  33. return 0x80A07040;
  34. case kShaderOpaque_ColorType:
  35. return SK_ColorWHITE;
  36. }
  37. SK_ABORT("Shouldn't reach here.");
  38. return 0;
  39. }
  40. static inline SkColor advance_color(SkColor old, ColorType ct, int step) {
  41. if (kAlternatingOpaqueAndTransparent_ColorType == ct) {
  42. ct = (step & 0x1) ? kChangingOpaque_ColorType : kChangingTransparent_ColorType ;
  43. }
  44. switch (ct) {
  45. case kConstantOpaque_ColorType:
  46. case kConstantTransparent_ColorType:
  47. case kShaderOpaque_ColorType:
  48. return old;
  49. case kChangingOpaque_ColorType:
  50. return 0xFF000000 | (old + 0x00010307);
  51. case kChangingTransparent_ColorType:
  52. return (0x00FFFFFF & (old + 0x00010307)) | 0x80000000;
  53. case kAlternatingOpaqueAndTransparent_ColorType:
  54. SK_ABORT("Can't get here");
  55. }
  56. SK_ABORT("Shouldn't reach here.");
  57. return 0;
  58. }
  59. static SkString to_lower(const char* str) {
  60. SkString lower(str);
  61. for (size_t i = 0; i < lower.size(); i++) {
  62. lower[i] = tolower(lower[i]);
  63. }
  64. return lower;
  65. }
  66. class RotRectBench: public Benchmark {
  67. public:
  68. RotRectBench(bool aa, ColorType ct, SkBlendMode mode, bool perspective = false)
  69. : fAA(aa)
  70. , fPerspective(perspective)
  71. , fColorType(ct)
  72. , fMode(mode) {
  73. this->makeName();
  74. }
  75. protected:
  76. const char* onGetName() override { return fName.c_str(); }
  77. void onDraw(int loops, SkCanvas* canvas) override {
  78. SkPaint paint;
  79. paint.setAntiAlias(fAA);
  80. paint.setBlendMode(fMode);
  81. SkColor color = start_color(fColorType);
  82. int w = this->getSize().x();
  83. int h = this->getSize().y();
  84. static const SkScalar kRectW = 25.1f;
  85. static const SkScalar kRectH = 25.9f;
  86. if (fColorType == kShaderOpaque_ColorType) {
  87. // The only requirement for the shader is that it requires local coordinates
  88. SkPoint pts[2] = { {0.0f, 0.0f}, {kRectW, kRectH} };
  89. SkColor colors[] = { color, SK_ColorBLUE };
  90. paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
  91. SkTileMode::kClamp));
  92. }
  93. SkMatrix rotate;
  94. // This value was chosen so that we frequently hit the axis-aligned case.
  95. rotate.setRotate(30.f, kRectW / 2, kRectH / 2);
  96. SkMatrix m = rotate;
  97. SkScalar tx = 0, ty = 0;
  98. if (fPerspective) {
  99. // Apply some fixed perspective to change how ops may draw the rects
  100. SkMatrix perspective;
  101. perspective.setIdentity();
  102. perspective.setPerspX(1e-4f);
  103. perspective.setPerspY(1e-3f);
  104. perspective.setSkewX(0.1f);
  105. canvas->concat(perspective);
  106. }
  107. for (int i = 0; i < loops; ++i) {
  108. canvas->save();
  109. canvas->translate(tx, ty);
  110. canvas->concat(m);
  111. paint.setColor(color);
  112. color = advance_color(color, fColorType, i);
  113. canvas->drawRect(SkRect::MakeWH(kRectW, kRectH), paint);
  114. canvas->restore();
  115. tx += kRectW + 2;
  116. if (tx > w) {
  117. tx = 0;
  118. ty += kRectH + 2;
  119. if (ty > h) {
  120. ty = 0;
  121. }
  122. }
  123. m.postConcat(rotate);
  124. }
  125. }
  126. private:
  127. void makeName() {
  128. fName = "rotated_rects";
  129. if (fAA) {
  130. fName.append("_aa");
  131. } else {
  132. fName.append("_bw");
  133. }
  134. if (fPerspective) {
  135. fName.append("_persp");
  136. }
  137. switch (fColorType) {
  138. case kConstantOpaque_ColorType:
  139. fName.append("_same_opaque");
  140. break;
  141. case kConstantTransparent_ColorType:
  142. fName.append("_same_transparent");
  143. break;
  144. case kChangingOpaque_ColorType:
  145. fName.append("_changing_opaque");
  146. break;
  147. case kChangingTransparent_ColorType:
  148. fName.append("_changing_transparent");
  149. break;
  150. case kAlternatingOpaqueAndTransparent_ColorType:
  151. fName.append("_alternating_transparent_and_opaque");
  152. break;
  153. case kShaderOpaque_ColorType:
  154. fName.append("_shader_opaque");
  155. break;
  156. }
  157. fName.appendf("_%s", to_lower(SkBlendMode_Name(fMode)).c_str());
  158. }
  159. bool fAA;
  160. bool fPerspective;
  161. ColorType fColorType;
  162. SkBlendMode fMode;
  163. SkString fName;
  164. typedef Benchmark INHERITED;
  165. };
  166. #define DEF_FOR_COLOR_TYPES(aa, blend) \
  167. DEF_BENCH(return new RotRectBench(aa, kConstantOpaque_ColorType, blend);) \
  168. DEF_BENCH(return new RotRectBench(aa, kConstantTransparent_ColorType, blend);) \
  169. DEF_BENCH(return new RotRectBench(aa, kChangingOpaque_ColorType, blend);) \
  170. DEF_BENCH(return new RotRectBench(aa, kChangingTransparent_ColorType, blend);) \
  171. DEF_BENCH(return new RotRectBench(aa, kAlternatingOpaqueAndTransparent_ColorType, blend);) \
  172. DEF_BENCH(return new RotRectBench(aa, kShaderOpaque_ColorType, blend);)
  173. #define DEF_FOR_AA_MODES(blend) \
  174. DEF_FOR_COLOR_TYPES(true, blend) \
  175. DEF_FOR_COLOR_TYPES(false, blend)
  176. // Choose kSrcOver because it always allows coverage and alpha to be conflated. kSrc only allows
  177. // conflation when opaque, and kDarken because it isn't possilbe with standard GL blending.
  178. DEF_FOR_AA_MODES(SkBlendMode::kSrcOver)
  179. DEF_FOR_AA_MODES(SkBlendMode::kSrc)
  180. DEF_FOR_AA_MODES(SkBlendMode::kDarken)
  181. // Only do a limited run of perspective tests
  182. #define DEF_FOR_PERSP_MODES(aa) \
  183. DEF_BENCH(return new RotRectBench(aa, kConstantOpaque_ColorType, SkBlendMode::kSrcOver, true);)\
  184. DEF_BENCH(return new RotRectBench(aa, kShaderOpaque_ColorType, SkBlendMode::kSrcOver, true);)
  185. DEF_FOR_PERSP_MODES(true)
  186. DEF_FOR_PERSP_MODES(false)