123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367 |
- /*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "bench/Benchmark.h"
- #include "include/core/SkBitmap.h"
- #include "include/core/SkCanvas.h"
- #include "include/core/SkColorPriv.h"
- #include "include/core/SkPaint.h"
- #include "include/core/SkShader.h"
- #include "include/core/SkString.h"
- #include "include/effects/SkGradientShader.h"
- struct GradData {
- int fCount;
- const SkColor* fColors;
- const SkScalar* fPos;
- const char* fName;
- };
- static const SkColor gColors[] = {
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK, // 10 lines, 50 colors
- };
- static const SkColor gShallowColors[] = { 0xFF555555, 0xFF444444 };
- static const SkScalar gPos[] = {0.25f, 0.75f};
- // We have several special-cases depending on the number (and spacing) of colors, so
- // try to exercise those here.
- static const GradData gGradData[] = {
- { 2, gColors, nullptr, "" },
- { 50, gColors, nullptr, "_hicolor" }, // many color gradient
- { 3, gColors, nullptr, "_3color" },
- { 2, gShallowColors, nullptr, "_shallow" },
- { 2, gColors, gPos, "_pos" },
- };
- /// Ignores scale
- static sk_sp<SkShader> MakeLinear(const SkPoint pts[2], const GradData& data,
- SkTileMode tm, float scale) {
- return SkGradientShader::MakeLinear(pts, data.fColors, data.fPos, data.fCount, tm);
- }
- static sk_sp<SkShader> MakeRadial(const SkPoint pts[2], const GradData& data,
- SkTileMode tm, float scale) {
- SkPoint center;
- center.set(SkScalarAve(pts[0].fX, pts[1].fX),
- SkScalarAve(pts[0].fY, pts[1].fY));
- return SkGradientShader::MakeRadial(center, center.fX * scale, data.fColors,
- data.fPos, data.fCount, tm);
- }
- /// Ignores scale
- static sk_sp<SkShader> MakeSweep(const SkPoint pts[2], const GradData& data,
- SkTileMode tm, float scale) {
- SkPoint center;
- center.set(SkScalarAve(pts[0].fX, pts[1].fX),
- SkScalarAve(pts[0].fY, pts[1].fY));
- return SkGradientShader::MakeSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount);
- }
- /// Ignores scale
- static sk_sp<SkShader> MakeConical(const SkPoint pts[2], const GradData& data,
- SkTileMode tm, 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::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
- center0, (pts[1].fX - pts[0].fX) / 2,
- data.fColors, data.fPos, data.fCount, tm);
- }
- /// Ignores scale
- static sk_sp<SkShader> MakeConicalZeroRad(const SkPoint pts[2], const GradData& data,
- SkTileMode tm, 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::MakeTwoPointConical(center1, 0.0,
- center0, (pts[1].fX - pts[0].fX) / 2,
- data.fColors, data.fPos, data.fCount, tm);
- }
- /// Ignores scale
- static sk_sp<SkShader> MakeConicalOutside(const SkPoint pts[2], const GradData& data,
- SkTileMode tm, float scale) {
- SkPoint center0, center1;
- SkScalar radius0 = (pts[1].fX - pts[0].fX) / 10;
- SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
- center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
- center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
- return SkGradientShader::MakeTwoPointConical(center0, radius0,
- center1, radius1,
- data.fColors, data.fPos,
- data.fCount, tm);
- }
- /// Ignores scale
- static sk_sp<SkShader> MakeConicalOutsideZeroRad(const SkPoint pts[2], const GradData& data,
- SkTileMode tm, float scale) {
- SkPoint center0, center1;
- SkScalar radius0 = (pts[1].fX - pts[0].fX) / 10;
- SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
- center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
- center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
- return SkGradientShader::MakeTwoPointConical(center0, 0.0,
- center1, radius1,
- data.fColors, data.fPos,
- data.fCount, tm);
- }
- typedef sk_sp<SkShader> (*GradMaker)(const SkPoint pts[2], const GradData& data,
- SkTileMode tm, float scale);
- static const struct {
- GradMaker fMaker;
- const char* fName;
- } gGrads[] = {
- { MakeLinear, "linear" },
- { MakeRadial, "radial1" },
- { MakeSweep, "sweep" },
- { MakeConical, "conical" },
- { MakeConicalZeroRad, "conicalZero" },
- { MakeConicalOutside, "conicalOut" },
- { MakeConicalOutsideZeroRad, "conicalOutZero" },
- };
- enum GradType { // these must match the order in gGrads
- kLinear_GradType,
- kRadial_GradType,
- kSweep_GradType,
- kConical_GradType,
- kConicalZero_GradType,
- kConicalOut_GradType,
- kConicalOutZero_GradType
- };
- enum GeomType {
- kRect_GeomType,
- kOval_GeomType
- };
- static const char* tilemodename(SkTileMode tm) {
- switch (tm) {
- case SkTileMode::kClamp:
- return "clamp";
- case SkTileMode::kRepeat:
- return "repeat";
- case SkTileMode::kMirror:
- return "mirror";
- case SkTileMode::kDecal:
- return "decal";
- }
- return "";
- }
- static const char* geomtypename(GeomType gt) {
- switch (gt) {
- case kRect_GeomType:
- return "rectangle";
- case kOval_GeomType:
- return "oval";
- default:
- SkDEBUGFAIL("unknown geometry type");
- return "error";
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- class GradientBench : public Benchmark {
- public:
- GradientBench(GradType gradType,
- GradData data = gGradData[0],
- SkTileMode tm = SkTileMode::kClamp,
- GeomType geomType = kRect_GeomType,
- float scale = 1.0f)
- : fGeomType(geomType) {
- fName.printf("gradient_%s_%s", gGrads[gradType].fName,
- tilemodename(tm));
- if (geomType != kRect_GeomType) {
- fName.appendf("_%s", geomtypename(geomType));
- }
- if (scale != 1.f) {
- fName.appendf("_scale_%g", scale);
- }
- fName.append(data.fName);
- this->setupPaint(&fPaint);
- fPaint.setShader(MakeShader(gradType, data, tm, scale));
- }
- GradientBench(GradType gradType, GradData data, bool dither)
- : fGeomType(kRect_GeomType) {
- const char *tmname = tilemodename(SkTileMode::kClamp);
- fName.printf("gradient_%s_%s", gGrads[gradType].fName, tmname);
- fName.append(data.fName);
- if (dither) {
- fName.appendf("_dither");
- }
- this->setupPaint(&fPaint);
- fPaint.setShader(MakeShader(gradType, data, SkTileMode::kClamp, 1.0f));
- fPaint.setDither(dither);
- }
- protected:
- const char* onGetName() override {
- return fName.c_str();
- }
- SkIPoint onGetSize() override {
- return SkIPoint::Make(kSize, kSize);
- }
- void onDraw(int loops, SkCanvas* canvas) override {
- const SkRect r = SkRect::MakeIWH(kSize, kSize);
- for (int i = 0; i < loops; i++) {
- switch (fGeomType) {
- case kRect_GeomType:
- canvas->drawRect(r, fPaint);
- break;
- case kOval_GeomType:
- canvas->drawOval(r, fPaint);
- break;
- }
- }
- }
- private:
- typedef Benchmark INHERITED;
- sk_sp<SkShader> MakeShader(GradType gradType, GradData data,
- SkTileMode tm, float scale) {
- const SkPoint pts[2] = {
- { 0, 0 },
- { SkIntToScalar(kSize), SkIntToScalar(kSize) }
- };
- return gGrads[gradType].fMaker(pts, data, tm, scale);
- }
- static const int kSize = 400;
- SkString fName;
- SkPaint fPaint;
- const GeomType fGeomType;
- };
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[0]); )
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[1]); )
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[2]); )
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[4]); )
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[0], SkTileMode::kRepeat); )
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[1], SkTileMode::kRepeat); )
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[2], SkTileMode::kRepeat); )
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[0], SkTileMode::kMirror); )
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[1], SkTileMode::kMirror); )
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[2], SkTileMode::kMirror); )
- DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0]); )
- DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[1]); )
- DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[2]); )
- // 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
- DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkTileMode::kClamp, 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)
- DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkTileMode::kClamp, kOval_GeomType); )
- DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkTileMode::kMirror); )
- DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkTileMode::kRepeat); )
- DEF_BENCH( return new GradientBench(kSweep_GradType); )
- DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[1]); )
- DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[2]); )
- DEF_BENCH( return new GradientBench(kConical_GradType); )
- DEF_BENCH( return new GradientBench(kConical_GradType, gGradData[1]); )
- DEF_BENCH( return new GradientBench(kConical_GradType, gGradData[2]); )
- DEF_BENCH( return new GradientBench(kConicalZero_GradType); )
- DEF_BENCH( return new GradientBench(kConicalZero_GradType, gGradData[1]); )
- DEF_BENCH( return new GradientBench(kConicalZero_GradType, gGradData[2]); )
- DEF_BENCH( return new GradientBench(kConicalOut_GradType); )
- DEF_BENCH( return new GradientBench(kConicalOut_GradType, gGradData[1]); )
- DEF_BENCH( return new GradientBench(kConicalOut_GradType, gGradData[2]); )
- DEF_BENCH( return new GradientBench(kConicalOutZero_GradType); )
- DEF_BENCH( return new GradientBench(kConicalOutZero_GradType, gGradData[1]); )
- DEF_BENCH( return new GradientBench(kConicalOutZero_GradType, gGradData[2]); )
- // Dithering
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[3], true); )
- DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[3], false); )
- DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[3], true); )
- DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[3], false); )
- DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[3], true); )
- DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[3], false); )
- DEF_BENCH( return new GradientBench(kConical_GradType, gGradData[3], true); )
- DEF_BENCH( return new GradientBench(kConical_GradType, gGradData[3], false); )
- ///////////////////////////////////////////////////////////////////////////////
- class Gradient2Bench : public Benchmark {
- SkString fName;
- bool fHasAlpha;
- public:
- Gradient2Bench(bool hasAlpha) {
- fName.printf("gradient_create_%s", hasAlpha ? "alpha" : "opaque");
- fHasAlpha = hasAlpha;
- }
- protected:
- virtual const char* onGetName() {
- return fName.c_str();
- }
- virtual void onDraw(int loops, SkCanvas* canvas) {
- SkPaint paint;
- this->setupPaint(&paint);
- const SkRect r = { 0, 0, SkIntToScalar(4), SkIntToScalar(4) };
- const SkPoint pts[] = {
- { 0, 0 },
- { SkIntToScalar(100), SkIntToScalar(100) },
- };
- for (int i = 0; i < loops; i++) {
- const int gray = i % 256;
- const int alpha = fHasAlpha ? gray : 0xFF;
- SkColor colors[] = {
- SK_ColorBLACK,
- SkColorSetARGB(alpha, gray, gray, gray),
- SK_ColorWHITE };
- paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr,
- SK_ARRAY_COUNT(colors),
- SkTileMode::kClamp));
- canvas->drawRect(r, paint);
- }
- }
- private:
- typedef Benchmark INHERITED;
- };
- DEF_BENCH( return new Gradient2Bench(false); )
- DEF_BENCH( return new Gradient2Bench(true); )
|