blob: fa07bce4fd1f1404f686b9ee44584765782b226e [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@google.com84e9c082011-04-13 17:44:24 +00008#include "SkBenchmark.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkColorPriv.h"
12#include "SkGradientShader.h"
13#include "SkPaint.h"
14#include "SkShader.h"
15#include "SkString.h"
reed@google.com84e9c082011-04-13 17:44:24 +000016
17struct GradData {
18 int fCount;
19 const SkColor* fColors;
20 const SkScalar* fPos;
commit-bot@chromium.org5396a042013-07-10 16:13:14 +000021 const char* fName;
reed@google.com84e9c082011-04-13 17:44:24 +000022};
23
24static const SkColor gColors[] = {
commit-bot@chromium.orgb6865392013-07-09 19:43:29 +000025 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
commit-bot@chromium.org5396a042013-07-10 16:13:14 +000026 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
27 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
28 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
29 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
30 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
31 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
32 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
33 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
34 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK, // 10 lines, 50 colors
reed@google.com84e9c082011-04-13 17:44:24 +000035};
36
commit-bot@chromium.org3400f4b2013-09-30 19:41:09 +000037// We have several special-cases depending on the number (and spacing) of colors, so
38// try to exercise those here.
reed@google.com84e9c082011-04-13 17:44:24 +000039static const GradData gGradData[] = {
commit-bot@chromium.org5396a042013-07-10 16:13:14 +000040 { 2, gColors, NULL, "" },
41 { 50, gColors, NULL, "_hicolor" }, // many color gradient
commit-bot@chromium.org3400f4b2013-09-30 19:41:09 +000042 { 3, gColors, NULL, "_3color" },
reed@google.com84e9c082011-04-13 17:44:24 +000043};
44
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000045/// Ignores scale
reed@google.com84e9c082011-04-13 17:44:24 +000046static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000047 SkShader::TileMode tm, float scale) {
48 return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos, data.fCount, tm);
reed@google.com84e9c082011-04-13 17:44:24 +000049}
50
51static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000052 SkShader::TileMode tm, float scale) {
reed@google.com84e9c082011-04-13 17:44:24 +000053 SkPoint center;
54 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
55 SkScalarAve(pts[0].fY, pts[1].fY));
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000056 return SkGradientShader::CreateRadial(center, center.fX * scale,
57 data.fColors,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000058 data.fPos, data.fCount, tm);
reed@google.com84e9c082011-04-13 17:44:24 +000059}
60
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000061/// Ignores scale
reed@google.com84e9c082011-04-13 17:44:24 +000062static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000063 SkShader::TileMode tm, float scale) {
reed@google.com84e9c082011-04-13 17:44:24 +000064 SkPoint center;
65 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
66 SkScalarAve(pts[0].fY, pts[1].fY));
67 return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000068 data.fPos, data.fCount);
reed@google.com84e9c082011-04-13 17:44:24 +000069}
70
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000071/// Ignores scale
reed@google.com84e9c082011-04-13 17:44:24 +000072static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000073 SkShader::TileMode tm, float scale) {
reed@google.com84e9c082011-04-13 17:44:24 +000074 SkPoint center0, center1;
75 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
76 SkScalarAve(pts[0].fY, pts[1].fY));
77 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
78 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
79 return SkGradientShader::CreateTwoPointRadial(
reed@google.com258e0bf2012-06-07 14:18:34 +000080 center1, (pts[1].fX - pts[0].fX) / 7,
81 center0, (pts[1].fX - pts[0].fX) / 2,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000082 data.fColors, data.fPos, data.fCount, tm);
reed@google.com258e0bf2012-06-07 14:18:34 +000083}
84
85/// Ignores scale
86static SkShader* MakeConical(const SkPoint pts[2], const GradData& data,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000087 SkShader::TileMode tm, float scale) {
reed@google.com258e0bf2012-06-07 14:18:34 +000088 SkPoint center0, center1;
89 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
90 SkScalarAve(pts[0].fY, pts[1].fY));
91 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
92 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
93 return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
94 center0, (pts[1].fX - pts[0].fX) / 2,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +000095 data.fColors, data.fPos, data.fCount, tm);
reed@google.com84e9c082011-04-13 17:44:24 +000096}
97
commit-bot@chromium.org95f79262014-04-14 16:02:31 +000098/// Ignores scale
99static SkShader* MakeConicalZeroRad(const SkPoint pts[2], const GradData& data,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000100 SkShader::TileMode tm, float scale) {
commit-bot@chromium.org95f79262014-04-14 16:02:31 +0000101 SkPoint center0, center1;
102 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
103 SkScalarAve(pts[0].fY, pts[1].fY));
104 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
105 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
106 return SkGradientShader::CreateTwoPointConical(center1, 0.0,
107 center0, (pts[1].fX - pts[0].fX) / 2,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000108 data.fColors, data.fPos, data.fCount, tm);
commit-bot@chromium.org95f79262014-04-14 16:02:31 +0000109}
110
111/// Ignores scale
112static SkShader* MakeConicalOutside(const SkPoint pts[2], const GradData& data,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000113 SkShader::TileMode tm, float scale) {
commit-bot@chromium.org95f79262014-04-14 16:02:31 +0000114 SkPoint center0, center1;
115 SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
116 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
117 center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
118 center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
119 return SkGradientShader::CreateTwoPointConical(center0, radius0,
120 center1, radius1,
121 data.fColors, data.fPos,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000122 data.fCount, tm);
commit-bot@chromium.org95f79262014-04-14 16:02:31 +0000123}
124
125/// Ignores scale
126static SkShader* MakeConicalOutsideZeroRad(const SkPoint pts[2], const GradData& data,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000127 SkShader::TileMode tm, float scale) {
commit-bot@chromium.org95f79262014-04-14 16:02:31 +0000128 SkPoint center0, center1;
129 SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
130 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
131 center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
132 center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
133 return SkGradientShader::CreateTwoPointConical(center0, 0.0,
134 center1, radius1,
135 data.fColors, data.fPos,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000136 data.fCount, tm);
commit-bot@chromium.org95f79262014-04-14 16:02:31 +0000137}
138
reed@google.com84e9c082011-04-13 17:44:24 +0000139typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000140 SkShader::TileMode tm, float scale);
reed@google.com84e9c082011-04-13 17:44:24 +0000141
142static const struct {
143 GradMaker fMaker;
144 const char* fName;
reed@google.com84e9c082011-04-13 17:44:24 +0000145} gGrads[] = {
commit-bot@chromium.org95f79262014-04-14 16:02:31 +0000146 { MakeLinear, "linear" },
147 { MakeRadial, "radial1" },
148 { MakeSweep, "sweep" },
149 { Make2Radial, "radial2" },
150 { MakeConical, "conical" },
151 { MakeConicalZeroRad, "conicalZero" },
152 { MakeConicalOutside, "conicalOut" },
153 { MakeConicalOutsideZeroRad, "conicalOutZero" },
reed@google.com84e9c082011-04-13 17:44:24 +0000154};
155
156enum GradType { // these must match the order in gGrads
157 kLinear_GradType,
158 kRadial_GradType,
159 kSweep_GradType,
reed@google.com258e0bf2012-06-07 14:18:34 +0000160 kRadial2_GradType,
commit-bot@chromium.org95f79262014-04-14 16:02:31 +0000161 kConical_GradType,
162 kConicalZero_GradType,
163 kConicalOut_GradType,
164 kConicalOutZero_GradType
reed@google.com84e9c082011-04-13 17:44:24 +0000165};
166
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000167enum GeomType {
168 kRect_GeomType,
169 kOval_GeomType
170};
171
reed@google.com72415162011-06-15 21:17:37 +0000172static const char* tilemodename(SkShader::TileMode tm) {
173 switch (tm) {
174 case SkShader::kClamp_TileMode:
175 return "clamp";
176 case SkShader::kRepeat_TileMode:
177 return "repeat";
178 case SkShader::kMirror_TileMode:
179 return "mirror";
180 default:
mtklein@google.com330313a2013-08-22 15:37:26 +0000181 SkDEBUGFAIL("unknown tilemode");
reed@google.com72415162011-06-15 21:17:37 +0000182 return "error";
183 }
184}
185
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000186static const char* geomtypename(GeomType gt) {
187 switch (gt) {
188 case kRect_GeomType:
189 return "rectangle";
190 case kOval_GeomType:
191 return "oval";
192 default:
mtklein@google.com330313a2013-08-22 15:37:26 +0000193 SkDEBUGFAIL("unknown geometry type");
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000194 return "error";
195 }
196}
197
reed@google.com84e9c082011-04-13 17:44:24 +0000198///////////////////////////////////////////////////////////////////////////////
199
200class GradientBench : public SkBenchmark {
201 SkString fName;
202 SkShader* fShader;
reed@google.com84e9c082011-04-13 17:44:24 +0000203 enum {
204 W = 400,
205 H = 400,
commit-bot@chromium.orgb120bd92013-10-07 17:18:21 +0000206 kRepeat = 15,
reed@google.com84e9c082011-04-13 17:44:24 +0000207 };
208public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000209 GradientBench(GradType gradType,
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000210 GradData data = gGradData[0],
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000211 SkShader::TileMode tm = SkShader::kClamp_TileMode,
212 GeomType geomType = kRect_GeomType,
commit-bot@chromium.org3400f4b2013-09-30 19:41:09 +0000213 float scale = 1.0f) {
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000214 fName.printf("gradient_%s_%s", gGrads[gradType].fName,
215 tilemodename(tm));
216 if (geomType != kRect_GeomType) {
217 fName.append("_");
218 fName.append(geomtypename(geomType));
219 }
reed@google.com84e9c082011-04-13 17:44:24 +0000220
commit-bot@chromium.org3400f4b2013-09-30 19:41:09 +0000221 if (scale != 1.f) {
222 fName.appendf("_scale_%g", scale);
223 }
224
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000225 fName.append(data.fName);
226
reed@google.com84e9c082011-04-13 17:44:24 +0000227 const SkPoint pts[2] = {
228 { 0, 0 },
229 { SkIntToScalar(W), SkIntToScalar(H) }
230 };
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000231
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000232 fShader = gGrads[gradType].fMaker(pts, data, tm, scale);
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000233 fGeomType = geomType;
reed@google.com84e9c082011-04-13 17:44:24 +0000234 }
235
236 virtual ~GradientBench() {
237 fShader->unref();
238 }
239
240protected:
241 virtual const char* onGetName() {
242 return fName.c_str();
243 }
244
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000245 virtual void onDraw(const int loops, SkCanvas* canvas) {
reed@google.com84e9c082011-04-13 17:44:24 +0000246 SkPaint paint;
247 this->setupPaint(&paint);
248
249 paint.setShader(fShader);
250
251 SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000252 for (int i = 0; i < loops * kRepeat; i++) {
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000253 switch (fGeomType) {
254 case kRect_GeomType:
255 canvas->drawRect(r, paint);
256 break;
257 case kOval_GeomType:
258 canvas->drawOval(r, paint);
259 break;
260 }
reed@google.com84e9c082011-04-13 17:44:24 +0000261 }
262 }
263
264private:
265 typedef SkBenchmark INHERITED;
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000266
267 GeomType fGeomType;
reed@google.com84e9c082011-04-13 17:44:24 +0000268};
269
commit-bot@chromium.orgb120bd92013-10-07 17:18:21 +0000270DEF_BENCH( return new GradientBench(kLinear_GradType); )
271DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[1]); )
272DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[2]); )
273DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[0], SkShader::kMirror_TileMode); )
274
275DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0]); )
276DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[1]); )
277DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[2]); )
278// Draw a radial gradient of radius 1/2 on a rectangle; half the lines should
279// be completely pinned, the other half should pe partially pinned
280DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kClamp_TileMode, kRect_GeomType, 0.5f); )
281
282// Draw a radial gradient on a circle of equal size; all the lines should
283// hit the unpinned fast path (so long as GradientBench.W == H)
284DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kClamp_TileMode, kOval_GeomType); )
285
286DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kMirror_TileMode); )
commit-bot@chromium.org34150b42013-10-16 18:59:44 +0000287DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kRepeat_TileMode); )
commit-bot@chromium.orgb120bd92013-10-07 17:18:21 +0000288DEF_BENCH( return new GradientBench(kSweep_GradType); )
289DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[1]); )
290DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[2]); )
291DEF_BENCH( return new GradientBench(kRadial2_GradType); )
292DEF_BENCH( return new GradientBench(kRadial2_GradType, gGradData[1]); )
293DEF_BENCH( return new GradientBench(kRadial2_GradType, gGradData[0], SkShader::kMirror_TileMode); )
294DEF_BENCH( return new GradientBench(kConical_GradType); )
295DEF_BENCH( return new GradientBench(kConical_GradType, gGradData[1]); )
296DEF_BENCH( return new GradientBench(kConical_GradType, gGradData[2]); )
commit-bot@chromium.org95f79262014-04-14 16:02:31 +0000297DEF_BENCH( return new GradientBench(kConicalZero_GradType); )
298DEF_BENCH( return new GradientBench(kConicalZero_GradType, gGradData[1]); )
299DEF_BENCH( return new GradientBench(kConicalZero_GradType, gGradData[2]); )
300DEF_BENCH( return new GradientBench(kConicalOut_GradType); )
301DEF_BENCH( return new GradientBench(kConicalOut_GradType, gGradData[1]); )
302DEF_BENCH( return new GradientBench(kConicalOut_GradType, gGradData[2]); )
303DEF_BENCH( return new GradientBench(kConicalOutZero_GradType); )
304DEF_BENCH( return new GradientBench(kConicalOutZero_GradType, gGradData[1]); )
305DEF_BENCH( return new GradientBench(kConicalOutZero_GradType, gGradData[2]); )
commit-bot@chromium.orgb120bd92013-10-07 17:18:21 +0000306
307///////////////////////////////////////////////////////////////////////////////
308
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000309class Gradient2Bench : public SkBenchmark {
reed@google.com73349aa2013-02-04 18:09:58 +0000310 SkString fName;
311 bool fHasAlpha;
312
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000313public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000314 Gradient2Bench(bool hasAlpha) {
reed@google.com73349aa2013-02-04 18:09:58 +0000315 fName.printf("gradient_create_%s", hasAlpha ? "alpha" : "opaque");
316 fHasAlpha = hasAlpha;
317 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000318
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000319protected:
320 virtual const char* onGetName() {
reed@google.com73349aa2013-02-04 18:09:58 +0000321 return fName.c_str();
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000322 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000323
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000324 virtual void onDraw(const int loops, SkCanvas* canvas) {
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000325 SkPaint paint;
326 this->setupPaint(&paint);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000327
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000328 const SkRect r = { 0, 0, SkIntToScalar(4), SkIntToScalar(4) };
reed@google.com1ca4f262011-06-24 19:17:37 +0000329 const SkPoint pts[] = {
330 { 0, 0 },
331 { SkIntToScalar(100), SkIntToScalar(100) },
332 };
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000333
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000334 for (int i = 0; i < loops; i++) {
reed@google.com73349aa2013-02-04 18:09:58 +0000335 const int gray = i % 256;
336 const int alpha = fHasAlpha ? gray : 0xFF;
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000337 SkColor colors[] = {
338 SK_ColorBLACK,
reed@google.com73349aa2013-02-04 18:09:58 +0000339 SkColorSetARGB(alpha, gray, gray, gray),
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000340 SK_ColorWHITE };
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000341 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
342 SK_ARRAY_COUNT(colors),
343 SkShader::kClamp_TileMode);
344 paint.setShader(s)->unref();
345 canvas->drawRect(r, paint);
346 }
347 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000348
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000349private:
350 typedef SkBenchmark INHERITED;
351};
352
mtklein@google.com410e6e82013-09-13 19:52:27 +0000353DEF_BENCH( return new Gradient2Bench(false); )
354DEF_BENCH( return new Gradient2Bench(true); )