blob: 3a9eb7bfa740a018b6471f473a9ffedb7e0c7fab [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
Chris Dalton383a2ef2018-01-08 17:21:41 -05008#include "GrCCCoverageProcessor.h"
Chris Dalton1a325d22017-07-14 15:17:41 -06009
Chris Dalton622650a2018-03-07 17:30:10 -070010#include "GrGpuCommandBuffer.h"
11#include "GrOpFlushState.h"
Chris Dalton6a3dbee2017-10-16 10:44:41 -060012#include "SkMakeUnique.h"
Chris Dalton383a2ef2018-01-08 17:21:41 -050013#include "ccpr/GrCCCubicShader.h"
14#include "ccpr/GrCCQuadraticShader.h"
Chris Dalton90e8fb12017-12-22 02:24:53 -070015#include "glsl/GrGLSLVertexGeoBuilder.h"
Chris Dalton1a325d22017-07-14 15:17:41 -060016#include "glsl/GrGLSLFragmentShaderBuilder.h"
Chris Dalton1fbdb612017-12-12 12:48:47 -070017#include "glsl/GrGLSLVertexGeoBuilder.h"
Chris Dalton1a325d22017-07-14 15:17:41 -060018
Chris Daltondf04ce22018-03-07 17:28:07 -070019void GrCCCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
20 GrProcessorKeyBuilder* b) const {
Chris Dalton622650a2018-03-07 17:30:10 -070021 int key = ((int)fRenderPass << 3);
22 if (GSTriangleSubpass::kCorners == fGSTriangleSubpass) {
23 key |= 4;
24 }
Chris Daltondf04ce22018-03-07 17:28:07 -070025 if (WindMethod::kInstanceData == fWindMethod) {
26 key |= 2;
27 }
28 if (Impl::kVertexShader == fImpl) {
29 key |= 1;
30 }
31#ifdef SK_DEBUG
32 uint32_t bloatBits;
33 memcpy(&bloatBits, &fDebugBloat, 4);
34 b->add32(bloatBits);
35#endif
36 b->add32(key);
37}
38
39GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
40 std::unique_ptr<Shader> shader;
41 switch (fRenderPass) {
42 case RenderPass::kTriangles:
Chris Dalton622650a2018-03-07 17:30:10 -070043 shader = skstd::make_unique<Shader>();
Chris Daltondf04ce22018-03-07 17:28:07 -070044 break;
45 case RenderPass::kQuadratics:
46 shader = skstd::make_unique<GrCCQuadraticShader>();
47 break;
48 case RenderPass::kCubics:
49 shader = skstd::make_unique<GrCCCubicShader>();
50 break;
51 }
52 return Impl::kGeometryShader == fImpl ? this->createGSImpl(std::move(shader))
53 : this->createVSImpl(std::move(shader));
54}
55
Chris Dalton622650a2018-03-07 17:30:10 -070056void GrCCCoverageProcessor::draw(GrOpFlushState* flushState, const GrPipeline& pipeline,
57 const GrMesh meshes[],
58 const GrPipeline::DynamicState dynamicStates[], int meshCount,
59 const SkRect& drawBounds) const {
60 GrGpuRTCommandBuffer* cmdBuff = flushState->rtCommandBuffer();
61 cmdBuff->draw(pipeline, *this, meshes, dynamicStates, meshCount, drawBounds);
62
63 // Geometry shader backend draws triangles in two subpasses.
64 if (RenderPass::kTriangles == fRenderPass && Impl::kGeometryShader == fImpl) {
65 SkASSERT(GSTriangleSubpass::kHullsAndEdges == fGSTriangleSubpass);
66 GrCCCoverageProcessor cornerProc(*this, GSTriangleSubpass::kCorners);
67 cmdBuff->draw(pipeline, cornerProc, meshes, dynamicStates, meshCount, drawBounds);
68 }
69}
70
71void GrCCCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
72 GrGLSLVarying::Scope scope, SkString* code,
73 const char* position, const char* coverage,
74 const char* wind) {
75 SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope);
76 code->appendf("half coverageTimesWind = %s * %s;", coverage, wind);
77 CoverageHandling coverageHandling = this->onEmitVaryings(varyingHandler, scope, code, position,
78 "coverageTimesWind");
79 if (CoverageHandling::kNotHandled == coverageHandling) {
80 fCoverageTimesWind.reset(kHalf_GrSLType, scope);
81 varyingHandler->addVarying("coverage_times_wind", &fCoverageTimesWind);
82 code->appendf("%s = coverageTimesWind;", OutName(fCoverageTimesWind));
83 }
84}
85
Chris Dalton383a2ef2018-01-08 17:21:41 -050086void GrCCCoverageProcessor::Shader::emitFragmentCode(const GrCCCoverageProcessor& proc,
Chris Dalton60283612018-02-14 13:38:14 -070087 GrGLSLFPFragmentBuilder* f,
Chris Dalton383a2ef2018-01-08 17:21:41 -050088 const char* skOutputColor,
89 const char* skOutputCoverage) const {
Chris Dalton622650a2018-03-07 17:30:10 -070090 f->codeAppendf("half coverage = +1;");
Chris Daltondf04ce22018-03-07 17:28:07 -070091 this->onEmitFragmentCode(proc, f, "coverage");
Chris Dalton622650a2018-03-07 17:30:10 -070092 if (fCoverageTimesWind.fsIn()) {
93 f->codeAppendf("coverage *= %s;", fCoverageTimesWind.fsIn());
94 }
Chris Daltonf510e262018-01-30 16:42:37 -070095 f->codeAppendf("%s.a = coverage;", skOutputColor);
Chris Dalton6a3dbee2017-10-16 10:44:41 -060096 f->codeAppendf("%s = half4(1);", skOutputCoverage);
Chris Dalton1a325d22017-07-14 15:17:41 -060097#ifdef SK_DEBUG
Chris Daltona640c492017-09-11 22:04:03 -070098 if (proc.debugVisualizationsEnabled()) {
Chris Daltondf04ce22018-03-07 17:28:07 -070099 f->codeAppendf("%s = half4(-%s.a, %s.a, 0, abs(%s.a));",
100 skOutputColor, skOutputColor, skOutputColor, skOutputColor);
Eric Borend6365e52017-10-16 12:31:14 +0000101 }
102#endif
Eric Borend6365e52017-10-16 12:31:14 +0000103}
104
Chris Dalton0a793812018-03-07 11:18:30 -0700105void GrCCCoverageProcessor::Shader::CalcEdgeCoverageAtBloatVertex(GrGLSLVertexGeoBuilder* s,
106 const char* leftPt,
107 const char* rightPt,
108 const char* rasterVertexDir,
109 const char* outputCoverage) {
110 // Here we find an edge's coverage at one corner of a conservative raster bloat box whose center
111 // falls on the edge in question. (A bloat box is axis-aligned and the size of one pixel.) We
112 // always set up coverage so it is -1 at the outermost corner, 0 at the innermost, and -.5 at
113 // the center. Interpolated, these coverage values convert jagged conservative raster edges into
114 // smooth antialiased edges.
115 //
116 // d1 == (P + sign(n) * bloat) dot n (Distance at the bloat box vertex whose
117 // == P dot n + (abs(n.x) + abs(n.y)) * bloatSize coverage=-1, where the bloat box is
118 // centered on P.)
119 //
120 // d0 == (P - sign(n) * bloat) dot n (Distance at the bloat box vertex whose
121 // == P dot n - (abs(n.x) + abs(n.y)) * bloatSize coverage=0, where the bloat box is
122 // centered on P.)
123 //
124 // d == (P + rasterVertexDir * bloatSize) dot n (Distance at the bloat box vertex whose
125 // == P dot n + (rasterVertexDir dot n) * bloatSize coverage we wish to calculate.)
126 //
127 // coverage == -(d - d0) / (d1 - d0) (coverage=-1 at d=d1; coverage=0 at d=d0)
128 //
129 // == (rasterVertexDir dot n) / (abs(n.x) + abs(n.y)) * -.5 - .5
130 //
131 s->codeAppendf("float2 n = float2(%s.y - %s.y, %s.x - %s.x);",
132 rightPt, leftPt, leftPt, rightPt);
133 s->codeAppend ("float nwidth = abs(n.x) + abs(n.y);");
134 s->codeAppendf("float t = dot(%s, n);", rasterVertexDir);
135 // The below conditional guarantees we get exactly 1 on the divide when nwidth=t (in case the
136 // GPU divides by multiplying by the reciprocal?) It also guards against NaN when nwidth=0.
137 s->codeAppendf("%s = (abs(t) != nwidth ? t / nwidth : sign(t)) * -.5 - .5;", outputCoverage);
138}
Chris Dalton622650a2018-03-07 17:30:10 -0700139
140void GrCCCoverageProcessor::Shader::CalcEdgeCoveragesAtBloatVertices(GrGLSLVertexGeoBuilder* s,
141 const char* leftPt,
142 const char* rightPt,
143 const char* bloatDir1,
144 const char* bloatDir2,
145 const char* outputCoverages) {
146 // See comments in CalcEdgeCoverageAtBloatVertex.
147 s->codeAppendf("float2 n = float2(%s.y - %s.y, %s.x - %s.x);",
148 rightPt, leftPt, leftPt, rightPt);
149 s->codeAppend ("float nwidth = abs(n.x) + abs(n.y);");
150 s->codeAppendf("float2 t = n * float2x2(%s, %s);", bloatDir1, bloatDir2);
151 s->codeAppendf("for (int i = 0; i < 2; ++i) {");
152 s->codeAppendf( "%s[i] = (abs(t[i]) != nwidth ? t[i] / nwidth : sign(t[i])) * -.5 - .5;",
153 outputCoverages);
154 s->codeAppendf("}");
155}