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