Clear out SK_SCALAR_IS_FLOAT from SkRadialGradient, and merge the logic for radial_mirror and radial_repeat.

New radial/repeated bench is 10-20x faster now using float instead of fixed; the rest are unaffected.

BUG=
R=reed@google.com

Author: mtklein@google.com

Review URL: https://codereview.chromium.org/26410003

git-svn-id: http://skia.googlecode.com/svn/trunk@11824 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2013-10-16 18:59:44 +00:00
parent cbbf1ca304
commit 34150b451d
2 changed files with 47 additions and 72 deletions

View File

@ -245,6 +245,7 @@ DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kC
DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kClamp_TileMode, kOval_GeomType); )
DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kMirror_TileMode); )
DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kRepeat_TileMode); )
DEF_BENCH( return new GradientBench(kSweep_GradType); )
DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[1]); )
DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[2]); )

View File

@ -46,6 +46,15 @@ void SkRadialGradient_BuildTable() {
namespace {
// GCC doesn't like using static functions as template arguments. So force these to be non-static.
inline SkFixed mirror_tileproc_nonstatic(SkFixed x) {
return mirror_tileproc(x);
}
inline SkFixed repeat_tileproc_nonstatic(SkFixed x) {
return repeat_tileproc(x);
}
void rad_to_unit_matrix(const SkPoint& center, SkScalar radius,
SkMatrix* matrix) {
SkScalar inv = SkScalarInvert(radius);
@ -105,51 +114,35 @@ void shadeSpan16_radial_clamp(SkScalar sfx, SkScalar sdx,
}
}
void shadeSpan16_radial_mirror(SkScalar sfx, SkScalar sdx,
SkScalar sfy, SkScalar sdy,
uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache,
int toggle, int count) {
template <SkFixed (*TileProc)(SkFixed)>
void shadeSpan16_radial(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache,
int toggle, int count) {
do {
#ifdef SK_SCALAR_IS_FLOAT
float fdist = sk_float_sqrt(sfx*sfx + sfy*sfy);
SkFixed dist = SkFloatToFixed(fdist);
#else
SkFixed magnitudeSquared = SkFixedSquare(sfx) +
SkFixedSquare(sfy);
if (magnitudeSquared < 0) // Overflow.
magnitudeSquared = SK_FixedMax;
SkFixed dist = SkFixedSqrt(magnitudeSquared);
#endif
unsigned fi = mirror_tileproc(dist);
const SkFixed dist = SkFloatToFixed(sk_float_sqrt(fx*fx + fy*fy));
const unsigned fi = TileProc(dist);
SkASSERT(fi <= 0xFFFF);
*dstC++ = cache[toggle + (fi >> SkGradientShaderBase::kCache16Shift)];
toggle = next_dither_toggle16(toggle);
sfx += sdx;
sfy += sdy;
} while (--count != 0);
}
void shadeSpan16_radial_repeat(SkScalar sfx, SkScalar sdx,
SkScalar sfy, SkScalar sdy,
uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache,
int toggle, int count) {
SkFixed fx = SkScalarToFixed(sfx);
SkFixed dx = SkScalarToFixed(sdx);
SkFixed fy = SkScalarToFixed(sfy);
SkFixed dy = SkScalarToFixed(sdy);
do {
SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
unsigned fi = repeat_tileproc(dist);
SkASSERT(fi <= 0xFFFF);
fx += dx;
fy += dy;
*dstC++ = cache[toggle + (fi >> SkGradientShaderBase::kCache16Shift)];
toggle = next_dither_toggle16(toggle);
} while (--count != 0);
}
void shadeSpan16_radial_mirror(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache,
int toggle, int count) {
shadeSpan16_radial<mirror_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, toggle, count);
}
void shadeSpan16_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache,
int toggle, int count) {
shadeSpan16_radial<repeat_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, toggle, count);
}
} // namespace
/////////////////////////////////////////////////////////////////////
SkRadialGradient::SkRadialGradient(const SkPoint& center, SkScalar radius,
@ -367,45 +360,13 @@ void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx,
// Unrolling this loop doesn't seem to help (when float); we're stalling to
// get the results of the sqrt (?), and don't have enough extra registers to
// have many in flight.
void shadeSpan_radial_mirror(SkScalar sfx, SkScalar sdx,
SkScalar sfy, SkScalar sdy,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count, int toggle) {
template <SkFixed (*TileProc)(SkFixed)>
void shadeSpan_radial(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count, int toggle) {
do {
#ifdef SK_SCALAR_IS_FLOAT
float fdist = sk_float_sqrt(sfx*sfx + sfy*sfy);
SkFixed dist = SkFloatToFixed(fdist);
#else
SkFixed magnitudeSquared = SkFixedSquare(sfx) +
SkFixedSquare(sfy);
if (magnitudeSquared < 0) // Overflow.
magnitudeSquared = SK_FixedMax;
SkFixed dist = SkFixedSqrt(magnitudeSquared);
#endif
unsigned fi = mirror_tileproc(dist);
SkASSERT(fi <= 0xFFFF);
*dstC++ = cache[toggle + (fi >> SkGradientShaderBase::kCache32Shift)];
toggle = next_dither_toggle(toggle);
sfx += sdx;
sfy += sdy;
} while (--count != 0);
}
void shadeSpan_radial_repeat(SkScalar sfx, SkScalar sdx,
SkScalar sfy, SkScalar sdy,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count, int toggle) {
SkFixed fx = SkScalarToFixed(sfx);
SkFixed dx = SkScalarToFixed(sdx);
SkFixed fy = SkScalarToFixed(sfy);
SkFixed dy = SkScalarToFixed(sdy);
do {
SkFixed magnitudeSquared = SkFixedSquare(fx) +
SkFixedSquare(fy);
if (magnitudeSquared < 0) // Overflow.
magnitudeSquared = SK_FixedMax;
SkFixed dist = SkFixedSqrt(magnitudeSquared);
unsigned fi = repeat_tileproc(dist);
const SkFixed dist = SkFloatToFixed(sk_float_sqrt(fx*fx + fy*fy));
const unsigned fi = TileProc(dist);
SkASSERT(fi <= 0xFFFF);
*dstC++ = cache[toggle + (fi >> SkGradientShaderBase::kCache32Shift)];
toggle = next_dither_toggle(toggle);
@ -413,8 +374,21 @@ void shadeSpan_radial_repeat(SkScalar sfx, SkScalar sdx,
fy += dy;
} while (--count != 0);
}
void shadeSpan_radial_mirror(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count, int toggle) {
shadeSpan_radial<mirror_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, count, toggle);
}
void shadeSpan_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count, int toggle) {
shadeSpan_radial<repeat_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, count, toggle);
}
} // namespace
void SkRadialGradient::shadeSpan(int x, int y,
SkPMColor* SK_RESTRICT dstC, int count) {
SkASSERT(count > 0);