blob: d40fd7783682523be22c52c8878ac60b356308ea [file] [log] [blame]
Chris Daltonc3318f02019-07-19 14:20:53 -06001/*
2 * Copyright 2019 Google LLC.
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 "src/gpu/ccpr/GrSampleMaskProcessor.h"
9
10#include "src/gpu/GrMesh.h"
11#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
12
13class GrSampleMaskProcessor::Impl : public GrGLSLGeometryProcessor {
14public:
15 Impl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
16
17private:
18 void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&,
Brian Salomonc241b582019-11-27 08:57:17 -050019 const CoordTransformRange&) override {}
Chris Daltonc3318f02019-07-19 14:20:53 -060020
21 void onEmitCode(EmitArgs&, GrGPArgs*) override;
22
23 const std::unique_ptr<Shader> fShader;
24};
25
26void GrSampleMaskProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
27 const GrSampleMaskProcessor& proc = args.fGP.cast<GrSampleMaskProcessor>();
28 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
29 GrGLSLVertexBuilder* v = args.fVertBuilder;
30 int numInputPoints = proc.numInputPoints();
31 int inputWidth = (4 == numInputPoints || proc.hasInputWeight()) ? 4 : 3;
32
33 varyingHandler->emitAttributes(proc);
Brian Salomon7d8b3972019-11-26 22:34:44 -050034 SkASSERT(!*args.fFPCoordTransformHandler);
Chris Daltonc3318f02019-07-19 14:20:53 -060035
36 if (PrimitiveType::kTriangles == proc.fPrimitiveType) {
37 SkASSERT(!proc.hasInstanceAttributes()); // Triangles are drawn with vertex arrays.
38 gpArgs->fPositionVar = proc.fInputAttribs.front().asShaderVar();
39 } else {
40 SkASSERT(!proc.hasVertexAttributes()); // Curves are drawn with instanced rendering.
41
42 // Shaders expect a global "bloat" variable when calculating gradients.
43 v->defineConstant("half", "bloat", ".5");
44
45 const char* swizzle = (4 == numInputPoints || proc.hasInputWeight()) ? "xyzw" : "xyz";
46 v->codeAppendf("float%ix2 pts = transpose(float2x%i(X.%s, Y.%s));",
47 inputWidth, inputWidth, swizzle, swizzle);
48
49 const char* hullPts = "pts";
50 fShader->emitSetupCode(v, "pts", &hullPts);
51 v->codeAppendf("float2 vertexpos = %s[sk_VertexID ^ (sk_VertexID >> 1)];", hullPts);
52 gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos");
53
54 fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag,
55 &AccessCodeString(v), "vertexpos", nullptr, nullptr, nullptr);
56 }
57
58 // Fragment shader.
59 fShader->emitSampleMaskCode(args.fFragBuilder);
60}
61
62void GrSampleMaskProcessor::reset(PrimitiveType primitiveType, GrResourceProvider* rp) {
63 fPrimitiveType = primitiveType; // This will affect the return values for numInputPoints, etc.
64 SkASSERT(PrimitiveType::kWeightedTriangles != fPrimitiveType);
65
66 this->resetCustomFeatures();
67 fInputAttribs.reset();
68
69 switch (fPrimitiveType) {
70 case PrimitiveType::kTriangles:
71 case PrimitiveType::kWeightedTriangles:
72 fInputAttribs.emplace_back("point", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
73 this->setVertexAttributes(fInputAttribs.begin(), 1);
74 this->setInstanceAttributes(nullptr, 0);
75 break;
76 case PrimitiveType::kQuadratics:
77 case PrimitiveType::kCubics:
78 case PrimitiveType::kConics: {
79 auto instanceAttribType = (PrimitiveType::kQuadratics == fPrimitiveType)
80 ? kFloat3_GrVertexAttribType : kFloat4_GrVertexAttribType;
81 auto shaderVarType = (PrimitiveType::kQuadratics == fPrimitiveType)
82 ? kFloat3_GrSLType : kFloat4_GrSLType;
83 fInputAttribs.emplace_back("X", instanceAttribType, shaderVarType);
84 fInputAttribs.emplace_back("Y", instanceAttribType, shaderVarType);
85 this->setVertexAttributes(nullptr, 0);
86 this->setInstanceAttributes(fInputAttribs.begin(), fInputAttribs.count());
87 this->setWillUseCustomFeature(CustomFeatures::kSampleLocations);
88 break;
89 }
90 }
91}
92
93void GrSampleMaskProcessor::appendMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount,
94 int baseInstance, SkTArray<GrMesh>* out) const {
95 SkASSERT(PrimitiveType::kWeightedTriangles != fPrimitiveType);
96
97 switch (fPrimitiveType) {
98 case PrimitiveType::kTriangles:
99 case PrimitiveType::kWeightedTriangles: {
100 GrMesh& mesh = out->emplace_back(GrPrimitiveType::kTriangles);
101 mesh.setNonIndexedNonInstanced(instanceCount * 3);
102 mesh.setVertexData(std::move(instanceBuffer), baseInstance * 3);
103 break;
104 }
105 case PrimitiveType::kQuadratics:
106 case PrimitiveType::kCubics:
107 case PrimitiveType::kConics: {
108 GrMesh& mesh = out->emplace_back(GrPrimitiveType::kTriangleStrip);
109 mesh.setInstanced(std::move(instanceBuffer), instanceCount, baseInstance, 4);
110 break;
111 }
112 }
113}
114
Robert Phillipscea290f2019-11-06 11:21:03 -0500115GrPrimitiveType GrSampleMaskProcessor::primType() const {
116 SkASSERT(PrimitiveType::kWeightedTriangles != fPrimitiveType);
117
118 switch (fPrimitiveType) {
119 case PrimitiveType::kTriangles:
120 case PrimitiveType::kWeightedTriangles:
121 return GrPrimitiveType::kTriangles;
122 case PrimitiveType::kQuadratics:
123 case PrimitiveType::kCubics:
124 case PrimitiveType::kConics:
125 return GrPrimitiveType::kTriangleStrip;
126 default:
127 return GrPrimitiveType::kTriangleStrip;
128 }
129}
130
Chris Daltonc3318f02019-07-19 14:20:53 -0600131GrGLSLPrimitiveProcessor* GrSampleMaskProcessor::onCreateGLSLInstance(
132 std::unique_ptr<Shader> shader) const {
133 return new Impl(std::move(shader));
134}