1 /*
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
13 class GrSampleMaskProcessor::Impl : public GrGLSLGeometryProcessor {
14 public:
Impl(std::unique_ptr<Shader> shader)15 Impl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
16
17 private:
setData(const GrGLSLProgramDataManager &,const GrPrimitiveProcessor &,FPCoordTransformIter &&)18 void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&,
19 FPCoordTransformIter&&) override {}
20
21 void onEmitCode(EmitArgs&, GrGPArgs*) override;
22
23 const std::unique_ptr<Shader> fShader;
24 };
25
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)26 void 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);
34 SkASSERT(!args.fFPCoordTransformHandler->nextCoordTransform());
35
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
reset(PrimitiveType primitiveType,GrResourceProvider * rp)62 void 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
appendMesh(sk_sp<const GrGpuBuffer> instanceBuffer,int instanceCount,int baseInstance,SkTArray<GrMesh> * out) const93 void 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
onCreateGLSLInstance(std::unique_ptr<Shader> shader) const115 GrGLSLPrimitiveProcessor* GrSampleMaskProcessor::onCreateGLSLInstance(
116 std::unique_ptr<Shader> shader) const {
117 return new Impl(std::move(shader));
118 }
119