1 /*
2 * Copyright 2014 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 "GrGLSLGeometryShaderBuilder.h"
9 #include "GrGLSLProgramBuilder.h"
10 #include "GrGLSLVarying.h"
11
input_type_name(GrGLSLGeometryBuilder::InputType in)12 static const char* input_type_name(GrGLSLGeometryBuilder::InputType in) {
13 using InputType = GrGLSLGeometryBuilder::InputType;
14 switch (in) {
15 case InputType::kPoints: return "points";
16 case InputType::kLines: return "lines";
17 case InputType::kLinesAdjacency: return "lines_adjacency";
18 case InputType::kTriangles: return "triangles";
19 case InputType::kTrianglesAdjacency: return "triangles_adjacency";
20 }
21 SkFAIL("invalid input type");
22 return "unknown_input";
23 }
24
output_type_name(GrGLSLGeometryBuilder::OutputType out)25 static const char* output_type_name(GrGLSLGeometryBuilder::OutputType out) {
26 using OutputType = GrGLSLGeometryBuilder::OutputType;
27 switch (out) {
28 case OutputType::kPoints: return "points";
29 case OutputType::kLineStrip: return "line_strip";
30 case OutputType::kTriangleStrip: return "triangle_strip";
31 }
32 SkFAIL("invalid output type");
33 return "unknown_output";
34 }
35
GrGLSLGeometryBuilder(GrGLSLProgramBuilder * program)36 GrGLSLGeometryBuilder::GrGLSLGeometryBuilder(GrGLSLProgramBuilder* program)
37 : INHERITED(program)
38 , fNumInvocations(0) {
39 }
40
configure(InputType inputType,OutputType outputType,int maxVertices,int numInvocations)41 void GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType, int maxVertices,
42 int numInvocations) {
43 SkASSERT(!this->isConfigured());
44 fNumInvocations = numInvocations;
45 if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) {
46 maxVertices *= numInvocations;
47 numInvocations = 1;
48 }
49 this->addLayoutQualifier(input_type_name(inputType), kIn_InterfaceQualifier);
50 this->addLayoutQualifier(SkStringPrintf("invocations = %i", numInvocations).c_str(),
51 kIn_InterfaceQualifier);
52 this->addLayoutQualifier(output_type_name(outputType), kOut_InterfaceQualifier);
53 this->addLayoutQualifier(SkStringPrintf("max_vertices = %i", maxVertices).c_str(),
54 kOut_InterfaceQualifier);
55 }
56
onFinalize()57 void GrGLSLGeometryBuilder::onFinalize() {
58 SkASSERT(this->isConfigured());
59 fProgramBuilder->varyingHandler()->getGeomDecls(&this->inputs(), &this->outputs());
60 GrShaderVar sk_InvocationID("sk_InvocationID", kInt_GrSLType);
61 this->declareGlobal(sk_InvocationID);
62 SkASSERT(sk_InvocationID.getName() == SkString("sk_InvocationID"));
63 if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) {
64 SkString invokeFn;
65 this->emitFunction(kVoid_GrSLType, "invoke", 0, nullptr, this->code().c_str(), &invokeFn);
66 this->code().printf("for (sk_InvocationID = 0; sk_InvocationID < %i; ++sk_InvocationID) {"
67 "%s();"
68 "EndPrimitive();"
69 "}", fNumInvocations, invokeFn.c_str());
70 } else {
71 this->codePrependf("sk_InvocationID = gl_InvocationID;");
72 }
73 }
74