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