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 
22 class PatchBench : public Benchmark {
23 
24 public:
25 
26     enum VertexMode {
27         kNone_VertexMode,
28         kColors_VertexMode,
29         kTexCoords_VertexMode,
30         kBoth_VertexMode
31     };
32 
PatchBench(SkPoint scale,VertexMode vertexMode)33     PatchBench(SkPoint scale, VertexMode vertexMode)
34     : fScale(scale)
35     , fVertexMode(vertexMode) { }
36 
37     // to add name of specific class override this method
appendName(SkString * name)38     virtual void appendName(SkString* name) {
39         name->append("normal");
40     }
41 
42     // to make other type of patches override this method
setCubics()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 
setColors()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 
setTexCoords()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
createShader()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, nullptr,
80                                               SK_ARRAY_COUNT(colors),
81                                               SkShader::kMirror_TileMode);
82     }
83 
84 protected:
onGetName()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 
onDelayedSetup()110     void onDelayedSetup() 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(nullptr);
122                 break;
123         }
124     }
125 
onDraw(int loops,SkCanvas * canvas)126     void onDraw(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, nullptr, nullptr, nullptr, fPaint);
132                     break;
133                 case kColors_VertexMode:
134                     canvas->drawPatch(fCubics, fColors, nullptr, nullptr, fPaint);
135                     break;
136                 case kTexCoords_VertexMode:
137                     canvas->drawPatch(fCubics, nullptr, fTexCoords, nullptr, fPaint);
138                     break;
139                 case kBoth_VertexMode:
140                     canvas->drawPatch(fCubics, fColors, fTexCoords, nullptr, 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 
159 class SquarePatchBench : public PatchBench {
160 public:
SquarePatchBench(SkPoint scale,VertexMode vertexMode)161     SquarePatchBench(SkPoint scale, VertexMode vertexMode)
162     : INHERITED(scale, vertexMode) { }
163 
appendName(SkString * name)164     void appendName(SkString* name) override {
165         name->append("square");
166     }
167 
setCubics()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     }
181 private:
182     typedef PatchBench INHERITED;
183 };
184 
185 class LODDiffPatchBench : public PatchBench {
186 public:
LODDiffPatchBench(SkPoint scale,VertexMode vertexMode)187     LODDiffPatchBench(SkPoint scale, VertexMode vertexMode)
188     : INHERITED(scale, vertexMode) { }
189 
appendName(SkString * name)190     void appendName(SkString* name) override {
191         name->append("LOD_Diff");
192     }
193 
setCubics()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     }
207 private:
208     typedef PatchBench INHERITED;
209 };
210 
211 class LoopPatchBench : public PatchBench {
212 public:
LoopPatchBench(SkPoint scale,VertexMode vertexMode)213     LoopPatchBench(SkPoint scale, VertexMode vertexMode)
214     : INHERITED(scale, vertexMode) { }
215 
appendName(SkString * name)216     void appendName(SkString* name) override {
217         name->append("loop");
218     }
219 
setCubics()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     }
233 private:
234     typedef PatchBench INHERITED;
235 };
236 
237 ///////////////////////////////////////////////////////////////////////////////
238 
239 DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kNone_VertexMode); )
240 DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kColors_VertexMode); )
241 DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kTexCoords_VertexMode); )
242 DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kBoth_VertexMode); )
243 DEF_BENCH( return new PatchBench(SkVector::Make(1.f, 1.0f), PatchBench::kNone_VertexMode); )
244 DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kColors_VertexMode); )
245 DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kTexCoords_VertexMode); )
246 DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kBoth_VertexMode); )
247 DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kNone_VertexMode); )
248 DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kColors_VertexMode); )
249 DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kTexCoords_VertexMode); )
250 DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kBoth_VertexMode); )
251 
252 DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f),
253                                        PatchBench::kNone_VertexMode); )
254 DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f),
255                                        PatchBench::kColors_VertexMode); )
256 DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f),
257                                        PatchBench::kTexCoords_VertexMode); )
258 DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f),
259                                        PatchBench::kBoth_VertexMode); )
260 DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.f, 1.0f),
261                                        PatchBench::kNone_VertexMode); )
262 DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f),
263                                        PatchBench::kColors_VertexMode); )
264 DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f),
265                                        PatchBench::kTexCoords_VertexMode); )
266 DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f),
267                                        PatchBench::kBoth_VertexMode); )
268 DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f),
269                                        PatchBench::kNone_VertexMode); )
270 DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f),
271                                        PatchBench::kColors_VertexMode); )
272 DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f),
273                                        PatchBench::kTexCoords_VertexMode); )
274 DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f),
275                                        PatchBench::kBoth_VertexMode); )
276 
277 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f),
278                                        PatchBench::kNone_VertexMode); )
279 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f),
280                                        PatchBench::kColors_VertexMode); )
281 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f),
282                                        PatchBench::kTexCoords_VertexMode); )
283 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f),
284                                        PatchBench::kBoth_VertexMode); )
285 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.f, 1.0f),
286                                        PatchBench::kNone_VertexMode); )
287 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f),
288                                        PatchBench::kColors_VertexMode); )
289 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f),
290                                        PatchBench::kTexCoords_VertexMode); )
291 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f),
292                                        PatchBench::kBoth_VertexMode); )
293 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f),
294                                        PatchBench::kNone_VertexMode); )
295 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f),
296                                        PatchBench::kColors_VertexMode); )
297 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f),
298                                        PatchBench::kTexCoords_VertexMode); )
299 DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f),
300                                        PatchBench::kBoth_VertexMode); )
301 
302 DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f),
303                                         PatchBench::kNone_VertexMode); )
304 DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f),
305                                         PatchBench::kColors_VertexMode); )
306 DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f),
307                                         PatchBench::kTexCoords_VertexMode); )
308 DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f),
309                                         PatchBench::kBoth_VertexMode); )
310 DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.f, 1.0f),
311                                         PatchBench::kNone_VertexMode); )
312 DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f),
313                                         PatchBench::kColors_VertexMode); )
314 DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f),
315                                         PatchBench::kTexCoords_VertexMode); )
316 DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f),
317                                         PatchBench::kBoth_VertexMode); )
318 DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f),
319                                         PatchBench::kNone_VertexMode); )
320 DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f),
321                                         PatchBench::kColors_VertexMode); )
322 DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f),
323                                         PatchBench::kTexCoords_VertexMode); )
324 DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f),
325                                         PatchBench::kBoth_VertexMode); )
326