/* * Copyright 2012 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkBenchmark.h" #include "SkCanvas.h" #include "SkColor.h" #include "SkPaint.h" #include "SkPicture.h" #include "SkPoint.h" #include "SkRandom.h" #include "SkRect.h" #include "SkString.h" class PictureRecordBench : public SkBenchmark { public: PictureRecordBench(void* param, const char name[]) : INHERITED(param) { fName.printf("picture_record_%s", name); fPictureWidth = SkIntToScalar(PICTURE_WIDTH); fPictureHeight = SkIntToScalar(PICTURE_HEIGHT); fIsRendering = false; } enum { N = SkBENCHLOOP(25), // number of times to create the picture PICTURE_WIDTH = 1000, PICTURE_HEIGHT = 4000, }; protected: virtual const char* onGetName() { return fName.c_str(); } virtual void onDraw(SkCanvas*) { int n = (int)(N * this->innerLoopScale()); n = SkMax32(1, n); for (int i = 0; i < n; i++) { SkPicture picture; SkCanvas* pCanvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT); recordCanvas(pCanvas); // we don't need to draw the picture as the endRecording step will // do the work of transferring the recorded content into a playback // object. picture.endRecording(); } } virtual void recordCanvas(SkCanvas* canvas) = 0; virtual float innerLoopScale() const { return 1; } SkString fName; SkScalar fPictureWidth; SkScalar fPictureHeight; SkScalar fTextSize; private: typedef SkBenchmark INHERITED; }; /* * An SkPicture has internal dictionaries to store bitmaps, matrices, paints, * and regions. This bench populates those dictionaries to test the speed of * reading and writing to those particular dictionary data structures. */ class DictionaryRecordBench : public PictureRecordBench { public: DictionaryRecordBench(void* param) : INHERITED(param, "dictionaries") { } enum { M = SkBENCHLOOP(100), // number of elements in each dictionary }; protected: virtual void recordCanvas(SkCanvas* canvas) { const SkPoint translateDelta = getTranslateDelta(); for (int i = 0; i < M; i++) { SkColor color = SK_ColorYELLOW + (i % 255); SkIRect rect = SkIRect::MakeWH(i,i); canvas->save(); // set the clip to the given region SkRegion region; region.setRect(rect); canvas->clipRegion(region); // fill the clip with a color SkPaint paint; paint.setColor(color); canvas->drawPaint(paint); // set a matrix on the canvas SkMatrix matrix; matrix.setRotate(SkIntToScalar(i % 360)); canvas->setMatrix(matrix); // create a simple bitmap SkBitmap bitmap; bitmap.setConfig(SkBitmap::kRGB_565_Config, 10, 10); bitmap.allocPixels(); // draw a single color into the bitmap SkCanvas bitmapCanvas(bitmap); bitmapCanvas.drawColor(SkColorSetA(color, i % 255)); // draw the bitmap onto the canvas canvas->drawBitmapMatrix(bitmap, matrix); canvas->restore(); canvas->translate(translateDelta.fX, translateDelta.fY); } } SkPoint getTranslateDelta() { SkIPoint canvasSize = onGetSize(); return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/M), SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/M)); } private: typedef PictureRecordBench INHERITED; }; /* * Populates the SkPaint dictionary with a large number of unique paint * objects that differ only by color */ class UniquePaintDictionaryRecordBench : public PictureRecordBench { public: UniquePaintDictionaryRecordBench(void* param) : INHERITED(param, "unique_paint_dictionary") { } enum { M = SkBENCHLOOP(15000), // number of unique paint objects }; protected: virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; } virtual void recordCanvas(SkCanvas* canvas) { SkRandom rand; for (int i = 0; i < M; i++) { SkPaint paint; paint.setColor(rand.nextU()); canvas->drawPaint(paint); } } private: typedef PictureRecordBench INHERITED; }; /* * Populates the SkPaint dictionary with a number of unique paint * objects that get reused repeatedly */ class RecurringPaintDictionaryRecordBench : public PictureRecordBench { public: RecurringPaintDictionaryRecordBench(void* param) : INHERITED(param, "recurring_paint_dictionary") { } enum { ObjCount = 100, // number of unique paint objects M = SkBENCHLOOP(50000), // number of draw iterations }; protected: virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; } virtual void recordCanvas(SkCanvas* canvas) { for (int i = 0; i < M; i++) { SkPaint paint; paint.setColor(i % ObjCount); canvas->drawPaint(paint); } } private: typedef PictureRecordBench INHERITED; }; /////////////////////////////////////////////////////////////////////////////// static SkBenchmark* Fact0(void* p) { return new DictionaryRecordBench(p); } static SkBenchmark* Fact1(void* p) { return new UniquePaintDictionaryRecordBench(p); } static SkBenchmark* Fact2(void* p) { return new RecurringPaintDictionaryRecordBench(p); } static BenchRegistry gReg0(Fact0); static BenchRegistry gReg1(Fact1); static BenchRegistry gReg2(Fact2);