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