blob: b20fc9a65d036f0a4920aabe24f749e84303e845 [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:
140 SkASSERT(!"unknown tilemode");
141 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:
152 SkASSERT(!"unknown geometry type");
153 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;
162 int fCount;
163 enum {
164 W = 400,
165 H = 400,
166 N = 1
167 };
168public:
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000169 GradientBench(void* param, GradType gradType,
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000170 GradData data = gGradData[0],
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000171 SkShader::TileMode tm = SkShader::kClamp_TileMode,
172 GeomType geomType = kRect_GeomType,
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000173 float scale = 1.0f
174 )
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000175 : INHERITED(param) {
176 fName.printf("gradient_%s_%s", gGrads[gradType].fName,
177 tilemodename(tm));
178 if (geomType != kRect_GeomType) {
179 fName.append("_");
180 fName.append(geomtypename(geomType));
181 }
reed@google.com84e9c082011-04-13 17:44:24 +0000182
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000183 fName.append(data.fName);
184
reed@google.com84e9c082011-04-13 17:44:24 +0000185 const SkPoint pts[2] = {
186 { 0, 0 },
187 { SkIntToScalar(W), SkIntToScalar(H) }
188 };
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000189
tomhudson@google.comca529d32011-10-28 15:34:49 +0000190 fCount = SkBENCHLOOP(N * gGrads[gradType].fRepeat);
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000191 fShader = gGrads[gradType].fMaker(pts, data, tm, NULL, scale);
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000192 fGeomType = geomType;
reed@google.com84e9c082011-04-13 17:44:24 +0000193 }
194
195 virtual ~GradientBench() {
196 fShader->unref();
197 }
198
199protected:
200 virtual const char* onGetName() {
201 return fName.c_str();
202 }
203
204 virtual void onDraw(SkCanvas* canvas) {
205 SkPaint paint;
206 this->setupPaint(&paint);
207
208 paint.setShader(fShader);
209
210 SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
211 for (int i = 0; i < fCount; i++) {
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000212 switch (fGeomType) {
213 case kRect_GeomType:
214 canvas->drawRect(r, paint);
215 break;
216 case kOval_GeomType:
217 canvas->drawOval(r, paint);
218 break;
219 }
reed@google.com84e9c082011-04-13 17:44:24 +0000220 }
221 }
222
223private:
224 typedef SkBenchmark INHERITED;
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000225
226 GeomType fGeomType;
reed@google.com84e9c082011-04-13 17:44:24 +0000227};
228
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000229class Gradient2Bench : public SkBenchmark {
reed@google.com73349aa2013-02-04 18:09:58 +0000230 SkString fName;
231 bool fHasAlpha;
232
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000233public:
reed@google.com73349aa2013-02-04 18:09:58 +0000234 Gradient2Bench(void* param, bool hasAlpha) : INHERITED(param) {
235 fName.printf("gradient_create_%s", hasAlpha ? "alpha" : "opaque");
236 fHasAlpha = hasAlpha;
237 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000238
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000239protected:
240 virtual const char* onGetName() {
reed@google.com73349aa2013-02-04 18:09:58 +0000241 return fName.c_str();
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000242 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000243
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000244 virtual void onDraw(SkCanvas* canvas) {
245 SkPaint paint;
246 this->setupPaint(&paint);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000247
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000248 const SkRect r = { 0, 0, SkIntToScalar(4), SkIntToScalar(4) };
reed@google.com1ca4f262011-06-24 19:17:37 +0000249 const SkPoint pts[] = {
250 { 0, 0 },
251 { SkIntToScalar(100), SkIntToScalar(100) },
252 };
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000253
tomhudson@google.comca529d32011-10-28 15:34:49 +0000254 for (int i = 0; i < SkBENCHLOOP(1000); i++) {
reed@google.com73349aa2013-02-04 18:09:58 +0000255 const int gray = i % 256;
256 const int alpha = fHasAlpha ? gray : 0xFF;
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000257 SkColor colors[] = {
258 SK_ColorBLACK,
reed@google.com73349aa2013-02-04 18:09:58 +0000259 SkColorSetARGB(alpha, gray, gray, gray),
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000260 SK_ColorWHITE };
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000261 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
262 SK_ARRAY_COUNT(colors),
263 SkShader::kClamp_TileMode);
264 paint.setShader(s)->unref();
265 canvas->drawRect(r, paint);
266 }
267 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000268
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000269private:
270 typedef SkBenchmark INHERITED;
271};
272
reed@google.com58ba4102013-02-04 18:00:54 +0000273DEF_BENCH( return new GradientBench(p, kLinear_GradType); )
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000274DEF_BENCH( return new GradientBench(p, kLinear_GradType, gGradData[1]); )
275DEF_BENCH( return new GradientBench(p, kLinear_GradType, gGradData[0], SkShader::kMirror_TileMode); )
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000276
277// Draw a radial gradient of radius 1/2 on a rectangle; half the lines should
278// be completely pinned, the other half should pe partially pinned
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000279DEF_BENCH( return new GradientBench(p, kRadial_GradType, gGradData[0], SkShader::kClamp_TileMode, kRect_GeomType, 0.5f); )
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000280
281// Draw a radial gradient on a circle of equal size; all the lines should
282// hit the unpinned fast path (so long as GradientBench.W == H)
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000283DEF_BENCH( return new GradientBench(p, kRadial_GradType, gGradData[0], SkShader::kClamp_TileMode, kOval_GeomType); )
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000284
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000285DEF_BENCH( return new GradientBench(p, kRadial_GradType, gGradData[0], SkShader::kMirror_TileMode); )
reed@google.com58ba4102013-02-04 18:00:54 +0000286DEF_BENCH( return new GradientBench(p, kSweep_GradType); )
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000287DEF_BENCH( return new GradientBench(p, kSweep_GradType, gGradData[1]); )
reed@google.com58ba4102013-02-04 18:00:54 +0000288DEF_BENCH( return new GradientBench(p, kRadial2_GradType); )
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000289DEF_BENCH( return new GradientBench(p, kRadial2_GradType, gGradData[1]); )
290DEF_BENCH( return new GradientBench(p, kRadial2_GradType, gGradData[0], SkShader::kMirror_TileMode); )
reed@google.com58ba4102013-02-04 18:00:54 +0000291DEF_BENCH( return new GradientBench(p, kConical_GradType); )
commit-bot@chromium.org5396a042013-07-10 16:13:14 +0000292DEF_BENCH( return new GradientBench(p, kConical_GradType, gGradData[1]); )
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000293
reed@google.com73349aa2013-02-04 18:09:58 +0000294DEF_BENCH( return new Gradient2Bench(p, false); )
295DEF_BENCH( return new Gradient2Bench(p, true); )