/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLSLVertexGeoBuilder.h"
#include "GrGLSLProgramBuilder.h"
#include "GrGLSLVarying.h"
#include "GrTypes.h"
void GrGLSLVertexGeoBuilder::emitNormalizedSkPosition(SkString* out, const char* devPos,
const char* rtAdjustName,
GrSLType devPosType) {
if (this->getProgramBuilder()->desc()->header().fSnapVerticesToPixelCenters) {
if (kFloat3_GrSLType == devPosType) {
const char* p = devPos;
out->appendf("{float2 _posTmp = float2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p);
} else {
SkASSERT(kFloat2_GrSLType == devPosType);
out->appendf("{float2 _posTmp = %s;", devPos);
}
out->appendf("_posTmp = floor(_posTmp) + half2(0.5, 0.5);"
"sk_Position = float4(_posTmp, 0, 1);}");
} else if (kFloat3_GrSLType == devPosType) {
out->appendf("sk_Position = float4(%s.x , %s.y, 0, %s.z);",
devPos, devPos, devPos);
} else {
SkASSERT(kFloat2_GrSLType == devPosType);
out->appendf("sk_Position = float4(%s.x , %s.y, 0, 1);",
devPos, devPos);
}
}
void GrGLSLVertexBuilder::onFinalize() {
// We could have the GrGeometryProcessor do this, but its just easier to have it performed
// here. If we ever need to set variable pointsize, then we can reinvestigate.
if (this->getProgramBuilder()->desc()->header().fHasPointSize) {
this->codeAppend("sk_PointSize = 1.0;");
}
fProgramBuilder->varyingHandler()->getVertexDecls(&this->inputs(), &this->outputs());
}
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";
}
SK_ABORT("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";
}
SK_ABORT("invalid output type");
return "unknown_output";
}
void GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType, int maxVertices,
int numInvocations) {
SkASSERT(!this->isConfigured());
fNumInvocations = numInvocations;
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::emitVertex(SkString* out, const char* devPos, const char* rtAdjustName,
GrSLType devPosType) {
this->emitNormalizedSkPosition(out, devPos, rtAdjustName, devPosType);
out->append("EmitVertex();");
}
void GrGLSLGeometryBuilder::endPrimitive() {
this->codeAppend("EndPrimitive();");
}
void GrGLSLGeometryBuilder::onFinalize() {
SkASSERT(this->isConfigured());
fProgramBuilder->varyingHandler()->getGeomDecls(&this->inputs(), &this->outputs());
}