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