Skip to content

Commit

Permalink
Use Sk4x to speed-up bounds of an array of points
Browse files Browse the repository at this point in the history
  • Loading branch information
reed-at-google authored and Commit bot committed Mar 25, 2015
1 parent e68f736 commit b25a83b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
4 changes: 3 additions & 1 deletion bench/ScalarBench.cpp
Expand Up @@ -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);
}
}
}

Expand Down
51 changes: 51 additions & 0 deletions src/core/SkRect.cpp
Expand Up @@ -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);

Expand All @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit b25a83b

Please sign in to comment.