blob: 1dc129f2ba4d5f893fd42a6daf8e374021e1d0c6 [file] [log] [blame]
Chris Dalton1a325d22017-07-14 15:17: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
8#include "GrCCPRCoverageProcessor.h"
9
Chris Dalton6a3dbee2017-10-16 10:44:41 -060010#include "SkMakeUnique.h"
11#include "ccpr/GrCCPRCubicShader.h"
12#include "ccpr/GrCCPRQuadraticShader.h"
13#include "ccpr/GrCCPRTriangleShader.h"
Chris Dalton1a325d22017-07-14 15:17:41 -060014#include "glsl/GrGLSLFragmentShaderBuilder.h"
Chris Dalton1a325d22017-07-14 15:17:41 -060015
Chris Dalton6a3dbee2017-10-16 10:44:41 -060016static GrVertexAttribType instance_array_format(GrCCPRCoverageProcessor::RenderPass renderPass) {
17 switch (renderPass) {
18 case GrCCPRCoverageProcessor::RenderPass::kTriangleHulls:
19 case GrCCPRCoverageProcessor::RenderPass::kTriangleEdges:
20 case GrCCPRCoverageProcessor::RenderPass::kTriangleCorners:
21 return kInt4_GrVertexAttribType;
22 case GrCCPRCoverageProcessor::RenderPass::kQuadraticHulls:
23 case GrCCPRCoverageProcessor::RenderPass::kQuadraticCorners:
24 case GrCCPRCoverageProcessor::RenderPass::kSerpentineHulls:
25 case GrCCPRCoverageProcessor::RenderPass::kLoopHulls:
26 case GrCCPRCoverageProcessor::RenderPass::kSerpentineCorners:
27 case GrCCPRCoverageProcessor::RenderPass::kLoopCorners:
28 return kInt2_GrVertexAttribType;
Chris Dalton1a325d22017-07-14 15:17:41 -060029 }
Chris Dalton6a3dbee2017-10-16 10:44:41 -060030 SK_ABORT("Unexpected GrCCPRCoverageProcessor::RenderPass.");
31 return kInt4_GrVertexAttribType;
Chris Dalton1a325d22017-07-14 15:17:41 -060032}
33
Chris Dalton6a3dbee2017-10-16 10:44:41 -060034GrCCPRCoverageProcessor::GrCCPRCoverageProcessor(RenderPass renderPass, GrBuffer* pointsBuffer)
Ethan Nicholasabff9562017-10-09 10:54:08 -040035 : INHERITED(kGrCCPRCoverageProcessor_ClassID)
Chris Dalton6a3dbee2017-10-16 10:44:41 -060036 , fRenderPass(renderPass)
37 , fInstanceAttrib(this->addInstanceAttrib("instance", instance_array_format(fRenderPass))) {
Chris Dalton1a325d22017-07-14 15:17:41 -060038 fPointsBufferAccess.reset(kRG_float_GrPixelConfig, pointsBuffer, kVertex_GrShaderFlag);
39 this->addBufferAccess(&fPointsBufferAccess);
40
41 this->setWillUseGeoShader();
Chris Dalton1a325d22017-07-14 15:17:41 -060042}
43
Chris Dalton6a3dbee2017-10-16 10:44:41 -060044void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
45 SkString* code, const char* position,
46 const char* coverage, const char* wind) {
47 WindHandling windHandling = this->onEmitVaryings(varyingHandler, code, position, coverage,
48 wind);
49 if (WindHandling::kNotHandled == windHandling) {
Chris Daltonfdde34e2017-10-16 14:15:26 -060050 varyingHandler->addFlatVarying("wind", &fWind);
Chris Dalton6a3dbee2017-10-16 10:44:41 -060051 code->appendf("%s = %s;", fWind.gsOut(), wind);
Chris Dalton1a325d22017-07-14 15:17:41 -060052 }
Eric Borend6365e52017-10-16 12:31:14 +000053}
54
Chris Dalton6a3dbee2017-10-16 10:44:41 -060055void GrCCPRCoverageProcessor::Shader::emitFragmentCode(const GrCCPRCoverageProcessor& proc,
56 GrGLSLPPFragmentBuilder* f,
57 const char* skOutputColor,
58 const char* skOutputCoverage) const {
59 f->codeAppendf("half coverage = 0;");
60 this->onEmitFragmentCode(f, "coverage");
61 if (fWind.fsIn()) {
62 f->codeAppendf("%s.a = coverage * %s;", skOutputColor, fWind.fsIn());
63 } else {
64 f->codeAppendf("%s.a = coverage;", skOutputColor);
Eric Borend6365e52017-10-16 12:31:14 +000065 }
Chris Dalton6a3dbee2017-10-16 10:44:41 -060066 f->codeAppendf("%s = half4(1);", skOutputCoverage);
Chris Dalton1a325d22017-07-14 15:17:41 -060067#ifdef SK_DEBUG
Chris Daltona640c492017-09-11 22:04:03 -070068 if (proc.debugVisualizationsEnabled()) {
Chris Dalton6a3dbee2017-10-16 10:44:41 -060069 f->codeAppendf("%s = half4(-%s.a, %s.a, 0, 1);",
70 skOutputColor, skOutputColor, skOutputColor);
Eric Borend6365e52017-10-16 12:31:14 +000071 }
72#endif
Eric Borend6365e52017-10-16 12:31:14 +000073}
74
Chris Dalton6a3dbee2017-10-16 10:44:41 -060075void GrCCPRCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLShaderBuilder* s,
76 const char* leftPt,
77 const char* rightPt,
78 const char* outputDistanceEquation) {
Chris Dalton6a3dbee2017-10-16 10:44:41 -060079 s->codeAppendf("float2 n = float2(%s.y - %s.y, %s.x - %s.x);",
Eric Borend6365e52017-10-16 12:31:14 +000080 rightPt, leftPt, leftPt, rightPt);
Chris Daltoncc0ab7e2017-10-24 14:16:52 -060081 s->codeAppend ("float nwidth = (abs(n.x) + abs(n.y)) * (bloat * 2);");
82 // When nwidth=0, wind must also be 0 (and coverage * wind = 0). So it doesn't matter what we
83 // come up with here as long as it isn't NaN or Inf.
84 s->codeAppend ("n /= (0 != nwidth) ? nwidth : 1;");
85 s->codeAppendf("%s = float3(-n, dot(n, %s) - .5);", outputDistanceEquation, leftPt);
Eric Borend6365e52017-10-16 12:31:14 +000086}
87
Chris Dalton6a3dbee2017-10-16 10:44:41 -060088int GrCCPRCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f,
89 const char* samplesName) {
Chris Dalton1a325d22017-07-14 15:17:41 -060090 // Standard DX11 sample locations.
91#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
Ethan Nicholas8aa45692017-09-20 11:24:15 -040092 f->defineConstant("float2[8]", samplesName, "float2[8]("
93 "float2(+1, -3)/16, float2(-1, +3)/16, float2(+5, +1)/16, float2(-3, -5)/16, "
94 "float2(-5, +5)/16, float2(-7, -1)/16, float2(+3, +7)/16, float2(+7, -7)/16."
Chris Dalton1a325d22017-07-14 15:17:41 -060095 ")");
96 return 8;
97#else
Ethan Nicholas8aa45692017-09-20 11:24:15 -040098 f->defineConstant("float2[16]", samplesName, "float2[16]("
99 "float2(+1, +1)/16, float2(-1, -3)/16, float2(-3, +2)/16, float2(+4, -1)/16, "
100 "float2(-5, -2)/16, float2(+2, +5)/16, float2(+5, +3)/16, float2(+3, -5)/16, "
101 "float2(-2, +6)/16, float2( 0, -7)/16, float2(-4, -6)/16, float2(-6, +4)/16, "
102 "float2(-8, 0)/16, float2(+7, -4)/16, float2(+6, +7)/16, float2(-7, -8)/16."
Chris Dalton1a325d22017-07-14 15:17:41 -0600103 ")");
104 return 16;
105#endif
106}
107
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600108void GrCCPRCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
109 GrProcessorKeyBuilder* b) const {
110 b->add32((int)fRenderPass);
111}
112
113GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
114 std::unique_ptr<Shader> shader;
115 switch (fRenderPass) {
116 using CubicType = GrCCPRCubicShader::CubicType;
117 case RenderPass::kTriangleHulls:
118 shader = skstd::make_unique<GrCCPRTriangleHullShader>();
119 break;
120 case RenderPass::kTriangleEdges:
121 shader = skstd::make_unique<GrCCPRTriangleEdgeShader>();
122 break;
123 case RenderPass::kTriangleCorners:
124 shader = skstd::make_unique<GrCCPRTriangleCornerShader>();
125 break;
126 case RenderPass::kQuadraticHulls:
127 shader = skstd::make_unique<GrCCPRQuadraticHullShader>();
128 break;
129 case RenderPass::kQuadraticCorners:
130 shader = skstd::make_unique<GrCCPRQuadraticCornerShader>();
131 break;
132 case RenderPass::kSerpentineHulls:
133 shader = skstd::make_unique<GrCCPRCubicHullShader>(CubicType::kSerpentine);
134 break;
135 case RenderPass::kLoopHulls:
136 shader = skstd::make_unique<GrCCPRCubicHullShader>(CubicType::kLoop);
137 break;
138 case RenderPass::kSerpentineCorners:
139 shader = skstd::make_unique<GrCCPRCubicCornerShader>(CubicType::kSerpentine);
140 break;
141 case RenderPass::kLoopCorners:
142 shader = skstd::make_unique<GrCCPRCubicCornerShader>(CubicType::kLoop);
143 break;
144 }
145 return CreateGSImpl(std::move(shader));
146}
147
148const char* GrCCPRCoverageProcessor::GetRenderPassName(RenderPass renderPass) {
149 switch (renderPass) {
150 case RenderPass::kTriangleHulls:
151 return "RenderPass::kTriangleHulls";
152 case RenderPass::kTriangleEdges:
153 return "RenderPass::kTriangleEdges";
154 case RenderPass::kTriangleCorners:
155 return "RenderPass::kTriangleCorners";
156 case RenderPass::kQuadraticHulls:
157 return "RenderPass::kQuadraticHulls";
158 case RenderPass::kQuadraticCorners:
159 return "RenderPass::kQuadraticCorners";
160 case RenderPass::kSerpentineHulls:
161 return "RenderPass::kSerpentineHulls";
162 case RenderPass::kLoopHulls:
163 return "RenderPass::kLoopHulls";
164 case RenderPass::kSerpentineCorners:
165 return "RenderPass::kSerpentineCorners";
166 case RenderPass::kLoopCorners:
167 return "RenderPass::kLoopCorners";
168 }
169 SK_ABORT("Unexpected GrCCPRCoverageProcessor::RenderPass.");
170 return nullptr;
171}