• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 "SkCanvas.h"
10 #include "SkColor.h"
11 #include "SkNullCanvas.h"
12 #include "SkPaint.h"
13 #include "SkPicture.h"
14 #include "SkPictureRecorder.h"
15 #include "SkString.h"
16 
17 class PictureNesting : public Benchmark {
18 public:
PictureNesting(const char * name,int maxLevel,int maxPictureLevel)19     PictureNesting(const char* name, int maxLevel, int maxPictureLevel)
20         : fMaxLevel(maxLevel)
21         , fMaxPictureLevel(maxPictureLevel) {
22         fName.printf("picture_nesting_%s_%d", name, this->countPics());
23         fPaint.setColor(SK_ColorRED);
24         fPaint.setAntiAlias(true);
25         fPaint.setStyle(SkPaint::kStroke_Style);
26     }
27 
28 protected:
onGetName()29     const char* onGetName() override {
30         return fName.c_str();
31     }
32 
doDraw(SkCanvas * canvas)33     void doDraw(SkCanvas* canvas) {
34         SkIPoint canvasSize = onGetSize();
35         canvas->save();
36         canvas->scale(SkIntToScalar(canvasSize.x()), SkIntToScalar(canvasSize.y()));
37 
38         SkDEBUGCODE(int pics = ) this->sierpinsky(canvas, 0, fPaint);
39         SkASSERT(pics == this->countPics());
40 
41         canvas->restore();
42     }
43 
sierpinsky(SkCanvas * canvas,int lvl,const SkPaint & paint)44     int sierpinsky(SkCanvas* canvas, int lvl, const SkPaint& paint) {
45         if (++lvl > fMaxLevel) {
46             return 0;
47         }
48 
49         int pics = 0;
50         bool recordPicture = lvl <= fMaxPictureLevel;
51         SkPictureRecorder recorder;
52         SkCanvas* c = canvas;
53 
54         if (recordPicture) {
55             c = recorder.beginRecording(1, 1);
56             pics++;
57         }
58 
59         c->drawLine(0.5, 0, 0, 1, paint);
60         c->drawLine(0.5, 0, 1, 1, paint);
61         c->drawLine(0,   1, 1, 1, paint);
62 
63         c->save();
64             c->scale(0.5, 0.5);
65 
66             c->translate(0, 1);
67             pics += this->sierpinsky(c, lvl, paint);
68 
69             c->translate(1, 0);
70             pics += this->sierpinsky(c, lvl, paint);
71 
72             c->translate(-0.5, -1);
73             pics += this->sierpinsky(c, lvl, paint);
74         c->restore();
75 
76         if (recordPicture) {
77             SkAutoTUnref<SkPicture> picture(recorder.endRecording());
78             canvas->drawPicture(picture);
79         }
80 
81         return pics;
82     }
83 
84     int fMaxLevel;
85     int fMaxPictureLevel;
86 
87 private:
countPics() const88     int countPics() const {
89         // Solve: pics from sierpinsky
90         // f(m) = 1 + 3*f(m - 1)
91         // f(0) = 0
92         //   via "recursive function to closed form" tricks
93         // f(m) = 1/2 (3^m - 1)
94         int pics = 1;
95         for (int i = 0; i < fMaxPictureLevel; i++) {
96             pics *= 3;
97         }
98         pics--;
99         pics /= 2;
100         return pics;
101     }
102 
103     SkString fName;
104     SkPaint  fPaint;
105 
106     typedef Benchmark INHERITED;
107 };
108 
109 class PictureNestingRecording : public PictureNesting {
110 public:
PictureNestingRecording(int maxLevel,int maxPictureLevel)111     PictureNestingRecording(int maxLevel, int maxPictureLevel)
112         : INHERITED("recording", maxLevel, maxPictureLevel) {
113     }
114 
115 protected:
isSuitableFor(Backend backend)116     virtual bool isSuitableFor(Backend backend) {
117         return backend == kNonRendering_Backend;
118     }
119 
onDraw(const int loops,SkCanvas *)120     virtual void onDraw(const int loops, SkCanvas*) {
121         SkIPoint canvasSize = onGetSize();
122         SkPictureRecorder recorder;
123 
124         for (int i = 0; i < loops; i++) {
125             SkCanvas* c = recorder.beginRecording(SkIntToScalar(canvasSize.x()),
126                                                   SkIntToScalar(canvasSize.y()));
127             this->doDraw(c);
128             SkAutoTUnref<SkPicture> picture(recorder.endRecording());
129         }
130     }
131 
132 private:
133     typedef PictureNesting INHERITED;
134 };
135 
136 class PictureNestingPlayback : public PictureNesting {
137 public:
PictureNestingPlayback(int maxLevel,int maxPictureLevel)138     PictureNestingPlayback(int maxLevel, int maxPictureLevel)
139         : INHERITED("playback", maxLevel, maxPictureLevel) {
140     }
141 protected:
onPreDraw()142     void onPreDraw() override {
143         this->INHERITED::onPreDraw();
144 
145         SkIPoint canvasSize = onGetSize();
146         SkPictureRecorder recorder;
147         SkCanvas* c = recorder.beginRecording(SkIntToScalar(canvasSize.x()),
148                                               SkIntToScalar(canvasSize.y()));
149 
150         this->doDraw(c);
151         fPicture.reset(recorder.endRecording());
152     }
153 
onDraw(const int loops,SkCanvas * canvas)154     virtual void onDraw(const int loops, SkCanvas* canvas) {
155         for (int i = 0; i < loops; i++) {
156             canvas->drawPicture(fPicture);
157         }
158     }
159 
160 private:
161     SkAutoTUnref<SkPicture> fPicture;
162 
163     typedef PictureNesting INHERITED;
164 };
165 
166 DEF_BENCH( return new PictureNestingRecording(8, 0); )
167 DEF_BENCH( return new PictureNestingRecording(8, 1); )
168 DEF_BENCH( return new PictureNestingRecording(8, 2); )
169 DEF_BENCH( return new PictureNestingRecording(8, 3); )
170 DEF_BENCH( return new PictureNestingRecording(8, 4); )
171 DEF_BENCH( return new PictureNestingRecording(8, 5); )
172 DEF_BENCH( return new PictureNestingRecording(8, 6); )
173 DEF_BENCH( return new PictureNestingRecording(8, 7); )
174 DEF_BENCH( return new PictureNestingRecording(8, 8); )
175 
176 DEF_BENCH( return new PictureNestingPlayback(8, 0); )
177 DEF_BENCH( return new PictureNestingPlayback(8, 1); )
178 DEF_BENCH( return new PictureNestingPlayback(8, 2); )
179 DEF_BENCH( return new PictureNestingPlayback(8, 3); )
180 DEF_BENCH( return new PictureNestingPlayback(8, 4); )
181 DEF_BENCH( return new PictureNestingPlayback(8, 5); )
182 DEF_BENCH( return new PictureNestingPlayback(8, 6); )
183 DEF_BENCH( return new PictureNestingPlayback(8, 7); )
184 DEF_BENCH( return new PictureNestingPlayback(8, 8); )
185