1
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 */
8#include "Benchmark.h"
9#include "SkCanvas.h"
10#include "SkCommandLineFlags.h"
11#include "SkPaint.h"
12#include "SkRandom.h"
13#include "SkShader.h"
14#include "SkString.h"
15
16DEFINE_double(strokeWidth, -1.0, "If set, use this stroke width in RectBench.");
17
18class RectBench : public Benchmark {
19public:
20    int fShift, fStroke;
21    enum {
22        W = 640,
23        H = 480,
24        N = 300,
25    };
26    SkRect  fRects[N];
27    SkColor fColors[N];
28
29    RectBench(int shift, int stroke = 0)
30        : fShift(shift)
31        , fStroke(stroke) {}
32
33    SkString fName;
34    const char* computeName(const char root[]) {
35        fName.printf("%s_%d", root, fShift);
36        if (fStroke > 0) {
37            fName.appendf("_stroke_%d", fStroke);
38        }
39        return fName.c_str();
40    }
41
42protected:
43    virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) {
44        c->drawRect(r, p);
45    }
46
47    virtual const char* onGetName() { return computeName("rects"); }
48
49    virtual void onPreDraw() {
50        SkRandom rand;
51        const SkScalar offset = SK_Scalar1/3;
52        for (int i = 0; i < N; i++) {
53            int x = rand.nextU() % W;
54            int y = rand.nextU() % H;
55            int w = rand.nextU() % W;
56            int h = rand.nextU() % H;
57            w >>= fShift;
58            h >>= fShift;
59            x -= w/2;
60            y -= h/2;
61            fRects[i].set(SkIntToScalar(x), SkIntToScalar(y),
62                          SkIntToScalar(x+w), SkIntToScalar(y+h));
63            fRects[i].offset(offset, offset);
64            fColors[i] = rand.nextU() | 0xFF808080;
65        }
66    }
67
68    virtual void onDraw(const int loops, SkCanvas* canvas) {
69        SkPaint paint;
70        if (fStroke > 0) {
71            paint.setStyle(SkPaint::kStroke_Style);
72            paint.setStrokeWidth(SkIntToScalar(fStroke));
73        }
74        for (int i = 0; i < loops; i++) {
75            paint.setColor(fColors[i % N]);
76            this->setupPaint(&paint);
77            this->drawThisRect(canvas, fRects[i % N], paint);
78        }
79    }
80private:
81    typedef Benchmark INHERITED;
82};
83
84class SrcModeRectBench : public RectBench {
85public:
86    SrcModeRectBench() : INHERITED(1, 0) {
87        fMode = SkXfermode::Create(SkXfermode::kSrc_Mode);
88    }
89
90    virtual ~SrcModeRectBench() {
91        SkSafeUnref(fMode);
92    }
93
94protected:
95    void setupPaint(SkPaint* paint) override {
96        this->INHERITED::setupPaint(paint);
97        // srcmode is most interesting when we're not opaque
98        paint->setAlpha(0x80);
99        paint->setXfermode(fMode);
100    }
101
102    const char* onGetName() override {
103        fName.set(this->INHERITED::onGetName());
104        fName.prepend("srcmode_");
105        return fName.c_str();
106    }
107
108private:
109    SkString fName;
110    SkXfermode* fMode;
111
112    typedef RectBench INHERITED;
113};
114
115class OvalBench : public RectBench {
116public:
117    OvalBench(int shift, int stroke = 0) : RectBench(shift, stroke) {}
118protected:
119    virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) {
120        c->drawOval(r, p);
121    }
122    virtual const char* onGetName() { return computeName("ovals"); }
123};
124
125class RRectBench : public RectBench {
126public:
127    RRectBench(int shift, int stroke = 0) : RectBench(shift, stroke) {}
128protected:
129    virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) {
130        c->drawRoundRect(r, r.width() / 4, r.height() / 4, p);
131    }
132    virtual const char* onGetName() { return computeName("rrects"); }
133};
134
135class PointsBench : public RectBench {
136public:
137    SkCanvas::PointMode fMode;
138    const char* fName;
139
140    PointsBench(SkCanvas::PointMode mode, const char* name)
141        : RectBench(2)
142        , fMode(mode) {
143        fName = name;
144    }
145
146protected:
147    virtual void onDraw(const int loops, SkCanvas* canvas) {
148        SkScalar gSizes[] = {
149            SkIntToScalar(7), 0
150        };
151        size_t sizes = SK_ARRAY_COUNT(gSizes);
152
153        if (FLAGS_strokeWidth >= 0) {
154            gSizes[0] = (SkScalar)FLAGS_strokeWidth;
155            sizes = 1;
156        }
157
158        SkPaint paint;
159        paint.setStrokeCap(SkPaint::kRound_Cap);
160
161        for (int loop = 0; loop < loops; loop++) {
162            for (size_t i = 0; i < sizes; i++) {
163                paint.setStrokeWidth(gSizes[i]);
164                this->setupPaint(&paint);
165                canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint);
166                paint.setColor(fColors[i % N]);
167            }
168        }
169    }
170    virtual const char* onGetName() { return fName; }
171};
172
173/*******************************************************************************
174 * to bench BlitMask [Opaque, Black, color, shader]
175 *******************************************************************************/
176
177class BlitMaskBench : public RectBench {
178public:
179    enum kMaskType {
180        kMaskOpaque = 0,
181        kMaskBlack,
182        kMaskColor,
183        KMaskShader
184    };
185    SkCanvas::PointMode fMode;
186    const char* fName;
187
188    BlitMaskBench(SkCanvas::PointMode mode,
189                  BlitMaskBench::kMaskType type, const char* name) :
190        RectBench(2), fMode(mode), _type(type) {
191        fName = name;
192    }
193
194protected:
195    virtual void onDraw(const int loops, SkCanvas* canvas) {
196        SkScalar gSizes[] = {
197            SkIntToScalar(13), SkIntToScalar(24)
198        };
199        size_t sizes = SK_ARRAY_COUNT(gSizes);
200
201        if (FLAGS_strokeWidth >= 0) {
202            gSizes[0] = (SkScalar)FLAGS_strokeWidth;
203            sizes = 1;
204        }
205        SkRandom rand;
206        SkColor color = 0xFF000000;
207        U8CPU alpha = 0xFF;
208        SkPaint paint;
209        paint.setStrokeCap(SkPaint::kRound_Cap);
210        if (_type == KMaskShader) {
211            SkBitmap srcBM;
212            srcBM.allocN32Pixels(10, 1);
213            srcBM.eraseColor(0xFF00FF00);
214
215            SkShader* s;
216            s  = SkShader::CreateBitmapShader(srcBM, SkShader::kClamp_TileMode,
217                                              SkShader::kClamp_TileMode);
218            paint.setShader(s)->unref();
219        }
220        for (int loop = 0; loop < loops; loop++) {
221            for (size_t i = 0; i < sizes; i++) {
222                switch (_type) {
223                    case kMaskOpaque:
224                        color = fColors[i];
225                        alpha = 0xFF;
226                        break;
227                    case kMaskBlack:
228                        alpha = 0xFF;
229                        color = 0xFF000000;
230                        break;
231                    case kMaskColor:
232                        color = fColors[i];
233                        alpha = rand.nextU() & 255;
234                        break;
235                    case KMaskShader:
236                        break;
237                }
238                paint.setStrokeWidth(gSizes[i]);
239                this->setupPaint(&paint);
240                paint.setColor(color);
241                paint.setAlpha(alpha);
242                canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint);
243           }
244        }
245    }
246    virtual const char* onGetName() { return fName; }
247private:
248    typedef RectBench INHERITED;
249    kMaskType _type;
250};
251
252
253DEF_BENCH( return SkNEW_ARGS(RectBench, (1)); )
254DEF_BENCH( return SkNEW_ARGS(RectBench, (1, 4)); )
255DEF_BENCH( return SkNEW_ARGS(RectBench, (3)); )
256DEF_BENCH( return SkNEW_ARGS(RectBench, (3, 4)); )
257DEF_BENCH( return SkNEW_ARGS(OvalBench, (1)); )
258DEF_BENCH( return SkNEW_ARGS(OvalBench, (3)); )
259DEF_BENCH( return SkNEW_ARGS(OvalBench, (1, 4)); )
260DEF_BENCH( return SkNEW_ARGS(OvalBench, (3, 4)); )
261DEF_BENCH( return SkNEW_ARGS(RRectBench, (1)); )
262DEF_BENCH( return SkNEW_ARGS(RRectBench, (1, 4)); )
263DEF_BENCH( return SkNEW_ARGS(RRectBench, (3)); )
264DEF_BENCH( return SkNEW_ARGS(RRectBench, (3, 4)); )
265DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kPoints_PointMode, "points")); )
266DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kLines_PointMode, "lines")); )
267DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kPolygon_PointMode, "polygon")); )
268
269DEF_BENCH( return SkNEW_ARGS(SrcModeRectBench, ()); )
270
271/* init the blitmask bench
272 */
273DEF_BENCH( return SkNEW_ARGS(BlitMaskBench,
274                      (SkCanvas::kPoints_PointMode,
275                      BlitMaskBench::kMaskOpaque, "maskopaque")
276                      ); )
277DEF_BENCH( return SkNEW_ARGS(BlitMaskBench,
278                      (SkCanvas::kPoints_PointMode,
279                      BlitMaskBench::kMaskBlack, "maskblack")
280                      ); )
281DEF_BENCH( return SkNEW_ARGS(BlitMaskBench,
282                      (SkCanvas::kPoints_PointMode,
283                      BlitMaskBench::kMaskColor, "maskcolor")
284                      ); )
285DEF_BENCH( return SkNEW_ARGS(BlitMaskBench,
286                     (SkCanvas::kPoints_PointMode,
287                     BlitMaskBench::KMaskShader, "maskshader")
288                     ); )
289