1/*
2 * Copyright 2013 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#include "Benchmark.h"
8#include "SkCanvas.h"
9#include "SkColorFilterImageFilter.h"
10#include "SkColorMatrixFilter.h"
11#include "SkLumaColorFilter.h"
12#include "SkTableColorFilter.h"
13
14#define FILTER_WIDTH_SMALL  SkIntToScalar(32)
15#define FILTER_HEIGHT_SMALL SkIntToScalar(32)
16#define FILTER_WIDTH_LARGE  SkIntToScalar(256)
17#define FILTER_HEIGHT_LARGE SkIntToScalar(256)
18
19class ColorFilterBaseBench : public Benchmark {
20
21public:
22    ColorFilterBaseBench(bool small) : fIsSmall(small) { }
23
24protected:
25    SkRect getFilterRect() const {
26        return isSmall() ? SkRect::MakeWH(FILTER_WIDTH_SMALL, FILTER_HEIGHT_SMALL) :
27                           SkRect::MakeWH(FILTER_WIDTH_LARGE, FILTER_HEIGHT_LARGE);
28    }
29
30    static SkImageFilter* make_brightness(float amount, SkImageFilter* input = NULL) {
31        SkScalar amount255 = SkScalarMul(amount, SkIntToScalar(255));
32        SkScalar matrix[20] = { 1, 0, 0, 0, amount255,
33                                0, 1, 0, 0, amount255,
34                                0, 0, 1, 0, amount255,
35                                0, 0, 0, 1, 0 };
36        SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
37        return SkColorFilterImageFilter::Create(filter, input);
38    }
39
40    static SkImageFilter* make_grayscale(SkImageFilter* input = NULL) {
41        SkScalar matrix[20];
42        memset(matrix, 0, 20 * sizeof(SkScalar));
43        matrix[0] = matrix[5] = matrix[10] = 0.2126f;
44        matrix[1] = matrix[6] = matrix[11] = 0.7152f;
45        matrix[2] = matrix[7] = matrix[12] = 0.0722f;
46        matrix[18] = 1.0f;
47        SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
48        return SkColorFilterImageFilter::Create(filter, input);
49    }
50
51    static SkImageFilter* make_mode_blue(SkImageFilter* input = NULL) {
52        SkAutoTUnref<SkColorFilter> filter(
53            SkColorFilter::CreateModeFilter(SK_ColorBLUE, SkXfermode::kSrcIn_Mode));
54        return SkColorFilterImageFilter::Create(filter, input);
55    }
56
57    inline bool isSmall() const { return fIsSmall; }
58private:
59    bool fIsSmall;
60
61    typedef Benchmark INHERITED;
62};
63
64class ColorFilterDimBrightBench : public ColorFilterBaseBench {
65
66public:
67    ColorFilterDimBrightBench(bool small) : INHERITED(small) {
68    }
69
70protected:
71    virtual const char* onGetName() SK_OVERRIDE {
72        return isSmall() ? "colorfilter_dim_bright_small" : "colorfilter_dim_bright_large";
73    }
74
75    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
76        SkRect r = getFilterRect();
77        SkPaint paint;
78        paint.setColor(SK_ColorRED);
79
80        for (int i = 0; i < loops; i++) {
81            for (float brightness = -1.0f; brightness <= 1.0f; brightness += 0.4f) {
82                SkAutoTUnref<SkImageFilter> dim(make_brightness(-brightness));
83                SkAutoTUnref<SkImageFilter> bright(make_brightness(brightness, dim));
84                paint.setImageFilter(bright);
85                canvas->drawRect(r, paint);
86            }
87        }
88    }
89
90private:
91    typedef ColorFilterBaseBench INHERITED;
92};
93
94class ColorFilterBrightGrayBench : public ColorFilterBaseBench {
95
96public:
97    ColorFilterBrightGrayBench(bool small) : INHERITED(small) {
98    }
99
100protected:
101    virtual const char* onGetName() SK_OVERRIDE {
102        return isSmall() ? "colorfilter_bright_gray_small" : "colorfilter_bright_gray_large";
103    }
104
105    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
106        SkRect r = getFilterRect();
107        SkPaint paint;
108        paint.setColor(SK_ColorRED);
109        for (int i = 0; i < loops; i++) {
110            SkAutoTUnref<SkImageFilter> brightness(make_brightness(0.9f));
111            SkAutoTUnref<SkImageFilter> grayscale(make_grayscale(brightness));
112            paint.setImageFilter(grayscale);
113            canvas->drawRect(r, paint);
114        }
115    }
116
117private:
118    typedef ColorFilterBaseBench INHERITED;
119};
120
121class ColorFilterGrayBrightBench : public ColorFilterBaseBench {
122
123public:
124    ColorFilterGrayBrightBench(bool small) : INHERITED(small) {
125    }
126
127protected:
128    virtual const char* onGetName() SK_OVERRIDE {
129        return isSmall() ? "colorfilter_gray_bright_small" : "colorfilter_gray_bright_large";
130    }
131
132    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
133        SkRect r = getFilterRect();
134        SkPaint paint;
135        paint.setColor(SK_ColorRED);
136        for (int i = 0; i < loops; i++) {
137            SkAutoTUnref<SkImageFilter> grayscale(make_grayscale());
138            SkAutoTUnref<SkImageFilter> brightness(make_brightness(0.9f, grayscale));
139            paint.setImageFilter(brightness);
140            canvas->drawRect(r, paint);
141        }
142    }
143
144private:
145    typedef ColorFilterBaseBench INHERITED;
146};
147
148class ColorFilterBlueBrightBench : public ColorFilterBaseBench {
149
150public:
151    ColorFilterBlueBrightBench(bool small) : INHERITED(small) {
152    }
153
154protected:
155    virtual const char* onGetName() SK_OVERRIDE {
156        return isSmall() ? "colorfilter_blue_bright_small" : "colorfilter_blue_bright_large";
157    }
158
159    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
160        SkRect r = getFilterRect();
161        SkPaint paint;
162        paint.setColor(SK_ColorRED);
163        for (int i = 0; i < loops; i++) {
164            SkAutoTUnref<SkImageFilter> blue(make_mode_blue());
165            SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f, blue));
166            paint.setImageFilter(brightness);
167            canvas->drawRect(r, paint);
168        }
169    }
170
171private:
172    typedef ColorFilterBaseBench INHERITED;
173};
174
175class ColorFilterBrightBlueBench : public ColorFilterBaseBench {
176
177public:
178    ColorFilterBrightBlueBench(bool small) : INHERITED(small) {
179    }
180
181protected:
182    virtual const char* onGetName() SK_OVERRIDE {
183        return isSmall() ? "colorfilter_bright_blue_small" : "colorfilter_bright_blue_large";
184    }
185
186    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
187        SkRect r = getFilterRect();
188        SkPaint paint;
189        paint.setColor(SK_ColorRED);
190        for (int i = 0; i < loops; i++) {
191            SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f));
192            SkAutoTUnref<SkImageFilter> blue(make_mode_blue(brightness));
193            paint.setImageFilter(blue);
194            canvas->drawRect(r, paint);
195        }
196    }
197
198private:
199    typedef ColorFilterBaseBench INHERITED;
200};
201
202class ColorFilterBrightBench : public ColorFilterBaseBench {
203
204public:
205    ColorFilterBrightBench(bool small) : INHERITED(small) {
206    }
207
208protected:
209    virtual const char* onGetName() SK_OVERRIDE {
210        return isSmall() ? "colorfilter_bright_small" : "colorfilter_bright_large";
211    }
212
213    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
214        SkRect r = getFilterRect();
215        SkPaint paint;
216        paint.setColor(SK_ColorRED);
217        for (int i = 0; i < loops; i++) {
218            SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f));
219            paint.setImageFilter(brightness);
220            canvas->drawRect(r, paint);
221        }
222    }
223
224private:
225    typedef ColorFilterBaseBench INHERITED;
226};
227
228class ColorFilterBlueBench : public ColorFilterBaseBench {
229
230public:
231    ColorFilterBlueBench(bool small) : INHERITED(small) {
232    }
233
234protected:
235    virtual const char* onGetName() SK_OVERRIDE {
236        return isSmall() ? "colorfilter_blue_small" : "colorfilter_blue_large";
237    }
238
239    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
240        SkRect r = getFilterRect();
241        SkPaint paint;
242        paint.setColor(SK_ColorRED);
243        for (int i = 0; i < loops; i++) {
244            SkAutoTUnref<SkImageFilter> blue(make_mode_blue());
245            paint.setImageFilter(blue);
246            canvas->drawRect(r, paint);
247        }
248    }
249
250private:
251    typedef ColorFilterBaseBench INHERITED;
252};
253
254class ColorFilterGrayBench : public ColorFilterBaseBench {
255
256public:
257    ColorFilterGrayBench(bool small) : INHERITED(small) {
258    }
259
260protected:
261    virtual const char* onGetName() SK_OVERRIDE {
262        return isSmall() ? "colorfilter_gray_small" : "colorfilter_gray_large";
263    }
264
265    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
266        SkRect r = getFilterRect();
267        SkPaint paint;
268        paint.setColor(SK_ColorRED);
269        for (int i = 0; i < loops; i++) {
270            SkAutoTUnref<SkImageFilter> grayscale(make_grayscale());
271            paint.setImageFilter(grayscale);
272            canvas->drawRect(r, paint);
273        }
274    }
275
276private:
277    typedef ColorFilterBaseBench INHERITED;
278};
279
280class TableColorFilterBench : public ColorFilterBaseBench {
281
282public:
283    TableColorFilterBench(bool small) : INHERITED(small) {
284    }
285
286protected:
287    virtual const char* onGetName() SK_OVERRIDE {
288        return isSmall() ? "table_colorfilter_small" : "table_colorfilter_large";
289    }
290
291    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
292        SkRect r = getFilterRect();
293        SkPaint paint;
294        paint.setColor(SK_ColorRED);
295        for (int i = 0; i < loops; i++) {
296            SkAutoTUnref<SkColorFilter> table_filter(make_table_filter());
297            paint.setColorFilter(table_filter);
298            canvas->drawRect(r, paint);
299        }
300    }
301
302private:
303    static void fill_table_data(uint8_t table[]) {
304        for (int i = 0; i < 256; ++i) {
305            int n = i >> 5;
306            table[i] = (n << 5) | (n << 2) | (n >> 1);
307        }
308    }
309
310    static SkColorFilter* make_table_filter() {
311        uint8_t table[256]; fill_table_data(table);
312        return SkTableColorFilter::Create(table);
313    }
314
315    typedef ColorFilterBaseBench INHERITED;
316};
317
318class LumaColorFilterBench : public ColorFilterBaseBench {
319
320public:
321    LumaColorFilterBench(bool small) : INHERITED(small) {
322    }
323
324protected:
325    virtual const char* onGetName() SK_OVERRIDE {
326        return isSmall() ? "luma_colorfilter_small" : "luma_colorfilter_large";
327    }
328
329    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
330        SkRect r = getFilterRect();
331        SkPaint paint;
332        paint.setColor(SK_ColorRED);
333
334        for (int i = 0; i < loops; i++) {
335            SkAutoTUnref<SkColorFilter> luma_filter(SkLumaColorFilter::Create());
336            paint.setColorFilter(luma_filter);
337            canvas->drawRect(r, paint);
338        }
339    }
340
341private:
342    typedef ColorFilterBaseBench INHERITED;
343};
344
345///////////////////////////////////////////////////////////////////////////////
346
347DEF_BENCH( return new ColorFilterDimBrightBench(true); )
348DEF_BENCH( return new ColorFilterBrightGrayBench(true); )
349DEF_BENCH( return new ColorFilterGrayBrightBench(true); )
350DEF_BENCH( return new ColorFilterBlueBrightBench(true); )
351DEF_BENCH( return new ColorFilterBrightBlueBench(true); )
352DEF_BENCH( return new ColorFilterBrightBench(true); )
353DEF_BENCH( return new ColorFilterBlueBench(true); )
354DEF_BENCH( return new ColorFilterGrayBench(true); )
355DEF_BENCH( return new TableColorFilterBench(true); )
356DEF_BENCH( return new LumaColorFilterBench(true); )
357
358DEF_BENCH( return new ColorFilterDimBrightBench(false); )
359DEF_BENCH( return new ColorFilterBrightGrayBench(false); )
360DEF_BENCH( return new ColorFilterGrayBrightBench(false); )
361DEF_BENCH( return new ColorFilterBlueBrightBench(false); )
362DEF_BENCH( return new ColorFilterBrightBlueBench(false); )
363DEF_BENCH( return new ColorFilterBrightBench(false); )
364DEF_BENCH( return new ColorFilterBlueBench(false); )
365DEF_BENCH( return new ColorFilterGrayBench(false); )
366DEF_BENCH( return new TableColorFilterBench(false); )
367DEF_BENCH( return new LumaColorFilterBench(false); )
368