blob: 61e431a2c9e94e5b49fee8df9bde4bccddce4a98 [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 Daltona3e92712017-12-04 11:45:51 -070016GrCCPRCoverageProcessor::GrCCPRCoverageProcessor(RenderPass renderPass)
Ethan Nicholasabff9562017-10-09 10:54:08 -040017 : INHERITED(kGrCCPRCoverageProcessor_ClassID)
Chris Daltona3e92712017-12-04 11:45:51 -070018 , fRenderPass(renderPass) {
19 if (RenderPassIsCubic(fRenderPass)) {
20 this->addInstanceAttrib("X", kFloat4_GrVertexAttribType);
21 this->addInstanceAttrib("Y", kFloat4_GrVertexAttribType);
22
23 SkASSERT(offsetof(CubicInstance, fX) ==
24 this->getInstanceAttrib(InstanceAttribs::kX).fOffsetInRecord);
25 SkASSERT(offsetof(CubicInstance, fY) ==
26 this->getInstanceAttrib(InstanceAttribs::kY).fOffsetInRecord);
27 SkASSERT(sizeof(CubicInstance) == this->getInstanceStride());
28 } else {
29 this->addInstanceAttrib("X", kFloat3_GrVertexAttribType);
30 this->addInstanceAttrib("Y", kFloat3_GrVertexAttribType);
31
32 SkASSERT(offsetof(TriangleInstance, fX) ==
33 this->getInstanceAttrib(InstanceAttribs::kX).fOffsetInRecord);
34 SkASSERT(offsetof(TriangleInstance, fY) ==
35 this->getInstanceAttrib(InstanceAttribs::kY).fOffsetInRecord);
36 SkASSERT(sizeof(TriangleInstance) == this->getInstanceStride());
37 }
Chris Dalton1a325d22017-07-14 15:17:41 -060038
39 this->setWillUseGeoShader();
Chris Dalton1a325d22017-07-14 15:17:41 -060040}
41
Chris Dalton6a3dbee2017-10-16 10:44:41 -060042void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
43 SkString* code, const char* position,
44 const char* coverage, const char* wind) {
45 WindHandling windHandling = this->onEmitVaryings(varyingHandler, code, position, coverage,
46 wind);
47 if (WindHandling::kNotHandled == windHandling) {
Chris Daltonfdde34e2017-10-16 14:15:26 -060048 varyingHandler->addFlatVarying("wind", &fWind);
Chris Dalton6a3dbee2017-10-16 10:44:41 -060049 code->appendf("%s = %s;", fWind.gsOut(), wind);
Chris Dalton1a325d22017-07-14 15:17:41 -060050 }
Eric Borend6365e52017-10-16 12:31:14 +000051}
52
Chris Dalton6a3dbee2017-10-16 10:44:41 -060053void GrCCPRCoverageProcessor::Shader::emitFragmentCode(const GrCCPRCoverageProcessor& proc,
54 GrGLSLPPFragmentBuilder* f,
55 const char* skOutputColor,
56 const char* skOutputCoverage) const {
57 f->codeAppendf("half coverage = 0;");
58 this->onEmitFragmentCode(f, "coverage");
59 if (fWind.fsIn()) {
60 f->codeAppendf("%s.a = coverage * %s;", skOutputColor, fWind.fsIn());
61 } else {
62 f->codeAppendf("%s.a = coverage;", skOutputColor);
Eric Borend6365e52017-10-16 12:31:14 +000063 }
Chris Dalton6a3dbee2017-10-16 10:44:41 -060064 f->codeAppendf("%s = half4(1);", skOutputCoverage);
Chris Dalton1a325d22017-07-14 15:17:41 -060065#ifdef SK_DEBUG
Chris Daltona640c492017-09-11 22:04:03 -070066 if (proc.debugVisualizationsEnabled()) {
Chris Dalton6a3dbee2017-10-16 10:44:41 -060067 f->codeAppendf("%s = half4(-%s.a, %s.a, 0, 1);",
68 skOutputColor, skOutputColor, skOutputColor);
Eric Borend6365e52017-10-16 12:31:14 +000069 }
70#endif
Eric Borend6365e52017-10-16 12:31:14 +000071}
72
Chris Dalton6a3dbee2017-10-16 10:44:41 -060073void GrCCPRCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLShaderBuilder* s,
74 const char* leftPt,
75 const char* rightPt,
76 const char* outputDistanceEquation) {
Chris Dalton6a3dbee2017-10-16 10:44:41 -060077 s->codeAppendf("float2 n = float2(%s.y - %s.y, %s.x - %s.x);",
Eric Borend6365e52017-10-16 12:31:14 +000078 rightPt, leftPt, leftPt, rightPt);
Chris Daltoncc0ab7e2017-10-24 14:16:52 -060079 s->codeAppend ("float nwidth = (abs(n.x) + abs(n.y)) * (bloat * 2);");
80 // When nwidth=0, wind must also be 0 (and coverage * wind = 0). So it doesn't matter what we
81 // come up with here as long as it isn't NaN or Inf.
82 s->codeAppend ("n /= (0 != nwidth) ? nwidth : 1;");
83 s->codeAppendf("%s = float3(-n, dot(n, %s) - .5);", outputDistanceEquation, leftPt);
Eric Borend6365e52017-10-16 12:31:14 +000084}
85
Chris Dalton6a3dbee2017-10-16 10:44:41 -060086int GrCCPRCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f,
87 const char* samplesName) {
Chris Dalton1a325d22017-07-14 15:17:41 -060088 // Standard DX11 sample locations.
89#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
Ethan Nicholas8aa45692017-09-20 11:24:15 -040090 f->defineConstant("float2[8]", samplesName, "float2[8]("
91 "float2(+1, -3)/16, float2(-1, +3)/16, float2(+5, +1)/16, float2(-3, -5)/16, "
92 "float2(-5, +5)/16, float2(-7, -1)/16, float2(+3, +7)/16, float2(+7, -7)/16."
Chris Dalton1a325d22017-07-14 15:17:41 -060093 ")");
94 return 8;
95#else
Ethan Nicholas8aa45692017-09-20 11:24:15 -040096 f->defineConstant("float2[16]", samplesName, "float2[16]("
97 "float2(+1, +1)/16, float2(-1, -3)/16, float2(-3, +2)/16, float2(+4, -1)/16, "
98 "float2(-5, -2)/16, float2(+2, +5)/16, float2(+5, +3)/16, float2(+3, -5)/16, "
99 "float2(-2, +6)/16, float2( 0, -7)/16, float2(-4, -6)/16, float2(-6, +4)/16, "
100 "float2(-8, 0)/16, float2(+7, -4)/16, float2(+6, +7)/16, float2(-7, -8)/16."
Chris Dalton1a325d22017-07-14 15:17:41 -0600101 ")");
102 return 16;
103#endif
104}
105
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600106void GrCCPRCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
107 GrProcessorKeyBuilder* b) const {
108 b->add32((int)fRenderPass);
109}
110
111GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
112 std::unique_ptr<Shader> shader;
113 switch (fRenderPass) {
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600114 case RenderPass::kTriangleHulls:
115 shader = skstd::make_unique<GrCCPRTriangleHullShader>();
116 break;
117 case RenderPass::kTriangleEdges:
118 shader = skstd::make_unique<GrCCPRTriangleEdgeShader>();
119 break;
120 case RenderPass::kTriangleCorners:
121 shader = skstd::make_unique<GrCCPRTriangleCornerShader>();
122 break;
123 case RenderPass::kQuadraticHulls:
124 shader = skstd::make_unique<GrCCPRQuadraticHullShader>();
125 break;
126 case RenderPass::kQuadraticCorners:
127 shader = skstd::make_unique<GrCCPRQuadraticCornerShader>();
128 break;
Chris Daltonbe4ffab2017-12-08 10:59:58 -0700129 case RenderPass::kCubicHulls:
130 shader = skstd::make_unique<GrCCPRCubicHullShader>();
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600131 break;
Chris Daltonbe4ffab2017-12-08 10:59:58 -0700132 case RenderPass::kCubicCorners:
133 shader = skstd::make_unique<GrCCPRCubicCornerShader>();
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600134 break;
135 }
136 return CreateGSImpl(std::move(shader));
137}