diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-06-01 15:11:22 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-06-01 15:11:22 +0000 |
commit | 3fb5187647397e056843c1f41a508992be22175d (patch) | |
tree | 119a14084dd42d5334140525d599548b32bb4612 | |
parent | ac2e663762cb88dfea334d77052c6428b1a07d87 (diff) |
speed-up SkMatrix::preScale by 3x, by special-casing it instead of just calling
concat. Inspired by the profile of the fishtank site
git-svn-id: http://skia.googlecode.com/svn/trunk@1462 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | bench/MatrixBench.cpp | 90 | ||||
-rw-r--r-- | include/core/SkMatrix.h | 21 | ||||
-rw-r--r-- | src/core/SkMatrix.cpp | 33 |
3 files changed, 142 insertions, 2 deletions
diff --git a/bench/MatrixBench.cpp b/bench/MatrixBench.cpp new file mode 100644 index 0000000000..1c99ab433e --- /dev/null +++ b/bench/MatrixBench.cpp @@ -0,0 +1,90 @@ +#include "SkBenchmark.h" +#include "SkMatrix.h" +#include "SkString.h" + +class MatrixBench : public SkBenchmark { + SkString fName; + enum { N = 100000 }; +public: + MatrixBench(void* param, const char name[]) : INHERITED(param) { + fName.printf("matrix_%s", name); + } + + virtual void performTest() = 0; + +protected: + virtual const char* onGetName() { + return fName.c_str(); + } + + virtual void onDraw(SkCanvas* canvas) { + for (int i = 0; i < N; i++) { + this->performTest(); + } + } + +private: + typedef SkBenchmark INHERITED; +}; + +// we want to stop the compiler from eliminating code that it thinks is a no-op +// so we have a non-static global we increment, hoping that will convince the +// compiler to execute everything +int gMatrixBench_NonStaticGlobal; + +#define always_do(pred) \ + do { \ + if (pred) { \ + ++gMatrixBench_NonStaticGlobal; \ + } \ + } while (0) + +class EqualsMatrixBench : public MatrixBench { +public: + EqualsMatrixBench(void* param) : INHERITED(param, "equals") {} +protected: + virtual void performTest() { + SkMatrix m0, m1, m2; + + m0.reset(); + m1.reset(); + m2.reset(); + always_do(m0 == m1); + always_do(m1 == m2); + always_do(m2 == m0); + always_do(m0.getType()); + always_do(m1.getType()); + always_do(m2.getType()); + } +private: + typedef MatrixBench INHERITED; +}; + +class ScaleMatrixBench : public MatrixBench { +public: + ScaleMatrixBench(void* param) : INHERITED(param, "scale") { + + fM0.reset(); + fM1.setScale(fSX, fSY); + fM2.setTranslate(fSX, fSY); + fSX = fSY = SkFloatToScalar(1.5f); + } +protected: + virtual void performTest() { + SkMatrix m; + m = fM0; m.preScale(fSX, fSY); + m = fM1; m.preScale(fSX, fSY); + m = fM2; m.preScale(fSX, fSY); + } +private: + SkMatrix fM0, fM1, fM2; + SkScalar fSX, fSY; + typedef MatrixBench INHERITED; +}; + +static SkBenchmark* M0(void* p) { return new EqualsMatrixBench(p); } +static SkBenchmark* M1(void* p) { return new ScaleMatrixBench(p); } + +static BenchRegistry gReg0(M0); +static BenchRegistry gReg1(M1); + diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h index 7c779027be..480e0777ac 100644 --- a/include/core/SkMatrix.h +++ b/include/core/SkMatrix.h @@ -438,6 +438,7 @@ public: */ bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const; +#ifdef SK_SCALAR_IS_FIXED friend bool operator==(const SkMatrix& a, const SkMatrix& b) { return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) == 0; } @@ -445,6 +446,12 @@ public: friend bool operator!=(const SkMatrix& a, const SkMatrix& b) { return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) != 0; } +#else + friend bool operator==(const SkMatrix& a, const SkMatrix& b); + friend bool operator!=(const SkMatrix& a, const SkMatrix& b) { + return !(a == b); + } +#endif enum { // flatten/unflatten will never return a value larger than this @@ -488,7 +495,12 @@ private: kRectStaysRect_Mask = 0x10, kUnknown_Mask = 0x80, - + + kORableMasks = kTranslate_Mask | + kScale_Mask | + kAffine_Mask | + kPerspective_Mask, + kAllMasks = kTranslate_Mask | kScale_Mask | kAffine_Mask | @@ -506,7 +518,12 @@ private: SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask); fTypeMask = SkToU8(mask); } - + + void orTypeMask(int mask) { + SkASSERT((mask & kORableMasks) == mask); + fTypeMask = SkToU8(fTypeMask | mask); + } + void clearTypeMask(int mask) { // only allow a valid mask SkASSERT((mask & kAllMasks) == mask); diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp index 983c8d21f2..06bca1e59d 100644 --- a/src/core/SkMatrix.cpp +++ b/src/core/SkMatrix.cpp @@ -119,6 +119,21 @@ uint8_t SkMatrix::computeTypeMask() const { /////////////////////////////////////////////////////////////////////////////// +#ifdef SK_SCALAR_IS_FLOAT + +bool operator==(const SkMatrix& a, const SkMatrix& b) { + const SkScalar* SK_RESTRICT ma = a.fMat; + const SkScalar* SK_RESTRICT mb = b.fMat; + + return ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] && + ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] && + ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8]; +} + +#endif + +/////////////////////////////////////////////////////////////////////////////// + void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) { if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) { fMat[kMTransX] = dx; @@ -202,9 +217,27 @@ bool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { } bool SkMatrix::preScale(SkScalar sx, SkScalar sy) { +#ifdef SK_SCALAR_IS_FIXED SkMatrix m; m.setScale(sx, sy); return this->preConcat(m); +#else + // the assumption is that these multiplies are very cheap, and that + // a full concat and/or just computing the matrix type is more expensive. + // Also, the fixed-point case checks for overflow, but the float doesn't, + // so we can get away with these blind multiplies. + + fMat[kMScaleX] = SkScalarMul(fMat[kMScaleX], sx); + fMat[kMSkewY] = SkScalarMul(fMat[kMSkewY], sx); + fMat[kMPersp0] = SkScalarMul(fMat[kMPersp0], sx); + + fMat[kMSkewX] = SkScalarMul(fMat[kMSkewX], sy); + fMat[kMScaleY] = SkScalarMul(fMat[kMScaleY], sy); + fMat[kMPersp1] = SkScalarMul(fMat[kMPersp1], sy); + + this->orTypeMask(kScale_Mask); + return true; +#endif } bool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { |