aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ccpr
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2018-03-28 20:09:58 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-04-02 16:05:05 +0000
commit7c7ff031a51901f3064d0ceca93c97111c85292e (patch)
tree6bd30cdf149ae4a9dc1cafa440d4fa33ccd17ec5 /src/gpu/ccpr
parent64ecdce4aded98b4b96d5d04ecba3bb08c16bc31 (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.cpp34
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());