1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Benchmark.h"
9
10#include "SkCanvas.h"
11#include "SkShader.h"
12#include "SkGradientShader.h"
13#include "SkString.h"
14#include "SkColor.h"
15#include "SkPaint.h"
16
17static const char* get_tilemode_name(SkShader::TileMode tilemode) {
18    switch (tilemode) {
19        case SkShader::kClamp_TileMode:
20            return "clamp";
21        case SkShader::kRepeat_TileMode:
22            return "repeat";
23        case SkShader::kMirror_TileMode:
24            return "mirror";
25        default:
26            SkDEBUGFAIL("Unknown tilemode");
27            return "error";
28    }
29}
30
31class HardStopGradientBench_ScaleNumColors : public Benchmark {
32public:
33    HardStopGradientBench_ScaleNumColors(SkShader::TileMode tilemode, int count) {
34        fName.printf("hardstop_scale_num_colors_%s_%03d_colors", get_tilemode_name(tilemode), count);
35
36        fTileMode   = tilemode;
37        fColorCount = count;
38    }
39
40    const char* onGetName() override {
41        return fName.c_str();
42    }
43
44    SkIPoint onGetSize() override {
45        return SkIPoint::Make(kSize, kSize);
46    }
47
48    /*
49     * Set up a linear gradient from left to right with
50     * fColorCount colors alternating between four
51     * different colors. The positions are evenly spaced,
52     * with the exception of the first two; these create a
53     * hard stop in order to trigger the hard stop code.
54     */
55    void onPreDraw(SkCanvas* canvas) override {
56        // Left to right
57        SkPoint points[2] = {
58            SkPoint::Make(0,        kSize/2),
59            SkPoint::Make(kSize-1,  kSize/2),
60        };
61
62        constexpr int kNumColorChoices = 4;
63        SkColor color_choices[kNumColorChoices] = {
64            SK_ColorRED,
65            SK_ColorGREEN,
66            SK_ColorBLUE,
67            SK_ColorYELLOW,
68        };
69
70        // Alternate between different choices
71        SkColor  colors[100];
72        for (int i = 0; i < fColorCount; i++) {
73            colors[i] = color_choices[i % kNumColorChoices];
74        }
75
76        // Create a hard stop
77        SkScalar positions[100];
78        positions[0] = 0.0f;
79        positions[1] = 0.0f;
80        for (int i = 2; i < fColorCount; i++) {
81            // Evenly spaced afterwards
82            positions[i] = i / (fColorCount - 1.0f);
83        }
84
85        fPaint.setShader(SkGradientShader::MakeLinear(points,
86                                                      colors,
87                                                      positions,
88                                                      fColorCount,
89                                                      fTileMode,
90                                                      0,
91                                                      nullptr));
92    }
93
94    /*
95     * Draw simple linear gradient from left to right
96     */
97    void onDraw(int loops, SkCanvas* canvas) override {
98        for (int i = 0; i < loops; i++) {
99            canvas->drawPaint(fPaint);
100        }
101    }
102
103private:
104    static const int kSize = 500;
105
106    SkShader::TileMode  fTileMode;
107    SkString            fName;
108    int                 fColorCount;
109    SkPaint             fPaint;
110
111    typedef Benchmark INHERITED;
112};
113
114// Clamp
115DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,   3);)
116DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,   4);)
117DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,   5);)
118DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,  10);)
119DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,  25);)
120DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode,  50);)
121DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kClamp_TileMode, 100);)
122
123// Repeat
124DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,   3);)
125DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,   4);)
126DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,   5);)
127DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,  10);)
128DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,  25);)
129DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode,  50);)
130DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kRepeat_TileMode, 100);)
131
132// Mirror
133DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,   3);)
134DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,   4);)
135DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,   5);)
136DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,  10);)
137DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,  25);)
138DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode,  50);)
139DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkShader::kMirror_TileMode, 100);)
140