aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/MathBench.cpp53
-rw-r--r--include/core/SkRect.h32
-rw-r--r--src/core/SkCanvas.cpp2
-rw-r--r--src/core/SkRect.cpp7
-rw-r--r--tests/InfRectTest.cpp6
5 files changed, 78 insertions, 22 deletions
diff --git a/bench/MathBench.cpp b/bench/MathBench.cpp
index 1644a9e200..ffee901545 100644
--- a/bench/MathBench.cpp
+++ b/bench/MathBench.cpp
@@ -3,6 +3,7 @@
#include "SkMatrix.h"
#include "SkRandom.h"
#include "SkString.h"
+#include "SkPaint.h"
class MathBench : public SkBenchmark {
enum {
@@ -211,6 +212,21 @@ static const struct {
#undef MAKEREC
+static bool SkScalarIsNaN_new(SkScalar x) {
+ float y = x * 0;
+ return y == y;
+}
+
+static bool isFinite(const SkRect& r) {
+ // x * 0 will be NaN iff x is infinity or NaN.
+ // a + b will be NaN iff either a or b is NaN.
+ float value = r.fLeft * 0 + r.fTop * 0 + r.fRight * 0 + r.fBottom * 0;
+
+ // value is either NaN or it is finite (zero).
+ // value==value will be true iff value is not NaN
+ return value == value;
+}
+
class IsFiniteBench : public SkBenchmark {
enum {
N = SkBENCHLOOP(1000),
@@ -225,20 +241,41 @@ public:
for (int i = 0; i < N; ++i) {
fData[i] = rand.nextSScalar1();
}
-
- fProc = gRec[index].fProc;
- fName = gRec[index].fName;
+
+ if (index < 0) {
+ fProc = NULL;
+ fName = "isfinite_rect";
+ } else {
+ fProc = gRec[index].fProc;
+ fName = gRec[index].fName;
+ }
}
protected:
virtual void onDraw(SkCanvas* canvas) {
IsFiniteProc proc = fProc;
const float* data = fData;
-
- for (int j = 0; j < NN; ++j) {
- for (int i = 0; i < N - 4; ++i) {
- proc(&data[i]);
+ // do this so the compiler won't throw away the function call
+ int counter = 0;
+
+ if (proc) {
+ for (int j = 0; j < NN; ++j) {
+ for (int i = 0; i < N - 4; ++i) {
+ counter += proc(&data[i]);
+ }
}
+ } else {
+ for (int j = 0; j < NN; ++j) {
+ for (int i = 0; i < N - 4; ++i) {
+ const SkRect* r = reinterpret_cast<const SkRect*>(&data[i]);
+ counter += r->isFinite();
+ }
+ }
+ }
+
+ SkPaint paint;
+ if (paint.getAlpha() == 0) {
+ SkDebugf("%d\n", counter);
}
}
@@ -261,6 +298,7 @@ static SkBenchmark* M2(void* p) { return new FastISqrtMathBench(p); }
static SkBenchmark* M3(void* p) { return new QMul64Bench(p); }
static SkBenchmark* M4(void* p) { return new QMul32Bench(p); }
+static SkBenchmark* M5neg1(void* p) { return new IsFiniteBench(p, -1); }
static SkBenchmark* M50(void* p) { return new IsFiniteBench(p, 0); }
static SkBenchmark* M51(void* p) { return new IsFiniteBench(p, 1); }
static SkBenchmark* M52(void* p) { return new IsFiniteBench(p, 2); }
@@ -274,6 +312,7 @@ static BenchRegistry gReg2(M2);
static BenchRegistry gReg3(M3);
static BenchRegistry gReg4(M4);
+static BenchRegistry gReg5neg1(M5neg1);
static BenchRegistry gReg50(M50);
static BenchRegistry gReg51(M51);
static BenchRegistry gReg52(M52);
diff --git a/include/core/SkRect.h b/include/core/SkRect.h
index 76c99df648..65e76116f0 100644
--- a/include/core/SkRect.h
+++ b/include/core/SkRect.h
@@ -335,10 +335,34 @@ struct SK_API SkRect {
return r;
}
- /** Return true if the rectangle's width or height are <= 0
- */
- bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
- bool hasValidCoordinates() const;
+ /**
+ * Return true if the rectangle's width or height are <= 0
+ */
+ bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
+
+ /**
+ * Returns true iff all values in the rect are finite. If any are
+ * infinite or NaN (or SK_FixedNaN when SkScalar is fixed) then this
+ * returns false.
+ */
+ bool isFinite() const {
+#ifdef SK_SCALAR_IS_FLOAT
+ // x * 0 will be NaN iff x is infinity or NaN.
+ // a + b will be NaN iff either a or b is NaN.
+ float value = fLeft * 0 + fTop * 0 + fRight * 0 + fBottom * 0;
+
+ // value is either NaN or it is finite (zero).
+ // value==value will be true iff value is not NaN
+ return value == value;
+#else
+ // use bit-or for speed, since we don't care about short-circuting the
+ // tests, and we expect the common case will be that we need to check all.
+ int isNaN = (SK_FixedNaN == fLeft) | (SK_FixedNaN == fTop) |
+ (SK_FixedNaN == fRight) | (SK_FixedNaN == fBottom);
+ return !isNaN;
+#endif
+ }
+
SkScalar left() const { return fLeft; }
SkScalar top() const { return fTop; }
SkScalar right() const { return fRight; }
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 70ee430bfb..f382893f8c 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1068,7 +1068,7 @@ void SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const {
*/
bool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const {
- if (!rect.hasValidCoordinates())
+ if (!rect.isFinite())
return true;
if (fMCRec->fRasterClip->isEmpty()) {
diff --git a/src/core/SkRect.cpp b/src/core/SkRect.cpp
index fab1412715..5e3d93c339 100644
--- a/src/core/SkRect.cpp
+++ b/src/core/SkRect.cpp
@@ -37,13 +37,6 @@ void SkIRect::sort() {
/////////////////////////////////////////////////////////////////////////////
-bool SkRect::hasValidCoordinates() const {
- return SkScalarIsFinite(fLeft) &&
- SkScalarIsFinite(fTop) &&
- SkScalarIsFinite(fRight) &&
- SkScalarIsFinite(fBottom);
-}
-
void SkRect::sort() {
if (fLeft > fRight) {
SkTSwap<SkScalar>(fLeft, fRight);
diff --git a/tests/InfRectTest.cpp b/tests/InfRectTest.cpp
index a78eba6dac..12356d9c2f 100644
--- a/tests/InfRectTest.cpp
+++ b/tests/InfRectTest.cpp
@@ -18,10 +18,10 @@ static void check_invalid(skiatest::Reporter* reporter,
SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
SkRect rect;
rect.set(l, t, r, b);
- REPORTER_ASSERT(reporter, !rect.hasValidCoordinates());
+ REPORTER_ASSERT(reporter, !rect.isFinite());
}
-// Tests that hasValidCoordinates() will reject any rect with +/-inf values
+// Tests that isFinite() will reject any rect with +/-inf values
// as one of its coordinates.
static void TestInfRect(skiatest::Reporter* reporter) {
#ifdef SK_SCALAR_IS_FLOAT
@@ -33,7 +33,7 @@ static void TestInfRect(skiatest::Reporter* reporter) {
SkScalar big = SkIntToScalar(100);
SkRect rect = SkRect::MakeXYWH(small, small, big, big);
- REPORTER_ASSERT(reporter, rect.hasValidCoordinates());
+ REPORTER_ASSERT(reporter, rect.isFinite());
check_invalid(reporter, small, small, big, invalid);
check_invalid(reporter, small, small, invalid, big);