• 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/SkCanvas.h"
10  #include "include/core/SkPath.h"
11  #include "include/core/SkRegion.h"
12  #include "include/core/SkString.h"
13  #include "include/utils/SkRandom.h"
14  #include "src/core/SkAAClip.h"
15  
16  ////////////////////////////////////////////////////////////////////////////////
17  // This bench tests out AA/BW clipping via canvas' clipPath and clipRect calls
18  class AAClipBench : public Benchmark {
19      SkString fName;
20      SkPath   fClipPath;
21      SkRect   fClipRect;
22      SkRect   fDrawRect;
23      bool     fDoPath;
24      bool     fDoAA;
25  
26  public:
AAClipBench(bool doPath,bool doAA)27      AAClipBench(bool doPath, bool doAA)
28          : fDoPath(doPath)
29          , fDoAA(doAA) {
30  
31          fName.printf("aaclip_%s_%s",
32                       doPath ? "path" : "rect",
33                       doAA ? "AA" : "BW");
34  
35          fClipRect.setLTRB(10.5f, 10.5f, 50.5f, 50.5f);
36          fClipPath.addRoundRect(fClipRect, SkIntToScalar(10), SkIntToScalar(10));
37          fDrawRect.setWH(100, 100);
38  
39          SkASSERT(fClipPath.isConvex());
40      }
41  
42  protected:
onGetName()43      const char* onGetName() override { return fName.c_str(); }
onDraw(int loops,SkCanvas * canvas)44      void onDraw(int loops, SkCanvas* canvas) override {
45  
46          SkPaint paint;
47          this->setupPaint(&paint);
48  
49          for (int i = 0; i < loops; ++i) {
50              // jostle the clip regions each time to prevent caching
51              fClipRect.offset((i % 2) == 0 ? SkIntToScalar(10) : SkIntToScalar(-10), 0);
52              fClipPath.reset();
53              fClipPath.addRoundRect(fClipRect,
54                                     SkIntToScalar(5), SkIntToScalar(5));
55              SkASSERT(fClipPath.isConvex());
56  
57              canvas->save();
58  #if 1
59              if (fDoPath) {
60                  canvas->clipPath(fClipPath, SkClipOp::kIntersect, fDoAA);
61              } else {
62                  canvas->clipRect(fClipRect, SkClipOp::kIntersect, fDoAA);
63              }
64  
65              canvas->drawRect(fDrawRect, paint);
66  #else
67              // this path tests out directly draw the clip primitive
68              // use it to comparing just drawing the clip vs. drawing using
69              // the clip
70              if (fDoPath) {
71                  canvas->drawPath(fClipPath, paint);
72              } else {
73                  canvas->drawRect(fClipRect, paint);
74              }
75  #endif
76              canvas->restore();
77          }
78      }
79  private:
80      using INHERITED = Benchmark;
81  };
82  
83  ////////////////////////////////////////////////////////////////////////////////
84  // This bench tests out nested clip stacks. It is intended to simulate
85  // how WebKit nests clips.
86  class NestedAAClipBench : public Benchmark {
87      SkString fName;
88      bool     fDoAA;
89      SkRect   fDrawRect;
90      SkRandom fRandom;
91  
92      static const int kNestingDepth = 3;
93      static const int kImageSize = 400;
94  
95      SkPoint fSizes[kNestingDepth+1];
96  
97  public:
NestedAAClipBench(bool doAA)98      NestedAAClipBench(bool doAA) : fDoAA(doAA) {
99          fName.printf("nested_aaclip_%s", doAA ? "AA" : "BW");
100  
101          fDrawRect = SkRect::MakeLTRB(0, 0,
102                                       SkIntToScalar(kImageSize),
103                                       SkIntToScalar(kImageSize));
104  
105          fSizes[0].set(SkIntToScalar(kImageSize), SkIntToScalar(kImageSize));
106  
107          for (int i = 1; i < kNestingDepth+1; ++i) {
108              fSizes[i].set(fSizes[i-1].fX/2, fSizes[i-1].fY/2);
109          }
110      }
111  
112  protected:
onGetName()113      const char* onGetName() override { return fName.c_str(); }
114  
115  
recurse(SkCanvas * canvas,int depth,const SkPoint & offset)116      void recurse(SkCanvas* canvas,
117                   int depth,
118                   const SkPoint& offset) {
119  
120              canvas->save();
121  
122              SkRect temp = SkRect::MakeLTRB(0, 0,
123                                             fSizes[depth].fX, fSizes[depth].fY);
124              temp.offset(offset);
125  
126              SkPath path;
127              path.addRoundRect(temp, SkIntToScalar(3), SkIntToScalar(3));
128              SkASSERT(path.isConvex());
129  
130              canvas->clipPath(path, SkClipOp::kIntersect, fDoAA);
131  
132              if (kNestingDepth == depth) {
133                  // we only draw the draw rect at the lowest nesting level
134                  SkPaint paint;
135                  paint.setColor(0xff000000 | fRandom.nextU());
136                  canvas->drawRect(fDrawRect, paint);
137              } else {
138                  SkPoint childOffset = offset;
139                  this->recurse(canvas, depth+1, childOffset);
140  
141                  childOffset += fSizes[depth+1];
142                  this->recurse(canvas, depth+1, childOffset);
143  
144                  childOffset.fX = offset.fX + fSizes[depth+1].fX;
145                  childOffset.fY = offset.fY;
146                  this->recurse(canvas, depth+1, childOffset);
147  
148                  childOffset.fX = offset.fX;
149                  childOffset.fY = offset.fY + fSizes[depth+1].fY;
150                  this->recurse(canvas, depth+1, childOffset);
151              }
152  
153              canvas->restore();
154      }
155  
onDraw(int loops,SkCanvas * canvas)156      void onDraw(int loops, SkCanvas* canvas) override {
157  
158          for (int i = 0; i < loops; ++i) {
159              SkPoint offset = SkPoint::Make(0, 0);
160              this->recurse(canvas, 0, offset);
161          }
162      }
163  
164  private:
165      using INHERITED = Benchmark;
166  };
167  
168  ////////////////////////////////////////////////////////////////////////////////
169  class AAClipBuilderBench : public Benchmark {
170      SkString fName;
171      SkPath   fPath;
172      SkRect   fRect;
173      SkIRect  fBounds;
174      bool     fDoPath;
175      bool     fDoAA;
176  
177  public:
AAClipBuilderBench(bool doPath,bool doAA)178      AAClipBuilderBench(bool doPath, bool doAA)  {
179          fDoPath = doPath;
180          fDoAA = doAA;
181  
182          fName.printf("aaclip_build_%s_%s", doPath ? "path" : "rect",
183                       doAA ? "AA" : "BW");
184          fBounds = {0, 0, 640, 480};
185          fRect.set(fBounds);
186          fRect.inset(SK_Scalar1/4, SK_Scalar1/4);
187          fPath.addRoundRect(fRect, SkIntToScalar(20), SkIntToScalar(20));
188      }
189  
190  protected:
onGetName()191      const char* onGetName() override { return fName.c_str(); }
onDraw(int loops,SkCanvas *)192      void onDraw(int loops, SkCanvas*) override {
193          SkPaint paint;
194          this->setupPaint(&paint);
195  
196          for (int i = 0; i < loops; ++i) {
197              SkAAClip clip;
198              if (fDoPath) {
199                  clip.setPath(fPath, fBounds, fDoAA);
200              } else {
201                  if (fDoAA) {
202                      clip.setPath(SkPath::Rect(fRect), fBounds, fDoAA);
203                  } else {
204                      clip.setRect(fBounds);
205                  }
206              }
207          }
208      }
209  private:
210      using INHERITED = Benchmark;
211  };
212  
213  ////////////////////////////////////////////////////////////////////////////////
214  class AAClipRegionBench : public Benchmark {
215  public:
AAClipRegionBench()216      AAClipRegionBench()  {
217          SkPath path;
218          // test conversion of a complex clip to a aaclip
219          path.addCircle(0, 0, SkIntToScalar(200));
220          path.addCircle(0, 0, SkIntToScalar(180));
221          // evenodd means we've constructed basically a stroked circle
222          path.setFillType(SkPathFillType::kEvenOdd);
223  
224          SkIRect bounds;
225          path.getBounds().roundOut(&bounds);
226          fRegion.setPath(path, SkRegion(bounds));
227      }
228  
229  protected:
onGetName()230      const char* onGetName() override { return "aaclip_setregion"; }
onDraw(int loops,SkCanvas *)231      void onDraw(int loops, SkCanvas*) override {
232          for (int i = 0; i < loops; ++i) {
233              SkAAClip clip;
234              clip.setRegion(fRegion);
235          }
236      }
237  
238  private:
239      SkRegion fRegion;
240      using INHERITED = Benchmark;
241  };
242  
243  ////////////////////////////////////////////////////////////////////////////////
244  
245  DEF_BENCH(return new AAClipBuilderBench(false, false);)
246  DEF_BENCH(return new AAClipBuilderBench(false, true);)
247  DEF_BENCH(return new AAClipBuilderBench(true, false);)
248  DEF_BENCH(return new AAClipBuilderBench(true, true);)
249  DEF_BENCH(return new AAClipRegionBench();)
250  DEF_BENCH(return new AAClipBench(false, false);)
251  DEF_BENCH(return new AAClipBench(false, true);)
252  DEF_BENCH(return new AAClipBench(true, false);)
253  DEF_BENCH(return new AAClipBench(true, true);)
254  DEF_BENCH(return new NestedAAClipBench(false);)
255  DEF_BENCH(return new NestedAAClipBench(true);)
256