aboutsummaryrefslogtreecommitdiffhomepage
path: root/bench/GradientBench.cpp
diff options
context:
space:
mode:
authorGravatar tomhudson@google.com <tomhudson@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-09-26 15:03:55 +0000
committerGravatar tomhudson@google.com <tomhudson@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-09-26 15:03:55 +0000
commit5ea050f6620fa9e675a1c801f738e946fa993e14 (patch)
tree917a10b9f137d853c3fd63de7ff4c43e90af2035 /bench/GradientBench.cpp
parentb01ced0042997af4574ab276e37041f1412fd744 (diff)
Optimize software radial gradients (remove branches from the inner loop where
we can, because an entire row is conservatively either outside or inside the gradient.) Change the gradient benchmark to capture both cases, and add new gm to detect errors in these optimized paths. git-svn-id: http://skia.googlecode.com/svn/trunk@2327 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'bench/GradientBench.cpp')
-rw-r--r--bench/GradientBench.cpp90
1 files changed, 73 insertions, 17 deletions
diff --git a/bench/GradientBench.cpp b/bench/GradientBench.cpp
index 707cfc5d4b..04923c9481 100644
--- a/bench/GradientBench.cpp
+++ b/bench/GradientBench.cpp
@@ -38,23 +38,29 @@ static const GradData gGradData[] = {
{ 5, gColors, gPos2 }
};
+/// Ignores scale
static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
- SkShader::TileMode tm, SkUnitMapper* mapper) {
+ SkShader::TileMode tm, SkUnitMapper* mapper,
+ float scale) {
return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
data.fCount, tm, mapper);
}
static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
- SkShader::TileMode tm, SkUnitMapper* mapper) {
+ SkShader::TileMode tm, SkUnitMapper* mapper,
+ float scale) {
SkPoint center;
center.set(SkScalarAve(pts[0].fX, pts[1].fX),
SkScalarAve(pts[0].fY, pts[1].fY));
- return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
+ return SkGradientShader::CreateRadial(center, center.fX * scale,
+ data.fColors,
data.fPos, data.fCount, tm, mapper);
}
+/// Ignores scale
static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
- SkShader::TileMode tm, SkUnitMapper* mapper) {
+ SkShader::TileMode tm, SkUnitMapper* mapper,
+ float scale) {
SkPoint center;
center.set(SkScalarAve(pts[0].fX, pts[1].fX),
SkScalarAve(pts[0].fY, pts[1].fY));
@@ -62,21 +68,24 @@ static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
data.fPos, data.fCount, mapper);
}
+/// Ignores scale
static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
- SkShader::TileMode tm, SkUnitMapper* mapper) {
+ SkShader::TileMode tm, SkUnitMapper* mapper,
+ float scale) {
SkPoint center0, center1;
center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
SkScalarAve(pts[0].fY, pts[1].fY));
center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
return SkGradientShader::CreateTwoPointRadial(
- center1, (pts[1].fX - pts[0].fX) / 7,
- center0, (pts[1].fX - pts[0].fX) / 2,
- data.fColors, data.fPos, data.fCount, tm, mapper);
+ center1, (pts[1].fX - pts[0].fX) / 7,
+ center0, (pts[1].fX - pts[0].fX) / 2,
+ data.fColors, data.fPos, data.fCount, tm, mapper);
}
typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
- SkShader::TileMode tm, SkUnitMapper* mapper);
+ SkShader::TileMode tm, SkUnitMapper* mapper,
+ float scale);
static const struct {
GradMaker fMaker;
@@ -96,6 +105,11 @@ enum GradType { // these must match the order in gGrads
kRadial2_GradType
};
+enum GeomType {
+ kRect_GeomType,
+ kOval_GeomType
+};
+
static const char* tilemodename(SkShader::TileMode tm) {
switch (tm) {
case SkShader::kClamp_TileMode:
@@ -110,6 +124,18 @@ static const char* tilemodename(SkShader::TileMode tm) {
}
}
+static const char* geomtypename(GeomType gt) {
+ switch (gt) {
+ case kRect_GeomType:
+ return "rectangle";
+ case kOval_GeomType:
+ return "oval";
+ default:
+ SkASSERT(!"unknown geometry type");
+ return "error";
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
class GradientBench : public SkBenchmark {
@@ -122,17 +148,26 @@ class GradientBench : public SkBenchmark {
N = 1
};
public:
- GradientBench(void* param, GradType gt,
- SkShader::TileMode tm = SkShader::kClamp_TileMode) : INHERITED(param) {
- fName.printf("gradient_%s_%s", gGrads[gt].fName, tilemodename(tm));
+ GradientBench(void* param, GradType gradType,
+ SkShader::TileMode tm = SkShader::kClamp_TileMode,
+ GeomType geomType = kRect_GeomType,
+ float scale = 1.0f)
+ : INHERITED(param) {
+ fName.printf("gradient_%s_%s", gGrads[gradType].fName,
+ tilemodename(tm));
+ if (geomType != kRect_GeomType) {
+ fName.append("_");
+ fName.append(geomtypename(geomType));
+ }
const SkPoint pts[2] = {
{ 0, 0 },
{ SkIntToScalar(W), SkIntToScalar(H) }
};
- fCount = N * gGrads[gt].fRepeat;
- fShader = gGrads[gt].fMaker(pts, gGradData[0], tm, NULL);
+ fCount = N * gGrads[gradType].fRepeat;
+ fShader = gGrads[gradType].fMaker(pts, gGradData[0], tm, NULL, scale);
+ fGeomType = geomType;
}
virtual ~GradientBench() {
@@ -152,12 +187,21 @@ protected:
SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
for (int i = 0; i < fCount; i++) {
- canvas->drawRect(r, paint);
+ switch (fGeomType) {
+ case kRect_GeomType:
+ canvas->drawRect(r, paint);
+ break;
+ case kOval_GeomType:
+ canvas->drawOval(r, paint);
+ break;
+ }
}
}
private:
typedef SkBenchmark INHERITED;
+
+ GeomType fGeomType;
};
class Gradient2Bench : public SkBenchmark {
@@ -181,7 +225,10 @@ protected:
for (int i = 0; i < 1000; i++) {
const int a = i % 256;
- SkColor colors[] = { SK_ColorBLACK, SkColorSetARGB(a, a, a, a), SK_ColorWHITE };
+ SkColor colors[] = {
+ SK_ColorBLACK,
+ SkColorSetARGB(a, a, a, a),
+ SK_ColorWHITE };
SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
SK_ARRAY_COUNT(colors),
SkShader::kClamp_TileMode);
@@ -196,7 +243,15 @@ private:
static SkBenchmark* Fact0(void* p) { return new GradientBench(p, kLinear_GradType); }
static SkBenchmark* Fact01(void* p) { return new GradientBench(p, kLinear_GradType, SkShader::kMirror_TileMode); }
-static SkBenchmark* Fact1(void* p) { return new GradientBench(p, kRadial_GradType); }
+
+// Draw a radial gradient of radius 1/2 on a rectangle; half the lines should
+// be completely pinned, the other half should pe partially pinned
+static SkBenchmark* Fact1(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kClamp_TileMode, kRect_GeomType, 0.5f); }
+
+// Draw a radial gradient on a circle of equal size; all the lines should
+// hit the unpinned fast path (so long as GradientBench.W == H)
+static SkBenchmark* Fact1o(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kClamp_TileMode, kOval_GeomType); }
+
static SkBenchmark* Fact11(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kMirror_TileMode); }
static SkBenchmark* Fact2(void* p) { return new GradientBench(p, kSweep_GradType); }
static SkBenchmark* Fact3(void* p) { return new GradientBench(p, kRadial2_GradType); }
@@ -207,6 +262,7 @@ static SkBenchmark* Fact4(void* p) { return new Gradient2Bench(p); }
static BenchRegistry gReg0(Fact0);
static BenchRegistry gReg01(Fact01);
static BenchRegistry gReg1(Fact1);
+static BenchRegistry gReg1o(Fact1o);
static BenchRegistry gReg11(Fact11);
static BenchRegistry gReg2(Fact2);
static BenchRegistry gReg3(Fact3);