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 
8 #include "Benchmark.h"
9 #include "SkBitmapSource.h"
10 #include "SkCanvas.h"
11 #include "SkDisplacementMapEffect.h"
12 
13 #define FILTER_WIDTH_SMALL  32
14 #define FILTER_HEIGHT_SMALL 32
15 #define FILTER_WIDTH_LARGE  256
16 #define FILTER_HEIGHT_LARGE 256
17 
18 class DisplacementBaseBench : public Benchmark {
19 public:
DisplacementBaseBench(bool small)20     DisplacementBaseBench(bool small) :
21         fInitialized(false), fIsSmall(small) {
22     }
23 
24 protected:
onPreDraw()25     void onPreDraw() override {
26         if (!fInitialized) {
27             this->makeBitmap();
28             this->makeCheckerboard();
29             fInitialized = true;
30         }
31     }
32 
makeBitmap()33     void makeBitmap() {
34         const int w = this->isSmall() ? FILTER_WIDTH_SMALL : FILTER_WIDTH_LARGE;
35         const int h = this->isSmall() ? FILTER_HEIGHT_LARGE : FILTER_HEIGHT_LARGE;
36         fBitmap.allocN32Pixels(w, h);
37         SkCanvas canvas(fBitmap);
38         canvas.clear(0x00000000);
39         SkPaint paint;
40         paint.setAntiAlias(true);
41         paint.setColor(0xFF884422);
42         paint.setTextSize(SkIntToScalar(96));
43         const char* str = "g";
44         canvas.drawText(str, strlen(str), SkIntToScalar(15), SkIntToScalar(55), paint);
45     }
46 
makeCheckerboard()47     void makeCheckerboard() {
48         const int w = this->isSmall() ? FILTER_WIDTH_SMALL : FILTER_WIDTH_LARGE;
49         const int h = this->isSmall() ? FILTER_HEIGHT_LARGE : FILTER_HEIGHT_LARGE;
50         fCheckerboard.allocN32Pixels(w, h);
51         SkCanvas canvas(fCheckerboard);
52         canvas.clear(0x00000000);
53         SkPaint darkPaint;
54         darkPaint.setColor(0xFF804020);
55         SkPaint lightPaint;
56         lightPaint.setColor(0xFF244484);
57         for (int y = 0; y < h; y += 16) {
58             for (int x = 0; x < w; x += 16) {
59                 canvas.save();
60                 canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
61                 canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint);
62                 canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint);
63                 canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint);
64                 canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint);
65                 canvas.restore();
66             }
67         }
68     }
69 
drawClippedBitmap(SkCanvas * canvas,int x,int y,const SkPaint & paint)70     void drawClippedBitmap(SkCanvas* canvas, int x, int y, const SkPaint& paint) {
71         canvas->save();
72         canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
73                                           SkIntToScalar(fBitmap.width()),
74                                           SkIntToScalar(fBitmap.height())));
75         canvas->drawBitmap(fBitmap, SkIntToScalar(x), SkIntToScalar(y), &paint);
76         canvas->restore();
77     }
78 
isSmall() const79     inline bool isSmall() const { return fIsSmall; }
80 
81     SkBitmap fBitmap, fCheckerboard;
82 private:
83     bool fInitialized;
84     bool fIsSmall;
85     typedef Benchmark INHERITED;
86 };
87 
88 class DisplacementZeroBench : public DisplacementBaseBench {
89 public:
DisplacementZeroBench(bool small)90     DisplacementZeroBench(bool small) : INHERITED(small) {
91     }
92 
93 protected:
onGetName()94     const char* onGetName() override {
95         return this->isSmall() ? "displacement_zero_small" : "displacement_zero_large";
96     }
97 
onDraw(const int loops,SkCanvas * canvas)98     void onDraw(const int loops, SkCanvas* canvas) override {
99         SkPaint paint;
100         SkAutoTUnref<SkImageFilter> displ(SkBitmapSource::Create(fCheckerboard));
101         // No displacement effect
102         paint.setImageFilter(SkDisplacementMapEffect::Create(
103             SkDisplacementMapEffect::kR_ChannelSelectorType,
104             SkDisplacementMapEffect::kG_ChannelSelectorType, 0.0f, displ))->unref();
105 
106         for (int i = 0; i < loops; i++) {
107             this->drawClippedBitmap(canvas, 0, 0, paint);
108         }
109     }
110 
111 private:
112     typedef DisplacementBaseBench INHERITED;
113 };
114 
115 class DisplacementAlphaBench : public DisplacementBaseBench {
116 public:
DisplacementAlphaBench(bool small)117     DisplacementAlphaBench(bool small) : INHERITED(small) {
118     }
119 
120 protected:
onGetName()121     const char* onGetName() override {
122         return isSmall() ? "displacement_alpha_small" : "displacement_alpha_large";
123     }
124 
onDraw(const int loops,SkCanvas * canvas)125     void onDraw(const int loops, SkCanvas* canvas) override {
126         SkPaint paint;
127         SkAutoTUnref<SkImageFilter> displ(SkBitmapSource::Create(fCheckerboard));
128         // Displacement, with 1 alpha component (which isn't pre-multiplied)
129         paint.setImageFilter(SkDisplacementMapEffect::Create(
130             SkDisplacementMapEffect::kB_ChannelSelectorType,
131             SkDisplacementMapEffect::kA_ChannelSelectorType, 16.0f, displ))->unref();
132         for (int i = 0; i < loops; i++) {
133             drawClippedBitmap(canvas, 100, 0, paint);
134         }
135     }
136 
137 private:
138     typedef DisplacementBaseBench INHERITED;
139 };
140 
141 class DisplacementFullBench : public DisplacementBaseBench {
142 public:
DisplacementFullBench(bool small)143     DisplacementFullBench(bool small) : INHERITED(small) {
144     }
145 
146 protected:
onGetName()147     const char* onGetName() override {
148         return isSmall() ? "displacement_full_small" : "displacement_full_large";
149     }
150 
onDraw(const int loops,SkCanvas * canvas)151     void onDraw(const int loops, SkCanvas* canvas) override {
152         SkPaint paint;
153         SkAutoTUnref<SkImageFilter> displ(SkBitmapSource::Create(fCheckerboard));
154         // Displacement, with 2 non-alpha components
155         paint.setImageFilter(SkDisplacementMapEffect::Create(
156             SkDisplacementMapEffect::kR_ChannelSelectorType,
157             SkDisplacementMapEffect::kB_ChannelSelectorType, 32.0f, displ))->unref();
158         for (int i = 0; i < loops; ++i) {
159             this->drawClippedBitmap(canvas, 200, 0, paint);
160         }
161     }
162 
163 private:
164     typedef DisplacementBaseBench INHERITED;
165 };
166 
167 ///////////////////////////////////////////////////////////////////////////////
168 
169 DEF_BENCH( return new DisplacementZeroBench(true); )
170 DEF_BENCH( return new DisplacementAlphaBench(true); )
171 DEF_BENCH( return new DisplacementFullBench(true); )
172 DEF_BENCH( return new DisplacementZeroBench(false); )
173 DEF_BENCH( return new DisplacementAlphaBench(false); )
174 DEF_BENCH( return new DisplacementFullBench(false); )
175