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             varyingType = kFloat3_GrSLType;
     82         }
     83         SkString strVaryingName;
     84         strVaryingName.printf("TransformedCoords_%d", i);
     85         GrGLSLVarying v(varyingType);
     86         varyingHandler->addVarying(strVaryingName.c_str(), &v);
     87 
     88         handler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
     89 
     90         if (kFloat2_GrSLType == varyingType) {
     91             vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), uniName, localCoords.c_str());
     92             if (threeComponentLocalCoords) {
     93                 vb->codeAppendf("%s /= %s.z;", v.vsOut(), localCoords.c_str());
     94             }
     95         } else {
     96             vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, localCoords.c_str());
     97         }
     98         ++i;
     99     }
    100 }
    101 
    102 void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix,
    103                                                      const GrGLSLProgramDataManager& pdman,
    104                                                      FPCoordTransformIter* transformIter) {
    105     int i = 0;
    106     while (const GrCoordTransform* coordTransform = transformIter->next()) {
    107         const SkMatrix& m = GetTransformMatrix(localMatrix, *coordTransform);
    108         if (!fInstalledTransforms[i].fCurrentValue.cheapEqualTo(m)) {
    109             pdman.setSkMatrix(fInstalledTransforms[i].fHandle.toIndex(), m);
    110             fInstalledTransforms[i].fCurrentValue = m;
    111         }
    112         ++i;
    113     }
    114     SkASSERT(i == fInstalledTransforms.count());
    115 }
    116 
    117 void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
    118                                                   GrGPArgs* gpArgs,
    119                                                   const char* posName) {
    120     gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
    121     vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
    122 }
    123 
    124 void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
    125                                                   GrGLSLUniformHandler* uniformHandler,
    126                                                   GrGPArgs* gpArgs,
    127                                                   const char* posName,
    128                                                   const SkMatrix& mat,
    129                                                   UniformHandle* viewMatrixUniform) {
    130     if (mat.isIdentity()) {
    131         gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
    132         vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
    133     } else {
    134         const char* viewMatrixName;
    135         *viewMatrixUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
    136                                                         kFloat3x3_GrSLType,
    137                                                         "uViewM",
    138                                                         &viewMatrixName);
    139         if (!mat.hasPerspective()) {
    140             gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
    141             vertBuilder->codeAppendf("float2 %s = (%s * float3(%s, 1)).xy;",
    142                                      gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
    143         } else {
    144             gpArgs->fPositionVar.set(kFloat3_GrSLType, "pos3");
    145             vertBuilder->codeAppendf("float3 %s = %s * float3(%s, 1);",
    146                                      gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
    147         }
    148     }
    149 }
    150