| /* |
| * 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(const char name[]) { |
| fName.printf("picture_record_%s", name); |
| } |
| |
| virtual bool isSuitableFor(Backend backend) SK_OVERRIDE { |
| return backend == kNonRendering_Backend; |
| } |
| |
| enum { |
| PICTURE_WIDTH = 1000, |
| PICTURE_HEIGHT = 4000, |
| }; |
| protected: |
| virtual const char* onGetName() SK_OVERRIDE { |
| return fName.c_str(); |
| } |
| private: |
| SkString fName; |
| typedef SkBenchmark INHERITED; |
| }; |
| |
| |
| static const int kMaxLoopsPerCanvas = 10000; |
| |
| /* |
| * 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() : INHERITED("dictionaries") {} |
| |
| protected: |
| virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE { |
| SkAutoTDelete<SkPicture> picture; |
| SkCanvas* canvas = NULL; |
| |
| const SkPoint translateDelta = getTranslateDelta(loops); |
| |
| for (int i = 0; i < loops; i++) { |
| if (0 == i % kMaxLoopsPerCanvas) { |
| picture.reset(SkNEW(SkPicture)); |
| canvas = picture->beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT); |
| } |
| |
| SkColor color = SK_ColorYELLOW + (i % 255); |
| SkIRect rect = SkIRect::MakeWH(i % PICTURE_WIDTH, i % PICTURE_HEIGHT); |
| |
| 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(int M) { |
| 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() : INHERITED("unique_paint_dictionary") { } |
| |
| protected: |
| virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE { |
| SkRandom rand; |
| SkPaint paint; |
| SkAutoTDelete<SkPicture> picture; |
| SkCanvas* canvas = NULL; |
| for (int i = 0; i < loops; i++) { |
| if (0 == i % kMaxLoopsPerCanvas) { |
| picture.reset(SkNEW(SkPicture)); |
| canvas = picture->beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT); |
| } |
| 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. |
| * |
| * Re-creating the paint objects in the inner loop slows the benchmark down 10%. |
| * Using setColor(i % objCount) instead of a random color creates a very high rate |
| * of hash conflicts, slowing us down 12%. |
| */ |
| class RecurringPaintDictionaryRecordBench : public PictureRecordBench { |
| public: |
| RecurringPaintDictionaryRecordBench() : INHERITED("recurring_paint_dictionary") { |
| SkRandom rand; |
| for (int i = 0; i < ObjCount; i++) { |
| fPaint[i].setColor(rand.nextU()); |
| } |
| } |
| |
| enum { |
| ObjCount = 100, // number of unique paint objects |
| }; |
| protected: |
| virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE { |
| SkPicture picture; |
| SkCanvas* canvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT); |
| for (int i = 0; i < loops; i++) { |
| canvas->drawPaint(fPaint[i % ObjCount]); |
| } |
| } |
| |
| private: |
| SkPaint fPaint [ObjCount]; |
| typedef PictureRecordBench INHERITED; |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| DEF_BENCH( return new DictionaryRecordBench(); ) |
| DEF_BENCH( return new UniquePaintDictionaryRecordBench(); ) |
| DEF_BENCH( return new RecurringPaintDictionaryRecordBench(); ) |