blob: d7ce74dc8ec5ecf239fccea3ff5286e5b97a9992 [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;
22};
23
24static const SkColor gColors[] = {
25 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
26};
27static const SkScalar gPos0[] = { 0, SK_Scalar1 };
28static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
29static const SkScalar gPos2[] = {
30 0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
31};
32
33static const GradData gGradData[] = {
34 { 2, gColors, NULL },
35 { 2, gColors, gPos0 },
36 { 2, gColors, gPos1 },
37 { 5, gColors, NULL },
38 { 5, gColors, gPos2 }
39};
40
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000041/// Ignores scale
reed@google.com84e9c082011-04-13 17:44:24 +000042static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000043 SkShader::TileMode tm, SkUnitMapper* mapper,
44 float scale) {
reed@google.com84e9c082011-04-13 17:44:24 +000045 return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
46 data.fCount, tm, mapper);
47}
48
49static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000050 SkShader::TileMode tm, SkUnitMapper* mapper,
51 float scale) {
reed@google.com84e9c082011-04-13 17:44:24 +000052 SkPoint center;
53 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
54 SkScalarAve(pts[0].fY, pts[1].fY));
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000055 return SkGradientShader::CreateRadial(center, center.fX * scale,
56 data.fColors,
reed@google.com84e9c082011-04-13 17:44:24 +000057 data.fPos, data.fCount, tm, mapper);
58}
59
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000060/// Ignores scale
reed@google.com84e9c082011-04-13 17:44:24 +000061static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000062 SkShader::TileMode tm, SkUnitMapper* mapper,
63 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,
68 data.fPos, data.fCount, mapper);
69}
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,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000073 SkShader::TileMode tm, SkUnitMapper* mapper,
74 float scale) {
reed@google.com84e9c082011-04-13 17:44:24 +000075 SkPoint center0, center1;
76 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
77 SkScalarAve(pts[0].fY, pts[1].fY));
78 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
79 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
80 return SkGradientShader::CreateTwoPointRadial(
reed@google.com258e0bf2012-06-07 14:18:34 +000081 center1, (pts[1].fX - pts[0].fX) / 7,
82 center0, (pts[1].fX - pts[0].fX) / 2,
83 data.fColors, data.fPos, data.fCount, tm, mapper);
84}
85
86/// Ignores scale
87static SkShader* MakeConical(const SkPoint pts[2], const GradData& data,
88 SkShader::TileMode tm, SkUnitMapper* mapper,
89 float scale) {
90 SkPoint center0, center1;
91 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
92 SkScalarAve(pts[0].fY, pts[1].fY));
93 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
94 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
95 return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
96 center0, (pts[1].fX - pts[0].fX) / 2,
97 data.fColors, data.fPos, data.fCount, tm, mapper);
reed@google.com84e9c082011-04-13 17:44:24 +000098}
99
100typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000101 SkShader::TileMode tm, SkUnitMapper* mapper,
102 float scale);
reed@google.com84e9c082011-04-13 17:44:24 +0000103
104static const struct {
105 GradMaker fMaker;
106 const char* fName;
107 int fRepeat;
108} gGrads[] = {
109 { MakeLinear, "linear", 15 },
reed@google.com80adceb2011-04-13 18:32:19 +0000110 { MakeRadial, "radial1", 10 },
reed@google.com84e9c082011-04-13 17:44:24 +0000111 { MakeSweep, "sweep", 1 },
112 { Make2Radial, "radial2", 5 },
reed@google.com258e0bf2012-06-07 14:18:34 +0000113 { MakeConical, "conical", 5 },
reed@google.com84e9c082011-04-13 17:44:24 +0000114};
115
116enum GradType { // these must match the order in gGrads
117 kLinear_GradType,
118 kRadial_GradType,
119 kSweep_GradType,
reed@google.com258e0bf2012-06-07 14:18:34 +0000120 kRadial2_GradType,
121 kConical_GradType
reed@google.com84e9c082011-04-13 17:44:24 +0000122};
123
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000124enum GeomType {
125 kRect_GeomType,
126 kOval_GeomType
127};
128
reed@google.com72415162011-06-15 21:17:37 +0000129static const char* tilemodename(SkShader::TileMode tm) {
130 switch (tm) {
131 case SkShader::kClamp_TileMode:
132 return "clamp";
133 case SkShader::kRepeat_TileMode:
134 return "repeat";
135 case SkShader::kMirror_TileMode:
136 return "mirror";
137 default:
138 SkASSERT(!"unknown tilemode");
139 return "error";
140 }
141}
142
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000143static const char* geomtypename(GeomType gt) {
144 switch (gt) {
145 case kRect_GeomType:
146 return "rectangle";
147 case kOval_GeomType:
148 return "oval";
149 default:
150 SkASSERT(!"unknown geometry type");
151 return "error";
152 }
153}
154
reed@google.com84e9c082011-04-13 17:44:24 +0000155///////////////////////////////////////////////////////////////////////////////
156
157class GradientBench : public SkBenchmark {
158 SkString fName;
159 SkShader* fShader;
160 int fCount;
161 enum {
162 W = 400,
163 H = 400,
164 N = 1
165 };
166public:
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000167 GradientBench(void* param, GradType gradType,
168 SkShader::TileMode tm = SkShader::kClamp_TileMode,
169 GeomType geomType = kRect_GeomType,
170 float scale = 1.0f)
171 : INHERITED(param) {
172 fName.printf("gradient_%s_%s", gGrads[gradType].fName,
173 tilemodename(tm));
174 if (geomType != kRect_GeomType) {
175 fName.append("_");
176 fName.append(geomtypename(geomType));
177 }
reed@google.com84e9c082011-04-13 17:44:24 +0000178
179 const SkPoint pts[2] = {
180 { 0, 0 },
181 { SkIntToScalar(W), SkIntToScalar(H) }
182 };
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000183
tomhudson@google.comca529d32011-10-28 15:34:49 +0000184 fCount = SkBENCHLOOP(N * gGrads[gradType].fRepeat);
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000185 fShader = gGrads[gradType].fMaker(pts, gGradData[0], tm, NULL, scale);
186 fGeomType = geomType;
reed@google.com84e9c082011-04-13 17:44:24 +0000187 }
188
189 virtual ~GradientBench() {
190 fShader->unref();
191 }
192
193protected:
194 virtual const char* onGetName() {
195 return fName.c_str();
196 }
197
198 virtual void onDraw(SkCanvas* canvas) {
199 SkPaint paint;
200 this->setupPaint(&paint);
201
202 paint.setShader(fShader);
203
204 SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
205 for (int i = 0; i < fCount; i++) {
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000206 switch (fGeomType) {
207 case kRect_GeomType:
208 canvas->drawRect(r, paint);
209 break;
210 case kOval_GeomType:
211 canvas->drawOval(r, paint);
212 break;
213 }
reed@google.com84e9c082011-04-13 17:44:24 +0000214 }
215 }
216
217private:
218 typedef SkBenchmark INHERITED;
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000219
220 GeomType fGeomType;
reed@google.com84e9c082011-04-13 17:44:24 +0000221};
222
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000223class Gradient2Bench : public SkBenchmark {
224public:
225 Gradient2Bench(void* param) : INHERITED(param) {}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000226
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000227protected:
228 virtual const char* onGetName() {
229 return "gradient_create";
230 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000231
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000232 virtual void onDraw(SkCanvas* canvas) {
233 SkPaint paint;
234 this->setupPaint(&paint);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000235
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000236 const SkRect r = { 0, 0, SkIntToScalar(4), SkIntToScalar(4) };
reed@google.com1ca4f262011-06-24 19:17:37 +0000237 const SkPoint pts[] = {
238 { 0, 0 },
239 { SkIntToScalar(100), SkIntToScalar(100) },
240 };
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000241
tomhudson@google.comca529d32011-10-28 15:34:49 +0000242 for (int i = 0; i < SkBENCHLOOP(1000); i++) {
bungeman@google.com6d0c02c2011-06-17 17:56:23 +0000243 const int a = i % 256;
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000244 SkColor colors[] = {
245 SK_ColorBLACK,
246 SkColorSetARGB(a, a, a, a),
247 SK_ColorWHITE };
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000248 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
249 SK_ARRAY_COUNT(colors),
250 SkShader::kClamp_TileMode);
251 paint.setShader(s)->unref();
252 canvas->drawRect(r, paint);
253 }
254 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000255
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000256private:
257 typedef SkBenchmark INHERITED;
258};
259
reed@google.com84e9c082011-04-13 17:44:24 +0000260static SkBenchmark* Fact0(void* p) { return new GradientBench(p, kLinear_GradType); }
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000261static SkBenchmark* Fact01(void* p) { return new GradientBench(p, kLinear_GradType, SkShader::kMirror_TileMode); }
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000262
263// Draw a radial gradient of radius 1/2 on a rectangle; half the lines should
264// be completely pinned, the other half should pe partially pinned
265static SkBenchmark* Fact1(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kClamp_TileMode, kRect_GeomType, 0.5f); }
266
267// Draw a radial gradient on a circle of equal size; all the lines should
268// hit the unpinned fast path (so long as GradientBench.W == H)
269static SkBenchmark* Fact1o(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kClamp_TileMode, kOval_GeomType); }
270
reed@google.com72415162011-06-15 21:17:37 +0000271static SkBenchmark* Fact11(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kMirror_TileMode); }
reed@google.com84e9c082011-04-13 17:44:24 +0000272static SkBenchmark* Fact2(void* p) { return new GradientBench(p, kSweep_GradType); }
273static SkBenchmark* Fact3(void* p) { return new GradientBench(p, kRadial2_GradType); }
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000274static SkBenchmark* Fact31(void* p) { return new GradientBench(p, kRadial2_GradType, SkShader::kMirror_TileMode); }
reed@google.com258e0bf2012-06-07 14:18:34 +0000275static SkBenchmark* Fact5(void* p) { return new GradientBench(p, kConical_GradType); }
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000276
277static SkBenchmark* Fact4(void* p) { return new Gradient2Bench(p); }
reed@google.com84e9c082011-04-13 17:44:24 +0000278
279static BenchRegistry gReg0(Fact0);
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000280static BenchRegistry gReg01(Fact01);
reed@google.com84e9c082011-04-13 17:44:24 +0000281static BenchRegistry gReg1(Fact1);
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000282static BenchRegistry gReg1o(Fact1o);
reed@google.com72415162011-06-15 21:17:37 +0000283static BenchRegistry gReg11(Fact11);
reed@google.com84e9c082011-04-13 17:44:24 +0000284static BenchRegistry gReg2(Fact2);
285static BenchRegistry gReg3(Fact3);
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000286static BenchRegistry gReg31(Fact31);
reed@google.com258e0bf2012-06-07 14:18:34 +0000287static BenchRegistry gReg5(Fact5);
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000288
289static BenchRegistry gReg4(Fact4);
reed@google.com84e9c082011-04-13 17:44:24 +0000290