1 /*
2  * Copyright 2016 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 
10 #include "SkCanvas.h"
11 #include "SkShader.h"
12 #include "SkGradientShader.h"
13 #include "SkString.h"
14 #include "SkColor.h"
15 #include "SkPaint.h"
16 
17 static const char* get_tilemode_name(SkShader::TileMode tilemode) {
18     switch (tilemode) {
19         case SkShader::kClamp_TileMode:
20             return "clamp";
21         case SkShader::kRepeat_TileMode:
22             return "repeat";
23         case SkShader::kMirror_TileMode:
24             return "mirror";
25         default:
26             SkDEBUGFAIL("Unknown tilemode");
27             return "error";
28     }
29 }
30 
31 class HardStopGradientBench_ScaleNumColors : public Benchmark {
32 public:
33     HardStopGradientBench_ScaleNumColors(SkShader::TileMode tilemode, int count) {
34         fName.printf("hardstop_scale_num_colors_%s_%03d_colors", get_tilemode_name(tilemode), count);
35 
36         fTileMode   = tilemode;
37         fColorCount = count;
38     }
39 
40     const char* onGetName() override {
41         return fName.c_str();
42     }
43 
44     SkIPoint onGetSize() override {
45         return SkIPoint::Make(kSize, kSize);
46     }
47 
48     /*
49      * Set up a linear gradient from left to right with
50      * fColorCount colors alternating between four
51      * different colors. The positions are evenly spaced,
52      * with the exception of the first two; these create a
53      * hard stop in order to trigger the hard stop code.
54      */
55     void onPreDraw(SkCanvas* canvas) override {
56         // Left to right
57         SkPoint points[2] = {
58             SkPoint::Make(0,        kSize/2),
59             SkPoint::Make(kSize-1,  kSize/2),
60         };
61 
62         constexpr int kNumColorChoices = 4;
63         SkColor color_choices[kNumColorChoices] = {
64             SK_ColorRED,
65             SK_ColorGREEN,
66             SK_ColorBLUE,
67             SK_ColorYELLOW,
68         };
69 
70         // Alternate between different choices
71         SkColor  colors[100];
72         for (int i = 0; i < fColorCount; i++) {
73             colors[i] = color_choices[i % kNumColorChoices];
74         }
75 
76         // Create a hard stop
77         SkScalar positions[100];
78         positions[0] = 0.0f;
79         positions[1] = 0.0f;
80         for (int i = 2; i < fColorCount; i++) {
81             // Evenly spaced afterwards
82             positions[i] = i / (fColorCount - 1.0f);
83         }
84 
85         fPaint.setShader(SkGradientShader::MakeLinear(points,
86                                                       colors,
87                                                       positions,
88                                                       fColorCount,
89                                                       fTileMode,
90                                                       0,
91                                                       nullptr));
92     }
93 
94     /*
95      * Draw simple linear gradient from left to right
96      */
97     void onDraw(int loops, SkCanvas* canvas) override {
98         for (int i = 0; i < loops; i++) {
99             canvas->drawPaint(fPaint);
100         }
101     }
102 
103 private:
104     static const int kSize = 500;
105 
106     SkShader::TileMode  fTileMode;
107     SkString            fName;
108     int                 fColorCount;
109     SkPaint             fPaint;
110 
111     typedef Benchmark INHERITED;
112 };
113 
114 // Clamp
115 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,   3);)
116 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,   4);)
117 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,   5);)
118 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,  10);)
119 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,  25);)
120 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,  50);)
121 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode, 100);)
122 
123 // Repeat
124 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,   3);)
125 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,   4);)
126 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,   5);)
127 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,  10);)
128 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,  25);)
129 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,  50);)
130 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode, 100);)
131 
132 // Mirror
133 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,   3);)
134 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,   4);)
135 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,   5);)
136 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,  10);)
137 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,  25);)
138 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,  50);)
139 DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode, 100);)
140