Home | History | Annotate | Download | only in builders
      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 "GrGLVertexShaderBuilder.h"
      9 #include "GrGLFullProgramBuilder.h"
     10 #include "GrGLShaderStringBuilder.h"
     11 #include "../GrGpuGL.h"
     12 #include "../../GrOptDrawState.h"
     13 
     14 #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
     15 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
     16 
     17 namespace {
     18 inline const char* color_attribute_name() { return "inColor"; }
     19 inline const char* coverage_attribute_name() { return "inCoverage"; }
     20 }
     21 
     22 GrGLVertexShaderBuilder::GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program)
     23     : INHERITED(program)
     24     , fPositionVar(NULL)
     25     , fLocalCoordsVar(NULL) {
     26 }
     27 bool GrGLVertexShaderBuilder::addAttribute(const GrShaderVar& var) {
     28     SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier());
     29     for (int i = 0; i < fInputs.count(); ++i) {
     30         const GrGLShaderVar& attr = fInputs[i];
     31         // if attribute already added, don't add it again
     32         if (attr.getName().equals(var.getName())) {
     33             return false;
     34         }
     35     }
     36     fInputs.push_back(var);
     37     return true;
     38 }
     39 
     40 void GrGLVertexShaderBuilder::emitAttributes(const GrGeometryProcessor& gp) {
     41     const GrGeometryProcessor::VertexAttribArray& vars = gp.getVertexAttribs();
     42     int numAttributes = vars.count();
     43     for (int a = 0; a < numAttributes; ++a) {
     44         this->addAttribute(vars[a]);
     45     }
     46 }
     47 
     48 void GrGLVertexShaderBuilder::addVarying(GrSLType type, const char* name, const char** vsOutName) {
     49     fOutputs.push_back();
     50     fOutputs.back().setType(type);
     51     fOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
     52     fProgramBuilder->nameVariable(fOutputs.back().accessName(), 'v', name);
     53 
     54     if (vsOutName) {
     55         *vsOutName = fOutputs.back().getName().c_str();
     56     }
     57 }
     58 
     59 
     60 void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) {
     61     const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
     62     GrGpuGL* gpu = fProgramBuilder->gpu();
     63 
     64     // Bind the attrib locations to same values for all shaders
     65     SkASSERT(-1 != header.fPositionAttributeIndex);
     66     GL_CALL(BindAttribLocation(programId,
     67                                header.fPositionAttributeIndex,
     68                                fPositionVar->c_str()));
     69     if (-1 != header.fLocalCoordAttributeIndex) {
     70         GL_CALL(BindAttribLocation(programId,
     71                                    header.fLocalCoordAttributeIndex,
     72                                    fLocalCoordsVar->c_str()));
     73     }
     74     if (-1 != header.fColorAttributeIndex) {
     75         GL_CALL(BindAttribLocation(programId,
     76                                    header.fColorAttributeIndex,
     77                                    color_attribute_name()));
     78     }
     79     if (-1 != header.fCoverageAttributeIndex) {
     80         GL_CALL(BindAttribLocation(programId,
     81                                    header.fCoverageAttributeIndex,
     82                                    coverage_attribute_name()));
     83     }
     84 
     85     // We pull the current state of attributes off of drawstate's optimized state and bind them in
     86     // order. This assumes that the drawState has not changed since we called flushGraphicsState()
     87     // higher up in the stack.
     88     const GrDrawTargetCaps* caps = fProgramBuilder->gpu()->caps();
     89     const GrDrawState& drawState = *fProgramBuilder->gpu()->drawState();
     90     SkAutoTUnref<GrOptDrawState> optState(drawState.createOptState(*caps));
     91     const GrVertexAttrib* vaPtr = optState->getVertexAttribs();
     92     const int vaCount = optState->getVertexAttribCount();
     93 
     94     int i = fEffectAttribOffset;
     95     for (int index = 0; index < vaCount; index++) {
     96         if (kGeometryProcessor_GrVertexAttribBinding != vaPtr[index].fBinding) {
     97             continue;
     98         }
     99         SkASSERT(index != header.fPositionAttributeIndex &&
    100                  index != header.fLocalCoordAttributeIndex &&
    101                  index != header.fColorAttributeIndex &&
    102                  index != header.fCoverageAttributeIndex);
    103         // We should never find another effect attribute if we have bound everything
    104         SkASSERT(i < fInputs.count());
    105         GL_CALL(BindAttribLocation(programId, index, fInputs[i].c_str()));
    106         i++;
    107     }
    108     // Make sure we bound everything
    109     SkASSERT(fInputs.count() == i);
    110 }
    111 
    112 bool GrGLVertexShaderBuilder::compileAndAttachShaders(GrGLuint programId,
    113         SkTDArray<GrGLuint>* shaderIds) const {
    114     GrGpuGL* gpu = fProgramBuilder->gpu();
    115     const GrGLContext& glCtx = gpu->glContext();
    116     const GrGLContextInfo& ctxInfo = gpu->ctxInfo();
    117     SkString vertShaderSrc(GrGetGLSLVersionDecl(ctxInfo));
    118     fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &vertShaderSrc);
    119     fProgramBuilder->appendDecls(fInputs, &vertShaderSrc);
    120     fProgramBuilder->appendDecls(fOutputs, &vertShaderSrc);
    121     vertShaderSrc.append("void main() {");
    122     vertShaderSrc.append(fCode);
    123     vertShaderSrc.append("}\n");
    124     GrGLuint vertShaderId = GrGLCompileAndAttachShader(glCtx, programId,
    125                                                        GR_GL_VERTEX_SHADER, vertShaderSrc,
    126                                                        gpu->gpuStats());
    127     if (!vertShaderId) {
    128         return false;
    129     }
    130     *shaderIds->append() = vertShaderId;
    131     return true;
    132 }
    133 
    134 void GrGLVertexShaderBuilder::emitCodeAfterEffects() {
    135     const char* rtAdjustName;
    136     fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
    137         fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
    138                              kVec4f_GrSLType,
    139                              "rtAdjustment",
    140                              &rtAdjustName);
    141 
    142     // Transform from Skia's device coords to GL's normalized device coords.
    143     this->codeAppendf(
    144         "gl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);",
    145         rtAdjustName, rtAdjustName);
    146 }
    147 
    148 void GrGLVertexShaderBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
    149     const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
    150 
    151     fPositionVar = &fInputs.push_back();
    152     fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition");
    153     if (-1 != header.fLocalCoordAttributeIndex) {
    154         fLocalCoordsVar = &fInputs.push_back();
    155         fLocalCoordsVar->set(kVec2f_GrSLType,
    156                              GrGLShaderVar::kAttribute_TypeModifier,
    157                              "inLocalCoords");
    158     } else {
    159         fLocalCoordsVar = fPositionVar;
    160     }
    161 
    162     const char* viewMName;
    163     fProgramBuilder->fUniformHandles.fViewMatrixUni =
    164             fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
    165                                  kMat33f_GrSLType,
    166                                  "ViewM",
    167                                  &viewMName);
    168 
    169     // Transform the position into Skia's device coords.
    170     this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);",
    171                       viewMName, fPositionVar->c_str());
    172 
    173     // we output point size in the GS if present
    174     if (header.fEmitsPointSize
    175 #if GR_GL_EXPERIMENTAL_GS
    176         && !header.fExperimentalGS
    177 #endif
    178         ) {
    179         this->codeAppend("gl_PointSize = 1.0;");
    180     }
    181 
    182     if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
    183         this->addAttribute(GrShaderVar(color_attribute_name(),
    184                                        kVec4f_GrSLType,
    185                                        GrShaderVar::kAttribute_TypeModifier));
    186         const char *vsName, *fsName;
    187         fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
    188         this->codeAppendf("%s = %s;", vsName, color_attribute_name());
    189         *color = fsName;
    190     }
    191 
    192     if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
    193         this->addAttribute(GrShaderVar(coverage_attribute_name(),
    194                                        kVec4f_GrSLType,
    195                                        GrShaderVar::kAttribute_TypeModifier));
    196         const char *vsName, *fsName;
    197         fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
    198         this->codeAppendf("%s = %s;", vsName, coverage_attribute_name());
    199         *coverage = fsName;
    200     }
    201     fEffectAttribOffset = fInputs.count();
    202 }
    203