blob: 01f223f4b3d16a172c7d6070d1e4c59ef7779972 [file] [log] [blame]
/*
* 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;");
}
}