From b25a83bd8802b7c3c5746c319e781f45337fe207 Mon Sep 17 00:00:00 2001 From: reed Date: Wed, 25 Mar 2015 14:30:49 -0700 Subject: [PATCH] Use Sk4x to speed-up bounds of an array of points BUG=skia: Review URL: https://codereview.chromium.org/1015633004 --- bench/ScalarBench.cpp | 4 +++- src/core/SkRect.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/bench/ScalarBench.cpp b/bench/ScalarBench.cpp index 21f9264e9c..f1a9b9adee 100644 --- a/bench/ScalarBench.cpp +++ b/bench/ScalarBench.cpp @@ -152,7 +152,9 @@ class RectBoundsBench : public Benchmark { void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE { SkRect r; for (int i = 0; i < loops; ++i) { - r.set(fPts, PTS); + for (int i = 0; i < 1000; ++i) { + r.set(fPts, PTS); + } } } diff --git a/src/core/SkRect.cpp b/src/core/SkRect.cpp index ecf6fa2989..2c973a1ef2 100644 --- a/src/core/SkRect.cpp +++ b/src/core/SkRect.cpp @@ -45,6 +45,14 @@ void SkRect::toQuad(SkPoint quad[4]) const { quad[3].set(fLeft, fBottom); } +//#include "Sk2x.h" +#include "Sk4x.h" + +static inline bool is_finite(const Sk4f& value) { + Sk4i finite = value * Sk4f(0) == Sk4f(0); + return finite.allTrue(); +} + bool SkRect::setBoundsCheck(const SkPoint pts[], int count) { SkASSERT((pts && count > 0) || count == 0); @@ -53,6 +61,7 @@ bool SkRect::setBoundsCheck(const SkPoint pts[], int count) { if (count <= 0) { sk_bzero(this, sizeof(SkRect)); } else { +#if 0 SkScalar l, t, r, b; l = r = pts[0].fX; @@ -79,11 +88,53 @@ bool SkRect::setBoundsCheck(const SkPoint pts[], int count) { } SkASSERT(!accum || !SkScalarIsFinite(accum)); + accum = 0; if (accum) { l = t = r = b = 0; isFinite = false; } this->set(l, t, r, b); +#else + Sk4f min, max, accum; + + if (count & 1) { + min = Sk4f(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY); + pts += 1; + count -= 1; + } else { + min = Sk4f::Load(&pts[0].fX); + pts += 2; + count -= 2; + } + accum = max = min; + accum *= Sk4f(0); + + count >>= 1; + for (int i = 0; i < count; ++i) { + Sk4f xy = Sk4f::Load(&pts->fX); + accum *= xy; + min = Sk4f::Min(min, xy); + max = Sk4f::Max(max, xy); + pts += 2; + } + + /** + * With some trickery, we may be able to use Min/Max to also propogate non-finites, + * in which case we could eliminate accum entirely, and just check min and max for + * "is_finite". + */ + if (is_finite(accum)) { + float minArray[4], maxArray[4]; + min.store(minArray); + max.store(maxArray); + this->set(SkTMin(minArray[0], minArray[2]), SkTMin(minArray[1], minArray[3]), + SkTMax(maxArray[0], maxArray[2]), SkTMax(maxArray[1], maxArray[3])); + } else { + // we hit a non-finite value, so zero everything and return false + this->setEmpty(); + isFinite = false; + } +#endif } return isFinite;