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