e2bfd8b7b1
so that we could track performance changes for ovals. However, rendering the stroked oval cases are now ~5ms slower since they're larger. This restores them to something close to their original performance by slightly shrinking the bounds. This will help determine what effect r7304 may have had. git-svn-id: http://skia.googlecode.com/svn/trunk@7365 2bbb7eff-a529-9590-31e7-b0007b416f81
991 lines
31 KiB
C++
991 lines
31 KiB
C++
|
|
/*
|
|
* Copyright 2011 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 "SkBitmap.h"
|
|
#include "SkCanvas.h"
|
|
#include "SkColorPriv.h"
|
|
#include "SkPaint.h"
|
|
#include "SkRandom.h"
|
|
#include "SkShader.h"
|
|
#include "SkString.h"
|
|
#include "SkTArray.h"
|
|
|
|
|
|
enum Flags {
|
|
kStroke_Flag = 1 << 0,
|
|
kBig_Flag = 1 << 1
|
|
};
|
|
|
|
#define FLAGS00 Flags(0)
|
|
#define FLAGS01 Flags(kStroke_Flag)
|
|
#define FLAGS10 Flags(kBig_Flag)
|
|
#define FLAGS11 Flags(kStroke_Flag | kBig_Flag)
|
|
|
|
class PathBench : public SkBenchmark {
|
|
SkPaint fPaint;
|
|
SkString fName;
|
|
Flags fFlags;
|
|
enum { N = SkBENCHLOOP(1000) };
|
|
public:
|
|
PathBench(void* param, Flags flags) : INHERITED(param), fFlags(flags) {
|
|
fPaint.setStyle(flags & kStroke_Flag ? SkPaint::kStroke_Style :
|
|
SkPaint::kFill_Style);
|
|
fPaint.setStrokeWidth(SkIntToScalar(5));
|
|
fPaint.setStrokeJoin(SkPaint::kBevel_Join);
|
|
}
|
|
|
|
virtual void appendName(SkString*) = 0;
|
|
virtual void makePath(SkPath*) = 0;
|
|
virtual int complexity() { return 0; }
|
|
|
|
protected:
|
|
virtual const char* onGetName() SK_OVERRIDE {
|
|
fName.printf("path_%s_%s_",
|
|
fFlags & kStroke_Flag ? "stroke" : "fill",
|
|
fFlags & kBig_Flag ? "big" : "small");
|
|
this->appendName(&fName);
|
|
return fName.c_str();
|
|
}
|
|
|
|
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
|
SkPaint paint(fPaint);
|
|
this->setupPaint(&paint);
|
|
|
|
SkPath path;
|
|
this->makePath(&path);
|
|
if (fFlags & kBig_Flag) {
|
|
SkMatrix m;
|
|
m.setScale(SkIntToScalar(10), SkIntToScalar(10));
|
|
path.transform(m);
|
|
}
|
|
|
|
int count = N;
|
|
if (fFlags & kBig_Flag) {
|
|
count >>= 2;
|
|
}
|
|
count >>= (3 * complexity());
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
canvas->drawPath(path, paint);
|
|
}
|
|
}
|
|
|
|
private:
|
|
typedef SkBenchmark INHERITED;
|
|
};
|
|
|
|
class TrianglePathBench : public PathBench {
|
|
public:
|
|
TrianglePathBench(void* param, Flags flags) : INHERITED(param, flags) {}
|
|
|
|
virtual void appendName(SkString* name) SK_OVERRIDE {
|
|
name->append("triangle");
|
|
}
|
|
virtual void makePath(SkPath* path) SK_OVERRIDE {
|
|
static const int gCoord[] = {
|
|
10, 10, 15, 5, 20, 20
|
|
};
|
|
path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1]));
|
|
path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3]));
|
|
path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5]));
|
|
path->close();
|
|
}
|
|
private:
|
|
typedef PathBench INHERITED;
|
|
};
|
|
|
|
class RectPathBench : public PathBench {
|
|
public:
|
|
RectPathBench(void* param, Flags flags) : INHERITED(param, flags) {}
|
|
|
|
virtual void appendName(SkString* name) SK_OVERRIDE {
|
|
name->append("rect");
|
|
}
|
|
virtual void makePath(SkPath* path) SK_OVERRIDE {
|
|
SkRect r = { 10, 10, 20, 20 };
|
|
path->addRect(r);
|
|
}
|
|
private:
|
|
typedef PathBench INHERITED;
|
|
};
|
|
|
|
class OvalPathBench : public PathBench {
|
|
public:
|
|
OvalPathBench(void* param, Flags flags) : INHERITED(param, flags) {}
|
|
|
|
virtual void appendName(SkString* name) SK_OVERRIDE {
|
|
name->append("oval");
|
|
}
|
|
virtual void makePath(SkPath* path) SK_OVERRIDE {
|
|
SkRect r = { 10, 10, 23, 20 };
|
|
path->addOval(r);
|
|
}
|
|
private:
|
|
typedef PathBench INHERITED;
|
|
};
|
|
|
|
class CirclePathBench: public PathBench {
|
|
public:
|
|
CirclePathBench(void* param, Flags flags) : INHERITED(param, flags) {}
|
|
|
|
virtual void appendName(SkString* name) SK_OVERRIDE {
|
|
name->append("circle");
|
|
}
|
|
virtual void makePath(SkPath* path) SK_OVERRIDE {
|
|
path->addCircle(SkIntToScalar(20), SkIntToScalar(20),
|
|
SkIntToScalar(10));
|
|
}
|
|
private:
|
|
typedef PathBench INHERITED;
|
|
};
|
|
|
|
class SawToothPathBench : public PathBench {
|
|
public:
|
|
SawToothPathBench(void* param, Flags flags) : INHERITED(param, flags) {}
|
|
|
|
virtual void appendName(SkString* name) SK_OVERRIDE {
|
|
name->append("sawtooth");
|
|
}
|
|
virtual void makePath(SkPath* path) {
|
|
SkScalar x = SkIntToScalar(20);
|
|
SkScalar y = SkIntToScalar(20);
|
|
const SkScalar x0 = x;
|
|
const SkScalar dx = SK_Scalar1 * 5;
|
|
const SkScalar dy = SK_Scalar1 * 10;
|
|
|
|
path->moveTo(x, y);
|
|
for (int i = 0; i < 32; i++) {
|
|
x += dx;
|
|
path->lineTo(x, y - dy);
|
|
x += dx;
|
|
path->lineTo(x, y + dy);
|
|
}
|
|
path->lineTo(x, y + 2 * dy);
|
|
path->lineTo(x0, y + 2 * dy);
|
|
path->close();
|
|
}
|
|
virtual int complexity() SK_OVERRIDE { return 1; }
|
|
private:
|
|
typedef PathBench INHERITED;
|
|
};
|
|
|
|
class LongCurvedPathBench : public PathBench {
|
|
public:
|
|
LongCurvedPathBench(void * param, Flags flags)
|
|
: INHERITED(param, flags) {
|
|
}
|
|
|
|
virtual void appendName(SkString* name) SK_OVERRIDE {
|
|
name->append("long_curved");
|
|
}
|
|
virtual void makePath(SkPath* path) SK_OVERRIDE {
|
|
SkRandom rand (12);
|
|
int i;
|
|
for (i = 0; i < 100; i++) {
|
|
path->quadTo(SkScalarMul(rand.nextUScalar1(), SkIntToScalar(640)),
|
|
SkScalarMul(rand.nextUScalar1(), SkIntToScalar(480)),
|
|
SkScalarMul(rand.nextUScalar1(), SkIntToScalar(640)),
|
|
SkScalarMul(rand.nextUScalar1(), SkIntToScalar(480)));
|
|
}
|
|
path->close();
|
|
}
|
|
virtual int complexity() SK_OVERRIDE { return 2; }
|
|
private:
|
|
typedef PathBench INHERITED;
|
|
};
|
|
|
|
class LongLinePathBench : public PathBench {
|
|
public:
|
|
LongLinePathBench(void * param, Flags flags)
|
|
: INHERITED(param, flags) {
|
|
}
|
|
|
|
virtual void appendName(SkString* name) SK_OVERRIDE {
|
|
name->append("long_line");
|
|
}
|
|
virtual void makePath(SkPath* path) SK_OVERRIDE {
|
|
SkRandom rand;
|
|
path->moveTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480);
|
|
for (size_t i = 1; i < 100; i++) {
|
|
path->lineTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480);
|
|
}
|
|
}
|
|
virtual int complexity() SK_OVERRIDE { return 2; }
|
|
private:
|
|
typedef PathBench INHERITED;
|
|
};
|
|
|
|
class RandomPathBench : public SkBenchmark {
|
|
public:
|
|
RandomPathBench(void* param) : INHERITED(param) {
|
|
fIsRendering = false;
|
|
}
|
|
|
|
protected:
|
|
void createData(int minVerbs,
|
|
int maxVerbs,
|
|
bool allowMoves = true,
|
|
SkRect* bounds = NULL) {
|
|
SkRect tempBounds;
|
|
if (NULL == bounds) {
|
|
tempBounds.setXYWH(0, 0, SK_Scalar1, SK_Scalar1);
|
|
bounds = &tempBounds;
|
|
}
|
|
fVerbCnts.reset(kNumVerbCnts);
|
|
for (int i = 0; i < kNumVerbCnts; ++i) {
|
|
fVerbCnts[i] = fRandom.nextRangeU(minVerbs, maxVerbs + 1);
|
|
}
|
|
fVerbs.reset(kNumVerbs);
|
|
for (int i = 0; i < kNumVerbs; ++i) {
|
|
do {
|
|
fVerbs[i] = static_cast<SkPath::Verb>(fRandom.nextULessThan(SkPath::kDone_Verb));
|
|
} while (!allowMoves && SkPath::kMove_Verb == fVerbs[i]);
|
|
}
|
|
fPoints.reset(kNumPoints);
|
|
for (int i = 0; i < kNumPoints; ++i) {
|
|
fPoints[i].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++) & (kNumVerbCnts - 1)];
|
|
for (int v = 0; v < vCount; ++v) {
|
|
int verb = fVerbs[(fCurrVerb++) & (kNumVerbs - 1)];
|
|
switch (verb) {
|
|
case SkPath::kMove_Verb:
|
|
path->moveTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
|
|
break;
|
|
case SkPath::kLine_Verb:
|
|
path->lineTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
|
|
break;
|
|
case SkPath::kQuad_Verb:
|
|
path->quadTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)],
|
|
fPoints[(fCurrPoint + 1) & (kNumPoints - 1)]);
|
|
fCurrPoint += 2;
|
|
break;
|
|
case SkPath::kCubic_Verb:
|
|
path->cubicTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)],
|
|
fPoints[(fCurrPoint + 1) & (kNumPoints - 1)],
|
|
fPoints[(fCurrPoint + 2) & (kNumPoints - 1)]);
|
|
fCurrPoint += 3;
|
|
break;
|
|
case SkPath::kClose_Verb:
|
|
path->close();
|
|
break;
|
|
default:
|
|
SkDEBUGFAIL("Unexpected path verb");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void finishedMakingPaths() {
|
|
fVerbCnts.reset(0);
|
|
fVerbs.reset(0);
|
|
fPoints.reset(0);
|
|
}
|
|
|
|
private:
|
|
enum {
|
|
// these should all be pow 2
|
|
kNumVerbCnts = 1 << 5,
|
|
kNumVerbs = 1 << 5,
|
|
kNumPoints = 1 << 5,
|
|
};
|
|
SkAutoTArray<int> fVerbCnts;
|
|
SkAutoTArray<SkPath::Verb> fVerbs;
|
|
SkAutoTArray<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);
|
|
fPaths.reset(kPathCnt);
|
|
}
|
|
|
|
virtual void onDraw(SkCanvas*) SK_OVERRIDE {
|
|
for (int i = 0; i < N; ++i) {
|
|
this->makePath(&fPaths[i & (kPathCnt - 1)]);
|
|
}
|
|
this->restartMakingPaths();
|
|
}
|
|
|
|
virtual void onPostDraw() SK_OVERRIDE {
|
|
this->finishedMakingPaths();
|
|
fPaths.reset(0);
|
|
}
|
|
|
|
private:
|
|
enum {
|
|
// must be a pow 2
|
|
kPathCnt = 1 << 5,
|
|
};
|
|
SkAutoTArray<SkPath> fPaths;
|
|
|
|
typedef RandomPathBench INHERITED;
|
|
};
|
|
|
|
class PathCopyBench : public RandomPathBench {
|
|
public:
|
|
PathCopyBench(void* param) : INHERITED(param) {
|
|
}
|
|
|
|
protected:
|
|
enum { N = SkBENCHLOOP(30000) };
|
|
|
|
virtual const char* onGetName() SK_OVERRIDE {
|
|
return "path_copy";
|
|
}
|
|
virtual void onPreDraw() SK_OVERRIDE {
|
|
this->createData(10, 100);
|
|
fPaths.reset(kPathCnt);
|
|
fCopies.reset(kPathCnt);
|
|
for (int i = 0; i < kPathCnt; ++i) {
|
|
this->makePath(&fPaths[i]);
|
|
}
|
|
this->finishedMakingPaths();
|
|
}
|
|
virtual void onDraw(SkCanvas*) SK_OVERRIDE {
|
|
for (int i = 0; i < N; ++i) {
|
|
int idx = i & (kPathCnt - 1);
|
|
fCopies[idx] = fPaths[idx];
|
|
}
|
|
}
|
|
virtual void onPostDraw() SK_OVERRIDE {
|
|
fPaths.reset(0);
|
|
fCopies.reset(0);
|
|
}
|
|
|
|
private:
|
|
enum {
|
|
// must be a pow 2
|
|
kPathCnt = 1 << 5,
|
|
};
|
|
SkAutoTArray<SkPath> fPaths;
|
|
SkAutoTArray<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);
|
|
fPaths.reset(kPathCnt);
|
|
for (int i = 0; i < kPathCnt; ++i) {
|
|
this->makePath(&fPaths[i]);
|
|
}
|
|
this->finishedMakingPaths();
|
|
if (!fInPlace) {
|
|
fTransformed.reset(kPathCnt);
|
|
}
|
|
}
|
|
|
|
virtual void onDraw(SkCanvas*) SK_OVERRIDE {
|
|
if (fInPlace) {
|
|
for (int i = 0; i < N; ++i) {
|
|
fPaths[i & (kPathCnt - 1)].transform(fMatrix);
|
|
}
|
|
} else {
|
|
for (int i = 0; i < N; ++i) {
|
|
int idx = i & (kPathCnt - 1);
|
|
fPaths[idx].transform(fMatrix, &fTransformed[idx]);
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void onPostDraw() SK_OVERRIDE {
|
|
fPaths.reset(0);
|
|
fTransformed.reset(0);
|
|
}
|
|
|
|
private:
|
|
enum {
|
|
// must be a pow 2
|
|
kPathCnt = 1 << 5,
|
|
};
|
|
SkAutoTArray<SkPath> fPaths;
|
|
SkAutoTArray<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);
|
|
fPaths.reset(kPathCnt);
|
|
fCopies.reset(kPathCnt);
|
|
for (int i = 0; i < kPathCnt; ++i) {
|
|
this->makePath(&fPaths[i]);
|
|
fCopies[i] = fPaths[i];
|
|
}
|
|
this->finishedMakingPaths();
|
|
}
|
|
|
|
virtual void onDraw(SkCanvas*) SK_OVERRIDE {
|
|
for (int i = 0; i < N; ++i) {
|
|
int idx = i & (kPathCnt - 1);
|
|
fParity ^= (fPaths[idx] == fCopies[idx & ~0x1]);
|
|
}
|
|
}
|
|
|
|
virtual void onPostDraw() SK_OVERRIDE {
|
|
fPaths.reset(0);
|
|
fCopies.reset(0);
|
|
}
|
|
|
|
private:
|
|
bool fParity; // attempt to keep compiler from optimizing out the ==
|
|
enum {
|
|
// must be a pow 2
|
|
kPathCnt = 1 << 5,
|
|
};
|
|
SkAutoTArray<SkPath> fPaths;
|
|
SkAutoTArray<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, allowMoves);
|
|
fPaths0.reset(kPathCnt);
|
|
fPaths1.reset(kPathCnt);
|
|
for (int i = 0; i < kPathCnt; ++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) {
|
|
int idx = i & (kPathCnt - 1);
|
|
SkPath result = fPaths0[idx];
|
|
result.addPath(fPaths1[idx]);
|
|
}
|
|
break;
|
|
case kAddTrans_AddType:
|
|
for (int i = 0; i < N; ++i) {
|
|
int idx = i & (kPathCnt - 1);
|
|
SkPath result = fPaths0[idx];
|
|
result.addPath(fPaths1[idx], 2 * SK_Scalar1, 5 * SK_Scalar1);
|
|
}
|
|
break;
|
|
case kAddMatrix_AddType:
|
|
for (int i = 0; i < N; ++i) {
|
|
int idx = i & (kPathCnt - 1);
|
|
SkPath result = fPaths0[idx];
|
|
result.addPath(fPaths1[idx], fMatrix);
|
|
}
|
|
break;
|
|
case kPathTo_AddType:
|
|
for (int i = 0; i < N; ++i) {
|
|
int idx = i & (kPathCnt - 1);
|
|
SkPath result = fPaths0[idx];
|
|
result.pathTo(fPaths1[idx]);
|
|
}
|
|
break;
|
|
case kReverseAdd_AddType:
|
|
for (int i = 0; i < N; ++i) {
|
|
int idx = i & (kPathCnt - 1);
|
|
SkPath result = fPaths0[idx];
|
|
result.reverseAddPath(fPaths1[idx]);
|
|
}
|
|
break;
|
|
case kReversePathTo_AddType:
|
|
for (int i = 0; i < N; ++i) {
|
|
int idx = i & (kPathCnt - 1);
|
|
SkPath result = fPaths0[idx];
|
|
result.reversePathTo(fPaths1[idx]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
virtual void onPostDraw() SK_OVERRIDE {
|
|
fPaths0.reset(0);
|
|
fPaths1.reset(0);
|
|
}
|
|
|
|
private:
|
|
AddType fType; // or reverseAddPath
|
|
enum {
|
|
// must be a pow 2
|
|
kPathCnt = 1 << 5,
|
|
};
|
|
SkAutoTArray<SkPath> fPaths0;
|
|
SkAutoTArray<SkPath> fPaths1;
|
|
SkMatrix fMatrix;
|
|
typedef RandomPathBench INHERITED;
|
|
};
|
|
|
|
|
|
class CirclesBench : public SkBenchmark {
|
|
protected:
|
|
SkString fName;
|
|
Flags fFlags;
|
|
|
|
enum {
|
|
N = SkBENCHLOOP(100)
|
|
};
|
|
public:
|
|
CirclesBench(void* param, Flags flags) : INHERITED(param), fFlags(flags) {
|
|
fName.printf("circles_%s", fFlags & kStroke_Flag ? "stroke" : "fill");
|
|
}
|
|
|
|
protected:
|
|
virtual const char* onGetName() SK_OVERRIDE {
|
|
return fName.c_str();
|
|
}
|
|
|
|
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
|
SkPaint paint;
|
|
|
|
paint.setColor(SK_ColorBLACK);
|
|
paint.setAntiAlias(true);
|
|
if (fFlags & kStroke_Flag) {
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
}
|
|
|
|
SkRandom rand;
|
|
|
|
SkRect r;
|
|
|
|
for (int i = 0; i < 5000; ++i) {
|
|
SkScalar radius = rand.nextUScalar1() * 3;
|
|
r.fLeft = rand.nextUScalar1() * 300;
|
|
r.fTop = rand.nextUScalar1() * 300;
|
|
r.fRight = r.fLeft + 2 * radius;
|
|
r.fBottom = r.fTop + 2 * radius;
|
|
|
|
if (fFlags & kStroke_Flag) {
|
|
paint.setStrokeWidth(rand.nextUScalar1() * 5.0f);
|
|
}
|
|
|
|
SkPath temp;
|
|
|
|
// mimic how Chrome does circles
|
|
temp.arcTo(r, 0, 0, false);
|
|
temp.addOval(r, SkPath::kCCW_Direction);
|
|
temp.arcTo(r, 360, 0, true);
|
|
temp.close();
|
|
|
|
canvas->drawPath(temp, paint);
|
|
}
|
|
}
|
|
|
|
private:
|
|
typedef SkBenchmark INHERITED;
|
|
};
|
|
|
|
|
|
// Chrome creates its own round rects with each corner possibly being different.
|
|
// In its "zero radius" incarnation it creates degenerate round rects.
|
|
// Note: PathTest::test_arb_round_rect_is_convex and
|
|
// test_arb_zero_rad_round_rect_is_rect perform almost exactly
|
|
// the same test (but with no drawing)
|
|
class ArbRoundRectBench : public SkBenchmark {
|
|
protected:
|
|
SkString fName;
|
|
|
|
enum {
|
|
N = SkBENCHLOOP(100)
|
|
};
|
|
public:
|
|
ArbRoundRectBench(void* param, bool zeroRad) : INHERITED(param), fZeroRad(zeroRad) {
|
|
if (zeroRad) {
|
|
fName.printf("zeroradroundrect");
|
|
} else {
|
|
fName.printf("arbroundrect");
|
|
}
|
|
}
|
|
|
|
protected:
|
|
virtual const char* onGetName() SK_OVERRIDE {
|
|
return fName.c_str();
|
|
}
|
|
|
|
static void add_corner_arc(SkPath* path, const SkRect& rect,
|
|
SkScalar xIn, SkScalar yIn,
|
|
int startAngle)
|
|
{
|
|
|
|
SkScalar rx = SkMinScalar(rect.width(), xIn);
|
|
SkScalar ry = SkMinScalar(rect.height(), yIn);
|
|
|
|
SkRect arcRect;
|
|
arcRect.set(-rx, -ry, rx, ry);
|
|
switch (startAngle) {
|
|
case 0:
|
|
arcRect.offset(rect.fRight - arcRect.fRight, rect.fBottom - arcRect.fBottom);
|
|
break;
|
|
case 90:
|
|
arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fBottom - arcRect.fBottom);
|
|
break;
|
|
case 180:
|
|
arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fTop - arcRect.fTop);
|
|
break;
|
|
case 270:
|
|
arcRect.offset(rect.fRight - arcRect.fRight, rect.fTop - arcRect.fTop);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
path->arcTo(arcRect, SkIntToScalar(startAngle), SkIntToScalar(90), false);
|
|
}
|
|
|
|
static void make_arb_round_rect(SkPath* path, const SkRect& r,
|
|
SkScalar xCorner, SkScalar yCorner) {
|
|
// we are lazy here and use the same x & y for each corner
|
|
add_corner_arc(path, r, xCorner, yCorner, 270);
|
|
add_corner_arc(path, r, xCorner, yCorner, 0);
|
|
add_corner_arc(path, r, xCorner, yCorner, 90);
|
|
add_corner_arc(path, r, xCorner, yCorner, 180);
|
|
path->close();
|
|
|
|
#ifndef SK_IGNORE_CONVEX_QUAD_OPT
|
|
SkASSERT(path->isConvex());
|
|
#endif
|
|
}
|
|
|
|
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
|
SkRandom rand;
|
|
SkRect r;
|
|
|
|
for (int i = 0; i < 5000; ++i) {
|
|
SkPaint paint;
|
|
paint.setColor(0xff000000 | rand.nextU());
|
|
paint.setAntiAlias(true);
|
|
|
|
SkScalar size = rand.nextUScalar1() * 30;
|
|
if (size < SK_Scalar1) {
|
|
continue;
|
|
}
|
|
r.fLeft = rand.nextUScalar1() * 300;
|
|
r.fTop = rand.nextUScalar1() * 300;
|
|
r.fRight = r.fLeft + 2 * size;
|
|
r.fBottom = r.fTop + 2 * size;
|
|
|
|
SkPath temp;
|
|
|
|
if (fZeroRad) {
|
|
make_arb_round_rect(&temp, r, 0, 0);
|
|
|
|
SkASSERT(temp.isRect(NULL));
|
|
} else {
|
|
make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15);
|
|
}
|
|
|
|
canvas->drawPath(temp, paint);
|
|
}
|
|
}
|
|
|
|
private:
|
|
bool fZeroRad; // should 0 radius rounds rects be tested?
|
|
|
|
typedef SkBenchmark INHERITED;
|
|
};
|
|
|
|
class ConservativelyContainsBench : public SkBenchmark {
|
|
public:
|
|
enum Type {
|
|
kRect_Type,
|
|
kRoundRect_Type,
|
|
kOval_Type,
|
|
};
|
|
|
|
ConservativelyContainsBench(void* param, Type type) : INHERITED(param) {
|
|
fIsRendering = false;
|
|
fParity = false;
|
|
fName = "conservatively_contains_";
|
|
switch (type) {
|
|
case kRect_Type:
|
|
fName.append("rect");
|
|
fPath.addRect(kBaseRect);
|
|
break;
|
|
case kRoundRect_Type:
|
|
fName.append("round_rect");
|
|
fPath.addRoundRect(kBaseRect, kRRRadii[0], kRRRadii[1]);
|
|
break;
|
|
case kOval_Type:
|
|
fName.append("oval");
|
|
fPath.addOval(kBaseRect);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private:
|
|
virtual const char* onGetName() SK_OVERRIDE {
|
|
return fName.c_str();
|
|
}
|
|
|
|
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
|
for (int i = 0; i < N; ++i) {
|
|
const SkRect& rect = fQueryRects[i % kQueryRectCnt];
|
|
fParity = fParity != fPath.conservativelyContainsRect(rect);
|
|
}
|
|
}
|
|
|
|
virtual void onPreDraw() SK_OVERRIDE {
|
|
fQueryRects.setCount(kQueryRectCnt);
|
|
|
|
SkRandom rand;
|
|
for (int i = 0; i < kQueryRectCnt; ++i) {
|
|
SkSize size;
|
|
SkPoint xy;
|
|
size.fWidth = rand.nextRangeScalar(kQueryMin.fWidth, kQueryMax.fWidth);
|
|
size.fHeight = rand.nextRangeScalar(kQueryMin.fHeight, kQueryMax.fHeight);
|
|
xy.fX = rand.nextRangeScalar(kBounds.fLeft, kBounds.fRight - size.fWidth);
|
|
xy.fY = rand.nextRangeScalar(kBounds.fTop, kBounds.fBottom - size.fHeight);
|
|
|
|
fQueryRects[i] = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight);
|
|
}
|
|
}
|
|
|
|
virtual void onPostDraw() SK_OVERRIDE {
|
|
fQueryRects.setCount(0);
|
|
}
|
|
|
|
enum {
|
|
N = SkBENCHLOOP(100000),
|
|
kQueryRectCnt = 400,
|
|
};
|
|
static const SkRect kBounds; // bounds for all random query rects
|
|
static const SkSize kQueryMin; // minimum query rect size, should be <= kQueryMax
|
|
static const SkSize kQueryMax; // max query rect size, should < kBounds
|
|
static const SkRect kBaseRect; // rect that is used to construct the path
|
|
static const SkScalar kRRRadii[2]; // x and y radii for round rect
|
|
|
|
SkString fName;
|
|
SkPath fPath;
|
|
bool fParity;
|
|
SkTDArray<SkRect> fQueryRects;
|
|
|
|
typedef SkBenchmark INHERITED;
|
|
};
|
|
|
|
const SkRect ConservativelyContainsBench::kBounds = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
|
|
const SkSize ConservativelyContainsBench::kQueryMin = SkSize::Make(SkIntToScalar(1), SkIntToScalar(1));
|
|
const SkSize ConservativelyContainsBench::kQueryMax = SkSize::Make(SkIntToScalar(40), SkIntToScalar(40));
|
|
const SkRect ConservativelyContainsBench::kBaseRect = SkRect::MakeXYWH(SkIntToScalar(25), SkIntToScalar(25), SkIntToScalar(50), SkIntToScalar(50));
|
|
const SkScalar ConservativelyContainsBench::kRRRadii[2] = {SkIntToScalar(5), SkIntToScalar(10)};
|
|
|
|
static SkBenchmark* FactT00(void* p) { return new TrianglePathBench(p, FLAGS00); }
|
|
static SkBenchmark* FactT01(void* p) { return new TrianglePathBench(p, FLAGS01); }
|
|
static SkBenchmark* FactT10(void* p) { return new TrianglePathBench(p, FLAGS10); }
|
|
static SkBenchmark* FactT11(void* p) { return new TrianglePathBench(p, FLAGS11); }
|
|
|
|
static SkBenchmark* FactR00(void* p) { return new RectPathBench(p, FLAGS00); }
|
|
static SkBenchmark* FactR01(void* p) { return new RectPathBench(p, FLAGS01); }
|
|
static SkBenchmark* FactR10(void* p) { return new RectPathBench(p, FLAGS10); }
|
|
static SkBenchmark* FactR11(void* p) { return new RectPathBench(p, FLAGS11); }
|
|
|
|
static SkBenchmark* FactO00(void* p) { return new OvalPathBench(p, FLAGS00); }
|
|
static SkBenchmark* FactO01(void* p) { return new OvalPathBench(p, FLAGS01); }
|
|
static SkBenchmark* FactO10(void* p) { return new OvalPathBench(p, FLAGS10); }
|
|
static SkBenchmark* FactO11(void* p) { return new OvalPathBench(p, FLAGS11); }
|
|
|
|
static SkBenchmark* FactC00(void* p) { return new CirclePathBench(p, FLAGS00); }
|
|
static SkBenchmark* FactC01(void* p) { return new CirclePathBench(p, FLAGS01); }
|
|
static SkBenchmark* FactC10(void* p) { return new CirclePathBench(p, FLAGS10); }
|
|
static SkBenchmark* FactC11(void* p) { return new CirclePathBench(p, FLAGS11); }
|
|
|
|
static SkBenchmark* FactS00(void* p) { return new SawToothPathBench(p, FLAGS00); }
|
|
static SkBenchmark* FactS01(void* p) { return new SawToothPathBench(p, FLAGS01); }
|
|
|
|
static SkBenchmark* FactLC00(void* p) {
|
|
return new LongCurvedPathBench(p, FLAGS00);
|
|
}
|
|
static SkBenchmark* FactLC01(void* p) {
|
|
return new LongCurvedPathBench(p, FLAGS01);
|
|
}
|
|
|
|
static SkBenchmark* FactLL00(void* p) {
|
|
return new LongLinePathBench(p, FLAGS00);
|
|
}
|
|
|
|
static SkBenchmark* FactLL01(void* p) {
|
|
return new LongLinePathBench(p, FLAGS01);
|
|
}
|
|
|
|
static BenchRegistry gRegT00(FactT00);
|
|
static BenchRegistry gRegT01(FactT01);
|
|
static BenchRegistry gRegT10(FactT10);
|
|
static BenchRegistry gRegT11(FactT11);
|
|
|
|
static BenchRegistry gRegR00(FactR00);
|
|
static BenchRegistry gRegR01(FactR01);
|
|
static BenchRegistry gRegR10(FactR10);
|
|
static BenchRegistry gRegR11(FactR11);
|
|
|
|
static BenchRegistry gRegO00(FactO00);
|
|
static BenchRegistry gRegO01(FactO01);
|
|
static BenchRegistry gRegO10(FactO10);
|
|
static BenchRegistry gRegO11(FactO11);
|
|
|
|
static BenchRegistry gRegC00(FactC00);
|
|
static BenchRegistry gRegC01(FactC01);
|
|
static BenchRegistry gRegC10(FactC10);
|
|
static BenchRegistry gRegC11(FactC11);
|
|
|
|
static BenchRegistry gRegS00(FactS00);
|
|
static BenchRegistry gRegS01(FactS01);
|
|
|
|
static BenchRegistry gRegLC00(FactLC00);
|
|
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);
|
|
|
|
static SkBenchmark* CirclesTest(void* p) { return new CirclesBench(p, FLAGS00); }
|
|
static BenchRegistry gRegCirclesTest(CirclesTest);
|
|
|
|
static SkBenchmark* CirclesStrokeTest(void* p) { return new CirclesBench(p, FLAGS01); }
|
|
static BenchRegistry gRegCirclesStrokeTest(CirclesStrokeTest);
|
|
|
|
static SkBenchmark* ArbRoundRectTest(void* p) { return new ArbRoundRectBench(p, false); }
|
|
static BenchRegistry gRegArbRoundRectTest(ArbRoundRectTest);
|
|
|
|
static SkBenchmark* ZeroRadRoundRectTest(void* p) { return new ArbRoundRectBench(p, true); }
|
|
static BenchRegistry gRegZeroRadRoundRectTest(ZeroRadRoundRectTest);
|
|
|
|
static SkBenchmark* RectConservativelyContainsTest(void* p) { return new ConservativelyContainsBench(p, ConservativelyContainsBench::kRect_Type); }
|
|
static BenchRegistry gRegRectConservativelyContainsTest(RectConservativelyContainsTest);
|
|
|
|
static SkBenchmark* RoundRectConservativelyContainsTest(void* p) { return new ConservativelyContainsBench(p, ConservativelyContainsBench::kRoundRect_Type); }
|
|
static BenchRegistry gRegRoundRectConservativelyContainsTest(RoundRectConservativelyContainsTest);
|
|
|
|
static SkBenchmark* OvalConservativelyContainsTest(void* p) { return new ConservativelyContainsBench(p, ConservativelyContainsBench::kOval_Type); }
|
|
static BenchRegistry gRegOvalConservativelyContainsTest(OvalConservativelyContainsTest);
|