PathBench.cpp revision 9bee33afbeca29f531c8455513b925f6e93da633
1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8#include "SkBenchmark.h" 9#include "SkBitmap.h" 10#include "SkCanvas.h" 11#include "SkColorPriv.h" 12#include "SkPaint.h" 13#include "SkRandom.h" 14#include "SkShader.h" 15#include "SkString.h" 16#include "SkTArray.h" 17 18 19enum Flags { 20 kStroke_Flag = 1 << 0, 21 kBig_Flag = 1 << 1 22}; 23 24#define FLAGS00 Flags(0) 25#define FLAGS01 Flags(kStroke_Flag) 26#define FLAGS10 Flags(kBig_Flag) 27#define FLAGS11 Flags(kStroke_Flag | kBig_Flag) 28 29class PathBench : public SkBenchmark { 30 SkPaint fPaint; 31 SkString fName; 32 Flags fFlags; 33 enum { N = SkBENCHLOOP(1000) }; 34public: 35 PathBench(void* param, Flags flags) : INHERITED(param), fFlags(flags) { 36 fPaint.setStyle(flags & kStroke_Flag ? SkPaint::kStroke_Style : 37 SkPaint::kFill_Style); 38 fPaint.setStrokeWidth(SkIntToScalar(5)); 39 fPaint.setStrokeJoin(SkPaint::kBevel_Join); 40 } 41 42 virtual void appendName(SkString*) = 0; 43 virtual void makePath(SkPath*) = 0; 44 virtual int complexity() { return 0; } 45 46protected: 47 virtual const char* onGetName() SK_OVERRIDE { 48 fName.printf("path_%s_%s_", 49 fFlags & kStroke_Flag ? "stroke" : "fill", 50 fFlags & kBig_Flag ? "big" : "small"); 51 this->appendName(&fName); 52 return fName.c_str(); 53 } 54 55 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 56 SkPaint paint(fPaint); 57 this->setupPaint(&paint); 58 59 SkPath path; 60 this->makePath(&path); 61 if (fFlags & kBig_Flag) { 62 SkMatrix m; 63 m.setScale(SkIntToScalar(10), SkIntToScalar(10)); 64 path.transform(m); 65 } 66 67 int count = N; 68 if (fFlags & kBig_Flag) { 69 count >>= 2; 70 } 71 count >>= (3 * complexity()); 72 73 for (int i = 0; i < count; i++) { 74 canvas->drawPath(path, paint); 75 } 76 } 77 78private: 79 typedef SkBenchmark INHERITED; 80}; 81 82class TrianglePathBench : public PathBench { 83public: 84 TrianglePathBench(void* param, Flags flags) : INHERITED(param, flags) {} 85 86 virtual void appendName(SkString* name) SK_OVERRIDE { 87 name->append("triangle"); 88 } 89 virtual void makePath(SkPath* path) SK_OVERRIDE { 90 static const int gCoord[] = { 91 10, 10, 15, 5, 20, 20 92 }; 93 path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1])); 94 path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3])); 95 path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5])); 96 path->close(); 97 } 98private: 99 typedef PathBench INHERITED; 100}; 101 102class RectPathBench : public PathBench { 103public: 104 RectPathBench(void* param, Flags flags) : INHERITED(param, flags) {} 105 106 virtual void appendName(SkString* name) SK_OVERRIDE { 107 name->append("rect"); 108 } 109 virtual void makePath(SkPath* path) SK_OVERRIDE { 110 SkRect r = { 10, 10, 20, 20 }; 111 path->addRect(r); 112 } 113private: 114 typedef PathBench INHERITED; 115}; 116 117class OvalPathBench : public PathBench { 118public: 119 OvalPathBench(void* param, Flags flags) : INHERITED(param, flags) {} 120 121 virtual void appendName(SkString* name) SK_OVERRIDE { 122 name->append("oval"); 123 } 124 virtual void makePath(SkPath* path) SK_OVERRIDE { 125 SkRect r = { 10, 10, 20, 20 }; 126 path->addOval(r); 127 } 128private: 129 typedef PathBench INHERITED; 130}; 131 132class CirclePathBench: public PathBench { 133public: 134 CirclePathBench(void* param, Flags flags) : INHERITED(param, flags) {} 135 136 virtual void appendName(SkString* name) SK_OVERRIDE { 137 name->append("circle"); 138 } 139 virtual void makePath(SkPath* path) SK_OVERRIDE { 140 path->addCircle(SkIntToScalar(20), SkIntToScalar(20), 141 SkIntToScalar(10)); 142 } 143private: 144 typedef PathBench INHERITED; 145}; 146 147class SawToothPathBench : public PathBench { 148public: 149 SawToothPathBench(void* param, Flags flags) : INHERITED(param, flags) {} 150 151 virtual void appendName(SkString* name) SK_OVERRIDE { 152 name->append("sawtooth"); 153 } 154 virtual void makePath(SkPath* path) { 155 SkScalar x = SkIntToScalar(20); 156 SkScalar y = SkIntToScalar(20); 157 const SkScalar x0 = x; 158 const SkScalar dx = SK_Scalar1 * 5; 159 const SkScalar dy = SK_Scalar1 * 10; 160 161 path->moveTo(x, y); 162 for (int i = 0; i < 32; i++) { 163 x += dx; 164 path->lineTo(x, y - dy); 165 x += dx; 166 path->lineTo(x, y + dy); 167 } 168 path->lineTo(x, y + 2 * dy); 169 path->lineTo(x0, y + 2 * dy); 170 path->close(); 171 } 172 virtual int complexity() SK_OVERRIDE { return 1; } 173private: 174 typedef PathBench INHERITED; 175}; 176 177class LongCurvedPathBench : public PathBench { 178public: 179 LongCurvedPathBench(void * param, Flags flags) 180 : INHERITED(param, flags) { 181 } 182 183 virtual void appendName(SkString* name) SK_OVERRIDE { 184 name->append("long_curved"); 185 } 186 virtual void makePath(SkPath* path) SK_OVERRIDE { 187 SkRandom rand (12); 188 int i; 189 for (i = 0; i < 100; i++) { 190 path->quadTo(SkScalarMul(rand.nextUScalar1(), SkIntToScalar(640)), 191 SkScalarMul(rand.nextUScalar1(), SkIntToScalar(480)), 192 SkScalarMul(rand.nextUScalar1(), SkIntToScalar(640)), 193 SkScalarMul(rand.nextUScalar1(), SkIntToScalar(480))); 194 } 195 path->close(); 196 } 197 virtual int complexity() SK_OVERRIDE { return 2; } 198private: 199 typedef PathBench INHERITED; 200}; 201 202class LongLinePathBench : public PathBench { 203public: 204 LongLinePathBench(void * param, Flags flags) 205 : INHERITED(param, flags) { 206 } 207 208 virtual void appendName(SkString* name) SK_OVERRIDE { 209 name->append("long_line"); 210 } 211 virtual void makePath(SkPath* path) SK_OVERRIDE { 212 SkRandom rand; 213 path->moveTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480); 214 for (size_t i = 1; i < 100; i++) { 215 path->lineTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480); 216 } 217 } 218 virtual int complexity() SK_OVERRIDE { return 2; } 219private: 220 typedef PathBench INHERITED; 221}; 222 223class RandomPathBench : public SkBenchmark { 224public: 225 RandomPathBench(void* param) : INHERITED(param) { 226 fIsRendering = false; 227 } 228 229protected: 230 void createData(int minVerbs, 231 int maxVerbs, 232 bool allowMoves = true, 233 SkRect* bounds = NULL) { 234 SkRect tempBounds; 235 if (NULL == bounds) { 236 tempBounds.setXYWH(0, 0, SK_Scalar1, SK_Scalar1); 237 bounds = &tempBounds; 238 } 239 fVerbCnts.reset(kNumVerbCnts); 240 for (int i = 0; i < kNumVerbCnts; ++i) { 241 fVerbCnts[i] = fRandom.nextRangeU(minVerbs, maxVerbs + 1); 242 } 243 fVerbs.reset(kNumVerbs); 244 for (int i = 0; i < kNumVerbs; ++i) { 245 do { 246 fVerbs[i] = static_cast<SkPath::Verb>(fRandom.nextULessThan(SkPath::kDone_Verb)); 247 } while (!allowMoves && SkPath::kMove_Verb == fVerbs[i]); 248 } 249 fPoints.reset(kNumPoints); 250 for (int i = 0; i < kNumPoints; ++i) { 251 fPoints[i].set(fRandom.nextRangeScalar(bounds->fLeft, bounds->fRight), 252 fRandom.nextRangeScalar(bounds->fTop, bounds->fBottom)); 253 } 254 this->restartMakingPaths(); 255 } 256 257 void restartMakingPaths() { 258 fCurrPath = 0; 259 fCurrVerb = 0; 260 fCurrPoint = 0; 261 } 262 263 void makePath(SkPath* path) { 264 int vCount = fVerbCnts[(fCurrPath++) & (kNumVerbCnts - 1)]; 265 for (int v = 0; v < vCount; ++v) { 266 int verb = fVerbs[(fCurrVerb++) & (kNumVerbs - 1)]; 267 switch (verb) { 268 case SkPath::kMove_Verb: 269 path->moveTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]); 270 break; 271 case SkPath::kLine_Verb: 272 path->lineTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]); 273 break; 274 case SkPath::kQuad_Verb: 275 path->quadTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)], 276 fPoints[(fCurrPoint + 1) & (kNumPoints - 1)]); 277 fCurrPoint += 2; 278 break; 279 case SkPath::kCubic_Verb: 280 path->cubicTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)], 281 fPoints[(fCurrPoint + 1) & (kNumPoints - 1)], 282 fPoints[(fCurrPoint + 2) & (kNumPoints - 1)]); 283 fCurrPoint += 3; 284 break; 285 case SkPath::kClose_Verb: 286 path->close(); 287 break; 288 default: 289 SkDEBUGFAIL("Unexpected path verb"); 290 break; 291 } 292 } 293 } 294 295 void finishedMakingPaths() { 296 fVerbCnts.reset(0); 297 fVerbs.reset(0); 298 fPoints.reset(0); 299 } 300 301private: 302 enum { 303 // these should all be pow 2 304 kNumVerbCnts = 1 << 5, 305 kNumVerbs = 1 << 5, 306 kNumPoints = 1 << 5, 307 }; 308 SkAutoTArray<int> fVerbCnts; 309 SkAutoTArray<SkPath::Verb> fVerbs; 310 SkAutoTArray<SkPoint> fPoints; 311 int fCurrPath; 312 int fCurrVerb; 313 int fCurrPoint; 314 SkRandom fRandom; 315 typedef SkBenchmark INHERITED; 316}; 317 318class PathCreateBench : public RandomPathBench { 319public: 320 PathCreateBench(void* param) : INHERITED(param) { 321 } 322 323protected: 324 enum { N = SkBENCHLOOP(5000) }; 325 326 virtual const char* onGetName() SK_OVERRIDE { 327 return "path_create"; 328 } 329 330 virtual void onPreDraw() SK_OVERRIDE { 331 this->createData(10, 100); 332 fPaths.reset(kPathCnt); 333 } 334 335 virtual void onDraw(SkCanvas*) SK_OVERRIDE { 336 for (int i = 0; i < N; ++i) { 337 this->makePath(&fPaths[i & (kPathCnt - 1)]); 338 } 339 this->restartMakingPaths(); 340 } 341 342 virtual void onPostDraw() SK_OVERRIDE { 343 this->finishedMakingPaths(); 344 fPaths.reset(0); 345 } 346 347private: 348 enum { 349 // must be a pow 2 350 kPathCnt = 1 << 5, 351 }; 352 SkAutoTArray<SkPath> fPaths; 353 354 typedef RandomPathBench INHERITED; 355}; 356 357class PathCopyBench : public RandomPathBench { 358public: 359 PathCopyBench(void* param) : INHERITED(param) { 360 } 361 362protected: 363 enum { N = SkBENCHLOOP(30000) }; 364 365 virtual const char* onGetName() SK_OVERRIDE { 366 return "path_copy"; 367 } 368 virtual void onPreDraw() SK_OVERRIDE { 369 this->createData(10, 100); 370 fPaths.reset(kPathCnt); 371 fCopies.reset(kPathCnt); 372 for (int i = 0; i < kPathCnt; ++i) { 373 this->makePath(&fPaths[i]); 374 } 375 this->finishedMakingPaths(); 376 } 377 virtual void onDraw(SkCanvas*) SK_OVERRIDE { 378 for (int i = 0; i < N; ++i) { 379 int idx = i & (kPathCnt - 1); 380 fCopies[idx] = fPaths[idx]; 381 } 382 } 383 virtual void onPostDraw() SK_OVERRIDE { 384 fPaths.reset(0); 385 fCopies.reset(0); 386 } 387 388private: 389 enum { 390 // must be a pow 2 391 kPathCnt = 1 << 5, 392 }; 393 SkAutoTArray<SkPath> fPaths; 394 SkAutoTArray<SkPath> fCopies; 395 396 typedef RandomPathBench INHERITED; 397}; 398 399class PathTransformBench : public RandomPathBench { 400public: 401 PathTransformBench(bool inPlace, void* param) 402 : INHERITED(param) 403 , fInPlace(inPlace) { 404 } 405 406protected: 407 enum { N = SkBENCHLOOP(30000) }; 408 409 virtual const char* onGetName() SK_OVERRIDE { 410 return fInPlace ? "path_transform_in_place" : "path_transform_copy"; 411 } 412 413 virtual void onPreDraw() SK_OVERRIDE { 414 fMatrix.setScale(5 * SK_Scalar1, 6 * SK_Scalar1); 415 this->createData(10, 100); 416 fPaths.reset(kPathCnt); 417 for (int i = 0; i < kPathCnt; ++i) { 418 this->makePath(&fPaths[i]); 419 } 420 this->finishedMakingPaths(); 421 if (!fInPlace) { 422 fTransformed.reset(kPathCnt); 423 } 424 } 425 426 virtual void onDraw(SkCanvas*) SK_OVERRIDE { 427 if (fInPlace) { 428 for (int i = 0; i < N; ++i) { 429 fPaths[i & (kPathCnt - 1)].transform(fMatrix); 430 } 431 } else { 432 for (int i = 0; i < N; ++i) { 433 int idx = i & (kPathCnt - 1); 434 fPaths[idx].transform(fMatrix, &fTransformed[idx]); 435 } 436 } 437 } 438 439 virtual void onPostDraw() SK_OVERRIDE { 440 fPaths.reset(0); 441 fTransformed.reset(0); 442 } 443 444private: 445 enum { 446 // must be a pow 2 447 kPathCnt = 1 << 5, 448 }; 449 SkAutoTArray<SkPath> fPaths; 450 SkAutoTArray<SkPath> fTransformed; 451 452 SkMatrix fMatrix; 453 bool fInPlace; 454 typedef RandomPathBench INHERITED; 455}; 456 457class PathEqualityBench : public RandomPathBench { 458public: 459 PathEqualityBench(void* param) 460 : INHERITED(param) { 461 } 462 463protected: 464 enum { N = SkBENCHLOOP(40000) }; 465 466 virtual const char* onGetName() SK_OVERRIDE { 467 return "path_equality_50%"; 468 } 469 470 virtual void onPreDraw() SK_OVERRIDE { 471 fParity = 0; 472 this->createData(10, 100); 473 fPaths.reset(kPathCnt); 474 fCopies.reset(kPathCnt); 475 for (int i = 0; i < kPathCnt; ++i) { 476 this->makePath(&fPaths[i]); 477 fCopies[i] = fPaths[i]; 478 } 479 this->finishedMakingPaths(); 480 } 481 482 virtual void onDraw(SkCanvas*) SK_OVERRIDE { 483 for (int i = 0; i < N; ++i) { 484 int idx = i & (kPathCnt - 1); 485 fParity ^= (fPaths[idx] == fCopies[idx & ~0x1]); 486 } 487 } 488 489 virtual void onPostDraw() SK_OVERRIDE { 490 fPaths.reset(0); 491 fCopies.reset(0); 492 } 493 494private: 495 bool fParity; // attempt to keep compiler from optimizing out the == 496 enum { 497 // must be a pow 2 498 kPathCnt = 1 << 5, 499 }; 500 SkAutoTArray<SkPath> fPaths; 501 SkAutoTArray<SkPath> fCopies; 502 typedef RandomPathBench INHERITED; 503}; 504 505class SkBench_AddPathTest : public RandomPathBench { 506public: 507 enum AddType { 508 kAdd_AddType, 509 kAddTrans_AddType, 510 kAddMatrix_AddType, 511 kPathTo_AddType, 512 kReverseAdd_AddType, 513 kReversePathTo_AddType, 514 }; 515 516 SkBench_AddPathTest(AddType type, void* param) 517 : INHERITED(param) 518 , fType(type) { 519 fMatrix.setRotate(60 * SK_Scalar1); 520 } 521 522protected: 523 enum { N = SkBENCHLOOP(15000) }; 524 525 virtual const char* onGetName() SK_OVERRIDE { 526 switch (fType) { 527 case kAdd_AddType: 528 return "path_add_path"; 529 case kAddTrans_AddType: 530 return "path_add_path_trans"; 531 case kAddMatrix_AddType: 532 return "path_add_path_matrix"; 533 case kPathTo_AddType: 534 return "path_path_to"; 535 case kReverseAdd_AddType: 536 return "path_reverse_add_path"; 537 case kReversePathTo_AddType: 538 return "path_reverse_path_to"; 539 default: 540 SkDEBUGFAIL("Bad add type"); 541 return ""; 542 } 543 } 544 545 virtual void onPreDraw() SK_OVERRIDE { 546 // pathTo and reversePathTo assume a single contour path. 547 bool allowMoves = kPathTo_AddType != fType && 548 kReversePathTo_AddType != fType; 549 this->createData(10, 100, allowMoves); 550 fPaths0.reset(kPathCnt); 551 fPaths1.reset(kPathCnt); 552 for (int i = 0; i < kPathCnt; ++i) { 553 this->makePath(&fPaths0[i]); 554 this->makePath(&fPaths1[i]); 555 } 556 this->finishedMakingPaths(); 557 } 558 559 virtual void onDraw(SkCanvas*) SK_OVERRIDE { 560 switch (fType) { 561 case kAdd_AddType: 562 for (int i = 0; i < N; ++i) { 563 int idx = i & (kPathCnt - 1); 564 SkPath result = fPaths0[idx]; 565 result.addPath(fPaths1[idx]); 566 } 567 break; 568 case kAddTrans_AddType: 569 for (int i = 0; i < N; ++i) { 570 int idx = i & (kPathCnt - 1); 571 SkPath result = fPaths0[idx]; 572 result.addPath(fPaths1[idx], 2 * SK_Scalar1, 5 * SK_Scalar1); 573 } 574 break; 575 case kAddMatrix_AddType: 576 for (int i = 0; i < N; ++i) { 577 int idx = i & (kPathCnt - 1); 578 SkPath result = fPaths0[idx]; 579 result.addPath(fPaths1[idx], fMatrix); 580 } 581 break; 582 case kPathTo_AddType: 583 for (int i = 0; i < N; ++i) { 584 int idx = i & (kPathCnt - 1); 585 SkPath result = fPaths0[idx]; 586 result.pathTo(fPaths1[idx]); 587 } 588 break; 589 case kReverseAdd_AddType: 590 for (int i = 0; i < N; ++i) { 591 int idx = i & (kPathCnt - 1); 592 SkPath result = fPaths0[idx]; 593 result.reverseAddPath(fPaths1[idx]); 594 } 595 break; 596 case kReversePathTo_AddType: 597 for (int i = 0; i < N; ++i) { 598 int idx = i & (kPathCnt - 1); 599 SkPath result = fPaths0[idx]; 600 result.reversePathTo(fPaths1[idx]); 601 } 602 break; 603 } 604 } 605 606 virtual void onPostDraw() SK_OVERRIDE { 607 fPaths0.reset(0); 608 fPaths1.reset(0); 609 } 610 611private: 612 AddType fType; // or reverseAddPath 613 enum { 614 // must be a pow 2 615 kPathCnt = 1 << 5, 616 }; 617 SkAutoTArray<SkPath> fPaths0; 618 SkAutoTArray<SkPath> fPaths1; 619 SkMatrix fMatrix; 620 typedef RandomPathBench INHERITED; 621}; 622 623 624class CirclesBench : public SkBenchmark { 625protected: 626 SkString fName; 627 628 enum { 629 N = SkBENCHLOOP(100) 630 }; 631public: 632 CirclesBench(void* param) : INHERITED(param) { 633 fName.printf("circles"); 634 } 635 636protected: 637 virtual const char* onGetName() SK_OVERRIDE { 638 return fName.c_str(); 639 } 640 641 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 642 SkPaint paint; 643 644 paint.setColor(SK_ColorBLACK); 645 paint.setAntiAlias(true); 646 647 SkRandom rand; 648 649 SkRect r; 650 651 for (int i = 0; i < 5000; ++i) { 652 SkScalar radius = rand.nextUScalar1() * 3; 653 r.fLeft = rand.nextUScalar1() * 300; 654 r.fTop = rand.nextUScalar1() * 300; 655 r.fRight = r.fLeft + 2 * radius; 656 r.fBottom = r.fTop + 2 * radius; 657 658 SkPath temp; 659 660 // mimic how Chrome does circles 661 temp.arcTo(r, 0, 0, false); 662 temp.addOval(r, SkPath::kCCW_Direction); 663 temp.arcTo(r, 360, 0, true); 664 temp.close(); 665 666 canvas->drawPath(temp, paint); 667 } 668 } 669 670private: 671 typedef SkBenchmark INHERITED; 672}; 673 674// Chrome creates its own round rects with each corner possibly being different. 675// In its "zero radius" incarnation it creates degenerate round rects. 676// Note: PathTest::test_arb_round_rect_is_convex and 677// test_arb_zero_rad_round_rect_is_rect perform almost exactly 678// the same test (but with no drawing) 679class ArbRoundRectBench : public SkBenchmark { 680protected: 681 SkString fName; 682 683 enum { 684 N = SkBENCHLOOP(100) 685 }; 686public: 687 ArbRoundRectBench(void* param, bool zeroRad) : INHERITED(param), fZeroRad(zeroRad) { 688 if (zeroRad) { 689 fName.printf("zeroradroundrect"); 690 } else { 691 fName.printf("arbroundrect"); 692 } 693 } 694 695protected: 696 virtual const char* onGetName() SK_OVERRIDE { 697 return fName.c_str(); 698 } 699 700 static void add_corner_arc(SkPath* path, const SkRect& rect, 701 SkScalar xIn, SkScalar yIn, 702 int startAngle) 703 { 704 705 SkScalar rx = SkMinScalar(rect.width(), xIn); 706 SkScalar ry = SkMinScalar(rect.height(), yIn); 707 708 SkRect arcRect; 709 arcRect.set(-rx, -ry, rx, ry); 710 switch (startAngle) { 711 case 0: 712 arcRect.offset(rect.fRight - arcRect.fRight, rect.fBottom - arcRect.fBottom); 713 break; 714 case 90: 715 arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fBottom - arcRect.fBottom); 716 break; 717 case 180: 718 arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fTop - arcRect.fTop); 719 break; 720 case 270: 721 arcRect.offset(rect.fRight - arcRect.fRight, rect.fTop - arcRect.fTop); 722 break; 723 default: 724 break; 725 } 726 727 path->arcTo(arcRect, SkIntToScalar(startAngle), SkIntToScalar(90), false); 728 } 729 730 static void make_arb_round_rect(SkPath* path, const SkRect& r, 731 SkScalar xCorner, SkScalar yCorner) { 732 // we are lazy here and use the same x & y for each corner 733 add_corner_arc(path, r, xCorner, yCorner, 270); 734 add_corner_arc(path, r, xCorner, yCorner, 0); 735 add_corner_arc(path, r, xCorner, yCorner, 90); 736 add_corner_arc(path, r, xCorner, yCorner, 180); 737 path->close(); 738 739#ifdef SK_REDEFINE_ROOT2OVER2_TO_MAKE_ARCTOS_CONVEX 740 SkASSERT(path->isConvex()); 741#endif 742 } 743 744 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 745 SkRandom rand; 746 SkRect r; 747 748 for (int i = 0; i < 5000; ++i) { 749 SkPaint paint; 750 paint.setColor(0xff000000 | rand.nextU()); 751 paint.setAntiAlias(true); 752 753 SkScalar size = rand.nextUScalar1() * 30; 754 if (size < SK_Scalar1) { 755 continue; 756 } 757 r.fLeft = rand.nextUScalar1() * 300; 758 r.fTop = rand.nextUScalar1() * 300; 759 r.fRight = r.fLeft + 2 * size; 760 r.fBottom = r.fTop + 2 * size; 761 762 SkPath temp; 763 764 if (fZeroRad) { 765 make_arb_round_rect(&temp, r, 0, 0); 766 767 SkASSERT(temp.isRect(NULL)); 768 } else { 769 make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15); 770 } 771 772 canvas->drawPath(temp, paint); 773 } 774 } 775 776private: 777 bool fZeroRad; // should 0 radius rounds rects be tested? 778 779 typedef SkBenchmark INHERITED; 780}; 781 782class ConservativelyContainsBench : public SkBenchmark { 783public: 784 enum Type { 785 kRect_Type, 786 kRoundRect_Type, 787 kOval_Type, 788 }; 789 790 ConservativelyContainsBench(void* param, Type type) : INHERITED(param) { 791 fIsRendering = false; 792 fParity = false; 793 fName = "conservatively_contains_"; 794 switch (type) { 795 case kRect_Type: 796 fName.append("rect"); 797 fPath.addRect(kBaseRect); 798 break; 799 case kRoundRect_Type: 800 fName.append("round_rect"); 801 fPath.addRoundRect(kBaseRect, kRRRadii[0], kRRRadii[1]); 802 break; 803 case kOval_Type: 804 fName.append("oval"); 805 fPath.addOval(kBaseRect); 806 break; 807 } 808 } 809 810private: 811 virtual const char* onGetName() SK_OVERRIDE { 812 return fName.c_str(); 813 } 814 815 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 816 for (int i = 0; i < N; ++i) { 817 const SkRect& rect = fQueryRects[i % kQueryRectCnt]; 818 fParity = fParity != fPath.conservativelyContainsRect(rect); 819 } 820 } 821 822 virtual void onPreDraw() SK_OVERRIDE { 823 fQueryRects.setCount(kQueryRectCnt); 824 825 SkRandom rand; 826 for (int i = 0; i < kQueryRectCnt; ++i) { 827 SkSize size; 828 SkPoint xy; 829 size.fWidth = rand.nextRangeScalar(kQueryMin.fWidth, kQueryMax.fWidth); 830 size.fHeight = rand.nextRangeScalar(kQueryMin.fHeight, kQueryMax.fHeight); 831 xy.fX = rand.nextRangeScalar(kBounds.fLeft, kBounds.fRight - size.fWidth); 832 xy.fY = rand.nextRangeScalar(kBounds.fTop, kBounds.fBottom - size.fHeight); 833 834 fQueryRects[i] = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight); 835 } 836 } 837 838 virtual void onPostDraw() SK_OVERRIDE { 839 fQueryRects.setCount(0); 840 } 841 842 enum { 843 N = SkBENCHLOOP(100000), 844 kQueryRectCnt = 400, 845 }; 846 static const SkRect kBounds; // bounds for all random query rects 847 static const SkSize kQueryMin; // minimum query rect size, should be <= kQueryMax 848 static const SkSize kQueryMax; // max query rect size, should < kBounds 849 static const SkRect kBaseRect; // rect that is used to construct the path 850 static const SkScalar kRRRadii[2]; // x and y radii for round rect 851 852 SkString fName; 853 SkPath fPath; 854 bool fParity; 855 SkTDArray<SkRect> fQueryRects; 856 857 typedef SkBenchmark INHERITED; 858}; 859 860const SkRect ConservativelyContainsBench::kBounds = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100)); 861const SkSize ConservativelyContainsBench::kQueryMin = SkSize::Make(SkIntToScalar(1), SkIntToScalar(1)); 862const SkSize ConservativelyContainsBench::kQueryMax = SkSize::Make(SkIntToScalar(40), SkIntToScalar(40)); 863const SkRect ConservativelyContainsBench::kBaseRect = SkRect::MakeXYWH(SkIntToScalar(25), SkIntToScalar(25), SkIntToScalar(50), SkIntToScalar(50)); 864const SkScalar ConservativelyContainsBench::kRRRadii[2] = {SkIntToScalar(5), SkIntToScalar(10)}; 865 866static SkBenchmark* FactT00(void* p) { return new TrianglePathBench(p, FLAGS00); } 867static SkBenchmark* FactT01(void* p) { return new TrianglePathBench(p, FLAGS01); } 868static SkBenchmark* FactT10(void* p) { return new TrianglePathBench(p, FLAGS10); } 869static SkBenchmark* FactT11(void* p) { return new TrianglePathBench(p, FLAGS11); } 870 871static SkBenchmark* FactR00(void* p) { return new RectPathBench(p, FLAGS00); } 872static SkBenchmark* FactR01(void* p) { return new RectPathBench(p, FLAGS01); } 873static SkBenchmark* FactR10(void* p) { return new RectPathBench(p, FLAGS10); } 874static SkBenchmark* FactR11(void* p) { return new RectPathBench(p, FLAGS11); } 875 876static SkBenchmark* FactO00(void* p) { return new OvalPathBench(p, FLAGS00); } 877static SkBenchmark* FactO01(void* p) { return new OvalPathBench(p, FLAGS01); } 878static SkBenchmark* FactO10(void* p) { return new OvalPathBench(p, FLAGS10); } 879static SkBenchmark* FactO11(void* p) { return new OvalPathBench(p, FLAGS11); } 880 881static SkBenchmark* FactC00(void* p) { return new CirclePathBench(p, FLAGS00); } 882static SkBenchmark* FactC01(void* p) { return new CirclePathBench(p, FLAGS01); } 883static SkBenchmark* FactC10(void* p) { return new CirclePathBench(p, FLAGS10); } 884static SkBenchmark* FactC11(void* p) { return new CirclePathBench(p, FLAGS11); } 885 886static SkBenchmark* FactS00(void* p) { return new SawToothPathBench(p, FLAGS00); } 887static SkBenchmark* FactS01(void* p) { return new SawToothPathBench(p, FLAGS01); } 888 889static SkBenchmark* FactLC00(void* p) { 890 return new LongCurvedPathBench(p, FLAGS00); 891} 892static SkBenchmark* FactLC01(void* p) { 893 return new LongCurvedPathBench(p, FLAGS01); 894} 895 896static SkBenchmark* FactLL00(void* p) { 897 return new LongLinePathBench(p, FLAGS00); 898} 899 900static SkBenchmark* FactLL01(void* p) { 901 return new LongLinePathBench(p, FLAGS01); 902} 903 904static BenchRegistry gRegT00(FactT00); 905static BenchRegistry gRegT01(FactT01); 906static BenchRegistry gRegT10(FactT10); 907static BenchRegistry gRegT11(FactT11); 908 909static BenchRegistry gRegR00(FactR00); 910static BenchRegistry gRegR01(FactR01); 911static BenchRegistry gRegR10(FactR10); 912static BenchRegistry gRegR11(FactR11); 913 914static BenchRegistry gRegO00(FactO00); 915static BenchRegistry gRegO01(FactO01); 916static BenchRegistry gRegO10(FactO10); 917static BenchRegistry gRegO11(FactO11); 918 919static BenchRegistry gRegC00(FactC00); 920static BenchRegistry gRegC01(FactC01); 921static BenchRegistry gRegC10(FactC10); 922static BenchRegistry gRegC11(FactC11); 923 924static BenchRegistry gRegS00(FactS00); 925static BenchRegistry gRegS01(FactS01); 926 927static BenchRegistry gRegLC00(FactLC00); 928static BenchRegistry gRegLC01(FactLC01); 929 930static BenchRegistry gRegLL00(FactLL00); 931static BenchRegistry gRegLL01(FactLL01); 932 933static SkBenchmark* FactCreate(void* p) { return new PathCreateBench(p); } 934static BenchRegistry gRegCreate(FactCreate); 935 936static SkBenchmark* FactCopy(void* p) { return new PathCopyBench(p); } 937static BenchRegistry gRegCopy(FactCopy); 938 939static SkBenchmark* FactPathTransformInPlace(void* p) { return new PathTransformBench(true, p); } 940static BenchRegistry gRegPathTransformInPlace(FactPathTransformInPlace); 941 942static SkBenchmark* FactPathTransformCopy(void* p) { return new PathTransformBench(false, p); } 943static BenchRegistry gRegPathTransformCopy(FactPathTransformCopy); 944 945static SkBenchmark* FactEquality(void* p) { return new PathEqualityBench(p); } 946static BenchRegistry gRegEquality(FactEquality); 947 948static SkBenchmark* FactAdd(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAdd_AddType, p); } 949static SkBenchmark* FactAddTrans(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAddTrans_AddType, p); } 950static SkBenchmark* FactAddMatrix(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAddMatrix_AddType, p); } 951static SkBenchmark* FactPathTo(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kPathTo_AddType, p); } 952static SkBenchmark* FactReverseAdd(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kReverseAdd_AddType, p); } 953static SkBenchmark* FactReverseTo(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kReversePathTo_AddType, p); } 954 955static BenchRegistry gRegAdd(FactAdd); 956static BenchRegistry gRegAddTrans(FactAddTrans); 957static BenchRegistry gRegAddMatrix(FactAddMatrix); 958static BenchRegistry gRegPathTo(FactPathTo); 959static BenchRegistry gRegReverseAdd(FactReverseAdd); 960static BenchRegistry gRegReverseTo(FactReverseTo); 961 962static SkBenchmark* CirclesTest(void* p) { return new CirclesBench(p); } 963static BenchRegistry gRegCirclesTest(CirclesTest); 964 965static SkBenchmark* ArbRoundRectTest(void* p) { return new ArbRoundRectBench(p, false); } 966static BenchRegistry gRegArbRoundRectTest(ArbRoundRectTest); 967 968static SkBenchmark* ZeroRadRoundRectTest(void* p) { return new ArbRoundRectBench(p, true); } 969static BenchRegistry gRegZeroRadRoundRectTest(ZeroRadRoundRectTest); 970 971static SkBenchmark* RectConservativelyContainsTest(void* p) { return new ConservativelyContainsBench(p, ConservativelyContainsBench::kRect_Type); } 972static BenchRegistry gRegRectConservativelyContainsTest(RectConservativelyContainsTest); 973 974static SkBenchmark* RoundRectConservativelyContainsTest(void* p) { return new ConservativelyContainsBench(p, ConservativelyContainsBench::kRoundRect_Type); } 975static BenchRegistry gRegRoundRectConservativelyContainsTest(RoundRectConservativelyContainsTest); 976 977static SkBenchmark* OvalConservativelyContainsTest(void* p) { return new ConservativelyContainsBench(p, ConservativelyContainsBench::kOval_Type); } 978static BenchRegistry gRegOvalConservativelyContainsTest(OvalConservativelyContainsTest); 979