Adds a bunch of benchmarks around creating, transforming, testing path equality,
and concatting paths. Also allows benchs to do setup / tear down steps outside of the cons/destructor via new SkBenchmark virtuals. Review URL: http://codereview.appspot.com/6454137/ git-svn-id: http://skia.googlecode.com/svn/trunk@5054 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
d6c38137e2
commit
30e6d2c205
@ -13,6 +13,8 @@
|
||||
#include "SkRandom.h"
|
||||
#include "SkShader.h"
|
||||
#include "SkString.h"
|
||||
#include "SkTArray.h"
|
||||
|
||||
|
||||
enum Flags {
|
||||
kStroke_Flag = 1 << 0,
|
||||
@ -218,6 +220,385 @@ private:
|
||||
typedef PathBench INHERITED;
|
||||
};
|
||||
|
||||
class RandomPathBench : public SkBenchmark {
|
||||
public:
|
||||
RandomPathBench(void* param) : INHERITED(param) {
|
||||
}
|
||||
|
||||
protected:
|
||||
void createData(int minVerbs,
|
||||
int maxVerbs,
|
||||
int pathCnt,
|
||||
bool allowMoves = true,
|
||||
SkRect* bounds = NULL) {
|
||||
SkRect tempBounds;
|
||||
if (NULL == bounds) {
|
||||
tempBounds.setXYWH(0, 0, SK_Scalar1, SK_Scalar1);
|
||||
bounds = &tempBounds;
|
||||
}
|
||||
fVerbCnts.setReserve(pathCnt);
|
||||
for (int i = 0; i < pathCnt; ++i) {
|
||||
int vCount = fRandom.nextRangeU(minVerbs, maxVerbs + 1);
|
||||
*fVerbCnts.append() = vCount;
|
||||
for (int v = 0; v < vCount; ++v) {
|
||||
int verb = fRandom.nextULessThan(SkPath::kDone_Verb);
|
||||
if (SkPath::kMove_Verb == verb && !allowMoves) {
|
||||
--v;
|
||||
continue;
|
||||
}
|
||||
*fVerbs.append() = static_cast<SkPath::Verb>(verb);
|
||||
static const int gPointCnt[] = {
|
||||
1, // kMove
|
||||
1, // kLine
|
||||
2, // kQuad
|
||||
3, // kCubic
|
||||
0, // kClose
|
||||
};
|
||||
int pCnt = gPointCnt[verb];
|
||||
for (int p = 0; p < pCnt; ++p) {
|
||||
fPoints.append()->set(fRandom.nextRangeScalar(bounds->fLeft, bounds->fRight),
|
||||
fRandom.nextRangeScalar(bounds->fTop, bounds->fBottom));
|
||||
}
|
||||
}
|
||||
}
|
||||
this->restartMakingPaths();
|
||||
}
|
||||
|
||||
void restartMakingPaths() {
|
||||
fCurrPath = 0;
|
||||
fCurrVerb = 0;
|
||||
fCurrPoint = 0;
|
||||
}
|
||||
|
||||
void makePath(SkPath* path) {
|
||||
int vCount = fVerbCnts[fCurrPath++];
|
||||
for (int v = 0; v < vCount; ++v) {
|
||||
switch (fVerbs[fCurrVerb++]) {
|
||||
case SkPath::kMove_Verb:
|
||||
path->moveTo(fPoints[fCurrPoint]);
|
||||
++fCurrPoint;
|
||||
break;
|
||||
case SkPath::kLine_Verb:
|
||||
path->lineTo(fPoints[fCurrPoint]);
|
||||
++fCurrPoint;
|
||||
break;
|
||||
case SkPath::kQuad_Verb:
|
||||
path->quadTo(fPoints[fCurrPoint], fPoints[fCurrPoint + 1]);
|
||||
fCurrPoint += 2;
|
||||
break;
|
||||
case SkPath::kCubic_Verb:
|
||||
path->cubicTo(fPoints[fCurrPoint],
|
||||
fPoints[fCurrPoint + 1],
|
||||
fPoints[fCurrPoint + 2]);
|
||||
fCurrPoint += 3;
|
||||
break;
|
||||
case SkPath::kClose_Verb:
|
||||
path->close();
|
||||
break;
|
||||
default:
|
||||
SkDEBUGFAIL("Unexpected path verb");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void finishedMakingPaths() {
|
||||
fVerbCnts.reset();
|
||||
fVerbs.reset();
|
||||
fPoints.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
SkTDArray<int> fVerbCnts;
|
||||
SkTDArray<SkPath::Verb> fVerbs;
|
||||
SkTDArray<SkPoint> fPoints;
|
||||
int fCurrPath;
|
||||
int fCurrVerb;
|
||||
int fCurrPoint;
|
||||
SkRandom fRandom;
|
||||
typedef SkBenchmark INHERITED;
|
||||
};
|
||||
|
||||
class PathCreateBench : public RandomPathBench {
|
||||
public:
|
||||
PathCreateBench(void* param) : INHERITED(param) {
|
||||
}
|
||||
|
||||
protected:
|
||||
enum { N = SkBENCHLOOP(5000) };
|
||||
|
||||
virtual const char* onGetName() SK_OVERRIDE {
|
||||
return "path_create";
|
||||
}
|
||||
|
||||
virtual void onPreDraw() SK_OVERRIDE {
|
||||
this->createData(10, 100, N);
|
||||
SkASSERT(0 == fPaths.count());
|
||||
fPaths.resize_back(N);
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas*) SK_OVERRIDE {
|
||||
for (int i = 0; i < N; ++i) {
|
||||
this->makePath(&fPaths[i]);
|
||||
}
|
||||
this->restartMakingPaths();
|
||||
}
|
||||
|
||||
virtual void onPostDraw() SK_OVERRIDE {
|
||||
this->finishedMakingPaths();
|
||||
fPaths.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
SkTArray<SkPath> fPaths;
|
||||
|
||||
typedef RandomPathBench INHERITED;
|
||||
};
|
||||
|
||||
class PathCopyBench : public RandomPathBench {
|
||||
public:
|
||||
PathCopyBench(void* param) : INHERITED(param) {
|
||||
}
|
||||
|
||||
protected:
|
||||
enum { N = SkBENCHLOOP(50000) };
|
||||
|
||||
virtual const char* onGetName() SK_OVERRIDE {
|
||||
return "path_copy";
|
||||
}
|
||||
virtual void onPreDraw() SK_OVERRIDE {
|
||||
this->createData(10, 100, N);
|
||||
SkASSERT(0 == fPaths.count());
|
||||
fPaths.resize_back(N);
|
||||
fCopies.resize_back(N);
|
||||
for (int i = 0; i < N; ++i) {
|
||||
this->makePath(&fPaths[i]);
|
||||
}
|
||||
this->finishedMakingPaths();
|
||||
}
|
||||
virtual void onDraw(SkCanvas*) SK_OVERRIDE {
|
||||
for (int i = 0; i < N; ++i) {
|
||||
fCopies[i] = fPaths[i];
|
||||
}
|
||||
}
|
||||
virtual void onPostDraw() SK_OVERRIDE {
|
||||
fPaths.reset();
|
||||
fCopies.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
SkTArray<SkPath> fPaths;
|
||||
SkTArray<SkPath> fCopies;
|
||||
|
||||
typedef RandomPathBench INHERITED;
|
||||
};
|
||||
|
||||
class PathTransformBench : public RandomPathBench {
|
||||
public:
|
||||
PathTransformBench(bool inPlace, void* param)
|
||||
: INHERITED(param)
|
||||
, fInPlace(inPlace) {
|
||||
}
|
||||
|
||||
protected:
|
||||
enum { N = SkBENCHLOOP(30000) };
|
||||
|
||||
virtual const char* onGetName() SK_OVERRIDE {
|
||||
return fInPlace ? "path_transform_in_place" : "path_transform_copy";
|
||||
}
|
||||
|
||||
virtual void onPreDraw() SK_OVERRIDE {
|
||||
fMatrix.setScale(5 * SK_Scalar1, 6 * SK_Scalar1);
|
||||
this->createData(10, 100, N);
|
||||
SkASSERT(0 == fPaths.count());
|
||||
SkASSERT(0 == fTransformed.count());
|
||||
fPaths.resize_back(N);
|
||||
for (int i = 0; i < N; ++i) {
|
||||
this->makePath(&fPaths[i]);
|
||||
}
|
||||
if (!fInPlace) {
|
||||
fTransformed.resize_back(N);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas*) SK_OVERRIDE {
|
||||
if (fInPlace) {
|
||||
for (int i = 0; i < N; ++i) {
|
||||
fPaths[i].transform(fMatrix);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < N; ++i) {
|
||||
fPaths[i].transform(fMatrix, &fTransformed[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void onPostDraw() SK_OVERRIDE {
|
||||
fPaths.reset();
|
||||
fTransformed.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
SkTArray<SkPath> fPaths;
|
||||
SkTArray<SkPath> fTransformed;
|
||||
SkMatrix fMatrix;
|
||||
bool fInPlace;
|
||||
typedef RandomPathBench INHERITED;
|
||||
};
|
||||
|
||||
class PathEqualityBench : public RandomPathBench {
|
||||
public:
|
||||
PathEqualityBench(void* param)
|
||||
: INHERITED(param) {
|
||||
}
|
||||
|
||||
protected:
|
||||
enum { N = SkBENCHLOOP(40000) };
|
||||
|
||||
virtual const char* onGetName() SK_OVERRIDE {
|
||||
return "path_equality_50%";
|
||||
}
|
||||
|
||||
virtual void onPreDraw() SK_OVERRIDE {
|
||||
fParity = 0;
|
||||
this->createData(10, 100, N);
|
||||
SkASSERT(0 == fPaths.count());
|
||||
SkASSERT(0 == fCopies.count());
|
||||
fPaths.resize_back(N);
|
||||
fCopies.resize_back(N);
|
||||
for (int i = 0; i < N; ++i) {
|
||||
this->makePath(&fPaths[i]);
|
||||
fCopies[i] = fPaths[i];
|
||||
}
|
||||
this->finishedMakingPaths();
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas*) SK_OVERRIDE {
|
||||
for (int i = 0; i < N; ++i) {
|
||||
fParity ^= (fPaths[i] == fCopies[i & ~0x1]);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void onPostDraw() SK_OVERRIDE {
|
||||
fPaths.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
bool fParity; // attempt to keep compiler from optimizing out the ==
|
||||
SkTArray<SkPath> fPaths;
|
||||
SkTArray<SkPath> fCopies;
|
||||
typedef RandomPathBench INHERITED;
|
||||
};
|
||||
|
||||
class SkBench_AddPathTest : public RandomPathBench {
|
||||
public:
|
||||
enum AddType {
|
||||
kAdd_AddType,
|
||||
kAddTrans_AddType,
|
||||
kAddMatrix_AddType,
|
||||
kPathTo_AddType,
|
||||
kReverseAdd_AddType,
|
||||
kReversePathTo_AddType,
|
||||
};
|
||||
|
||||
SkBench_AddPathTest(AddType type, void* param)
|
||||
: INHERITED(param)
|
||||
, fType(type) {
|
||||
fMatrix.setRotate(60 * SK_Scalar1);
|
||||
}
|
||||
|
||||
protected:
|
||||
enum { N = SkBENCHLOOP(15000) };
|
||||
|
||||
virtual const char* onGetName() SK_OVERRIDE {
|
||||
switch (fType) {
|
||||
case kAdd_AddType:
|
||||
return "path_add_path";
|
||||
case kAddTrans_AddType:
|
||||
return "path_add_path_trans";
|
||||
case kAddMatrix_AddType:
|
||||
return "path_add_path_matrix";
|
||||
case kPathTo_AddType:
|
||||
return "path_path_to";
|
||||
case kReverseAdd_AddType:
|
||||
return "path_reverse_add_path";
|
||||
case kReversePathTo_AddType:
|
||||
return "path_reverse_path_to";
|
||||
default:
|
||||
SkDEBUGFAIL("Bad add type");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void onPreDraw() SK_OVERRIDE {
|
||||
// pathTo and reversePathTo assume a single contour path.
|
||||
bool allowMoves = kPathTo_AddType != fType &&
|
||||
kReversePathTo_AddType != fType;
|
||||
this->createData(10, 100, 2 * N, allowMoves);
|
||||
SkASSERT(0 == fPaths0.count());
|
||||
SkASSERT(0 == fPaths1.count());
|
||||
fPaths0.resize_back(N);
|
||||
fPaths1.resize_back(N);
|
||||
for (int i = 0; i < N; ++i) {
|
||||
this->makePath(&fPaths0[i]);
|
||||
this->makePath(&fPaths1[i]);
|
||||
}
|
||||
this->finishedMakingPaths();
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas*) SK_OVERRIDE {
|
||||
switch (fType) {
|
||||
case kAdd_AddType:
|
||||
for (int i = 0; i < N; ++i) {
|
||||
SkPath result = fPaths0[i];
|
||||
result.addPath(fPaths1[i]);
|
||||
}
|
||||
break;
|
||||
case kAddTrans_AddType:
|
||||
for (int i = 0; i < N; ++i) {
|
||||
SkPath result = fPaths0[i];
|
||||
result.addPath(fPaths1[i], 2 * SK_Scalar1, 5 * SK_Scalar1);
|
||||
}
|
||||
break;
|
||||
case kAddMatrix_AddType:
|
||||
for (int i = 0; i < N; ++i) {
|
||||
SkPath result = fPaths0[i];
|
||||
result.addPath(fPaths1[i], fMatrix);
|
||||
}
|
||||
break;
|
||||
case kPathTo_AddType:
|
||||
for (int i = 0; i < N; ++i) {
|
||||
SkPath result = fPaths0[i];
|
||||
result.pathTo(fPaths1[i]);
|
||||
}
|
||||
break;
|
||||
case kReverseAdd_AddType:
|
||||
for (int i = 0; i < N; ++i) {
|
||||
SkPath result = fPaths0[i];
|
||||
result.reverseAddPath(fPaths1[i]);
|
||||
}
|
||||
break;
|
||||
case kReversePathTo_AddType:
|
||||
for (int i = 0; i < N; ++i) {
|
||||
SkPath result = fPaths0[i];
|
||||
result.reversePathTo(fPaths1[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void onPostDraw() SK_OVERRIDE {
|
||||
fPaths0.reset();
|
||||
fPaths1.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
AddType fType; // or reverseAddPath
|
||||
SkTArray<SkPath> fPaths0;
|
||||
SkTArray<SkPath> fPaths1;
|
||||
SkMatrix fMatrix;
|
||||
typedef RandomPathBench INHERITED;
|
||||
};
|
||||
|
||||
static SkBenchmark* FactT00(void* p) { return new TrianglePathBench(p, FLAGS00); }
|
||||
static SkBenchmark* FactT01(void* p) { return new TrianglePathBench(p, FLAGS01); }
|
||||
@ -286,3 +667,31 @@ static BenchRegistry gRegLC01(FactLC01);
|
||||
static BenchRegistry gRegLL00(FactLL00);
|
||||
static BenchRegistry gRegLL01(FactLL01);
|
||||
|
||||
static SkBenchmark* FactCreate(void* p) { return new PathCreateBench(p); }
|
||||
static BenchRegistry gRegCreate(FactCreate);
|
||||
|
||||
static SkBenchmark* FactCopy(void* p) { return new PathCopyBench(p); }
|
||||
static BenchRegistry gRegCopy(FactCopy);
|
||||
|
||||
static SkBenchmark* FactPathTransformInPlace(void* p) { return new PathTransformBench(true, p); }
|
||||
static BenchRegistry gRegPathTransformInPlace(FactPathTransformInPlace);
|
||||
|
||||
static SkBenchmark* FactPathTransformCopy(void* p) { return new PathTransformBench(false, p); }
|
||||
static BenchRegistry gRegPathTransformCopy(FactPathTransformCopy);
|
||||
|
||||
static SkBenchmark* FactEquality(void* p) { return new PathEqualityBench(p); }
|
||||
static BenchRegistry gRegEquality(FactEquality);
|
||||
|
||||
static SkBenchmark* FactAdd(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAdd_AddType, p); }
|
||||
static SkBenchmark* FactAddTrans(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAddTrans_AddType, p); }
|
||||
static SkBenchmark* FactAddMatrix(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kAddMatrix_AddType, p); }
|
||||
static SkBenchmark* FactPathTo(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kPathTo_AddType, p); }
|
||||
static SkBenchmark* FactReverseAdd(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kReverseAdd_AddType, p); }
|
||||
static SkBenchmark* FactReverseTo(void* p) { return new SkBench_AddPathTest(SkBench_AddPathTest::kReversePathTo_AddType, p); }
|
||||
|
||||
static BenchRegistry gRegAdd(FactAdd);
|
||||
static BenchRegistry gRegAddTrans(FactAddTrans);
|
||||
static BenchRegistry gRegAddMatrix(FactAddMatrix);
|
||||
static BenchRegistry gRegPathTo(FactPathTo);
|
||||
static BenchRegistry gRegReverseAdd(FactReverseAdd);
|
||||
static BenchRegistry gRegReverseTo(FactReverseTo);
|
||||
|
@ -29,10 +29,18 @@ SkIPoint SkBenchmark::getSize() {
|
||||
return this->onGetSize();
|
||||
}
|
||||
|
||||
void SkBenchmark::preDraw() {
|
||||
this->onPreDraw();
|
||||
}
|
||||
|
||||
void SkBenchmark::draw(SkCanvas* canvas) {
|
||||
this->onDraw(canvas);
|
||||
}
|
||||
|
||||
void SkBenchmark::postDraw() {
|
||||
this->onPostDraw();
|
||||
}
|
||||
|
||||
void SkBenchmark::setupPaint(SkPaint* paint) {
|
||||
paint->setAlpha(fForceAlpha);
|
||||
paint->setAntiAlias(fForceAA);
|
||||
|
@ -39,8 +39,19 @@ public:
|
||||
|
||||
const char* getName();
|
||||
SkIPoint getSize();
|
||||
|
||||
// Call before draw, allows the benchmark to do setup work outside of the
|
||||
// timer. When a benchmark is repeatedly drawn, this should be called once
|
||||
// before the initial draw.
|
||||
void preDraw();
|
||||
|
||||
void draw(SkCanvas*);
|
||||
|
||||
|
||||
// Call after draw, allows the benchmark to do cleanup work outside of the
|
||||
// timer. When a benchmark is repeatedly drawn, this is only called once
|
||||
// after the last draw.
|
||||
void postDraw();
|
||||
|
||||
void setForceAlpha(int alpha) {
|
||||
fForceAlpha = alpha;
|
||||
}
|
||||
@ -78,7 +89,9 @@ protected:
|
||||
void setupPaint(SkPaint* paint);
|
||||
|
||||
virtual const char* onGetName() = 0;
|
||||
virtual void onPreDraw() {}
|
||||
virtual void onDraw(SkCanvas*) = 0;
|
||||
virtual void onPostDraw() {}
|
||||
|
||||
virtual SkIPoint onGetSize();
|
||||
|
||||
|
@ -133,6 +133,18 @@ private:
|
||||
void* fParam;
|
||||
};
|
||||
|
||||
class AutoPrePostDraw {
|
||||
public:
|
||||
AutoPrePostDraw(SkBenchmark* bench) : fBench(bench) {
|
||||
fBench->preDraw();
|
||||
}
|
||||
~AutoPrePostDraw() {
|
||||
fBench->postDraw();
|
||||
}
|
||||
private:
|
||||
SkBenchmark* fBench;
|
||||
};
|
||||
|
||||
static void make_filename(const char name[], SkString* path) {
|
||||
path->set(name);
|
||||
for (int i = 0; name[i]; i++) {
|
||||
@ -750,6 +762,8 @@ int main (int argc, char * const argv[]) {
|
||||
logger.logProgress(str);
|
||||
}
|
||||
|
||||
AutoPrePostDraw appd(bench);
|
||||
|
||||
for (int x = 0; x < configs.count(); ++x) {
|
||||
int configIndex = configs[x];
|
||||
|
||||
|
@ -866,6 +866,7 @@ private:
|
||||
|
||||
friend class SkAutoPathBoundsUpdate;
|
||||
friend class SkAutoDisableOvalCheck;
|
||||
friend class SkBench_AddPathTest; // perf test pathTo/reversePathTo
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user