blob: 68166c02b6c7299f3dbe4252197434758d8d4686 [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 Dalton1fbdb612017-12-12 12:48:47 -070015#include "glsl/GrGLSLVertexGeoBuilder.h"
Chris Dalton1a325d22017-07-14 15:17:41 -060016
Chris Dalton6a3dbee2017-10-16 10:44:41 -060017void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
18 SkString* code, const char* position,
19 const char* coverage, const char* wind) {
20 WindHandling windHandling = this->onEmitVaryings(varyingHandler, code, position, coverage,
21 wind);
22 if (WindHandling::kNotHandled == windHandling) {
Chris Daltonfdde34e2017-10-16 14:15:26 -060023 varyingHandler->addFlatVarying("wind", &fWind);
Chris Dalton6a3dbee2017-10-16 10:44:41 -060024 code->appendf("%s = %s;", fWind.gsOut(), wind);
Chris Dalton1a325d22017-07-14 15:17:41 -060025 }
Eric Borend6365e52017-10-16 12:31:14 +000026}
27
Chris Dalton6a3dbee2017-10-16 10:44:41 -060028void GrCCPRCoverageProcessor::Shader::emitFragmentCode(const GrCCPRCoverageProcessor& proc,
29 GrGLSLPPFragmentBuilder* f,
30 const char* skOutputColor,
31 const char* skOutputCoverage) const {
32 f->codeAppendf("half coverage = 0;");
33 this->onEmitFragmentCode(f, "coverage");
34 if (fWind.fsIn()) {
35 f->codeAppendf("%s.a = coverage * %s;", skOutputColor, fWind.fsIn());
36 } else {
37 f->codeAppendf("%s.a = coverage;", skOutputColor);
Eric Borend6365e52017-10-16 12:31:14 +000038 }
Chris Dalton6a3dbee2017-10-16 10:44:41 -060039 f->codeAppendf("%s = half4(1);", skOutputCoverage);
Chris Dalton1a325d22017-07-14 15:17:41 -060040#ifdef SK_DEBUG
Chris Daltona640c492017-09-11 22:04:03 -070041 if (proc.debugVisualizationsEnabled()) {
Chris Dalton6a3dbee2017-10-16 10:44:41 -060042 f->codeAppendf("%s = half4(-%s.a, %s.a, 0, 1);",
43 skOutputColor, skOutputColor, skOutputColor);
Eric Borend6365e52017-10-16 12:31:14 +000044 }
45#endif
Eric Borend6365e52017-10-16 12:31:14 +000046}
47
Chris Dalton1fbdb612017-12-12 12:48:47 -070048void GrCCPRCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLVertexGeoBuilder* s,
Chris Dalton6a3dbee2017-10-16 10:44:41 -060049 const char* leftPt,
50 const char* rightPt,
51 const char* outputDistanceEquation) {
Chris Dalton6a3dbee2017-10-16 10:44:41 -060052 s->codeAppendf("float2 n = float2(%s.y - %s.y, %s.x - %s.x);",
Eric Borend6365e52017-10-16 12:31:14 +000053 rightPt, leftPt, leftPt, rightPt);
Chris Daltoncc0ab7e2017-10-24 14:16:52 -060054 s->codeAppend ("float nwidth = (abs(n.x) + abs(n.y)) * (bloat * 2);");
55 // When nwidth=0, wind must also be 0 (and coverage * wind = 0). So it doesn't matter what we
56 // come up with here as long as it isn't NaN or Inf.
57 s->codeAppend ("n /= (0 != nwidth) ? nwidth : 1;");
58 s->codeAppendf("%s = float3(-n, dot(n, %s) - .5);", outputDistanceEquation, leftPt);
Eric Borend6365e52017-10-16 12:31:14 +000059}
60
Chris Dalton6a3dbee2017-10-16 10:44:41 -060061int GrCCPRCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f,
62 const char* samplesName) {
Chris Dalton1a325d22017-07-14 15:17:41 -060063 // Standard DX11 sample locations.
64#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
Ethan Nicholas8aa45692017-09-20 11:24:15 -040065 f->defineConstant("float2[8]", samplesName, "float2[8]("
66 "float2(+1, -3)/16, float2(-1, +3)/16, float2(+5, +1)/16, float2(-3, -5)/16, "
67 "float2(-5, +5)/16, float2(-7, -1)/16, float2(+3, +7)/16, float2(+7, -7)/16."
Chris Dalton1a325d22017-07-14 15:17:41 -060068 ")");
69 return 8;
70#else
Ethan Nicholas8aa45692017-09-20 11:24:15 -040071 f->defineConstant("float2[16]", samplesName, "float2[16]("
72 "float2(+1, +1)/16, float2(-1, -3)/16, float2(-3, +2)/16, float2(+4, -1)/16, "
73 "float2(-5, -2)/16, float2(+2, +5)/16, float2(+5, +3)/16, float2(+3, -5)/16, "
74 "float2(-2, +6)/16, float2( 0, -7)/16, float2(-4, -6)/16, float2(-6, +4)/16, "
75 "float2(-8, 0)/16, float2(+7, -4)/16, float2(+6, +7)/16, float2(-7, -8)/16."
Chris Dalton1a325d22017-07-14 15:17:41 -060076 ")");
77 return 16;
78#endif
79}
80
Chris Dalton6a3dbee2017-10-16 10:44:41 -060081void GrCCPRCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
82 GrProcessorKeyBuilder* b) const {
83 b->add32((int)fRenderPass);
84}
85
86GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
87 std::unique_ptr<Shader> shader;
88 switch (fRenderPass) {
Chris Dalton6a3dbee2017-10-16 10:44:41 -060089 case RenderPass::kTriangleHulls:
90 shader = skstd::make_unique<GrCCPRTriangleHullShader>();
91 break;
92 case RenderPass::kTriangleEdges:
93 shader = skstd::make_unique<GrCCPRTriangleEdgeShader>();
94 break;
95 case RenderPass::kTriangleCorners:
96 shader = skstd::make_unique<GrCCPRTriangleCornerShader>();
97 break;
98 case RenderPass::kQuadraticHulls:
99 shader = skstd::make_unique<GrCCPRQuadraticHullShader>();
100 break;
101 case RenderPass::kQuadraticCorners:
102 shader = skstd::make_unique<GrCCPRQuadraticCornerShader>();
103 break;
Chris Daltonbe4ffab2017-12-08 10:59:58 -0700104 case RenderPass::kCubicHulls:
105 shader = skstd::make_unique<GrCCPRCubicHullShader>();
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600106 break;
Chris Daltonbe4ffab2017-12-08 10:59:58 -0700107 case RenderPass::kCubicCorners:
108 shader = skstd::make_unique<GrCCPRCubicCornerShader>();
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600109 break;
110 }
Chris Dalton1fbdb612017-12-12 12:48:47 -0700111 return this->createGSImpl(std::move(shader));
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600112}