aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-03-27 14:00:41 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-03-27 14:00:41 -0700
commitd8b34c26c2a2f8e37e0cc9a7910306aecacadd92 (patch)
tree2ef5373303afcdd495fd2169b7082ed2c94808af
parent5cffba8d8e6965b10017fae7d8b67c8724e12822 (diff)
use table of procs (and unrolling) to speed up mapPts
-rw-r--r--bench/MatrixBench.cpp5
-rw-r--r--include/core/SkMatrix.h9
-rw-r--r--src/core/SkMatrix.cpp89
3 files changed, 64 insertions, 39 deletions
diff --git a/bench/MatrixBench.cpp b/bench/MatrixBench.cpp
index 6bd1e2a8a6..68195e70e4 100644
--- a/bench/MatrixBench.cpp
+++ b/bench/MatrixBench.cpp
@@ -267,8 +267,7 @@ DEF_BENCH( return new InvertMapRectMatrixBench(
///////////////////////////////////////////////////////////////////////////////
-static SkMatrix make_ident() { SkMatrix m; m.reset(); return m; }
-static SkMatrix make_trans() { SkMatrix m; m.setTranslate(2, 3); return m; }
+static SkMatrix make_trans() { return SkMatrix::MakeTrans(2, 3); }
static SkMatrix make_scale() { SkMatrix m(make_trans()); m.postScale(1.5f, 0.5f); return m; }
static SkMatrix make_afine() { SkMatrix m(make_trans()); m.postRotate(15); return m; }
@@ -302,8 +301,6 @@ public:
}
}
};
-DEF_BENCH( return new MapPointsMatrixBench("mappts_ident0", make_ident(), false); )
-DEF_BENCH( return new MapPointsMatrixBench("mappts_ident1", make_ident(), true); )
DEF_BENCH( return new MapPointsMatrixBench("mappts_trans0", make_trans(), false); )
DEF_BENCH( return new MapPointsMatrixBench("mappts_trans1", make_trans(), true); )
DEF_BENCH( return new MapPointsMatrixBench("mappts_scale0", make_scale(), false); )
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h
index 89bd7935c9..0408634ead 100644
--- a/include/core/SkMatrix.h
+++ b/include/core/SkMatrix.h
@@ -426,7 +426,9 @@ public:
this->mapPoints(pts, pts, count);
}
- void mapPts(SkPoint dst[], const SkPoint src[], int count) const;
+ void mapPts(SkPoint dst[], const SkPoint src[], int count) const {
+ gMapVPtsProcs[this->getType() & 0xF](*this, dst, src, count);
+ }
/** Like mapPoints but with custom byte stride between the points. Stride
* should be a multiple of sizeof(SkScalar).
@@ -799,7 +801,12 @@ private:
int count);
static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+ static void Trans_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+ static void Scale_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+ static void Affine_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+
static const MapPtsProc gMapPtsProcs[];
+ static const MapPtsProc gMapVPtsProcs[];
friend class SkPerspIter;
};
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index 81b8960855..a43e00f3af 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1022,22 +1022,12 @@ void SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
#include "Sk4x.h"
-void SkMatrix::mapPts(SkPoint dst[], const SkPoint src[], int count) const {
- if (count <= 0) {
- return;
- }
+void SkMatrix::Trans_vpts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {
+ SkASSERT(m.getType() <= kTranslate_Mask);
- unsigned mask = this->getType() & 0xF;
-
- if (SkMatrix::kIdentity_Mask == mask) {
- if (src != dst) {
- memcpy(dst, src, count * sizeof(SkPoint));
- }
- return;
- }
- if (SkMatrix::kTranslate_Mask == mask) {
- SkScalar tx = this->getTranslateX();
- SkScalar ty = this->getTranslateY();
+ if (count > 0) {
+ SkScalar tx = m.getTranslateX();
+ SkScalar ty = m.getTranslateY();
if (count & 1) {
dst->fX = src->fX + tx;
dst->fY = src->fY + ty;
@@ -1046,18 +1036,29 @@ void SkMatrix::mapPts(SkPoint dst[], const SkPoint src[], int count) const {
}
Sk4f trans4(tx, ty, tx, ty);
count >>= 1;
- for (int i = 0; i < count; ++i) {
+ if (count & 1) {
(Sk4f::Load(&src->fX) + trans4).store(&dst->fX);
src += 2;
dst += 2;
}
- return;
+ count >>= 1;
+ for (int i = 0; i < count; ++i) {
+ (Sk4f::Load(&src[0].fX) + trans4).store(&dst[0].fX);
+ (Sk4f::Load(&src[2].fX) + trans4).store(&dst[2].fX);
+ src += 4;
+ dst += 4;
+ }
}
- if (mask <= SkMatrix::kScale_Mask + SkMatrix::kTranslate_Mask) {
- SkScalar tx = this->getTranslateX();
- SkScalar ty = this->getTranslateY();
- SkScalar sx = this->getScaleX();
- SkScalar sy = this->getScaleY();
+}
+
+void SkMatrix::Scale_vpts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {
+ SkASSERT(m.getType() <= (kScale_Mask | kTranslate_Mask));
+
+ if (count > 0) {
+ SkScalar tx = m.getTranslateX();
+ SkScalar ty = m.getTranslateY();
+ SkScalar sx = m.getScaleX();
+ SkScalar sy = m.getScaleY();
if (count & 1) {
dst->fX = src->fX * sx + tx;
dst->fY = src->fY * sy + ty;
@@ -1067,20 +1068,31 @@ void SkMatrix::mapPts(SkPoint dst[], const SkPoint src[], int count) const {
Sk4f trans4(tx, ty, tx, ty);
Sk4f scale4(sx, sy, sx, sy);
count >>= 1;
- for (int i = 0; i < count; ++i) {
+ if (count & 1) {
(Sk4f::Load(&src->fX) * scale4 + trans4).store(&dst->fX);
src += 2;
dst += 2;
}
- return;
+ count >>= 1;
+ for (int i = 0; i < count; ++i) {
+ (Sk4f::Load(&src[0].fX) * scale4 + trans4).store(&dst[0].fX);
+ (Sk4f::Load(&src[2].fX) * scale4 + trans4).store(&dst[2].fX);
+ src += 4;
+ dst += 4;
+ }
}
- if (mask < SkMatrix::kPerspective_Mask) { // affine
- SkScalar tx = this->getTranslateX();
- SkScalar ty = this->getTranslateY();
- SkScalar sx = this->getScaleX();
- SkScalar sy = this->getScaleY();
- SkScalar kx = this->getSkewX();
- SkScalar ky = this->getSkewY();
+}
+
+void SkMatrix::Affine_vpts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {
+ SkASSERT(m.getType() != kPerspective_Mask);
+
+ if (count > 0) {
+ SkScalar tx = m.getTranslateX();
+ SkScalar ty = m.getTranslateY();
+ SkScalar sx = m.getScaleX();
+ SkScalar sy = m.getScaleY();
+ SkScalar kx = m.getSkewX();
+ SkScalar ky = m.getSkewY();
if (count & 1) {
dst->set(src->fX * sx + src->fY * kx + tx,
src->fX * ky + src->fY * sy + ty);
@@ -1098,12 +1110,21 @@ void SkMatrix::mapPts(SkPoint dst[], const SkPoint src[], int count) const {
src += 2;
dst += 2;
}
- return;
}
- // fall through for perspective
- this->mapPoints(dst, src, count);
}
+const SkMatrix::MapPtsProc SkMatrix::gMapVPtsProcs[] = {
+ SkMatrix::Identity_pts, SkMatrix::Trans_vpts,
+ SkMatrix::Scale_vpts, SkMatrix::Scale_vpts,
+ SkMatrix::Affine_vpts, SkMatrix::Affine_vpts,
+ SkMatrix::Affine_vpts, SkMatrix::Affine_vpts,
+ // repeat the persp proc 8 times
+ SkMatrix::Persp_pts, SkMatrix::Persp_pts,
+ SkMatrix::Persp_pts, SkMatrix::Persp_pts,
+ SkMatrix::Persp_pts, SkMatrix::Persp_pts,
+ SkMatrix::Persp_pts, SkMatrix::Persp_pts
+};
+
///////////////////////////////////////////////////////////////////////////////
void SkMatrix::mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const {