2012-05-30 16:50:11 +00:00
|
|
|
/*
|
|
|
|
* 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"
|
2012-07-10 13:17:45 +00:00
|
|
|
#include "SkRandom.h"
|
2012-05-30 16:50:11 +00:00
|
|
|
#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);
|
2013-05-30 19:52:38 +00:00
|
|
|
fIsRendering = false;
|
2012-05-30 16:50:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2013-03-05 18:50:01 +00:00
|
|
|
virtual void onDraw(SkCanvas*) {
|
2012-07-03 13:53:41 +00:00
|
|
|
int n = (int)(N * this->innerLoopScale());
|
|
|
|
n = SkMax32(1, n);
|
2012-05-30 16:50:11 +00:00
|
|
|
|
2012-07-03 13:53:41 +00:00
|
|
|
for (int i = 0; i < n; i++) {
|
2012-05-30 16:50:11 +00:00
|
|
|
|
|
|
|
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;
|
2012-07-03 13:53:41 +00:00
|
|
|
virtual float innerLoopScale() const { return 1; }
|
2012-05-30 16:50:11 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2012-06-27 20:03:16 +00:00
|
|
|
/*
|
|
|
|
* 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:
|
2012-07-03 13:53:41 +00:00
|
|
|
virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; }
|
2012-06-27 20:03:16 +00:00
|
|
|
virtual void recordCanvas(SkCanvas* canvas) {
|
2012-07-10 13:17:45 +00:00
|
|
|
SkRandom rand;
|
2012-06-27 20:03:16 +00:00
|
|
|
for (int i = 0; i < M; i++) {
|
|
|
|
SkPaint paint;
|
2012-07-10 13:17:45 +00:00
|
|
|
paint.setColor(rand.nextU());
|
2012-06-27 20:03:16 +00:00
|
|
|
canvas->drawPaint(paint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
typedef PictureRecordBench INHERITED;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Populates the SkPaint dictionary with a number of unique paint
|
2013-07-11 14:26:09 +00:00
|
|
|
* 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%.
|
2012-06-27 20:03:16 +00:00
|
|
|
*/
|
|
|
|
class RecurringPaintDictionaryRecordBench : public PictureRecordBench {
|
|
|
|
public:
|
|
|
|
RecurringPaintDictionaryRecordBench(void* param)
|
2013-07-11 14:26:09 +00:00
|
|
|
: INHERITED(param, "recurring_paint_dictionary") {
|
|
|
|
SkRandom rand;
|
|
|
|
for (int i = 0; i < ObjCount; i++) {
|
|
|
|
fPaint[i].setColor(rand.nextU());
|
|
|
|
}
|
|
|
|
}
|
2012-06-27 20:03:16 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
ObjCount = 100, // number of unique paint objects
|
|
|
|
M = SkBENCHLOOP(50000), // number of draw iterations
|
|
|
|
};
|
|
|
|
protected:
|
2012-07-03 13:53:41 +00:00
|
|
|
virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; }
|
2012-06-27 20:03:16 +00:00
|
|
|
virtual void recordCanvas(SkCanvas* canvas) {
|
|
|
|
|
|
|
|
for (int i = 0; i < M; i++) {
|
2013-07-11 14:26:09 +00:00
|
|
|
canvas->drawPaint(fPaint[i % ObjCount]);
|
2012-06-27 20:03:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2013-07-11 14:26:09 +00:00
|
|
|
SkPaint fPaint [ObjCount];
|
2012-06-27 20:03:16 +00:00
|
|
|
typedef PictureRecordBench INHERITED;
|
|
|
|
};
|
|
|
|
|
2012-05-30 16:50:11 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static SkBenchmark* Fact0(void* p) { return new DictionaryRecordBench(p); }
|
2012-06-27 20:03:16 +00:00
|
|
|
static SkBenchmark* Fact1(void* p) { return new UniquePaintDictionaryRecordBench(p); }
|
|
|
|
static SkBenchmark* Fact2(void* p) { return new RecurringPaintDictionaryRecordBench(p); }
|
2012-05-30 16:50:11 +00:00
|
|
|
|
|
|
|
static BenchRegistry gReg0(Fact0);
|
2012-06-27 20:03:16 +00:00
|
|
|
static BenchRegistry gReg1(Fact1);
|
|
|
|
static BenchRegistry gReg2(Fact2);
|