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