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 19enum ColorType { 20 kConstantOpaque_ColorType, 21 kConstantTransparent_ColorType, 22 kChangingOpaque_ColorType, 23 kChangingTransparent_ColorType, 24 kAlternatingOpaqueAndTransparent_ColorType, 25}; 26 27static 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 41static 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 60static 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 68class RotRectBench: public Benchmark { 69public: 70 RotRectBench(bool aa, ColorType ct, SkXfermode::Mode mode) 71 : fAA(aa) 72 , fColorType(ct) 73 , fMode(mode) { 74 this->makeName(); 75 } 76 77protected: 78 virtual const char* onGetName() SK_OVERRIDE { return fName.c_str(); } 79 80 virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE { 81 SkPaint paint; 82 paint.setAntiAlias(fAA); 83 paint.setXfermodeMode(fMode); 84 SkColor color = start_color(fColorType); 85 86 int w = canvas->getBaseLayerSize().width(); 87 int h = canvas->getBaseLayerSize().height(); 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 122private: 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. 160DEF_BENCH(return new RotRectBench(true, kConstantOpaque_ColorType, SkXfermode::kSrcOver_Mode);) 161DEF_BENCH(return new RotRectBench(true, kConstantTransparent_ColorType, SkXfermode::kSrcOver_Mode);) 162DEF_BENCH(return new RotRectBench(true, kChangingOpaque_ColorType, SkXfermode::kSrcOver_Mode);) 163DEF_BENCH(return new RotRectBench(true, kChangingTransparent_ColorType, SkXfermode::kSrcOver_Mode);) 164DEF_BENCH(return new RotRectBench(true, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrcOver_Mode);) 165 166DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType, SkXfermode::kSrcOver_Mode);) 167DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType, SkXfermode::kSrcOver_Mode);) 168DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType, SkXfermode::kSrcOver_Mode);) 169DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType, SkXfermode::kSrcOver_Mode);) 170DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrcOver_Mode);) 171 172DEF_BENCH(return new RotRectBench(true, kConstantOpaque_ColorType, SkXfermode::kSrc_Mode);) 173DEF_BENCH(return new RotRectBench(true, kConstantTransparent_ColorType, SkXfermode::kSrc_Mode);) 174DEF_BENCH(return new RotRectBench(true, kChangingOpaque_ColorType, SkXfermode::kSrc_Mode);) 175DEF_BENCH(return new RotRectBench(true, kChangingTransparent_ColorType, SkXfermode::kSrc_Mode);) 176DEF_BENCH(return new RotRectBench(true, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrc_Mode);) 177 178DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType, SkXfermode::kSrc_Mode);) 179DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType, SkXfermode::kSrc_Mode);) 180DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType, SkXfermode::kSrc_Mode);) 181DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType, SkXfermode::kSrc_Mode);) 182DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrc_Mode);) 183 184DEF_BENCH(return new RotRectBench(true, kConstantOpaque_ColorType, SkXfermode::kDarken_Mode);) 185DEF_BENCH(return new RotRectBench(true, kConstantTransparent_ColorType, SkXfermode::kDarken_Mode);) 186DEF_BENCH(return new RotRectBench(true, kChangingOpaque_ColorType, SkXfermode::kDarken_Mode);) 187DEF_BENCH(return new RotRectBench(true, kChangingTransparent_ColorType, SkXfermode::kDarken_Mode);) 188DEF_BENCH(return new RotRectBench(true, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kDarken_Mode);) 189 190DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType, SkXfermode::kDarken_Mode);) 191DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType, SkXfermode::kDarken_Mode);) 192DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType, SkXfermode::kDarken_Mode);) 193DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType, SkXfermode::kDarken_Mode);) 194DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kDarken_Mode);) 195