| Index: src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
|
| diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6abc0857060f66fad7f07a353d7884a75a8317cb
|
| --- /dev/null
|
| +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
|
| @@ -0,0 +1,200 @@
|
| +/*
|
| + * 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 "GrGLVertexShaderBuilder.h"
|
| +#include "GrGLProgramBuilder.h"
|
| +#include "GrGLShaderStringBuilder.h"
|
| +#include "../GrGpuGL.h"
|
| +
|
| +#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
|
| +#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
|
| +
|
| +namespace {
|
| +inline const char* color_attribute_name() { return "aColor"; }
|
| +inline const char* coverage_attribute_name() { return "aCoverage"; }
|
| +}
|
| +
|
| +GrGLVertexShaderBuilder::GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program)
|
| + : INHERITED(program)
|
| + , fPositionVar(NULL)
|
| + , fLocalCoordsVar(NULL) {
|
| +}
|
| +bool GrGLVertexShaderBuilder::addAttribute(GrSLType type, const char* name) {
|
| + for (int i = 0; i < fInputs.count(); ++i) {
|
| + const GrGLShaderVar& attr = fInputs[i];
|
| + // if attribute already added, don't add it again
|
| + if (attr.getName().equals(name)) {
|
| + return false;
|
| + }
|
| + }
|
| + fInputs.push_back().set(type, GrGLShaderVar::kAttribute_TypeModifier, name);
|
| + return true;
|
| +}
|
| +
|
| +bool GrGLVertexShaderBuilder::addEffectAttribute(int attributeIndex,
|
| + GrSLType type,
|
| + const SkString& name) {
|
| + if (!this->addAttribute(type, name.c_str())) {
|
| + return false;
|
| + }
|
| +
|
| + fEffectAttributes.push_back().set(attributeIndex, name);
|
| + return true;
|
| +}
|
| +
|
| +void GrGLVertexShaderBuilder::emitAttributes(const GrEffectStage& stage) {
|
| + int numAttributes = stage.getVertexAttribIndexCount();
|
| + const int* attributeIndices = stage.getVertexAttribIndices();
|
| + for (int a = 0; a < numAttributes; ++a) {
|
| + // TODO: Make addAttribute mangle the name.
|
| + SkString attributeName("aAttr");
|
| + attributeName.appendS32(attributeIndices[a]);
|
| + this->addEffectAttribute(attributeIndices[a],
|
| + stage.getEffect()->vertexAttribType(a),
|
| + attributeName);
|
| + }
|
| +}
|
| +
|
| +const SkString* GrGLVertexShaderBuilder::getEffectAttributeName(int attributeIndex) const {
|
| + const AttributePair* attribEnd = fEffectAttributes.end();
|
| + for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) {
|
| + if (attrib->fIndex == attributeIndex) {
|
| + return &attrib->fName;
|
| + }
|
| + }
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +void GrGLVertexShaderBuilder::addVarying(GrSLType type, const char* name, const char** vsOutName) {
|
| + fOutputs.push_back();
|
| + fOutputs.back().setType(type);
|
| + fOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
|
| + fProgramBuilder->nameVariable(fOutputs.back().accessName(), 'v', name);
|
| +
|
| + if (vsOutName) {
|
| + *vsOutName = fOutputs.back().getName().c_str();
|
| + }
|
| +}
|
| +
|
| +
|
| +void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) {
|
| + const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
|
| + GrGpuGL* gpu = fProgramBuilder->gpu();
|
| +
|
| + // Bind the attrib locations to same values for all shaders
|
| + SkASSERT(-1 != header.fPositionAttributeIndex);
|
| + GL_CALL(BindAttribLocation(programId,
|
| + header.fPositionAttributeIndex,
|
| + fPositionVar->c_str()));
|
| + if (-1 != header.fLocalCoordAttributeIndex) {
|
| + GL_CALL(BindAttribLocation(programId,
|
| + header.fLocalCoordAttributeIndex,
|
| + fLocalCoordsVar->c_str()));
|
| + }
|
| + if (-1 != header.fColorAttributeIndex) {
|
| + GL_CALL(BindAttribLocation(programId,
|
| + header.fColorAttributeIndex,
|
| + color_attribute_name()));
|
| + }
|
| + if (-1 != header.fCoverageAttributeIndex) {
|
| + GL_CALL(BindAttribLocation(programId,
|
| + header.fCoverageAttributeIndex,
|
| + coverage_attribute_name()));
|
| + }
|
| +
|
| + const AttributePair* attribEnd = fEffectAttributes.end();
|
| + for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) {
|
| + GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str()));
|
| + }
|
| +}
|
| +
|
| +bool GrGLVertexShaderBuilder::compileAndAttachShaders(GrGLuint programId,
|
| + SkTDArray<GrGLuint>* shaderIds) const {
|
| + GrGpuGL* gpu = fProgramBuilder->gpu();
|
| + const GrGLContext& glCtx = gpu->glContext();
|
| + const GrGLContextInfo& ctxInfo = gpu->ctxInfo();
|
| + SkString vertShaderSrc(GrGetGLSLVersionDecl(ctxInfo));
|
| + fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &vertShaderSrc);
|
| + fProgramBuilder->appendDecls(fInputs, &vertShaderSrc);
|
| + fProgramBuilder->appendDecls(fOutputs, &vertShaderSrc);
|
| + vertShaderSrc.append("void main() {\n");
|
| + vertShaderSrc.append(fCode);
|
| + vertShaderSrc.append("}\n");
|
| + GrGLuint vertShaderId = GrGLCompileAndAttachShader(glCtx, programId,
|
| + GR_GL_VERTEX_SHADER, vertShaderSrc);
|
| + if (!vertShaderId) {
|
| + return false;
|
| + }
|
| + *shaderIds->append() = vertShaderId;
|
| + return true;
|
| +}
|
| +
|
| +void GrGLVertexShaderBuilder::emitCodeAfterEffects() {
|
| + const char* rtAdjustName;
|
| + fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
|
| + fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
| + kVec4f_GrSLType,
|
| + "rtAdjustment",
|
| + &rtAdjustName);
|
| +
|
| + // Transform from Skia's device coords to GL's normalized device coords.
|
| + this->codeAppendf(
|
| + "\tgl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);\n",
|
| + rtAdjustName, rtAdjustName);
|
| +}
|
| +
|
| +void GrGLVertexShaderBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
|
| + const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
|
| +
|
| + fPositionVar = &fInputs.push_back();
|
| + fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
|
| + if (-1 != header.fLocalCoordAttributeIndex) {
|
| + fLocalCoordsVar = &fInputs.push_back();
|
| + fLocalCoordsVar->set(kVec2f_GrSLType,
|
| + GrGLShaderVar::kAttribute_TypeModifier,
|
| + "aLocalCoords");
|
| + } else {
|
| + fLocalCoordsVar = fPositionVar;
|
| + }
|
| +
|
| + const char* viewMName;
|
| + fProgramBuilder->fUniformHandles.fViewMatrixUni =
|
| + fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
| + kMat33f_GrSLType,
|
| + "ViewM",
|
| + &viewMName);
|
| +
|
| + // Transform the position into Skia's device coords.
|
| + this->codeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n",
|
| + viewMName, fPositionVar->c_str());
|
| +
|
| + // we output point size in the GS if present
|
| + if (header.fEmitsPointSize
|
| +#if GR_GL_EXPERIMENTAL_GS
|
| + && !header.fExperimentalGS
|
| +#endif
|
| + ) {
|
| + this->codeAppend("\tgl_PointSize = 1.0;\n");
|
| + }
|
| +
|
| + if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
|
| + this->addAttribute(kVec4f_GrSLType, color_attribute_name());
|
| + const char *vsName, *fsName;
|
| + fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
|
| + this->codeAppendf("\t%s = %s;\n", vsName, color_attribute_name());
|
| + *color = fsName;
|
| + }
|
| +
|
| + if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
|
| + this->addAttribute(kVec4f_GrSLType, coverage_attribute_name());
|
| + const char *vsName, *fsName;
|
| + fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
|
| + this->codeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name());
|
| + *coverage = fsName;
|
| + }
|
| +}
|
|
|