aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-07 14:20:52 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-07 14:20:52 +0000
commitaca29ae8cdebdc3406c70bc1d8bd6dbfd5ffbbf5 (patch)
tree4c6e5720d6cae2873a4e6bb85c6403232ea54a32
parent258e0bf00cbb6fcc9c1b0db1a6b7dbd90b1b83f6 (diff)
optimize quad-root for conical gradients
Review URL: https://codereview.appspot.com/6307052 git-svn-id: http://skia.googlecode.com/svn/trunk@4204 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--src/effects/SkGradientShader.cpp55
1 files changed, 31 insertions, 24 deletions
diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp
index 6d3e922e72..5c53e8e22f 100644
--- a/src/effects/SkGradientShader.cpp
+++ b/src/effects/SkGradientShader.cpp
@@ -2057,24 +2057,34 @@ static int find_quad_roots(float A, float B, float C, float roots[2]) {
return valid_divide(-C, B, roots);
}
- float* r = roots;
float R = B*B - 4*A*C;
- if (R < 0 || sk_float_isnan(R)) { // complex roots
+ if (R < 0) {
return 0;
}
R = sk_float_sqrt(R);
-
- float Q = (B < 0) ? -(B-R)/2 : -(B+R)/2;
- r += valid_divide(Q, A, r);
- r += valid_divide(C, Q, r);
- if (r - roots == 2) {
- if (roots[0] > roots[1]) {
- SkTSwap<float>(roots[0], roots[1]);
- } else if (roots[0] == roots[1]) { // nearly-equal?
- r -= 1; // skip the double root
- }
+
+#if 1
+ float Q = B;
+ if (Q < 0) {
+ Q -= R;
+ } else {
+ Q += R;
}
- return (int)(r - roots);
+#else
+ // on 10.6 this was much slower than the above branch :(
+ float Q = B + copysignf(R, B);
+#endif
+ Q *= -0.5f;
+ if (0 == Q) {
+ roots[0] = 0;
+ return 1;
+ }
+
+ float r0 = Q / A;
+ float r1 = C / Q;
+ roots[0] = r0 < r1 ? r0 : r1;
+ roots[1] = r0 > r1 ? r0 : r1;
+ return 2;
}
static float lerp(float x, float dx, float t) {
@@ -2126,10 +2136,7 @@ struct TwoPtRadial {
SkFixed nextT() {
float roots[2];
- float dx = fRelX;
- float dy = fRelY;
-
- float C = sqr(dx) + sqr(dy) - fRadius2;
+ float C = sqr(fRelX) + sqr(fRelY) - fRadius2;
int countRoots = find_quad_roots(fA, fB, C, roots);
fRelX += fIncX;
@@ -2155,15 +2162,15 @@ struct TwoPtRadial {
}
static bool DontDrawT(SkFixed t) {
- return kDontDrawT == t;
+ return kDontDrawT == (uint32_t)t;
}
};
typedef void (*TwoPointRadialProc)(TwoPtRadial* rec, SkPMColor* dstC,
const SkPMColor* cache, int count);
-void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
- const SkPMColor* SK_RESTRICT cache, int count) {
+static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
+ const SkPMColor* SK_RESTRICT cache, int count) {
for (; count > 0; --count) {
SkFixed t = rec->nextT();
if (TwoPtRadial::DontDrawT(t)) {
@@ -2176,8 +2183,8 @@ void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
}
}
-void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
- const SkPMColor* SK_RESTRICT cache, int count) {
+static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
+ const SkPMColor* SK_RESTRICT cache, int count) {
for (; count > 0; --count) {
SkFixed t = rec->nextT();
if (TwoPtRadial::DontDrawT(t)) {
@@ -2190,8 +2197,8 @@ void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
}
}
-void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
- const SkPMColor* SK_RESTRICT cache, int count) {
+static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
+ const SkPMColor* SK_RESTRICT cache, int count) {
for (; count > 0; --count) {
SkFixed t = rec->nextT();
if (TwoPtRadial::DontDrawT(t)) {