skia2/bench/PictureRecordBench.cpp
commit-bot@chromium.org 6485b0be74 Switch out random number generator for tests, benches, samples.
This change makes tests, benches and samples use the new SkMWCRandom PRNG. GMs will be saved for another time, as they'll require rebaselining.

R=reed@google.com, bsalomon@google.com

Author: jvanverth@google.com

Review URL: https://chromiumcodereview.appspot.com/23653018

git-svn-id: http://skia.googlecode.com/svn/trunk@11136 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-09-06 19:05:11 +00:00

203 lines
6.0 KiB
C++

/*
* 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) {
SkMWCRandom 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.
*
* 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(void* param)
: INHERITED(param, "recurring_paint_dictionary") {
SkMWCRandom rand;
for (int i = 0; i < ObjCount; i++) {
fPaint[i].setColor(rand.nextU());
}
}
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++) {
canvas->drawPaint(fPaint[i % ObjCount]);
}
}
private:
SkPaint fPaint [ObjCount];
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);