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