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
8#include "Benchmark.h"
9#include "SkCanvas.h"
10#include "SkGradientShader.h"
11#include "SkPaint.h"
12#include "SkPatchGrid.h"
13#include "SkString.h"
14
15 /**
16 * This bench measures the rendering time of a gridof patches.
17 * 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 also has 3 possible sizes small, medium and big to test if the size of the patches
20 * in the grid affects time.
21 */
22
23class PatchGridBench : public Benchmark {
24
25public:
26
27    enum Size {
28        kSmall_Size,
29        kMedium_Size,
30        kBig_Size
31    };
32
33    enum VertexMode {
34        kNone_VertexMode,
35        kColors_VertexMode,
36        kTexCoords_VertexMode,
37        kBoth_VertexMode
38    };
39
40    PatchGridBench(Size size, VertexMode vertexMode)
41    : fVertexMode(vertexMode)
42    , fSize(size) { }
43
44    void setScale(SkCanvas* canvas){
45        switch (fSize) {
46            case kSmall_Size:
47                canvas->scale(0.1f, 0.1f);
48                break;
49            case kMedium_Size:
50                canvas->scale(1.0f, 1.0f);
51                break;
52            case kBig_Size:
53                canvas->scale(3.0f, 3.0f);
54                break;
55        }
56    }
57
58    void setGrid() {
59        SkPoint vertices[4][5] = {
60            {{50,50}, {150,50}, {250,50},{350,50},{450,50}},
61            {{50,150}, {120,120}, {250,150},{350,150},{450,150}},
62            {{50,250}, {150,250}, {250,250},{350,250},{450,250}},
63            {{100,300}, {150,350}, {250,350},{350,350},{450,350}}
64        };
65
66        SkColor cornerColors[4][5] = {
67            {SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE},
68            {SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED},
69            {SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE},
70            {SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED},
71        };
72
73        SkPoint texCoords[4][5] = {
74            {{0.0f,0.0f}, {1.0f,0.0f}, {2.0f,0.0f}, {3.0f,0.0f}, {4.0f,0.0f}},
75            {{0.0f,1.0f}, {1.0f,1.0f}, {2.0f,1.0f}, {3.0f,1.0f}, {4.0f,1.0f}},
76            {{0.0f,2.0f}, {1.0f,2.0f}, {2.0f,2.0f}, {3.0f,2.0f}, {4.0f,2.0f}},
77            {{0.0f,3.0f}, {1.0f,3.0f}, {2.0f,3.0f}, {3.0f,3.0f}, {4.0f,3.0f}},
78        };
79
80        SkPoint hrzCtrl[4][8] = {
81            {{75,30},{125,45},{175,70},{225,20},{275,50},{325,50},{375,5},{425,90}},
82            {{75,150},{125,150},{175,150},{225,150},{275,150},{325,150},{375,150},{425,150}},
83            {{75,250},{125,250},{175,250},{225,250},{275,200},{325,150},{375,250},{425,250}},
84            {{75,350},{125,350},{175,350},{225,350},{275,350},{325,350},{375,350},{425,350}}
85        };
86
87        SkPoint vrtCtrl[6][5] = {
88            {{50,75},{150,75},{250,75},{350,75},{450,75}},
89            {{50,125},{150,125},{250,125},{350,125},{450,125}},
90            {{50,175},{150,175},{220,225},{350,175},{470,225}},
91            {{50,225},{150,225},{220,175},{350,225},{470,155}},
92            {{50,275},{150,275},{250,275},{350,275},{400,305}},
93            {{50,325},{150,325},{250,325},{350,325},{450,325}}
94        };
95
96        static const int kRows = 3;
97        static const int kCols = 4;
98
99        fGrid.reset(kRows, kCols, SkPatchGrid::kColors_VertexType, NULL);
100        for (int i = 0; i < kRows; i++) {
101            for (int j = 0; j < kCols; j++) {
102                SkPoint points[12];
103
104                //set corners
105                points[SkPatchUtils::kTopP0_CubicCtrlPts] = vertices[i][j];
106                points[SkPatchUtils::kTopP3_CubicCtrlPts] = vertices[i][j + 1];
107                points[SkPatchUtils::kBottomP0_CubicCtrlPts] = vertices[i + 1][j];
108                points[SkPatchUtils::kBottomP3_CubicCtrlPts] = vertices[i + 1][j + 1];
109
110                points[SkPatchUtils::kTopP1_CubicCtrlPts] = hrzCtrl[i][j * 2];
111                points[SkPatchUtils::kTopP2_CubicCtrlPts] = hrzCtrl[i][j * 2 + 1];
112                points[SkPatchUtils::kBottomP1_CubicCtrlPts] = hrzCtrl[i + 1][j * 2];
113                points[SkPatchUtils::kBottomP2_CubicCtrlPts] = hrzCtrl[i + 1][j * 2 + 1];
114
115                points[SkPatchUtils::kLeftP1_CubicCtrlPts] = vrtCtrl[i * 2][j];
116                points[SkPatchUtils::kLeftP2_CubicCtrlPts] = vrtCtrl[i * 2 + 1][j];
117                points[SkPatchUtils::kRightP1_CubicCtrlPts] = vrtCtrl[i * 2][j + 1];
118                points[SkPatchUtils::kRightP2_CubicCtrlPts] = vrtCtrl[i * 2 + 1][j + 1];
119
120                SkColor colors[4];
121                colors[0] = cornerColors[i][j];
122                colors[1] = cornerColors[i][j + 1];
123                colors[3] = cornerColors[i + 1][j];
124                colors[2] = cornerColors[i + 1][j + 1];
125
126                SkPoint texs[4];
127                texs[0] = texCoords[i][j];
128                texs[1] = texCoords[i][j + 1];
129                texs[3] = texCoords[i + 1][j];
130                texs[2] = texCoords[i + 1][j + 1];
131
132                switch (fVertexMode) {
133                    case kNone_VertexMode:
134                        fGrid.setPatch(j, i, points, NULL, NULL);
135                        break;
136                    case kColors_VertexMode:
137                        fGrid.setPatch(j, i, points, colors, NULL);
138                        break;
139                    case kTexCoords_VertexMode:
140                        fGrid.setPatch(j, i, points, NULL, texs);
141                        break;
142                    case kBoth_VertexMode:
143                        fGrid.setPatch(j, i, points, colors, texs);
144                        break;
145                    default:
146                        break;
147                }
148            }
149        }
150    }
151
152    // override this method to change the shader
153    SkShader* createShader() {
154        const SkColor colors[] = {
155            SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE,
156            SK_ColorMAGENTA, SK_ColorBLUE, SK_ColorYELLOW,
157        };
158        const SkPoint pts[] = { { 200.f / 4.f, 0.f }, { 3.f * 200.f / 4, 200.f } };
159
160        return SkGradientShader::CreateLinear(pts, colors, NULL,
161                                              SK_ARRAY_COUNT(colors),
162                                              SkShader::kMirror_TileMode);
163    }
164
165protected:
166    const char* onGetName() override {
167        SkString vertexMode;
168        switch (fVertexMode) {
169            case kNone_VertexMode:
170                vertexMode.set("meshlines");
171                break;
172            case kColors_VertexMode:
173                vertexMode.set("colors");
174                break;
175            case kTexCoords_VertexMode:
176                vertexMode.set("texs");
177                break;
178            case kBoth_VertexMode:
179                vertexMode.set("colors_texs");
180                break;
181            default:
182                break;
183        }
184
185        SkString size;
186        switch (fSize) {
187            case kSmall_Size:
188                size.set("small");
189                break;
190            case kMedium_Size:
191                size.set("medium");
192                break;
193            case kBig_Size:
194                size.set("big");
195                break;
196            default:
197                break;
198        }
199        fName.printf("patch_grid_%s_%s", vertexMode.c_str(), size.c_str());
200        return fName.c_str();
201    }
202
203    void onPreDraw() override {
204        this->setGrid();
205        switch (fVertexMode) {
206            case kTexCoords_VertexMode:
207            case kBoth_VertexMode:
208                fPaint.setShader(createShader())->unref();
209                break;
210            default:
211                fPaint.setShader(NULL);
212                break;
213        }
214        this->setupPaint(&fPaint);
215    }
216
217    void onDraw(const int loops, SkCanvas* canvas) override {
218        this->setScale(canvas);
219        for (int i = 0; i < loops; i++) {
220            fGrid.draw(canvas, fPaint);
221        }
222    }
223
224    SkPaint     fPaint;
225    SkString    fName;
226    SkPatchGrid fGrid;
227    VertexMode  fVertexMode;
228    Size        fSize;
229
230    typedef Benchmark INHERITED;
231};
232
233
234///////////////////////////////////////////////////////////////////////////////
235
236DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
237                                     PatchGridBench::kNone_VertexMode); )
238DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
239                                     PatchGridBench::kColors_VertexMode); )
240DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
241                                     PatchGridBench::kTexCoords_VertexMode); )
242DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
243                                     PatchGridBench::kBoth_VertexMode); )
244DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
245                                     PatchGridBench::kNone_VertexMode); )
246DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
247                                     PatchGridBench::kColors_VertexMode); )
248DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
249                                     PatchGridBench::kTexCoords_VertexMode); )
250DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
251                                     PatchGridBench::kBoth_VertexMode); )
252DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
253                                     PatchGridBench::kNone_VertexMode); )
254DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
255                                     PatchGridBench::kColors_VertexMode); )
256DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
257                                     PatchGridBench::kTexCoords_VertexMode); )
258DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
259                                     PatchGridBench::kBoth_VertexMode); )
260