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/core/SkString.h" 11 #include "include/core/SkVertices.h" 12 #include "include/effects/SkGradientShader.h" 13 #include "src/utils/SkPatchUtils.h" 14 15 /** 16 * This bench measures the rendering time of the call SkCanvas::drawPatch with different types of 17 * input patches (regular case, with loops, a square, with a big difference between "parallel" 18 * sides). This bench also tests the different combination of optional parameters for the function 19 * (passing texture coordinates and colors, only textures coordinates, only colors or none). 20 * Finally, it applies a scale to test if the size affects the rendering time. 21 */ 22 23 class PatchBench : public Benchmark { 24 25 public: 26 27 enum VertexMode { 28 kNone_VertexMode, 29 kColors_VertexMode, 30 kTexCoords_VertexMode, 31 kBoth_VertexMode 32 }; 33 PatchBench(SkPoint scale,VertexMode vertexMode)34 PatchBench(SkPoint scale, VertexMode vertexMode) 35 : fScale(scale) 36 , fVertexMode(vertexMode) { } 37 38 // to add name of specific class override this method appendName(SkString * name)39 virtual void appendName(SkString* name) { 40 name->append("normal"); 41 } 42 43 // to make other type of patches override this method setCubics()44 virtual void setCubics() { 45 const SkPoint points[SkPatchUtils::kNumCtrlPts] = { 46 //top points 47 {100,100},{150,50},{250,150}, {300,100}, 48 //right points 49 {350, 150},{250,200}, 50 //bottom points 51 {300,300},{250,250},{150,350},{100,300}, 52 //left points 53 {50,250},{150,50} 54 }; 55 memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); 56 } 57 setColors()58 virtual void setColors() { 59 const SkColor colors[SkPatchUtils::kNumCorners] = { 60 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN 61 }; 62 memcpy(fColors, colors, SkPatchUtils::kNumCorners * sizeof(SkColor)); 63 } 64 setTexCoords()65 virtual void setTexCoords() { 66 const SkPoint texCoords[SkPatchUtils::kNumCorners] = { 67 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f,1.0f}, {0.0f, 1.0f} 68 }; 69 memcpy(fTexCoords, texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint)); 70 } 71 72 // override this method to change the shader createShader()73 virtual sk_sp<SkShader> createShader() { 74 const SkColor colors[] = { 75 SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE, 76 SK_ColorMAGENTA, SK_ColorBLUE, SK_ColorYELLOW, 77 }; 78 const SkPoint pts[] = { { 200.f / 4.f, 0.f }, { 3.f * 200.f / 4, 200.f } }; 79 80 return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors), 81 SkTileMode::kMirror); 82 } 83 84 protected: onGetName()85 const char* onGetName() override { 86 SkString vertexMode; 87 switch (fVertexMode) { 88 case kNone_VertexMode: 89 vertexMode.set("meshlines"); 90 break; 91 case kColors_VertexMode: 92 vertexMode.set("colors"); 93 break; 94 case kTexCoords_VertexMode: 95 vertexMode.set("texs"); 96 break; 97 case kBoth_VertexMode: 98 vertexMode.set("colors_texs"); 99 break; 100 default: 101 break; 102 } 103 SkString type; 104 this->appendName(&type); 105 fName.printf("patch_%s_%s_%fx%f", type.c_str(), vertexMode.c_str(), 106 fScale.x(), fScale.y()); 107 return fName.c_str(); 108 } 109 onDelayedSetup()110 void onDelayedSetup() override { 111 this->setCubics(); 112 this->setColors(); 113 this->setTexCoords(); 114 this->setupPaint(&fPaint); 115 switch (fVertexMode) { 116 case kTexCoords_VertexMode: 117 case kBoth_VertexMode: 118 fPaint.setShader(this->createShader()); 119 break; 120 default: 121 fPaint.setShader(nullptr); 122 break; 123 } 124 } 125 onDraw(int loops,SkCanvas * canvas)126 void onDraw(int loops, SkCanvas* canvas) override { 127 canvas->scale(fScale.x(), fScale.y()); 128 for (int i = 0; i < loops; i++) { 129 switch (fVertexMode) { 130 case kNone_VertexMode: 131 canvas->drawPatch(fCubics, nullptr, nullptr, fPaint); 132 break; 133 case kColors_VertexMode: 134 canvas->drawPatch(fCubics, fColors, nullptr, fPaint); 135 break; 136 case kTexCoords_VertexMode: 137 canvas->drawPatch(fCubics, nullptr, fTexCoords, fPaint); 138 break; 139 case kBoth_VertexMode: 140 canvas->drawPatch(fCubics, fColors, fTexCoords, fPaint); 141 break; 142 default: 143 break; 144 } 145 } 146 } 147 148 SkPaint fPaint; 149 SkString fName; 150 SkVector fScale; 151 SkPoint fCubics[12]; 152 SkPoint fTexCoords[4]; 153 SkColor fColors[4]; 154 VertexMode fVertexMode; 155 156 using INHERITED = Benchmark; 157 }; 158 159 class SquarePatchBench : public PatchBench { 160 public: SquarePatchBench(SkPoint scale,VertexMode vertexMode)161 SquarePatchBench(SkPoint scale, VertexMode vertexMode) 162 : INHERITED(scale, vertexMode) { } 163 appendName(SkString * name)164 void appendName(SkString* name) override { 165 name->append("square"); 166 } 167 setCubics()168 void setCubics() override { 169 const SkPoint points[SkPatchUtils::kNumCtrlPts] = { 170 //top points 171 {100,100},{150,100},{250,100}, {300,100}, 172 //right points 173 {300, 150},{300,250}, 174 //bottom points 175 {300,300},{250,300},{150,300},{100,300}, 176 //left points 177 {100,250},{100,150} 178 }; 179 memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); 180 } 181 private: 182 using INHERITED = PatchBench; 183 }; 184 185 class LODDiffPatchBench : public PatchBench { 186 public: LODDiffPatchBench(SkPoint scale,VertexMode vertexMode)187 LODDiffPatchBench(SkPoint scale, VertexMode vertexMode) 188 : INHERITED(scale, vertexMode) { } 189 appendName(SkString * name)190 void appendName(SkString* name) override { 191 name->append("LOD_Diff"); 192 } 193 setCubics()194 void setCubics() override { 195 const SkPoint points[SkPatchUtils::kNumCtrlPts] = { 196 //top points 197 {100,175},{150,100},{250,100}, {300,0}, 198 //right points 199 {300, 150},{300,250}, 200 //bottom points 201 {300,400},{250,300},{150,300},{100,225}, 202 //left points 203 {100,215},{100,185} 204 }; 205 memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); 206 } 207 private: 208 using INHERITED = PatchBench; 209 }; 210 211 class LoopPatchBench : public PatchBench { 212 public: LoopPatchBench(SkPoint scale,VertexMode vertexMode)213 LoopPatchBench(SkPoint scale, VertexMode vertexMode) 214 : INHERITED(scale, vertexMode) { } 215 appendName(SkString * name)216 void appendName(SkString* name) override { 217 name->append("loop"); 218 } 219 setCubics()220 void setCubics() override { 221 const SkPoint points[SkPatchUtils::kNumCtrlPts] = { 222 //top points 223 {100,100},{300,200},{100,200}, {300,100}, 224 //right points 225 {380, 400},{380,0}, 226 //bottom points 227 {300,300},{250,250},{30,200},{100,300}, 228 //left points 229 {140,325},{150,150} 230 }; 231 memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); 232 } 233 private: 234 using INHERITED = PatchBench; 235 }; 236 237 /////////////////////////////////////////////////////////////////////////////// 238 239 DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kNone_VertexMode); ) 240 DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kColors_VertexMode); ) 241 DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kTexCoords_VertexMode); ) 242 DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kBoth_VertexMode); ) 243 DEF_BENCH( return new PatchBench(SkVector::Make(1.f, 1.0f), PatchBench::kNone_VertexMode); ) 244 DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kColors_VertexMode); ) 245 DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kTexCoords_VertexMode); ) 246 DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kBoth_VertexMode); ) 247 DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kNone_VertexMode); ) 248 DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kColors_VertexMode); ) 249 DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kTexCoords_VertexMode); ) 250 DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kBoth_VertexMode); ) 251 252 DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f), 253 PatchBench::kNone_VertexMode); ) 254 DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f), 255 PatchBench::kColors_VertexMode); ) 256 DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f), 257 PatchBench::kTexCoords_VertexMode); ) 258 DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f), 259 PatchBench::kBoth_VertexMode); ) 260 DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.f, 1.0f), 261 PatchBench::kNone_VertexMode); ) 262 DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f), 263 PatchBench::kColors_VertexMode); ) 264 DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f), 265 PatchBench::kTexCoords_VertexMode); ) 266 DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f), 267 PatchBench::kBoth_VertexMode); ) 268 DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f), 269 PatchBench::kNone_VertexMode); ) 270 DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f), 271 PatchBench::kColors_VertexMode); ) 272 DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f), 273 PatchBench::kTexCoords_VertexMode); ) 274 DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f), 275 PatchBench::kBoth_VertexMode); ) 276 277 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f), 278 PatchBench::kNone_VertexMode); ) 279 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f), 280 PatchBench::kColors_VertexMode); ) 281 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f), 282 PatchBench::kTexCoords_VertexMode); ) 283 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f), 284 PatchBench::kBoth_VertexMode); ) 285 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.f, 1.0f), 286 PatchBench::kNone_VertexMode); ) 287 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f), 288 PatchBench::kColors_VertexMode); ) 289 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f), 290 PatchBench::kTexCoords_VertexMode); ) 291 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f), 292 PatchBench::kBoth_VertexMode); ) 293 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f), 294 PatchBench::kNone_VertexMode); ) 295 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f), 296 PatchBench::kColors_VertexMode); ) 297 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f), 298 PatchBench::kTexCoords_VertexMode); ) 299 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f), 300 PatchBench::kBoth_VertexMode); ) 301 302 DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f), 303 PatchBench::kNone_VertexMode); ) 304 DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f), 305 PatchBench::kColors_VertexMode); ) 306 DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f), 307 PatchBench::kTexCoords_VertexMode); ) 308 DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f), 309 PatchBench::kBoth_VertexMode); ) 310 DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.f, 1.0f), 311 PatchBench::kNone_VertexMode); ) 312 DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f), 313 PatchBench::kColors_VertexMode); ) 314 DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f), 315 PatchBench::kTexCoords_VertexMode); ) 316 DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f), 317 PatchBench::kBoth_VertexMode); ) 318 DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f), 319 PatchBench::kNone_VertexMode); ) 320 DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f), 321 PatchBench::kColors_VertexMode); ) 322 DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f), 323 PatchBench::kTexCoords_VertexMode); ) 324 DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f), 325 PatchBench::kBoth_VertexMode); ) 326 327 ////////////////////////////////////////////// 328 #include "src/utils/SkPatchUtils.h" 329 330 class PatchUtilsBench : public Benchmark { 331 SkString fName; 332 const bool fLinearInterp; 333 public: PatchUtilsBench(bool linearInterp)334 PatchUtilsBench(bool linearInterp) : fLinearInterp(linearInterp) { 335 fName.printf("patchutils_%s", linearInterp ? "linear" : "legacy"); 336 } 337 onGetName()338 const char* onGetName() override { return fName.c_str(); } 339 isSuitableFor(Backend backend)340 bool isSuitableFor(Backend backend) override { 341 return backend == kNonRendering_Backend; 342 } 343 onDraw(int loops,SkCanvas *)344 void onDraw(int loops, SkCanvas*) override { 345 const SkColor colors[] = { 0xFF000000, 0xFF00FF00, 0xFF0000FF, 0xFFFF0000 }; 346 const SkPoint pts[] = { 347 { 0, 0 }, { 10, 0 }, { 20, 0 }, { 30, 0 }, 348 { 30,10}, { 30,20 }, { 30,30 }, { 20,30 }, 349 { 10,30}, { 0, 30 }, { 0, 20 }, { 0, 10 }, 350 }; 351 const SkPoint tex[] = { 352 { 0, 0 }, { 10, 0 }, { 10, 10 }, { 0, 10 }, 353 }; 354 355 auto cs = fLinearInterp ? SkColorSpace::MakeSRGBLinear() : nullptr; 356 for (int i = 0; i < 100*loops; ++i) { 357 SkPatchUtils::MakeVertices(pts, colors, tex, 20, 20, cs.get()); 358 } 359 } 360 }; 361 DEF_BENCH( return new PatchUtilsBench(false); ) 362 DEF_BENCH( return new PatchUtilsBench(true); ) 363