blob: e164cff86292f789a6dcb6b0da767a13b15a80ab [file] [log] [blame]
Chris Dalton6a3dbee2017-10-16 10:44:41 -06001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Chris Dalton383a2ef2018-01-08 17:21:41 -05008#include "GrCCQuadraticShader.h"
Chris Dalton6a3dbee2017-10-16 10:44:41 -06009
Chris Dalton90e8fb12017-12-22 02:24:53 -070010#include "glsl/GrGLSLVertexGeoBuilder.h"
Chris Dalton6a3dbee2017-10-16 10:44:41 -060011#include "glsl/GrGLSLFragmentShaderBuilder.h"
Chris Dalton1fbdb612017-12-12 12:48:47 -070012#include "glsl/GrGLSLVertexGeoBuilder.h"
Chris Dalton6a3dbee2017-10-16 10:44:41 -060013
Chris Dalton383a2ef2018-01-08 17:21:41 -050014using Shader = GrCCCoverageProcessor::Shader;
Chris Daltonde5a8142017-12-18 10:05:15 -070015
Chris Dalton622650a2018-03-07 17:30:10 -070016const char* GrCCQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts) const {
Chris Dalton6a3dbee2017-10-16 10:44:41 -060017 s->declareGlobal(fCanonicalMatrix);
18 s->codeAppendf("%s = float3x3(0.0, 0, 1, "
19 "0.5, 0, 1, "
20 "1.0, 1, 1) * "
21 "inverse(float3x3(%s[0], 1, "
22 "%s[1], 1, "
23 "%s[2], 1));",
24 fCanonicalMatrix.c_str(), pts, pts, pts);
25
Chris Dalton6a3dbee2017-10-16 10:44:41 -060026 // Find the T value whose tangent is halfway between the tangents at the endpionts.
27 s->codeAppendf("float2 tan0 = %s[1] - %s[0];", pts, pts);
28 s->codeAppendf("float2 tan1 = %s[2] - %s[1];", pts, pts);
29 s->codeAppend ("float2 midnorm = normalize(tan0) - normalize(tan1);");
30 s->codeAppend ("float2 T = midnorm * float2x2(tan0 - tan1, tan0);");
31 s->codeAppend ("float t = clamp(T.t / T.s, 0, 1);"); // T.s != 0; we cull flat curves on CPU.
32
33 // Clip the bezier triangle by the tangent at our new t value. This is a simple application for
34 // De Casteljau's algorithm.
35 s->codeAppendf("float4x2 quadratic_hull = float4x2(%s[0], "
36 "%s[0] + tan0 * t, "
37 "%s[1] + tan1 * t, "
38 "%s[2]);", pts, pts, pts, pts);
Chris Dalton622650a2018-03-07 17:30:10 -070039 return "quadratic_hull";
Chris Dalton6a3dbee2017-10-16 10:44:41 -060040}
41
Chris Dalton622650a2018-03-07 17:30:10 -070042Shader::CoverageHandling GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
43 GrGLSLVarying::Scope scope,
44 SkString* code, const char* position,
45 const char* coverageTimesWind) {
Chris Daltondf04ce22018-03-07 17:28:07 -070046 fCoords.reset(kFloat4_GrSLType, scope);
47 varyingHandler->addVarying("coords", &fCoords);
48 code->appendf("%s.xy = (%s * float3(%s, 1)).xy;",
49 OutName(fCoords), fCanonicalMatrix.c_str(), position);
50 code->appendf("%s.zw = float2(2 * %s.x, -1) * float2x2(%s);",
51 OutName(fCoords), OutName(fCoords), fCanonicalMatrix.c_str());
Chris Dalton622650a2018-03-07 17:30:10 -070052 return CoverageHandling::kNotHandled;
Chris Dalton6a3dbee2017-10-16 10:44:41 -060053}
54
Chris Daltondf04ce22018-03-07 17:28:07 -070055void GrCCQuadraticShader::onEmitFragmentCode(const GrCCCoverageProcessor& proc,
56 GrGLSLFPFragmentBuilder* f,
Chris Daltonf510e262018-01-30 16:42:37 -070057 const char* outputCoverage) const {
Chris Daltondf04ce22018-03-07 17:28:07 -070058 f->codeAppendf("float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s.zw, %s.zw));",
59 fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn());
60#ifdef SK_DEBUG
61 if (proc.debugVisualizationsEnabled()) {
62 f->codeAppendf("d /= %f;", proc.debugBloat());
63 }
64#endif
Chris Dalton622650a2018-03-07 17:30:10 -070065 f->codeAppendf("%s = clamp(0.5 - d, 0, 1);", outputCoverage);
Chris Dalton6a3dbee2017-10-16 10:44:41 -060066}