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