/** Multiplify value by 0..256, and shift the result down 8
(i.e. return (value * alpha256) >> 8)
*/
-#define SkAlphaMul(value, alpha256) (SkMulS16(value, alpha256) >> 8)
+#define SkAlphaMul(value, alpha256) (((value) * (alpha256)) >> 8)
// The caller may want negative values, so keep all params signed (int)
// so we don't accidentally slip into unsigned math and lose the sign
SkASSERT((int16_t)dst == dst);
SkASSERT((uint8_t)alpha == alpha);
- int prod = SkMulS16(src - dst, alpha) + 128;
+ int prod = (src - dst) * alpha + 128;
prod = (prod + (prod >> 8)) >> 8;
return dst + prod;
}
///////////////////////////////////////////////////////////////////////////////
/**
- * SkMulS16(a, b) multiplies a * b, but requires that a and b are both int16_t.
- * With this requirement, we can generate faster instructions on some
- * architectures.
- */
-#ifdef SK_ARM_HAS_EDSP
- static inline int32_t SkMulS16(S16CPU x, S16CPU y) {
- SkASSERT((int16_t)x == x);
- SkASSERT((int16_t)y == y);
- int32_t product;
- asm("smulbb %0, %1, %2 \n"
- : "=r"(product)
- : "r"(x), "r"(y)
- );
- return product;
- }
-#else
- #ifdef SK_DEBUG
- static inline int32_t SkMulS16(S16CPU x, S16CPU y) {
- SkASSERT((int16_t)x == x);
- SkASSERT((int16_t)y == y);
- return x * y;
- }
- #else
- #define SkMulS16(x, y) ((x) * (y))
- #endif
-#endif
-
-/**
* Return a*b/((1 << shift) - 1), rounding any fractional bits.
* Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8
*/
SkASSERT(a <= 32767);
SkASSERT(b <= 32767);
SkASSERT(shift > 0 && shift <= 8);
- unsigned prod = SkMulS16(a, b) + (1 << (shift - 1));
+ unsigned prod = a*b + (1 << (shift - 1));
return (prod + (prod >> shift)) >> shift;
}
static inline U8CPU SkMulDiv255Round(U16CPU a, U16CPU b) {
SkASSERT(a <= 32767);
SkASSERT(b <= 32767);
- unsigned prod = SkMulS16(a, b) + 128;
+ unsigned prod = a*b + 128;
return (prod + (prod >> 8)) >> 8;
}
#else
#define SK_ARM_ARCH 3
#endif
-
- #if defined(__thumb2__) && (SK_ARM_ARCH >= 6) \
- || !defined(__thumb__) && ((SK_ARM_ARCH > 5) || defined(__ARM_ARCH_5E__) \
- || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__))
- #define SK_ARM_HAS_EDSP
- #endif
#endif
#endif
static inline U8CPU SkMulDiv255Trunc(U8CPU a, U8CPU b) {
SkASSERT((uint8_t)a == a);
SkASSERT((uint8_t)b == b);
- unsigned prod = SkMulS16(a, b) + 1;
+ unsigned prod = a*b + 1;
return (prod + (prod >> 8)) >> 8;
}
static inline U8CPU SkMulDiv255Ceiling(U8CPU a, U8CPU b) {
SkASSERT((uint8_t)a == a);
SkASSERT((uint8_t)b == b);
- unsigned prod = SkMulS16(a, b) + 255;
+ unsigned prod = a*b + 255;
return (prod + (prod >> 8)) >> 8;
}
static inline int SmallDot6Scale(int value, int dot6) {
SkASSERT((int16_t)value == value);
SkASSERT((unsigned)dot6 <= 64);
- return SkMulS16(value, dot6) >> 6;
+ return (value * dot6) >> 6;
}
//#define TEST_GAMMA
public:
SkFixed drawCap(int x, SkFixed fy, SkFixed dy, int mod64) override {
fy += SK_Fixed1/2;
-
+
int lower_y = fy >> 16;
uint8_t a = (uint8_t)(fy >> 8);
unsigned a0 = SmallDot6Scale(255 - a, mod64);
unsigned a1 = SmallDot6Scale(a, mod64);
this->getBlitter()->blitAntiV2(x, lower_y - 1, a0, a1);
-
+
return fy + dy - SK_Fixed1/2;
}
-
+
SkFixed drawLine(int x, int stopx, SkFixed fy, SkFixed dy) override {
SkASSERT(x < stopx);
-
+
fy += SK_Fixed1/2;
SkBlitter* blitter = this->getBlitter();
do {
blitter->blitAntiV2(x, lower_y - 1, 255 - a, a);
fy += dy;
} while (++x < stopx);
-
+
return fy - SK_Fixed1/2;
}
};
public:
SkFixed drawCap(int y, SkFixed fx, SkFixed dx, int mod64) override {
fx += SK_Fixed1/2;
-
+
int x = fx >> 16;
uint8_t a = (uint8_t)(fx >> 8);
this->getBlitter()->blitAntiH2(x - 1, y,
SmallDot6Scale(255 - a, mod64), SmallDot6Scale(a, mod64));
-
+
return fx + dx - SK_Fixed1/2;
}
-
+
SkFixed drawLine(int y, int stopy, SkFixed fx, SkFixed dx) override {
SkASSERT(y < stopy);
fx += SK_Fixed1/2;
this->getBlitter()->blitAntiH2(x - 1, y, 255 - a, a);
fx += dx;
} while (++y < stopy);
-
+
return fx - SK_Fixed1/2;
}
};
clipBounds.set(clip->getBounds());
/* We perform integral clipping later on, but we do a scalar clip first
to ensure that our coordinates are expressible in fixed/integers.
-
+
antialiased hairlines can draw up to 1/2 of a pixel outside of
their bounds, so we need to outset the clip before calling the
clipper. To make the numerics safer, we outset by a whole pixel,
if (sc) {
uint16_t dc = *dst;
unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
- unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale);
- unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale);
- unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale);
+ unsigned dr = (SkPacked32ToR16(sc) * alpha) + (SkGetPackedR16(dc) * dst_scale);
+ unsigned dg = (SkPacked32ToG16(sc) * alpha) + (SkGetPackedG16(dc) * dst_scale);
+ unsigned db = (SkPacked32ToB16(sc) * alpha) + (SkGetPackedB16(dc) * dst_scale);
*dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
}
dst += 1;
if (sc) {
uint16_t dc = *dst;
unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
- unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) +
- SkMulS16(SkGetPackedR16(dc), dst_scale);
- unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) +
- SkMulS16(SkGetPackedG16(dc), dst_scale);
- unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) +
- SkMulS16(SkGetPackedB16(dc), dst_scale);
+ unsigned dr = (SkPacked32ToR16(sc) * alpha) + (SkGetPackedR16(dc) * dst_scale);
+ unsigned dg = (SkPacked32ToG16(sc) * alpha) + (SkGetPackedG16(dc) * dst_scale);
+ unsigned db = (SkPacked32ToB16(sc) * alpha) + (SkGetPackedB16(dc) * dst_scale);
*dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
}
dst += 1;