PathBench.cpp revision fbfcd5602128ec010c82cb733c9cdc0a3254f9f3
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    }
227
228protected:
229    void createData(int minVerbs,
230                    int maxVerbs,
231                    bool allowMoves = true,
232                    SkRect* bounds = NULL) {
233        SkRect tempBounds;
234        if (NULL == bounds) {
235            tempBounds.setXYWH(0, 0, SK_Scalar1, SK_Scalar1);
236            bounds = &tempBounds;
237        }
238        fVerbCnts.reset(kNumVerbCnts);
239        for (int i = 0; i < kNumVerbCnts; ++i) {
240            fVerbCnts[i] = fRandom.nextRangeU(minVerbs, maxVerbs + 1);
241        }
242        fVerbs.reset(kNumVerbs);
243        for (int i = 0; i < kNumVerbs; ++i) {
244            do {
245                fVerbs[i] = static_cast<SkPath::Verb>(fRandom.nextULessThan(SkPath::kDone_Verb));
246            } while (!allowMoves && SkPath::kMove_Verb == fVerbs[i]);
247        }
248        fPoints.reset(kNumPoints);
249        for (int i = 0; i < kNumPoints; ++i) {
250            fPoints[i].set(fRandom.nextRangeScalar(bounds->fLeft, bounds->fRight),
251                           fRandom.nextRangeScalar(bounds->fTop, bounds->fBottom));
252        }
253        this->restartMakingPaths();
254    }
255
256    void restartMakingPaths() {
257        fCurrPath = 0;
258        fCurrVerb = 0;
259        fCurrPoint = 0;
260    }
261
262    void makePath(SkPath* path) {
263        int vCount = fVerbCnts[(fCurrPath++) & (kNumVerbCnts - 1)];
264        for (int v = 0; v < vCount; ++v) {
265            int verb = fVerbs[(fCurrVerb++) & (kNumVerbs - 1)];
266            switch (verb) {
267                case SkPath::kMove_Verb:
268                    path->moveTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
269                    break;
270                case SkPath::kLine_Verb:
271                    path->lineTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
272                    break;
273                case SkPath::kQuad_Verb:
274                    path->quadTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)],
275                                 fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
276                    break;
277                case SkPath::kCubic_Verb:
278                    path->cubicTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)],
279                                  fPoints[(fCurrPoint++) & (kNumPoints - 1)],
280                                  fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
281                    break;
282                case SkPath::kClose_Verb:
283                    path->close();
284                    break;
285                default:
286                    SkDEBUGFAIL("Unexpected path verb");
287                    break;
288            }
289        }
290    }
291
292    void finishedMakingPaths() {
293        fVerbCnts.reset(0);
294        fVerbs.reset(0);
295        fPoints.reset(0);
296    }
297
298private:
299    enum {
300        // these should all be pow 2
301        kNumVerbCnts = 1 << 5,
302        kNumVerbs    = 1 << 5,
303        kNumPoints   = 1 << 5,
304    };
305    SkAutoTArray<int>           fVerbCnts;
306    SkAutoTArray<SkPath::Verb>  fVerbs;
307    SkAutoTArray<SkPoint>       fPoints;
308    int                         fCurrPath;
309    int                         fCurrVerb;
310    int                         fCurrPoint;
311    SkRandom                    fRandom;
312    typedef SkBenchmark INHERITED;
313};
314
315class PathCreateBench : public RandomPathBench {
316public:
317    PathCreateBench(void* param) : INHERITED(param) {
318    }
319
320protected:
321    enum { N = SkBENCHLOOP(5000) };
322
323    virtual const char* onGetName() SK_OVERRIDE {
324        return "path_create";
325    }
326
327    virtual void onPreDraw() SK_OVERRIDE {
328        this->createData(10, 100);
329        fPaths.reset(kPathCnt);
330    }
331
332    virtual void onDraw(SkCanvas*) SK_OVERRIDE {
333        for (int i = 0; i < N; ++i) {
334            this->makePath(&fPaths[i & (kPathCnt - 1)]);
335        }
336        this->restartMakingPaths();
337    }
338
339    virtual void onPostDraw() SK_OVERRIDE {
340        this->finishedMakingPaths();
341        fPaths.reset(0);
342    }
343
344private:
345    enum {
346        // must be a pow 2
347        kPathCnt = 1 << 5,
348    };
349    SkAutoTArray<SkPath> fPaths;
350
351    typedef RandomPathBench INHERITED;
352};
353
354class PathCopyBench : public RandomPathBench {
355public:
356    PathCopyBench(void* param) : INHERITED(param) {
357    }
358
359protected:
360    enum { N = SkBENCHLOOP(30000) };
361
362    virtual const char* onGetName() SK_OVERRIDE {
363        return "path_copy";
364    }
365    virtual void onPreDraw() SK_OVERRIDE {
366        this->createData(10, 100);
367        fPaths.reset(kPathCnt);
368        fCopies.reset(kPathCnt);
369        for (int i = 0; i < kPathCnt; ++i) {
370            this->makePath(&fPaths[i]);
371        }
372        this->finishedMakingPaths();
373    }
374    virtual void onDraw(SkCanvas*) SK_OVERRIDE {
375        for (int i = 0; i < N; ++i) {
376            int idx = i & (kPathCnt - 1);
377            fCopies[idx] = fPaths[idx];
378        }
379    }
380    virtual void onPostDraw() SK_OVERRIDE {
381        fPaths.reset(0);
382        fCopies.reset(0);
383    }
384
385private:
386    enum {
387        // must be a pow 2
388        kPathCnt = 1 << 5,
389    };
390    SkAutoTArray<SkPath> fPaths;
391    SkAutoTArray<SkPath> fCopies;
392
393    typedef RandomPathBench INHERITED;
394};
395
396class PathTransformBench : public RandomPathBench {
397public:
398    PathTransformBench(bool inPlace, void* param)
399        : INHERITED(param)
400        , fInPlace(inPlace) {
401    }
402
403protected:
404    enum { N = SkBENCHLOOP(30000) };
405
406    virtual const char* onGetName() SK_OVERRIDE {
407        return fInPlace ? "path_transform_in_place" : "path_transform_copy";
408    }
409
410    virtual void onPreDraw() SK_OVERRIDE {
411        fMatrix.setScale(5 * SK_Scalar1, 6 * SK_Scalar1);
412        this->createData(10, 100);
413        fPaths.reset(kPathCnt);
414        for (int i = 0; i < kPathCnt; ++i) {
415            this->makePath(&fPaths[i]);
416        }
417        this->finishedMakingPaths();
418        if (!fInPlace) {
419            fTransformed.reset(kPathCnt);
420        }
421    }
422
423    virtual void onDraw(SkCanvas*) SK_OVERRIDE {
424        if (fInPlace) {
425            for (int i = 0; i < N; ++i) {
426                fPaths[i & (kPathCnt - 1)].transform(fMatrix);
427            }
428        } else {
429            for (int i = 0; i < N; ++i) {
430                int idx = i & (kPathCnt - 1);
431                fPaths[idx].transform(fMatrix, &fTransformed[idx]);
432            }
433        }
434    }
435
436    virtual void onPostDraw() SK_OVERRIDE {
437        fPaths.reset(0);
438        fTransformed.reset(0);
439    }
440
441private:
442    enum {
443        // must be a pow 2
444        kPathCnt = 1 << 5,
445    };
446    SkAutoTArray<SkPath> fPaths;
447    SkAutoTArray<SkPath> fTransformed;
448
449    SkMatrix fMatrix;
450    bool fInPlace;
451    typedef RandomPathBench INHERITED;
452};
453
454class PathEqualityBench : public RandomPathBench {
455public:
456    PathEqualityBench(void* param)
457        : INHERITED(param) {
458    }
459
460protected:
461    enum { N = SkBENCHLOOP(40000) };
462
463    virtual const char* onGetName() SK_OVERRIDE {
464        return "path_equality_50%";
465    }
466
467    virtual void onPreDraw() SK_OVERRIDE {
468        fParity = 0;
469        this->createData(10, 100);
470        fPaths.reset(kPathCnt);
471        fCopies.reset(kPathCnt);
472        for (int i = 0; i < kPathCnt; ++i) {
473            this->makePath(&fPaths[i]);
474            fCopies[i] = fPaths[i];
475        }
476        this->finishedMakingPaths();
477    }
478
479    virtual void onDraw(SkCanvas*) SK_OVERRIDE {
480        for (int i = 0; i < N; ++i) {
481            int idx = i & (kPathCnt - 1);
482            fParity ^= (fPaths[idx] == fCopies[idx & ~0x1]);
483        }
484    }
485
486    virtual void onPostDraw() SK_OVERRIDE {
487        fPaths.reset(0);
488        fCopies.reset(0);
489    }
490
491private:
492    bool fParity; // attempt to keep compiler from optimizing out the ==
493    enum {
494        // must be a pow 2
495        kPathCnt = 1 << 5,
496    };
497    SkAutoTArray<SkPath> fPaths;
498    SkAutoTArray<SkPath> fCopies;
499    typedef RandomPathBench INHERITED;
500};
501
502class SkBench_AddPathTest : public RandomPathBench {
503public:
504    enum AddType {
505        kAdd_AddType,
506        kAddTrans_AddType,
507        kAddMatrix_AddType,
508        kPathTo_AddType,
509        kReverseAdd_AddType,
510        kReversePathTo_AddType,
511    };
512
513    SkBench_AddPathTest(AddType type, void* param)
514        : INHERITED(param)
515        , fType(type) {
516        fMatrix.setRotate(60 * SK_Scalar1);
517    }
518
519protected:
520    enum { N = SkBENCHLOOP(15000) };
521
522    virtual const char* onGetName() SK_OVERRIDE {
523        switch (fType) {
524            case kAdd_AddType:
525                return "path_add_path";
526            case kAddTrans_AddType:
527                return "path_add_path_trans";
528            case kAddMatrix_AddType:
529                return "path_add_path_matrix";
530            case kPathTo_AddType:
531                return "path_path_to";
532            case kReverseAdd_AddType:
533                return "path_reverse_add_path";
534            case kReversePathTo_AddType:
535                return "path_reverse_path_to";
536            default:
537                SkDEBUGFAIL("Bad add type");
538                return "";
539        }
540    }
541
542    virtual void onPreDraw() SK_OVERRIDE {
543        // pathTo and reversePathTo assume a single contour path.
544        bool allowMoves = kPathTo_AddType != fType &&
545                          kReversePathTo_AddType != fType;
546        this->createData(10, 100, allowMoves);
547        fPaths0.reset(kPathCnt);
548        fPaths1.reset(kPathCnt);
549        for (int i = 0; i < kPathCnt; ++i) {
550            this->makePath(&fPaths0[i]);
551            this->makePath(&fPaths1[i]);
552        }
553        this->finishedMakingPaths();
554    }
555
556    virtual void onDraw(SkCanvas*) SK_OVERRIDE {
557        switch (fType) {
558            case kAdd_AddType:
559                for (int i = 0; i < N; ++i) {
560                    int idx = i & (kPathCnt - 1);
561                    SkPath result = fPaths0[idx];
562                    result.addPath(fPaths1[idx]);
563                }
564                break;
565            case kAddTrans_AddType:
566                for (int i = 0; i < N; ++i) {
567                    int idx = i & (kPathCnt - 1);
568                    SkPath result = fPaths0[idx];
569                    result.addPath(fPaths1[idx], 2 * SK_Scalar1, 5 * SK_Scalar1);
570                }
571                break;
572            case kAddMatrix_AddType:
573                for (int i = 0; i < N; ++i) {
574                    int idx = i & (kPathCnt - 1);
575                    SkPath result = fPaths0[idx];
576                    result.addPath(fPaths1[idx], fMatrix);
577                }
578                break;
579            case kPathTo_AddType:
580                for (int i = 0; i < N; ++i) {
581                    int idx = i & (kPathCnt - 1);
582                    SkPath result = fPaths0[idx];
583                    result.pathTo(fPaths1[idx]);
584                }
585                break;
586            case kReverseAdd_AddType:
587                for (int i = 0; i < N; ++i) {
588                    int idx = i & (kPathCnt - 1);
589                    SkPath result = fPaths0[idx];
590                    result.reverseAddPath(fPaths1[idx]);
591                }
592                break;
593            case kReversePathTo_AddType:
594                for (int i = 0; i < N; ++i) {
595                    int idx = i & (kPathCnt - 1);
596                    SkPath result = fPaths0[idx];
597                    result.reversePathTo(fPaths1[idx]);
598                }
599                break;
600        }
601    }
602
603    virtual void onPostDraw() SK_OVERRIDE {
604        fPaths0.reset(0);
605        fPaths1.reset(0);
606    }
607
608private:
609    AddType fType; // or reverseAddPath
610    enum {
611        // must be a pow 2
612        kPathCnt = 1 << 5,
613    };
614    SkAutoTArray<SkPath> fPaths0;
615    SkAutoTArray<SkPath> fPaths1;
616    SkMatrix         fMatrix;
617    typedef RandomPathBench INHERITED;
618};
619
620
621class CirclesBench : public SkBenchmark {
622protected:
623    SkString            fName;
624
625    enum {
626        N = SkBENCHLOOP(100)
627    };
628public:
629    CirclesBench(void* param) : INHERITED(param) {
630        fName.printf("circles");
631    }
632
633protected:
634    virtual const char* onGetName() SK_OVERRIDE {
635        return fName.c_str();
636    }
637
638    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
639        SkPaint paint;
640
641        paint.setColor(SK_ColorBLACK);
642        paint.setAntiAlias(true);
643
644        SkRandom rand;
645
646        SkRect r;
647
648        for (int i = 0; i < 5000; ++i) {
649            SkScalar radius = rand.nextUScalar1() * 3;
650            r.fLeft = rand.nextUScalar1() * 300;
651            r.fTop =  rand.nextUScalar1() * 300;
652            r.fRight =  r.fLeft + 2 * radius;
653            r.fBottom = r.fTop + 2 * radius;
654
655            SkPath temp;
656
657            // mimic how Chrome does circles
658            temp.arcTo(r, 0, 0, false);
659            temp.addOval(r, SkPath::kCCW_Direction);
660            temp.arcTo(r, 360, 0, true);
661            temp.close();
662
663            canvas->drawPath(temp, paint);
664        }
665    }
666
667private:
668    typedef SkBenchmark INHERITED;
669};
670
671static SkBenchmark* FactT00(void* p) { return new TrianglePathBench(p, FLAGS00); }
672static SkBenchmark* FactT01(void* p) { return new TrianglePathBench(p, FLAGS01); }
673static SkBenchmark* FactT10(void* p) { return new TrianglePathBench(p, FLAGS10); }
674static SkBenchmark* FactT11(void* p) { return new TrianglePathBench(p, FLAGS11); }
675
676static SkBenchmark* FactR00(void* p) { return new RectPathBench(p, FLAGS00); }
677static SkBenchmark* FactR01(void* p) { return new RectPathBench(p, FLAGS01); }
678static SkBenchmark* FactR10(void* p) { return new RectPathBench(p, FLAGS10); }
679static SkBenchmark* FactR11(void* p) { return new RectPathBench(p, FLAGS11); }
680
681static SkBenchmark* FactO00(void* p) { return new OvalPathBench(p, FLAGS00); }
682static SkBenchmark* FactO01(void* p) { return new OvalPathBench(p, FLAGS01); }
683static SkBenchmark* FactO10(void* p) { return new OvalPathBench(p, FLAGS10); }
684static SkBenchmark* FactO11(void* p) { return new OvalPathBench(p, FLAGS11); }
685
686static SkBenchmark* FactC00(void* p) { return new CirclePathBench(p, FLAGS00); }
687static SkBenchmark* FactC01(void* p) { return new CirclePathBench(p, FLAGS01); }
688static SkBenchmark* FactC10(void* p) { return new CirclePathBench(p, FLAGS10); }
689static SkBenchmark* FactC11(void* p) { return new CirclePathBench(p, FLAGS11); }
690
691static SkBenchmark* FactS00(void* p) { return new SawToothPathBench(p, FLAGS00); }
692static SkBenchmark* FactS01(void* p) { return new SawToothPathBench(p, FLAGS01); }
693
694static SkBenchmark* FactLC00(void* p) {
695    return new LongCurvedPathBench(p, FLAGS00);
696}
697static SkBenchmark* FactLC01(void* p) {
698    return new LongCurvedPathBench(p, FLAGS01);
699}
700
701static SkBenchmark* FactLL00(void* p) {
702    return new LongLinePathBench(p, FLAGS00);
703}
704
705static SkBenchmark* FactLL01(void* p) {
706    return new LongLinePathBench(p, FLAGS01);
707}
708
709static BenchRegistry gRegT00(FactT00);
710static BenchRegistry gRegT01(FactT01);
711static BenchRegistry gRegT10(FactT10);
712static BenchRegistry gRegT11(FactT11);
713
714static BenchRegistry gRegR00(FactR00);
715static BenchRegistry gRegR01(FactR01);
716static BenchRegistry gRegR10(FactR10);
717static BenchRegistry gRegR11(FactR11);
718
719static BenchRegistry gRegO00(FactO00);
720static BenchRegistry gRegO01(FactO01);
721static BenchRegistry gRegO10(FactO10);
722static BenchRegistry gRegO11(FactO11);
723
724static BenchRegistry gRegC00(FactC00);
725static BenchRegistry gRegC01(FactC01);
726static BenchRegistry gRegC10(FactC10);
727static BenchRegistry gRegC11(FactC11);
728
729static BenchRegistry gRegS00(FactS00);
730static BenchRegistry gRegS01(FactS01);
731
732static BenchRegistry gRegLC00(FactLC00);
733static BenchRegistry gRegLC01(FactLC01);
734
735static BenchRegistry gRegLL00(FactLL00);
736static BenchRegistry gRegLL01(FactLL01);
737
738static SkBenchmark* FactCreate(void* p) { return new PathCreateBench(p); }
739static BenchRegistry gRegCreate(FactCreate);
740
741static SkBenchmark* FactCopy(void* p) { return new PathCopyBench(p); }
742static BenchRegistry gRegCopy(FactCopy);
743
744static SkBenchmark* FactPathTransformInPlace(void* p) { return new PathTransformBench(true, p); }
745static BenchRegistry gRegPathTransformInPlace(FactPathTransformInPlace);
746
747static SkBenchmark* FactPathTransformCopy(void* p) { return new PathTransformBench(false, p); }
748static BenchRegistry gRegPathTransformCopy(FactPathTransformCopy);
749
750static SkBenchmark* FactEquality(void* p) { return new PathEqualityBench(p); }
751static BenchRegistry gRegEquality(FactEquality);
752
753static SkBenchmark* FactAdd(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAdd_AddType, p); }
754static SkBenchmark* FactAddTrans(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAddTrans_AddType, p); }
755static SkBenchmark* FactAddMatrix(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAddMatrix_AddType, p); }
756static SkBenchmark* FactPathTo(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kPathTo_AddType, p); }
757static SkBenchmark* FactReverseAdd(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kReverseAdd_AddType, p); }
758static SkBenchmark* FactReverseTo(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kReversePathTo_AddType, p); }
759
760static BenchRegistry gRegAdd(FactAdd);
761static BenchRegistry gRegAddTrans(FactAddTrans);
762static BenchRegistry gRegAddMatrix(FactAddMatrix);
763static BenchRegistry gRegPathTo(FactPathTo);
764static BenchRegistry gRegReverseAdd(FactReverseAdd);
765static BenchRegistry gRegReverseTo(FactReverseTo);
766
767static SkBenchmark* CirclesTest(void* p) { return new CirclesBench(p); }
768static BenchRegistry gRegCirclesTest(CirclesTest);
769
770