• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 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 "bench/Benchmark.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkShader.h"
13 #include "include/core/SkString.h"
14 #include "include/effects/SkGradientShader.h"
15 #include "include/utils/SkRandom.h"
16 #include "tools/flags/CommandLineFlags.h"
17 
18 static DEFINE_double(strokeWidth, -1.0, "If set, use this stroke width in RectBench.");
19 
20 class RectBench : public Benchmark {
21 public:
22     int fShift, fStroke;
23     enum {
24         W = 640,
25         H = 480,
26         N = 300,
27     };
28     SkRect  fRects[N];
29     SkColor fColors[N];
30     bool    fAA;
31     bool    fPerspective;
32 
RectBench(int shift,int stroke=0,bool aa=true,bool perspective=false)33     RectBench(int shift, int stroke = 0, bool aa = true, bool perspective = false)
34         : fShift(shift)
35         , fStroke(stroke)
36         , fAA(aa)
37         , fPerspective(perspective) {}
38 
computeName(const char root[])39     const char* computeName(const char root[]) {
40         fBaseName.printf("%s_%d", root, fShift);
41         if (fStroke > 0) {
42             fBaseName.appendf("_stroke_%d", fStroke);
43         }
44         if (fAA) {
45             fBaseName.appendf("_aa");
46         } else {
47             fBaseName.appendf("_bw");
48         }
49         if (fPerspective) {
50             fBaseName.appendf("_persp");
51         }
52         return fBaseName.c_str();
53     }
54 
55 protected:
56 
drawThisRect(SkCanvas * c,const SkRect & r,const SkPaint & p)57     virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) {
58         c->drawRect(r, p);
59     }
60 
onGetName()61     const char* onGetName() override { return computeName("rects"); }
62 
onDelayedSetup()63     void onDelayedSetup() override {
64         SkRandom rand;
65         const SkScalar offset = SK_Scalar1/3;
66         for (int i = 0; i < N; i++) {
67             int x = rand.nextU() % W;
68             int y = rand.nextU() % H;
69             int w = rand.nextU() % W;
70             int h = rand.nextU() % H;
71             w >>= fShift;
72             h >>= fShift;
73             x -= w/2;
74             y -= h/2;
75             fRects[i].setXYWH(SkIntToScalar(x), SkIntToScalar(y),
76                               SkIntToScalar(w), SkIntToScalar(h));
77             fRects[i].offset(offset, offset);
78             fColors[i] = rand.nextU() | 0xFF808080;
79         }
80     }
81 
onDraw(int loops,SkCanvas * canvas)82     void onDraw(int loops, SkCanvas* canvas) override {
83         SkPaint paint;
84         if (fStroke > 0) {
85             paint.setStyle(SkPaint::kStroke_Style);
86             paint.setStrokeWidth(SkIntToScalar(fStroke));
87         }
88         if (fPerspective) {
89             // Apply some fixed perspective to change how ops may draw the rects
90             SkMatrix perspective;
91             perspective.setIdentity();
92             perspective.setPerspX(1e-4f);
93             perspective.setPerspY(1e-3f);
94             perspective.setSkewX(0.1f);
95             canvas->concat(perspective);
96         }
97         for (int i = 0; i < loops; i++) {
98             paint.setColor(fColors[i % N]);
99             this->setupPaint(&paint);
100             this->drawThisRect(canvas, fRects[i % N], paint);
101         }
102     }
103 
setupPaint(SkPaint * paint)104     void setupPaint(SkPaint* paint) override {
105         this->INHERITED::setupPaint(paint);
106         paint->setAntiAlias(fAA);
107     }
108 
109 private:
110     SkString fBaseName;
111     using INHERITED = Benchmark;
112 };
113 
114 class SrcModeRectBench : public RectBench {
115 public:
SrcModeRectBench()116     SrcModeRectBench() : INHERITED(1, 0) {
117         fMode = SkBlendMode::kSrc;
118     }
119 
120 protected:
setupPaint(SkPaint * paint)121     void setupPaint(SkPaint* paint) override {
122         this->INHERITED::setupPaint(paint);
123         // srcmode is most interesting when we're not opaque
124         paint->setAlpha(0x80);
125         paint->setBlendMode(fMode);
126     }
127 
onGetName()128     const char* onGetName() override {
129         fName.set(this->INHERITED::onGetName());
130         fName.prepend("srcmode_");
131         return fName.c_str();
132     }
133 
134 private:
135     SkBlendMode fMode;
136     SkString fName;
137 
138     using INHERITED = RectBench;
139 };
140 
141 class TransparentRectBench : public RectBench {
142 public:
TransparentRectBench()143     TransparentRectBench() : INHERITED(1, 0) {}
144 
145 protected:
setupPaint(SkPaint * paint)146     void setupPaint(SkPaint* paint) override {
147         this->INHERITED::setupPaint(paint);
148         // draw non opaque rect
149         paint->setAlpha(0x80);
150     }
151 
onGetName()152     const char* onGetName() override {
153         fName.set(this->INHERITED::onGetName());
154         fName.prepend("transparent_");
155         return fName.c_str();
156     }
157 
158 private:
159     SkString fName;
160     using INHERITED = RectBench;
161 };
162 
163 // Adds a shader to the paint that requires local coordinates to be used
164 class LocalCoordsRectBench : public RectBench {
165 public:
LocalCoordsRectBench(bool aa,bool perspective=false)166     LocalCoordsRectBench(bool aa, bool perspective = false) : INHERITED(1, 0, aa, perspective) { }
167 
168 protected:
onDelayedSetup()169     void onDelayedSetup() override {
170         this->INHERITED::onDelayedSetup();
171         // Create the shader once, so that isn't included in the timing
172         SkPoint pts[2] = { {0.f, 0.f}, {50.f, 50.f} };
173         SkColor colors[] = { SK_ColorWHITE, SK_ColorBLUE };
174         fShader = SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
175     }
176 
setupPaint(SkPaint * paint)177     void setupPaint(SkPaint* paint) override {
178         this->INHERITED::setupPaint(paint);
179         paint->setShader(fShader);
180     }
181 
onGetName()182     const char* onGetName() override {
183         fName.set(this->INHERITED::onGetName());
184         fName.append("_localcoords");
185         return fName.c_str();
186     }
187 
188 private:
189     SkString fName;
190     sk_sp<SkShader> fShader;
191 
192     using INHERITED = RectBench;
193 };
194 
195 
196 class OvalBench : public RectBench {
197 public:
OvalBench(int shift,int stroke=0)198     OvalBench(int shift, int stroke = 0) : RectBench(shift, stroke) {}
199 protected:
drawThisRect(SkCanvas * c,const SkRect & r,const SkPaint & p)200     void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) override {
201         c->drawOval(r, p);
202     }
onGetName()203     const char* onGetName() override { return computeName("ovals"); }
204 };
205 
206 class RRectBench : public RectBench {
207 public:
RRectBench(int shift,int stroke=0)208     RRectBench(int shift, int stroke = 0) : RectBench(shift, stroke) {}
209 protected:
drawThisRect(SkCanvas * c,const SkRect & r,const SkPaint & p)210     void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) override {
211         c->drawRoundRect(r, r.width() / 4, r.height() / 4, p);
212     }
onGetName()213     const char* onGetName() override { return computeName("rrects"); }
214 };
215 
216 class PointsBench : public RectBench {
217 public:
218     SkCanvas::PointMode fMode;
219 
PointsBench(SkCanvas::PointMode mode,const char * name)220     PointsBench(SkCanvas::PointMode mode, const char* name)
221         : RectBench(2)
222         , fMode(mode) {
223         fName = name;
224     }
225 
226 protected:
onDraw(int loops,SkCanvas * canvas)227     void onDraw(int loops, SkCanvas* canvas) override {
228         SkScalar gSizes[] = {
229             SkIntToScalar(7), 0
230         };
231         size_t sizes = SK_ARRAY_COUNT(gSizes);
232 
233         if (FLAGS_strokeWidth >= 0) {
234             gSizes[0] = (SkScalar)FLAGS_strokeWidth;
235             sizes = 1;
236         }
237 
238         SkPaint paint;
239         paint.setStrokeCap(SkPaint::kRound_Cap);
240 
241         for (int loop = 0; loop < loops; loop++) {
242             for (size_t i = 0; i < sizes; i++) {
243                 paint.setStrokeWidth(gSizes[i]);
244                 this->setupPaint(&paint);
245                 canvas->drawPoints(fMode, N * 2, reinterpret_cast<SkPoint*>(fRects), paint);
246                 paint.setColor(fColors[i % N]);
247             }
248         }
249     }
onGetName()250     const char* onGetName() override { return fName.c_str(); }
251 
252 private:
253     SkString fName;
254 
255 };
256 
257 /*******************************************************************************
258  * to bench BlitMask [Opaque, Black, color, shader]
259  *******************************************************************************/
260 
261 class BlitMaskBench : public RectBench {
262 public:
263     enum kMaskType {
264         kMaskOpaque = 0,
265         kMaskBlack,
266         kMaskColor,
267         KMaskShader
268     };
269     SkCanvas::PointMode fMode;
270 
BlitMaskBench(SkCanvas::PointMode mode,BlitMaskBench::kMaskType type,const char * name)271     BlitMaskBench(SkCanvas::PointMode mode,
272                   BlitMaskBench::kMaskType type, const char* name) :
273         RectBench(2), fMode(mode), _type(type) {
274         fName = name;
275     }
276 
277 protected:
onDraw(int loops,SkCanvas * canvas)278     void onDraw(int loops, SkCanvas* canvas) override {
279         SkScalar gSizes[] = {
280             SkIntToScalar(13), SkIntToScalar(24)
281         };
282         size_t sizes = SK_ARRAY_COUNT(gSizes);
283 
284         if (FLAGS_strokeWidth >= 0) {
285             gSizes[0] = (SkScalar)FLAGS_strokeWidth;
286             sizes = 1;
287         }
288         SkRandom rand;
289         SkColor color = 0xFF000000;
290         U8CPU alpha = 0xFF;
291         SkPaint paint;
292         paint.setStrokeCap(SkPaint::kRound_Cap);
293         if (_type == KMaskShader) {
294             SkBitmap srcBM;
295             srcBM.allocN32Pixels(10, 1);
296             srcBM.eraseColor(0xFF00FF00);
297 
298             paint.setShader(srcBM.makeShader(SkSamplingOptions()));
299         }
300         for (int loop = 0; loop < loops; loop++) {
301             for (size_t i = 0; i < sizes; i++) {
302                 switch (_type) {
303                     case kMaskOpaque:
304                         color = fColors[i];
305                         alpha = 0xFF;
306                         break;
307                     case kMaskBlack:
308                         alpha = 0xFF;
309                         color = 0xFF000000;
310                         break;
311                     case kMaskColor:
312                         color = fColors[i];
313                         alpha = rand.nextU() & 255;
314                         break;
315                     case KMaskShader:
316                         break;
317                 }
318                 paint.setStrokeWidth(gSizes[i]);
319                 this->setupPaint(&paint);
320                 paint.setColor(color);
321                 paint.setAlpha(alpha);
322                 canvas->drawPoints(fMode, N * 2, reinterpret_cast<SkPoint*>(fRects), paint);
323            }
324         }
325     }
onGetName()326     const char* onGetName() override { return fName.c_str(); }
327 
328 private:
329     using INHERITED = RectBench;
330     kMaskType _type;
331     SkString fName;
332 };
333 
334 // AA rects
335 DEF_BENCH(return new RectBench(1, 0, true);)
336 DEF_BENCH(return new RectBench(1, 4, true);)
337 DEF_BENCH(return new RectBench(3, 0, true);)
338 DEF_BENCH(return new RectBench(3, 4, true);)
339 // Non-AA rects
340 DEF_BENCH(return new RectBench(1, 0, false);)
341 DEF_BENCH(return new RectBench(1, 4, false);)
342 DEF_BENCH(return new RectBench(3, 0, false);)
343 DEF_BENCH(return new RectBench(3, 4, false);)
344 
345 DEF_BENCH(return new OvalBench(1);)
346 DEF_BENCH(return new OvalBench(3);)
347 DEF_BENCH(return new OvalBench(1, 4);)
348 DEF_BENCH(return new OvalBench(3, 4);)
349 DEF_BENCH(return new RRectBench(1);)
350 DEF_BENCH(return new RRectBench(1, 4);)
351 DEF_BENCH(return new RRectBench(3);)
352 DEF_BENCH(return new RRectBench(3, 4);)
353 DEF_BENCH(return new PointsBench(SkCanvas::kPoints_PointMode, "points");)
354 DEF_BENCH(return new PointsBench(SkCanvas::kLines_PointMode, "lines");)
355 DEF_BENCH(return new PointsBench(SkCanvas::kPolygon_PointMode, "polygon");)
356 
357 DEF_BENCH(return new SrcModeRectBench();)
358 
359 DEF_BENCH(return new TransparentRectBench();)
360 
361 DEF_BENCH(return new LocalCoordsRectBench(true);)
362 DEF_BENCH(return new LocalCoordsRectBench(false);)
363 
364 // Perspective rects
365 DEF_BENCH(return new RectBench(1, 0, true, true);)
366 DEF_BENCH(return new RectBench(1, 0, false, true);)
367 DEF_BENCH(return new LocalCoordsRectBench(true, true);)
368 DEF_BENCH(return new LocalCoordsRectBench(false, true);)
369 
370 /* init the blitmask bench
371  */
372 DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode,
373                                    BlitMaskBench::kMaskOpaque,
374                                    "maskopaque");)
375 DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode,
376                                    BlitMaskBench::kMaskBlack,
377                                    "maskblack");)
378 DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode,
379                                    BlitMaskBench::kMaskColor,
380                                    "maskcolor");)
381 DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode,
382                                    BlitMaskBench::KMaskShader,
383                                    "maskshader");)
384