blob: a5032eaa78845777ab0e9bbe5c401517fce8ba97 [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(
tomhudson@google.com5ea050f2011-09-26 15:03:55 +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);
reed@google.com84e9c082011-04-13 17:44:24 +000084}
85
86typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
tomhudson@google.com5ea050f2011-09-26 15:03:55 +000087 SkShader::TileMode tm, SkUnitMapper* mapper,
88 float scale);
reed@google.com84e9c082011-04-13 17:44:24 +000089
90static const struct {
91 GradMaker fMaker;
92 const char* fName;
93 int fRepeat;
94} gGrads[] = {
95 { MakeLinear, "linear", 15 },
reed@google.com80adceb2011-04-13 18:32:19 +000096 { MakeRadial, "radial1", 10 },
reed@google.com84e9c082011-04-13 17:44:24 +000097 { MakeSweep, "sweep", 1 },
98 { Make2Radial, "radial2", 5 },
99};
100
101enum GradType { // these must match the order in gGrads
102 kLinear_GradType,
103 kRadial_GradType,
104 kSweep_GradType,
105 kRadial2_GradType
106};
107
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000108enum GeomType {
109 kRect_GeomType,
110 kOval_GeomType
111};
112
reed@google.com72415162011-06-15 21:17:37 +0000113static const char* tilemodename(SkShader::TileMode tm) {
114 switch (tm) {
115 case SkShader::kClamp_TileMode:
116 return "clamp";
117 case SkShader::kRepeat_TileMode:
118 return "repeat";
119 case SkShader::kMirror_TileMode:
120 return "mirror";
121 default:
122 SkASSERT(!"unknown tilemode");
123 return "error";
124 }
125}
126
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000127static const char* geomtypename(GeomType gt) {
128 switch (gt) {
129 case kRect_GeomType:
130 return "rectangle";
131 case kOval_GeomType:
132 return "oval";
133 default:
134 SkASSERT(!"unknown geometry type");
135 return "error";
136 }
137}
138
reed@google.com84e9c082011-04-13 17:44:24 +0000139///////////////////////////////////////////////////////////////////////////////
140
141class GradientBench : public SkBenchmark {
142 SkString fName;
143 SkShader* fShader;
144 int fCount;
145 enum {
146 W = 400,
147 H = 400,
148 N = 1
149 };
150public:
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000151 GradientBench(void* param, GradType gradType,
152 SkShader::TileMode tm = SkShader::kClamp_TileMode,
153 GeomType geomType = kRect_GeomType,
154 float scale = 1.0f)
155 : INHERITED(param) {
156 fName.printf("gradient_%s_%s", gGrads[gradType].fName,
157 tilemodename(tm));
158 if (geomType != kRect_GeomType) {
159 fName.append("_");
160 fName.append(geomtypename(geomType));
161 }
reed@google.com84e9c082011-04-13 17:44:24 +0000162
163 const SkPoint pts[2] = {
164 { 0, 0 },
165 { SkIntToScalar(W), SkIntToScalar(H) }
166 };
167
tomhudson@google.comca529d32011-10-28 15:34:49 +0000168 fCount = SkBENCHLOOP(N * gGrads[gradType].fRepeat);
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000169 fShader = gGrads[gradType].fMaker(pts, gGradData[0], tm, NULL, scale);
170 fGeomType = geomType;
reed@google.com84e9c082011-04-13 17:44:24 +0000171 }
172
173 virtual ~GradientBench() {
174 fShader->unref();
175 }
176
177protected:
178 virtual const char* onGetName() {
179 return fName.c_str();
180 }
181
182 virtual void onDraw(SkCanvas* canvas) {
183 SkPaint paint;
184 this->setupPaint(&paint);
185
186 paint.setShader(fShader);
187
188 SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
189 for (int i = 0; i < fCount; i++) {
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000190 switch (fGeomType) {
191 case kRect_GeomType:
192 canvas->drawRect(r, paint);
193 break;
194 case kOval_GeomType:
195 canvas->drawOval(r, paint);
196 break;
197 }
reed@google.com84e9c082011-04-13 17:44:24 +0000198 }
199 }
200
201private:
202 typedef SkBenchmark INHERITED;
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000203
204 GeomType fGeomType;
reed@google.com84e9c082011-04-13 17:44:24 +0000205};
206
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000207class Gradient2Bench : public SkBenchmark {
208public:
209 Gradient2Bench(void* param) : INHERITED(param) {}
210
211protected:
212 virtual const char* onGetName() {
213 return "gradient_create";
214 }
215
216 virtual void onDraw(SkCanvas* canvas) {
217 SkPaint paint;
218 this->setupPaint(&paint);
219
220 const SkRect r = { 0, 0, SkIntToScalar(4), SkIntToScalar(4) };
reed@google.com1ca4f262011-06-24 19:17:37 +0000221 const SkPoint pts[] = {
222 { 0, 0 },
223 { SkIntToScalar(100), SkIntToScalar(100) },
224 };
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000225
tomhudson@google.comca529d32011-10-28 15:34:49 +0000226 for (int i = 0; i < SkBENCHLOOP(1000); i++) {
bungeman@google.com6d0c02c2011-06-17 17:56:23 +0000227 const int a = i % 256;
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000228 SkColor colors[] = {
229 SK_ColorBLACK,
230 SkColorSetARGB(a, a, a, a),
231 SK_ColorWHITE };
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000232 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
233 SK_ARRAY_COUNT(colors),
234 SkShader::kClamp_TileMode);
235 paint.setShader(s)->unref();
236 canvas->drawRect(r, paint);
237 }
238 }
239
240private:
241 typedef SkBenchmark INHERITED;
242};
243
reed@google.com84e9c082011-04-13 17:44:24 +0000244static SkBenchmark* Fact0(void* p) { return new GradientBench(p, kLinear_GradType); }
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000245static SkBenchmark* Fact01(void* p) { return new GradientBench(p, kLinear_GradType, SkShader::kMirror_TileMode); }
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000246
247// Draw a radial gradient of radius 1/2 on a rectangle; half the lines should
248// be completely pinned, the other half should pe partially pinned
249static SkBenchmark* Fact1(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kClamp_TileMode, kRect_GeomType, 0.5f); }
250
251// Draw a radial gradient on a circle of equal size; all the lines should
252// hit the unpinned fast path (so long as GradientBench.W == H)
253static SkBenchmark* Fact1o(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kClamp_TileMode, kOval_GeomType); }
254
reed@google.com72415162011-06-15 21:17:37 +0000255static SkBenchmark* Fact11(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kMirror_TileMode); }
reed@google.com84e9c082011-04-13 17:44:24 +0000256static SkBenchmark* Fact2(void* p) { return new GradientBench(p, kSweep_GradType); }
257static SkBenchmark* Fact3(void* p) { return new GradientBench(p, kRadial2_GradType); }
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000258static SkBenchmark* Fact31(void* p) { return new GradientBench(p, kRadial2_GradType, SkShader::kMirror_TileMode); }
259
260static SkBenchmark* Fact4(void* p) { return new Gradient2Bench(p); }
reed@google.com84e9c082011-04-13 17:44:24 +0000261
262static BenchRegistry gReg0(Fact0);
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000263static BenchRegistry gReg01(Fact01);
reed@google.com84e9c082011-04-13 17:44:24 +0000264static BenchRegistry gReg1(Fact1);
tomhudson@google.com5ea050f2011-09-26 15:03:55 +0000265static BenchRegistry gReg1o(Fact1o);
reed@google.com72415162011-06-15 21:17:37 +0000266static BenchRegistry gReg11(Fact11);
reed@google.com84e9c082011-04-13 17:44:24 +0000267static BenchRegistry gReg2(Fact2);
268static BenchRegistry gReg3(Fact3);
reed@google.com8ac7a0f2011-06-16 13:14:19 +0000269static BenchRegistry gReg31(Fact31);
270
271static BenchRegistry gReg4(Fact4);
reed@google.com84e9c082011-04-13 17:44:24 +0000272