Home | History | Annotate | Download | only in glsl
      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 "GrGLSLGeometryProcessor.h"
      9 
     10 #include "GrCoordTransform.h"
     11 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     12 #include "glsl/GrGLSLUniformHandler.h"
     13 #include "glsl/GrGLSLVarying.h"
     14 #include "glsl/GrGLSLVertexGeoBuilder.h"
     15 
     16 void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
     17     GrGPArgs gpArgs;
     18     this->onEmitCode(args, &gpArgs);
     19 
     20     GrGLSLVertexBuilder* vBuilder = args.fVertBuilder;
     21     if (!args.fGP.willUseGeoShader()) {
     22         // Emit the vertex position to the hardware in the normalized window coordinates it expects.
     23         SkASSERT(kFloat2_GrSLType == gpArgs.fPositionVar.getType() ||
     24                  kFloat3_GrSLType == gpArgs.fPositionVar.getType());
     25         vBuilder->emitNormalizedSkPosition(gpArgs.fPositionVar.c_str(), args.fRTAdjustName,
     26                                            gpArgs.fPositionVar.getType());
     27         if (kFloat2_GrSLType == gpArgs.fPositionVar.getType()) {
     28             args.fVaryingHandler->setNoPerspective();
     29         }
     30     } else {
     31         // Since we have a geometry shader, leave the vertex position in Skia device space for now.
     32         // The geometry Shader will operate in device space, and then convert the final positions to
     33         // normalized hardware window coordinates under the hood, once everything else has finished.
     34         // The subclass must call setNoPerspective on the varying handler, if applicable.
     35         vBuilder->codeAppendf("sk_Position = float4(%s", gpArgs.fPositionVar.c_str());
     36         switch (gpArgs.fPositionVar.getType()) {
     37             case kFloat_GrSLType:
     38                 vBuilder->codeAppend(", 0"); // fallthru.
     39             case kFloat2_GrSLType:
     40                 vBuilder->codeAppend(", 0"); // fallthru.
     41             case kFloat3_GrSLType:
     42                 vBuilder->codeAppend(", 1"); // fallthru.
     43             case kFloat4_GrSLType:
     44                 vBuilder->codeAppend(");");
     45                 break;
     46             default:
     47                 SK_ABORT("Invalid position var type");
     48                 break;
     49         }
     50     }
     51 }
     52 
     53 void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
     54                                              GrGLSLVaryingHandler* varyingHandler,
     55                                              GrGLSLUniformHandler* uniformHandler,
     56                                              const GrShaderVar& localCoordsVar,
     57                                              const SkMatrix& localMatrix,
     58                                              FPCoordTransformHandler* handler) {
     59     SkASSERT(GrSLTypeIsFloatType(localCoordsVar.getType()));
     60     SkASSERT(2 == GrSLTypeVecLength(localCoordsVar.getType()) ||
     61              3 == GrSLTypeVecLength(localCoordsVar.getType()));
     62 
     63     bool threeComponentLocalCoords = 3 == GrSLTypeVecLength(localCoordsVar.getType());
     64     SkString localCoords;
     65     if (threeComponentLocalCoords) {
     66         localCoords = localCoordsVar.getName();
     67     } else {
     68         localCoords.printf("float3(%s, 1)", localCoordsVar.c_str());
     69     }
     70     int i = 0;
     71     while (const GrCoordTransform* coordTransform = handler->nextCoordTransform()) {
     72         SkString strUniName;
     73         strUniName.printf("CoordTransformMatrix_%d", i);
     74         const char* uniName;
     75         fInstalledTransforms.push_back().fHandle = uniformHandler->addUniform(kVertex_GrShaderFlag,
     76                                                                               kFloat3x3_GrSLType,
     77                                                                               strUniName.c_str(),
     78                                                                               &uniName).toIndex();
     79         GrSLType varyingType = kFloat2_GrSLType;
     80         if (localMatrix.hasPerspective() || coordTransform->getMatrix().hasPerspective()
     81             || threeComponentLocalCoords) {
     82             varyingType = kFloat3_GrSLType;
     83         }
     84         SkString strVaryingName;
     85         strVaryingName.printf("TransformedCoords_%d", i);
     86         GrGLSLVarying v(varyingType);
     87         varyingHandler->addVarying(strVaryingName.c_str(), &v);
     88 
     89         handler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
     90 
     91         if (kFloat2_GrSLType == varyingType) {
     92             vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), uniName, localCoords.c_str());
     93         } else {
     94             vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, localCoords.c_str());
     95         }
     96         ++i;
     97     }
     98 }
     99 
    100 void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix,
    101                                                      const GrGLSLProgramDataManager& pdman,
    102                                                      FPCoordTransformIter* transformIter) {
    103     int i = 0;
    104     while (const GrCoordTransform* coordTransform = transformIter->next()) {
    105         const SkMatrix& m = GetTransformMatrix(localMatrix, *coordTransform);
    106         if (!fInstalledTransforms[i].fCurrentValue.cheapEqualTo(m)) {
    107             pdman.setSkMatrix(fInstalledTransforms[i].fHandle.toIndex(), m);
    108             fInstalledTransforms[i].fCurrentValue = m;
    109         }
    110         ++i;
    111     }
    112     SkASSERT(i == fInstalledTransforms.count());
    113 }
    114 
    115 void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
    116                                                   GrGPArgs* gpArgs,
    117                                                   const char* posName) {
    118     gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
    119     vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
    120 }
    121 
    122 void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
    123                                                   GrGLSLUniformHandler* uniformHandler,
    124                                                   GrGPArgs* gpArgs,
    125                                                   const char* posName,
    126                                                   const SkMatrix& mat,
    127                                                   UniformHandle* viewMatrixUniform) {
    128     if (mat.isIdentity()) {
    129         gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
    130         vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
    131     } else {
    132         const char* viewMatrixName;
    133         *viewMatrixUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
    134                                                         kFloat3x3_GrSLType,
    135                                                         "uViewM",
    136                                                         &viewMatrixName);
    137         if (!mat.hasPerspective()) {
    138             gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
    139             vertBuilder->codeAppendf("float2 %s = (%s * float3(%s, 1)).xy;",
    140                                      gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
    141         } else {
    142             gpArgs->fPositionVar.set(kFloat3_GrSLType, "pos3");
    143             vertBuilder->codeAppendf("float3 %s = %s * float3(%s, 1);",
    144                                      gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
    145         }
    146     }
    147 }
    148