| /* |
| * Copyright 2014 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "GrGLSLGeometryShaderBuilder.h" |
| #include "GrGLSLProgramBuilder.h" |
| #include "GrGLSLVarying.h" |
| |
| static const char* input_type_name(GrGLSLGeometryBuilder::InputType in) { |
| using InputType = GrGLSLGeometryBuilder::InputType; |
| switch (in) { |
| case InputType::kPoints: return "points"; |
| case InputType::kLines: return "lines"; |
| case InputType::kLinesAdjacency: return "lines_adjacency"; |
| case InputType::kTriangles: return "triangles"; |
| case InputType::kTrianglesAdjacency: return "triangles_adjacency"; |
| } |
| SkFAIL("invalid input type"); |
| return "unknown_input"; |
| } |
| |
| static const char* output_type_name(GrGLSLGeometryBuilder::OutputType out) { |
| using OutputType = GrGLSLGeometryBuilder::OutputType; |
| switch (out) { |
| case OutputType::kPoints: return "points"; |
| case OutputType::kLineStrip: return "line_strip"; |
| case OutputType::kTriangleStrip: return "triangle_strip"; |
| } |
| SkFAIL("invalid output type"); |
| return "unknown_output"; |
| } |
| |
| GrGLSLGeometryBuilder::GrGLSLGeometryBuilder(GrGLSLProgramBuilder* program) |
| : INHERITED(program) |
| , fNumInvocations(0) { |
| } |
| |
| void GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType, int maxVertices, |
| int numInvocations) { |
| SkASSERT(!this->isConfigured()); |
| fNumInvocations = numInvocations; |
| if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) { |
| maxVertices *= numInvocations; |
| numInvocations = 1; |
| } |
| this->addLayoutQualifier(input_type_name(inputType), kIn_InterfaceQualifier); |
| this->addLayoutQualifier(SkStringPrintf("invocations = %i", numInvocations).c_str(), |
| kIn_InterfaceQualifier); |
| this->addLayoutQualifier(output_type_name(outputType), kOut_InterfaceQualifier); |
| this->addLayoutQualifier(SkStringPrintf("max_vertices = %i", maxVertices).c_str(), |
| kOut_InterfaceQualifier); |
| } |
| |
| void GrGLSLGeometryBuilder::onFinalize() { |
| SkASSERT(this->isConfigured()); |
| fProgramBuilder->varyingHandler()->getGeomDecls(&this->inputs(), &this->outputs()); |
| GrShaderVar sk_InvocationID("sk_InvocationID", kInt_GrSLType); |
| this->declareGlobal(sk_InvocationID); |
| SkASSERT(sk_InvocationID.getName() == SkString("sk_InvocationID")); |
| if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) { |
| SkString invokeFn; |
| this->emitFunction(kVoid_GrSLType, "invoke", 0, nullptr, this->code().c_str(), &invokeFn); |
| this->code().printf("for (sk_InvocationID = 0; sk_InvocationID < %i; ++sk_InvocationID) {" |
| "%s();" |
| "EndPrimitive();" |
| "}", fNumInvocations, invokeFn.c_str()); |
| } else { |
| this->codePrependf("sk_InvocationID = gl_InvocationID;"); |
| } |
| } |