1 /* 2 * Copyright 2013 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 #include "SkRandom.h" 12 #include "SkShader.h" 13 #include "SkString.h" 14 15 #if SK_SUPPORT_GPU 16 #include "GrDrawTargetCaps.h" 17 #include "GrTest.h" 18 #endif 19 20 enum Flags { 21 kBig_Flag = 1 << 0, 22 kAA_Flag = 1 << 1 23 }; 24 25 #define FLAGS00 Flags(0) 26 #define FLAGS01 Flags(kBig_Flag) 27 #define FLAGS10 Flags(kAA_Flag) 28 #define FLAGS11 Flags(kBig_Flag | kAA_Flag) 29 30 static const int points[] = { 31 10, 10, 15, 5, 20, 20, 32 30, 5, 25, 20, 15, 12, 33 21, 21, 30, 30, 12, 4, 34 32, 28, 20, 18, 12, 10 35 }; 36 37 static const int kMaxPathSize = 10; 38 39 class HairlinePathBench : public Benchmark { 40 public: HairlinePathBench(Flags flags)41 HairlinePathBench(Flags flags) : fFlags(flags) { 42 fPaint.setStyle(SkPaint::kStroke_Style); 43 fPaint.setStrokeWidth(SkIntToScalar(0)); 44 } 45 46 virtual void appendName(SkString*) = 0; 47 virtual void makePath(SkPath*) = 0; 48 49 protected: onGetName()50 virtual const char* onGetName() SK_OVERRIDE { 51 fName.printf("path_hairline_%s_%s_", 52 fFlags & kBig_Flag ? "big" : "small", 53 fFlags & kAA_Flag ? "AA" : "noAA"); 54 this->appendName(&fName); 55 return fName.c_str(); 56 } 57 onDraw(const int loops,SkCanvas * canvas)58 virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE { 59 SkPaint paint(fPaint); 60 this->setupPaint(&paint); 61 62 paint.setAntiAlias(fFlags & kAA_Flag ? true : false); 63 64 SkPath path; 65 this->makePath(&path); 66 if (fFlags & kBig_Flag) { 67 SkMatrix m; 68 m.setScale(SkIntToScalar(3), SkIntToScalar(3)); 69 path.transform(m); 70 } 71 72 for (int i = 0; i < loops; i++) { 73 canvas->drawPath(path, paint); 74 } 75 } 76 77 private: 78 SkPaint fPaint; 79 SkString fName; 80 Flags fFlags; 81 typedef Benchmark INHERITED; 82 }; 83 84 class LinePathBench : public HairlinePathBench { 85 public: LinePathBench(Flags flags)86 LinePathBench(Flags flags) : INHERITED(flags) {} 87 appendName(SkString * name)88 virtual void appendName(SkString* name) SK_OVERRIDE { 89 name->append("line"); 90 } makePath(SkPath * path)91 virtual void makePath(SkPath* path) SK_OVERRIDE { 92 SkRandom rand; 93 int size = SK_ARRAY_COUNT(points); 94 int hSize = size / 2; 95 for (int i = 0; i < kMaxPathSize; ++i) { 96 int xTrans = 10 + 40 * (i%(kMaxPathSize/2)); 97 int yTrans = 0; 98 if (i > kMaxPathSize/2 - 1) { 99 yTrans = 40; 100 } 101 int base1 = 2 * rand.nextULessThan(hSize); 102 int base2 = 2 * rand.nextULessThan(hSize); 103 int base3 = 2 * rand.nextULessThan(hSize); 104 path->moveTo(SkIntToScalar(points[base1] + xTrans), 105 SkIntToScalar(points[base1+1] + yTrans)); 106 path->lineTo(SkIntToScalar(points[base2] + xTrans), 107 SkIntToScalar(points[base2+1] + yTrans)); 108 path->lineTo(SkIntToScalar(points[base3] + xTrans), 109 SkIntToScalar(points[base3+1] + yTrans)); 110 } 111 } 112 private: 113 typedef HairlinePathBench INHERITED; 114 }; 115 116 class QuadPathBench : public HairlinePathBench { 117 public: QuadPathBench(Flags flags)118 QuadPathBench(Flags flags) : INHERITED(flags) {} 119 appendName(SkString * name)120 virtual void appendName(SkString* name) SK_OVERRIDE { 121 name->append("quad"); 122 } makePath(SkPath * path)123 virtual void makePath(SkPath* path) SK_OVERRIDE { 124 SkRandom rand; 125 int size = SK_ARRAY_COUNT(points); 126 int hSize = size / 2; 127 for (int i = 0; i < kMaxPathSize; ++i) { 128 int xTrans = 10 + 40 * (i%(kMaxPathSize/2)); 129 int yTrans = 0; 130 if (i > kMaxPathSize/2 - 1) { 131 yTrans = 40; 132 } 133 int base1 = 2 * rand.nextULessThan(hSize); 134 int base2 = 2 * rand.nextULessThan(hSize); 135 int base3 = 2 * rand.nextULessThan(hSize); 136 path->moveTo(SkIntToScalar(points[base1] + xTrans), 137 SkIntToScalar(points[base1+1] + yTrans)); 138 path->quadTo(SkIntToScalar(points[base2] + xTrans), 139 SkIntToScalar(points[base2+1] + yTrans), 140 SkIntToScalar(points[base3] + xTrans), 141 SkIntToScalar(points[base3+1] + yTrans)); 142 } 143 } 144 private: 145 typedef HairlinePathBench INHERITED; 146 }; 147 148 class ConicPathBench : public HairlinePathBench { 149 public: ConicPathBench(Flags flags)150 ConicPathBench(Flags flags) : INHERITED(flags) {} 151 appendName(SkString * name)152 virtual void appendName(SkString* name) SK_OVERRIDE { 153 name->append("conic"); 154 } makePath(SkPath * path)155 virtual void makePath(SkPath* path) SK_OVERRIDE { 156 SkRandom rand; 157 SkRandom randWeight; 158 int size = SK_ARRAY_COUNT(points); 159 int hSize = size / 2; 160 for (int i = 0; i < kMaxPathSize; ++i) { 161 int xTrans = 10 + 40 * (i%(kMaxPathSize/2)); 162 int yTrans = 0; 163 if (i > kMaxPathSize/2 - 1) { 164 yTrans = 40; 165 } 166 int base1 = 2 * rand.nextULessThan(hSize); 167 int base2 = 2 * rand.nextULessThan(hSize); 168 int base3 = 2 * rand.nextULessThan(hSize); 169 float weight = randWeight.nextRangeF(0.0f, 2.0f); 170 path->moveTo(SkIntToScalar(points[base1] + xTrans), 171 SkIntToScalar(points[base1+1] + yTrans)); 172 path->conicTo(SkIntToScalar(points[base2] + xTrans), 173 SkIntToScalar(points[base2+1] + yTrans), 174 SkIntToScalar(points[base3] + xTrans), 175 SkIntToScalar(points[base3+1] + yTrans), 176 weight); 177 } 178 } 179 onDraw(const int loops,SkCanvas * canvas)180 virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE { 181 #if SK_SUPPORT_GPU 182 GrContext* context = canvas->getGrContext(); 183 // This is a workaround for skbug.com/2078. See also skbug.com/2033. 184 if (context) { 185 GrTestTarget tt; 186 context->getTestTarget(&tt); 187 if (tt.target()->caps()->pathRenderingSupport()) { 188 return; 189 } 190 } 191 #endif 192 INHERITED::onDraw(loops, canvas); 193 } 194 195 private: 196 typedef HairlinePathBench INHERITED; 197 }; 198 199 class CubicPathBench : public HairlinePathBench { 200 public: CubicPathBench(Flags flags)201 CubicPathBench(Flags flags) : INHERITED(flags) {} 202 appendName(SkString * name)203 virtual void appendName(SkString* name) SK_OVERRIDE { 204 name->append("cubic"); 205 } makePath(SkPath * path)206 virtual void makePath(SkPath* path) SK_OVERRIDE { 207 SkRandom rand; 208 int size = SK_ARRAY_COUNT(points); 209 int hSize = size / 2; 210 for (int i = 0; i < kMaxPathSize; ++i) { 211 int xTrans = 10 + 40 * (i%(kMaxPathSize/2)); 212 int yTrans = 0; 213 if (i > kMaxPathSize/2 - 1) { 214 yTrans = 40; 215 } 216 int base1 = 2 * rand.nextULessThan(hSize); 217 int base2 = 2 * rand.nextULessThan(hSize); 218 int base3 = 2 * rand.nextULessThan(hSize); 219 int base4 = 2 * rand.nextULessThan(hSize); 220 path->moveTo(SkIntToScalar(points[base1] + xTrans), 221 SkIntToScalar(points[base1+1] + yTrans)); 222 path->cubicTo(SkIntToScalar(points[base2] + xTrans), 223 SkIntToScalar(points[base2+1] + yTrans), 224 SkIntToScalar(points[base3] + xTrans), 225 SkIntToScalar(points[base3+1] + yTrans), 226 SkIntToScalar(points[base4] + xTrans), 227 SkIntToScalar(points[base4+1] + yTrans)); 228 } 229 } 230 private: 231 typedef HairlinePathBench INHERITED; 232 }; 233 234 // FLAG00 - no AA, small 235 // FLAG01 - no AA, small 236 // FLAG10 - AA, big 237 // FLAG11 - AA, big 238 239 DEF_BENCH( return new LinePathBench(FLAGS00); ) 240 DEF_BENCH( return new LinePathBench(FLAGS01); ) 241 DEF_BENCH( return new LinePathBench(FLAGS10); ) 242 DEF_BENCH( return new LinePathBench(FLAGS11); ) 243 244 DEF_BENCH( return new QuadPathBench(FLAGS00); ) 245 DEF_BENCH( return new QuadPathBench(FLAGS01); ) 246 DEF_BENCH( return new QuadPathBench(FLAGS10); ) 247 DEF_BENCH( return new QuadPathBench(FLAGS11); ) 248 249 // Don't have default path renderer for conics yet on GPU, so must use AA 250 // DEF_BENCH( return new ConicPathBench(FLAGS00); ) 251 // DEF_BENCH( return new ConicPathBench(FLAGS01); ) 252 DEF_BENCH( return new ConicPathBench(FLAGS10); ) 253 DEF_BENCH( return new ConicPathBench(FLAGS11); ) 254 255 DEF_BENCH( return new CubicPathBench(FLAGS00); ) 256 DEF_BENCH( return new CubicPathBench(FLAGS01); ) 257 DEF_BENCH( return new CubicPathBench(FLAGS10); ) 258 DEF_BENCH( return new CubicPathBench(FLAGS11); ) 259