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