1 /* 2 * Copyright 2012 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 #include "SkBenchmark.h" 8 #include "SkCanvas.h" 9 #include "SkColor.h" 10 #include "SkPaint.h" 11 #include "SkPicture.h" 12 #include "SkPoint.h" 13 #include "SkRandom.h" 14 #include "SkRect.h" 15 #include "SkString.h" 16 17 class PictureRecordBench : public SkBenchmark { 18 public: 19 PictureRecordBench(void* param, const char name[]) : INHERITED(param) { 20 fName.printf("picture_record_%s", name); 21 fPictureWidth = SkIntToScalar(PICTURE_WIDTH); 22 fPictureHeight = SkIntToScalar(PICTURE_HEIGHT); 23 } 24 25 enum { 26 N = SkBENCHLOOP(25), // number of times to create the picture 27 PICTURE_WIDTH = 1000, 28 PICTURE_HEIGHT = 4000, 29 }; 30 protected: 31 virtual const char* onGetName() { 32 return fName.c_str(); 33 } 34 35 virtual void onDraw(SkCanvas* canvas) { 36 int n = (int)(N * this->innerLoopScale()); 37 n = SkMax32(1, n); 38 39 for (int i = 0; i < n; i++) { 40 41 SkPicture picture; 42 43 SkCanvas* pCanvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT); 44 recordCanvas(pCanvas); 45 46 // we don't need to draw the picture as the endRecording step will 47 // do the work of transferring the recorded content into a playback 48 // object. 49 picture.endRecording(); 50 } 51 } 52 53 virtual void recordCanvas(SkCanvas* canvas) = 0; 54 virtual float innerLoopScale() const { return 1; } 55 56 SkString fName; 57 SkScalar fPictureWidth; 58 SkScalar fPictureHeight; 59 SkScalar fTextSize; 60 private: 61 typedef SkBenchmark INHERITED; 62 }; 63 64 /* 65 * An SkPicture has internal dictionaries to store bitmaps, matrices, paints, 66 * and regions. This bench populates those dictionaries to test the speed of 67 * reading and writing to those particular dictionary data structures. 68 */ 69 class DictionaryRecordBench : public PictureRecordBench { 70 public: 71 DictionaryRecordBench(void* param) 72 : INHERITED(param, "dictionaries") { } 73 74 enum { 75 M = SkBENCHLOOP(100), // number of elements in each dictionary 76 }; 77 protected: 78 virtual void recordCanvas(SkCanvas* canvas) { 79 80 const SkPoint translateDelta = getTranslateDelta(); 81 82 for (int i = 0; i < M; i++) { 83 84 SkColor color = SK_ColorYELLOW + (i % 255); 85 SkIRect rect = SkIRect::MakeWH(i,i); 86 87 canvas->save(); 88 89 // set the clip to the given region 90 SkRegion region; 91 region.setRect(rect); 92 canvas->clipRegion(region); 93 94 // fill the clip with a color 95 SkPaint paint; 96 paint.setColor(color); 97 canvas->drawPaint(paint); 98 99 // set a matrix on the canvas 100 SkMatrix matrix; 101 matrix.setRotate(SkIntToScalar(i % 360)); 102 canvas->setMatrix(matrix); 103 104 // create a simple bitmap 105 SkBitmap bitmap; 106 bitmap.setConfig(SkBitmap::kRGB_565_Config, 10, 10); 107 bitmap.allocPixels(); 108 109 // draw a single color into the bitmap 110 SkCanvas bitmapCanvas(bitmap); 111 bitmapCanvas.drawColor(SkColorSetA(color, i % 255)); 112 113 // draw the bitmap onto the canvas 114 canvas->drawBitmapMatrix(bitmap, matrix); 115 116 canvas->restore(); 117 canvas->translate(translateDelta.fX, translateDelta.fY); 118 } 119 } 120 121 SkPoint getTranslateDelta() { 122 SkIPoint canvasSize = onGetSize(); 123 return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/M), 124 SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/M)); 125 } 126 private: 127 typedef PictureRecordBench INHERITED; 128 }; 129 130 /* 131 * Populates the SkPaint dictionary with a large number of unique paint 132 * objects that differ only by color 133 */ 134 class UniquePaintDictionaryRecordBench : public PictureRecordBench { 135 public: 136 UniquePaintDictionaryRecordBench(void* param) 137 : INHERITED(param, "unique_paint_dictionary") { } 138 139 enum { 140 M = SkBENCHLOOP(15000), // number of unique paint objects 141 }; 142 protected: 143 virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; } 144 virtual void recordCanvas(SkCanvas* canvas) { 145 SkRandom rand; 146 for (int i = 0; i < M; i++) { 147 SkPaint paint; 148 paint.setColor(rand.nextU()); 149 canvas->drawPaint(paint); 150 } 151 } 152 153 private: 154 typedef PictureRecordBench INHERITED; 155 }; 156 157 /* 158 * Populates the SkPaint dictionary with a number of unique paint 159 * objects that get reused repeatedly 160 */ 161 class RecurringPaintDictionaryRecordBench : public PictureRecordBench { 162 public: 163 RecurringPaintDictionaryRecordBench(void* param) 164 : INHERITED(param, "recurring_paint_dictionary") { } 165 166 enum { 167 ObjCount = 100, // number of unique paint objects 168 M = SkBENCHLOOP(50000), // number of draw iterations 169 }; 170 protected: 171 virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; } 172 virtual void recordCanvas(SkCanvas* canvas) { 173 174 for (int i = 0; i < M; i++) { 175 SkPaint paint; 176 paint.setColor(i % ObjCount); 177 canvas->drawPaint(paint); 178 } 179 } 180 181 private: 182 typedef PictureRecordBench INHERITED; 183 }; 184 185 /////////////////////////////////////////////////////////////////////////////// 186 187 static SkBenchmark* Fact0(void* p) { return new DictionaryRecordBench(p); } 188 static SkBenchmark* Fact1(void* p) { return new UniquePaintDictionaryRecordBench(p); } 189 static SkBenchmark* Fact2(void* p) { return new RecurringPaintDictionaryRecordBench(p); } 190 191 static BenchRegistry gReg0(Fact0); 192 static BenchRegistry gReg1(Fact1); 193 static BenchRegistry gReg2(Fact2); 194