diff options
author | Chris Dalton <csmartdalton@google.com> | 2018-03-28 20:09:58 -0600 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-04-02 16:05:05 +0000 |
commit | 7c7ff031a51901f3064d0ceca93c97111c85292e (patch) | |
tree | 6bd30cdf149ae4a9dc1cafa440d4fa33ccd17ec5 /src/gpu/ccpr | |
parent | 64ecdce4aded98b4b96d5d04ecba3bb08c16bc31 (diff) |
ccpr: Normalize homogeneous coords with frexp/ldexp
Hopefully increases cubic accuracy by manipulating exponents
instead of calling normalize().
Bug: skia:
Change-Id: I8d3596e858a2fbb6650c158753133c5a2e01e166
Reviewed-on: https://skia-review.googlesource.com/117009
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Diffstat (limited to 'src/gpu/ccpr')
-rw-r--r-- | src/gpu/ccpr/GrCCCubicShader.cpp | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/src/gpu/ccpr/GrCCCubicShader.cpp b/src/gpu/ccpr/GrCCCubicShader.cpp index d0228d59ad..c5fefdd78e 100644 --- a/src/gpu/ccpr/GrCCCubicShader.cpp +++ b/src/gpu/ccpr/GrCCCubicShader.cpp @@ -8,12 +8,35 @@ #include "GrCCCubicShader.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" +#include "glsl/GrGLSLProgramBuilder.h" #include "glsl/GrGLSLVertexGeoBuilder.h" using Shader = GrCCCoverageProcessor::Shader; void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, const char* wind, const char** /*tighterHull*/) const { + // Define a function that normalizes the homogeneous coordinates T=t/s in order to avoid + // exponent overflow. + SkString normalizeHomogCoordFn; + GrShaderVar coord("coord", kFloat2_GrSLType); + s->emitFunction(kFloat2_GrSLType, "normalize_homogeneous_coord", 1, &coord, + s->getProgramBuilder()->shaderCaps()->fpManipulationSupport() + // Exponent manipulation version: Scale the exponents so the larger + // component has a magnitude in 1..2. + // (Neither component should be infinity because ccpr crops big paths.) + ? "int exp;" + "frexp(max(abs(coord.t), abs(coord.s)), exp);" + "return coord * ldexp(1, 1 - exp);" + + // Division version: Divide by the component with the larger magnitude. + // (Both should not be 0 because ccpr catches degenerate cubics.) + : "bool swap = abs(coord.t) > abs(coord.s);" + "coord = swap ? coord.ts : coord;" + "coord = float2(1, coord.t/coord.s);" + "return swap ? coord.ts : coord;", + + &normalizeHomogCoordFn); + // Find the cubic's power basis coefficients. s->codeAppendf("float2x4 C = float4x4(-1, 3, -3, 1, " " 3, -6, 3, 0, " @@ -33,9 +56,10 @@ void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, s->codeAppend ("q = x*D2 + (D2 >= 0 ? q : -q);"); s->codeAppend ("float2 l, m;"); - s->codeAppend ("l.ts = normalize(float2(q, 2*x * D1));"); - s->codeAppend ("m.ts = normalize(float2(2, q) * (discr >= 0 ? float2(D3, 1) " - ": float2(D2*D2 - D3*D1, D1)));"); + s->codeAppendf("l.ts = %s(float2(q, 2*x * D1));", normalizeHomogCoordFn.c_str()); + s->codeAppendf("m.ts = %s(float2(2, q) * (discr >= 0 ? float2(D3, 1) " + ": float2(D2*D2 - D3*D1, D1)));", + normalizeHomogCoordFn.c_str()); s->codeAppend ("float4 K;"); s->codeAppend ("float4 lm = l.sstt * m.stst;"); @@ -46,7 +70,7 @@ void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, s->codeAppend ("L = float4(-1,x,-x,1) * l.sstt * (discr >= 0 ? l.ssst * l.sttt : lm);"); s->codeAppend ("M = float4(-1,x,-x,1) * m.sstt * (discr >= 0 ? m.ssst * m.sttt : lm.xzyw);"); - s->codeAppend ("short middlerow = abs(D2) > abs(D1) ? 2 : 1;"); + s->codeAppend ("int middlerow = abs(D2) > abs(D1) ? 2 : 1;"); s->codeAppend ("float3x3 CI = inverse(float3x3(C[0][0], C[0][middlerow], C[0][3], " "C[1][0], C[1][middlerow], C[1][3], " " 0, 0, 1));"); @@ -66,7 +90,7 @@ void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, // Determine the amount of additional coverage to subtract out for the flat edge (P3 -> P0). s->declareGlobal(fEdgeDistanceEquation); - s->codeAppendf("short edgeidx0 = %s > 0 ? 3 : 0;", wind); + s->codeAppendf("int edgeidx0 = %s > 0 ? 3 : 0;", wind); s->codeAppendf("float2 edgept0 = %s[edgeidx0];", pts); s->codeAppendf("float2 edgept1 = %s[3 - edgeidx0];", pts); Shader::EmitEdgeDistanceEquation(s, "edgept0", "edgept1", fEdgeDistanceEquation.c_str()); |