blob: 8dec68bfc34e6f4c56f69b5941a657785338158f [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"
16#include "SkUnitMapper.h"
17
18struct GradData {
19 int fCount;
20 const SkColor* fColors;
21 const SkScalar* fPos;
commit-bot@chromium.org5396a042013-07-10 16:13:14 +000022 const char* fName;
reed@google.com84e9c082011-04-13 17:44:24 +000023};
24
25static const SkColor gColors[] = {
commit-bot@chromium.orgb6865392013-07-09 19:43:29 +000026 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
commit-bot@chromium.org5396a042013-07-10 16:13:14 +000027 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,
35 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK, // 10 lines, 50 colors
reed@google.com84e9c082011-04-13 17:44:24 +000036};
37
38static const GradData gGradData[] = {
commit-bot@chromium.org5396a042013-07-10 16:13:14 +000039 { 2, gColors, NULL, "" },
40 { 50, gColors, NULL, "_hicolor" }, // many color gradient
reed@google.com84e9c082011-04-13 17:44:24 +000041};
42
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000043/// Ignores scale
reed@google.com84e9c082011-04-13 17:44:24 +000044static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000045 SkShader::TileMode tm, SkUnitMapper* mapper,
46 float scale) {
reed@google.com84e9c082011-04-13 17:44:24 +000047 return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
48 data.fCount, tm, mapper);
49}
50
51static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000052 SkShader::TileMode tm, SkUnitMapper* mapper,
53 float scale) {
reed@google.com84e9c082011-04-13 17:44:24 +000054 SkPoint center;
55 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
56 SkScalarAve(pts[0].fY, pts[1].fY));
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000057 return SkGradientShader::CreateRadial(center, center.fX * scale,
58 data.fColors,
reed@google.com84e9c082011-04-13 17:44:24 +000059 data.fPos, data.fCount, tm, mapper);
60}
61
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000062/// Ignores scale
reed@google.com84e9c082011-04-13 17:44:24 +000063static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000064 SkShader::TileMode tm, SkUnitMapper* mapper,
65 float scale) {
reed@google.com84e9c082011-04-13 17:44:24 +000066 SkPoint center;
67 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
68 SkScalarAve(pts[0].fY, pts[1].fY));
69 return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
70 data.fPos, data.fCount, mapper);
71}
72
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000073/// Ignores scale
reed@google.com84e9c082011-04-13 17:44:24 +000074static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000075 SkShader::TileMode tm, SkUnitMapper* mapper,
76 float scale) {
reed@google.com84e9c082011-04-13 17:44:24 +000077 SkPoint center0, center1;
78 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
79 SkScalarAve(pts[0].fY, pts[1].fY));
80 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
81 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
82 return SkGradientShader::CreateTwoPointRadial(
reed@google.com258e0bf2012-06-07 14:18:34 +000083 center1, (pts[1].fX - pts[0].fX) / 7,
84 center0, (pts[1].fX - pts[0].fX) / 2,
85 data.fColors, data.fPos, data.fCount, tm, mapper);
86}
87
88/// Ignores scale
89static SkShader* MakeConical(const SkPoint pts[2], const GradData& data,
90 SkShader::TileMode tm, SkUnitMapper* mapper,
91 float scale) {
92 SkPoint center0, center1;
93 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
94 SkScalarAve(pts[0].fY, pts[1].fY));
95 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
96 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
97 return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
98 center0, (pts[1].fX - pts[0].fX) / 2,
99 data.fColors, data.fPos, data.fCount, tm, mapper);
reed@google.com84e9c082011-04-13 17:44:24 +0000100}
101
102typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000103 SkShader::TileMode tm, SkUnitMapper* mapper,
104 float scale);
reed@google.com84e9c082011-04-13 17:44:24 +0000105
106static const struct {
107 GradMaker fMaker;
108 const char* fName;
109 int fRepeat;
110} gGrads[] = {
111 { MakeLinear, "linear", 15 },
reed@google.com80adceb2011-04-13 18:32:19 +0000112 { MakeRadial, "radial1", 10 },
reed@google.com84e9c082011-04-13 17:44:24 +0000113 { MakeSweep, "sweep", 1 },
114 { Make2Radial, "radial2", 5 },
reed@google.com258e0bf2012-06-07 14:18:34 +0000115 { MakeConical, "conical", 5 },
reed@google.com84e9c082011-04-13 17:44:24 +0000116};
117
118enum GradType { // these must match the order in gGrads
119 kLinear_GradType,
120 kRadial_GradType,
121 kSweep_GradType,
reed@google.com258e0bf2012-06-07 14:18:34 +0000122 kRadial2_GradType,
123 kConical_GradType
reed@google.com84e9c082011-04-13 17:44:24 +0000124};
125
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000126enum GeomType {
127 kRect_GeomType,
128 kOval_GeomType
129};
130
reed@google.com72415162011-06-15 21:17:37 +0000131static const char* tilemodename(SkShader::TileMode tm) {
132 switch (tm) {
133 case SkShader::kClamp_TileMode:
134 return "clamp";
135 case SkShader::kRepeat_TileMode:
136 return "repeat";
137 case SkShader::kMirror_TileMode:
138 return "mirror";
139 default:
mtklein@google.com330313a2013-08-22 15:37:26 +0000140 SkDEBUGFAIL("unknown tilemode");
reed@google.com72415162011-06-15 21:17:37 +0000141 return "error";
142 }
143}
144
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000145static const char* geomtypename(GeomType gt) {
146 switch (gt) {
147 case kRect_GeomType:
148 return "rectangle";
149 case kOval_GeomType:
150 return "oval";
151 default:
mtklein@google.com330313a2013-08-22 15:37:26 +0000152 SkDEBUGFAIL("unknown geometry type");
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000153 return "error";
154 }
155}
156
reed@google.com84e9c082011-04-13 17:44:24 +0000157///////////////////////////////////////////////////////////////////////////////
158
159class GradientBench : public SkBenchmark {
160 SkString fName;
161 SkShader* fShader;
mtklein@google.comc2897432013-09-10 19:23:38 +0000162 int fRepeat;
reed@google.com84e9c082011-04-13 17:44:24 +0000163 enum {
164 W = 400,
165 H = 400,
reed@google.com84e9c082011-04-13 17:44:24 +0000166 };
167public:
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000168 GradientBench(void* param, GradType gradType,
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000169 GradData data = gGradData[0],
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000170 SkShader::TileMode tm = SkShader::kClamp_TileMode,
171 GeomType geomType = kRect_GeomType,
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000172 float scale = 1.0f
173 )
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000174 : INHERITED(param) {
175 fName.printf("gradient_%s_%s", gGrads[gradType].fName,
176 tilemodename(tm));
177 if (geomType != kRect_GeomType) {
178 fName.append("_");
179 fName.append(geomtypename(geomType));
180 }
reed@google.com84e9c082011-04-13 17:44:24 +0000181
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000182 fName.append(data.fName);
183
reed@google.com84e9c082011-04-13 17:44:24 +0000184 const SkPoint pts[2] = {
185 { 0, 0 },
186 { SkIntToScalar(W), SkIntToScalar(H) }
187 };
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000188
mtklein@google.comc2897432013-09-10 19:23:38 +0000189 fRepeat = gGrads[gradType].fRepeat;
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000190 fShader = gGrads[gradType].fMaker(pts, data, tm, NULL, scale);
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000191 fGeomType = geomType;
reed@google.com84e9c082011-04-13 17:44:24 +0000192 }
193
194 virtual ~GradientBench() {
195 fShader->unref();
196 }
197
198protected:
199 virtual const char* onGetName() {
200 return fName.c_str();
201 }
202
203 virtual void onDraw(SkCanvas* canvas) {
204 SkPaint paint;
205 this->setupPaint(&paint);
206
207 paint.setShader(fShader);
208
209 SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
mtklein@google.comc2897432013-09-10 19:23:38 +0000210 for (int i = 0; i < this->getLoops() * fRepeat; i++) {
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000211 switch (fGeomType) {
212 case kRect_GeomType:
213 canvas->drawRect(r, paint);
214 break;
215 case kOval_GeomType:
216 canvas->drawOval(r, paint);
217 break;
218 }
reed@google.com84e9c082011-04-13 17:44:24 +0000219 }
220 }
221
222private:
223 typedef SkBenchmark INHERITED;
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000224
225 GeomType fGeomType;
reed@google.com84e9c082011-04-13 17:44:24 +0000226};
227
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000228class Gradient2Bench : public SkBenchmark {
reed@google.com73349aa2013-02-04 18:09:58 +0000229 SkString fName;
230 bool fHasAlpha;
231
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000232public:
reed@google.com73349aa2013-02-04 18:09:58 +0000233 Gradient2Bench(void* param, bool hasAlpha) : INHERITED(param) {
234 fName.printf("gradient_create_%s", hasAlpha ? "alpha" : "opaque");
235 fHasAlpha = hasAlpha;
236 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000237
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000238protected:
239 virtual const char* onGetName() {
reed@google.com73349aa2013-02-04 18:09:58 +0000240 return fName.c_str();
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000241 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000242
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000243 virtual void onDraw(SkCanvas* canvas) {
244 SkPaint paint;
245 this->setupPaint(&paint);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000246
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000247 const SkRect r = { 0, 0, SkIntToScalar(4), SkIntToScalar(4) };
reed@google.com1ca4f262011-06-24 19:17:37 +0000248 const SkPoint pts[] = {
249 { 0, 0 },
250 { SkIntToScalar(100), SkIntToScalar(100) },
251 };
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000252
mtklein@google.comc2897432013-09-10 19:23:38 +0000253 for (int i = 0; i < this->getLoops(); i++) {
reed@google.com73349aa2013-02-04 18:09:58 +0000254 const int gray = i % 256;
255 const int alpha = fHasAlpha ? gray : 0xFF;
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000256 SkColor colors[] = {
257 SK_ColorBLACK,
reed@google.com73349aa2013-02-04 18:09:58 +0000258 SkColorSetARGB(alpha, gray, gray, gray),
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000259 SK_ColorWHITE };
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000260 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
261 SK_ARRAY_COUNT(colors),
262 SkShader::kClamp_TileMode);
263 paint.setShader(s)->unref();
264 canvas->drawRect(r, paint);
265 }
266 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000267
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000268private:
269 typedef SkBenchmark INHERITED;
270};
271
reed@google.com58ba4102013-02-04 18:00:54 +0000272DEF_BENCH( return new GradientBench(p, kLinear_GradType); )
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000273DEF_BENCH( return new GradientBench(p, kLinear_GradType, gGradData[1]); )
274DEF_BENCH( return new GradientBench(p, kLinear_GradType, gGradData[0], SkShader::kMirror_TileMode); )
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000275
276// Draw a radial gradient of radius 1/2 on a rectangle; half the lines should
277// be completely pinned, the other half should pe partially pinned
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000278DEF_BENCH( return new GradientBench(p, kRadial_GradType, gGradData[0], SkShader::kClamp_TileMode, kRect_GeomType, 0.5f); )
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000279
280// Draw a radial gradient on a circle of equal size; all the lines should
281// hit the unpinned fast path (so long as GradientBench.W == H)
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000282DEF_BENCH( return new GradientBench(p, kRadial_GradType, gGradData[0], SkShader::kClamp_TileMode, kOval_GeomType); )
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000283
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000284DEF_BENCH( return new GradientBench(p, kRadial_GradType, gGradData[0], SkShader::kMirror_TileMode); )
reed@google.com58ba4102013-02-04 18:00:54 +0000285DEF_BENCH( return new GradientBench(p, kSweep_GradType); )
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000286DEF_BENCH( return new GradientBench(p, kSweep_GradType, gGradData[1]); )
reed@google.com58ba4102013-02-04 18:00:54 +0000287DEF_BENCH( return new GradientBench(p, kRadial2_GradType); )
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000288DEF_BENCH( return new GradientBench(p, kRadial2_GradType, gGradData[1]); )
289DEF_BENCH( return new GradientBench(p, kRadial2_GradType, gGradData[0], SkShader::kMirror_TileMode); )
reed@google.com58ba4102013-02-04 18:00:54 +0000290DEF_BENCH( return new GradientBench(p, kConical_GradType); )
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000291DEF_BENCH( return new GradientBench(p, kConical_GradType, gGradData[1]); )
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000292
reed@google.com73349aa2013-02-04 18:09:58 +0000293DEF_BENCH( return new Gradient2Bench(p, false); )
294DEF_BENCH( return new Gradient2Bench(p, true); )