diff options
author | reed <reed@google.com> | 2015-03-27 14:00:41 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-27 14:00:41 -0700 |
commit | d8b34c26c2a2f8e37e0cc9a7910306aecacadd92 (patch) | |
tree | 2ef5373303afcdd495fd2169b7082ed2c94808af | |
parent | 5cffba8d8e6965b10017fae7d8b67c8724e12822 (diff) |
use table of procs (and unrolling) to speed up mapPts
BUG=skia:
Review URL: https://codereview.chromium.org/1040783002
-rw-r--r-- | bench/MatrixBench.cpp | 5 | ||||
-rw-r--r-- | include/core/SkMatrix.h | 9 | ||||
-rw-r--r-- | src/core/SkMatrix.cpp | 89 |
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 { |