blob: baa10fd34e9efbf463155e7ea3d5b3a0bfe917d6 [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 Daltonfe462ef2018-03-08 15:54:01 +000016void GrCCQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
17 const char* /*repetitionID*/, const char* /*wind*/,
18 GeometryVars* vars) const {
Chris Dalton6a3dbee2017-10-16 10:44:41 -060019 s->declareGlobal(fCanonicalMatrix);
20 s->codeAppendf("%s = float3x3(0.0, 0, 1, "
21 "0.5, 0, 1, "
22 "1.0, 1, 1) * "
23 "inverse(float3x3(%s[0], 1, "
24 "%s[1], 1, "
25 "%s[2], 1));",
26 fCanonicalMatrix.c_str(), pts, pts, pts);
27
Chris Dalton6a3dbee2017-10-16 10:44:41 -060028 // Find the T value whose tangent is halfway between the tangents at the endpionts.
29 s->codeAppendf("float2 tan0 = %s[1] - %s[0];", pts, pts);
30 s->codeAppendf("float2 tan1 = %s[2] - %s[1];", pts, pts);
31 s->codeAppend ("float2 midnorm = normalize(tan0) - normalize(tan1);");
32 s->codeAppend ("float2 T = midnorm * float2x2(tan0 - tan1, tan0);");
33 s->codeAppend ("float t = clamp(T.t / T.s, 0, 1);"); // T.s != 0; we cull flat curves on CPU.
34
35 // Clip the bezier triangle by the tangent at our new t value. This is a simple application for
36 // De Casteljau's algorithm.
37 s->codeAppendf("float4x2 quadratic_hull = float4x2(%s[0], "
38 "%s[0] + tan0 * t, "
39 "%s[1] + tan1 * t, "
40 "%s[2]);", pts, pts, pts, pts);
Chris Daltonfe462ef2018-03-08 15:54:01 +000041 vars->fHullVars.fAlternatePoints = "quadratic_hull";
Chris Dalton6a3dbee2017-10-16 10:44:41 -060042}
43
Chris Daltonfe462ef2018-03-08 15:54:01 +000044void GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
45 GrGLSLVarying::Scope scope, SkString* code,
46 const char* position, const char* inputCoverage,
47 const char* wind) {
Chris Daltondf04ce22018-03-07 17:28:07 -070048 fCoords.reset(kFloat4_GrSLType, scope);
49 varyingHandler->addVarying("coords", &fCoords);
50 code->appendf("%s.xy = (%s * float3(%s, 1)).xy;",
51 OutName(fCoords), fCanonicalMatrix.c_str(), position);
52 code->appendf("%s.zw = float2(2 * %s.x, -1) * float2x2(%s);",
53 OutName(fCoords), OutName(fCoords), fCanonicalMatrix.c_str());
Chris Daltonfe462ef2018-03-08 15:54:01 +000054
55 fCoverageTimesWind.reset(kHalf_GrSLType, scope);
56 varyingHandler->addVarying("coverage_times_wind", &fCoverageTimesWind);
57 code->appendf("%s = %s * %s;", OutName(fCoverageTimesWind), inputCoverage, wind);
Chris Dalton6a3dbee2017-10-16 10:44:41 -060058}
59
Chris Daltondf04ce22018-03-07 17:28:07 -070060void GrCCQuadraticShader::onEmitFragmentCode(const GrCCCoverageProcessor& proc,
61 GrGLSLFPFragmentBuilder* f,
Chris Daltonf510e262018-01-30 16:42:37 -070062 const char* outputCoverage) const {
Chris Daltondf04ce22018-03-07 17:28:07 -070063 f->codeAppendf("float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s.zw, %s.zw));",
64 fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn());
65#ifdef SK_DEBUG
66 if (proc.debugVisualizationsEnabled()) {
67 f->codeAppendf("d /= %f;", proc.debugBloat());
68 }
69#endif
Chris Daltonfe462ef2018-03-08 15:54:01 +000070 f->codeAppendf("%s = clamp(0.5 - d, 0, 1) * %s;", outputCoverage, fCoverageTimesWind.fsIn());
Chris Dalton6a3dbee2017-10-16 10:44:41 -060071}