aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/private/SkFixed.h144
-rw-r--r--src/core/SkScan.h2
-rw-r--r--src/effects/gradients/SkTwoPointConicalGradient.cpp2
3 files changed, 78 insertions, 70 deletions
diff --git a/include/private/SkFixed.h b/include/private/SkFixed.h
index c90d5e9ffd..7023f59cac 100644
--- a/include/private/SkFixed.h
+++ b/include/private/SkFixed.h
@@ -31,7 +31,63 @@ typedef int32_t SkFixed;
#define SK_FixedRoot2Over2 (0xB505)
#define SkFixedToFloat(x) ((x) * 1.52587890625e-5f)
-#define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1))
+
+///////////////////////////////////////////////////////////////////////////////
+// ASM alternatives for our portable versions.
+
+#if defined(SK_CPU_ARM32)
+ /* This guy does not handle NaN or other obscurities, but is faster than
+ than (int)(x*65536). When built on Android with -Os, needs forcing
+ to inline or we lose the speed benefit.
+ */
+ SK_ALWAYS_INLINE SkFixed SkFloatToFixed_arm(float x)
+ {
+ int32_t y, z;
+ asm("movs %1, %3, lsl #1 \n"
+ "mov %2, #0x8E \n"
+ "sub %1, %2, %1, lsr #24 \n"
+ "mov %2, %3, lsl #8 \n"
+ "orr %2, %2, #0x80000000 \n"
+ "mov %1, %2, lsr %1 \n"
+ "it cs \n"
+ "rsbcs %1, %1, #0 \n"
+ : "=r"(x), "=&r"(y), "=&r"(z)
+ : "r"(x)
+ : "cc"
+ );
+ return y;
+ }
+ inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y)
+ {
+ int32_t t;
+ asm("smull %0, %2, %1, %3 \n"
+ "mov %0, %0, lsr #16 \n"
+ "orr %0, %0, %2, lsl #16 \n"
+ : "=r"(x), "=&r"(y), "=r"(t)
+ : "r"(x), "1"(y)
+ :
+ );
+ return x;
+ }
+
+ #define SkFixedMul(x, y) SkFixedMul_arm(x, y)
+ #define SkFloatToFixed_Unsafe(x) SkFloatToFixed_arm(x)
+#else
+ inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) {
+ return (SkFixed)((int64_t)a * b >> 16);
+ }
+
+ #define SkFixedMul(x, y) SkFixedMul_longlong(x, y)
+ #define SkFloatToFixed_Unsafe(x) ((SkFixed)((x) * SK_Fixed1))
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+static inline SkFixed SkFloatToFixed(float x) {
+ const SkFixed result = SkFloatToFixed_Unsafe(x);
+ SkASSERT(truncf(x * SK_Fixed1) == static_cast<float>(result));
+ return result;
+}
// Pins over/under flows to SK_FixedMax/SK_FixedMin (slower than just a cast).
static inline SkFixed SkFloatPinToFixed(float x) {
@@ -44,19 +100,14 @@ static inline SkFixed SkFloatPinToFixed(float x) {
return result;
}
-#ifdef SK_DEBUG
- static inline SkFixed SkFloatToFixed_Check(float x) {
- int64_t n64 = (int64_t)(x * SK_Fixed1);
- SkFixed n32 = (SkFixed)n64;
- SkASSERT(n64 == n32);
- return n32;
- }
-#else
- #define SkFloatToFixed_Check(x) SkFloatToFixed(x)
-#endif
+#define SkFixedToDouble(x) ((x) * 1.52587890625e-5)
+#define SkDoubleToFixed_Unsafe(x) ((SkFixed)((x) * SK_Fixed1))
-#define SkFixedToDouble(x) ((x) * 1.52587890625e-5)
-#define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1))
+static inline SkFixed SkDoubleToFixed(double x) {
+ const SkFixed result = SkDoubleToFixed_Unsafe(x);
+ SkASSERT(trunc(x * SK_Fixed1) == static_cast<double>(result));
+ return result;
+}
// Pins over/under flows to SK_FixedMax/SK_FixedMin (slower than just a cast).
static inline SkFixed SkDoublePinToFixed(double x) {
@@ -107,56 +158,6 @@ static inline SkFixed SkDoublePinToFixed(double x) {
SkToS32(SkTPin<int64_t>((SkLeftShift((int64_t)numer, 16) / denom), SK_MinS32, SK_MaxS32))
#endif
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-// Now look for ASM overrides for our portable versions (should consider putting this in its own file)
-
-inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) {
- return (SkFixed)((int64_t)a * b >> 16);
-}
-#define SkFixedMul(a,b) SkFixedMul_longlong(a,b)
-
-
-#if defined(SK_CPU_ARM32)
- /* This guy does not handle NaN or other obscurities, but is faster than
- than (int)(x*65536). When built on Android with -Os, needs forcing
- to inline or we lose the speed benefit.
- */
- SK_ALWAYS_INLINE SkFixed SkFloatToFixed_arm(float x)
- {
- int32_t y, z;
- asm("movs %1, %3, lsl #1 \n"
- "mov %2, #0x8E \n"
- "sub %1, %2, %1, lsr #24 \n"
- "mov %2, %3, lsl #8 \n"
- "orr %2, %2, #0x80000000 \n"
- "mov %1, %2, lsr %1 \n"
- "it cs \n"
- "rsbcs %1, %1, #0 \n"
- : "=r"(x), "=&r"(y), "=&r"(z)
- : "r"(x)
- : "cc"
- );
- return y;
- }
- inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y)
- {
- int32_t t;
- asm("smull %0, %2, %1, %3 \n"
- "mov %0, %0, lsr #16 \n"
- "orr %0, %0, %2, lsl #16 \n"
- : "=r"(x), "=&r"(y), "=r"(t)
- : "r"(x), "1"(y)
- :
- );
- return x;
- }
- #undef SkFixedMul
- #define SkFixedMul(x, y) SkFixedMul_arm(x, y)
-
- #undef SkFloatToFixed
- #define SkFloatToFixed(x) SkFloatToFixed_arm(x)
-#endif
-
///////////////////////////////////////////////////////////////////////////////
#if SK_SCALAR_IS_FLOAT
@@ -177,11 +178,18 @@ inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) {
typedef int64_t SkFixed3232; // 32.32
-#define SkIntToFixed3232(x) (SkLeftShift((SkFixed3232)(x), 32))
-#define SkFixed3232ToInt(x) ((int)((x) >> 32))
-#define SkFixedToFixed3232(x) (SkLeftShift((SkFixed3232)(x), 16))
-#define SkFixed3232ToFixed(x) ((SkFixed)((x) >> 16))
-#define SkFloatToFixed3232(x) ((SkFixed3232)((x) * (65536.0f * 65536.0f)))
+#define SK_Fixed3232_1 (static_cast<SkFixed3232>(1) << 32)
+#define SkIntToFixed3232(x) (SkLeftShift((SkFixed3232)(x), 32))
+#define SkFixed3232ToInt(x) ((int)((x) >> 32))
+#define SkFixedToFixed3232(x) (SkLeftShift((SkFixed3232)(x), 16))
+#define SkFixed3232ToFixed(x) ((SkFixed)((x) >> 16))
+#define SkFloatToFixed3232_Unsafe(x) (static_cast<SkFixed3232>((x) * SK_Fixed3232_1))
+
+static inline SkFixed3232 SkFloatToFixed3232(float x) {
+ const SkFixed3232 result = SkFloatToFixed3232_Unsafe(x);
+ SkASSERT(truncf(x * SK_Fixed3232_1) == static_cast<float>(result));
+ return result;
+}
#define SkScalarToFixed3232(x) SkFloatToFixed3232(x)
diff --git a/src/core/SkScan.h b/src/core/SkScan.h
index 4aa8e44399..2185e1ea08 100644
--- a/src/core/SkScan.h
+++ b/src/core/SkScan.h
@@ -93,7 +93,7 @@ static inline void XRect_set(SkXRect* xr, const SkIRect& src) {
}
/** Assign an SkXRect from a SkRect, by promoting the src rect's coordinates
- from SkScalar to SkFixed. Does not check for overflow if the src coordinates
+ from SkScalar to SkFixed. Behavior is undefined if the src coordinates
exceed 32K
*/
static inline void XRect_set(SkXRect* xr, const SkRect& src) {
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index f33dcc5a75..3c3180c2c5 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -129,7 +129,7 @@ SkFixed TwoPtRadialContext::nextT() {
return TwoPtRadial::kDontDrawT;
}
}
- return SkFloatToFixed(t);
+ return SkFloatPinToFixed(t);
}
typedef void (*TwoPointConicalProc)(TwoPtRadialContext* rec, SkPMColor* dstC,