Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2012 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 "gl/GrGLShaderBuilder.h"
      9 #include "gl/GrGLProgram.h"
     10 #include "gl/GrGLUniformHandle.h"
     11 #include "GrDrawEffect.h"
     12 #include "GrTexture.h"
     13 
     14 // number of each input/output type in a single allocation block
     15 static const int kVarsPerBlock = 8;
     16 
     17 // except FS outputs where we expect 2 at most.
     18 static const int kMaxFSOutputs = 2;
     19 
     20 // ES2 FS only guarantees mediump and lowp support
     21 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
     22 
     23 typedef GrGLUniformManager::UniformHandle UniformHandle;
     24 ///////////////////////////////////////////////////////////////////////////////
     25 
     26 namespace {
     27 
     28 inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) {
     29     if (kVec2f_GrSLType == type) {
     30         return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D";
     31     } else {
     32         GrAssert(kVec3f_GrSLType == type);
     33         return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj";
     34     }
     35 }
     36 
     37 /**
     38  * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
     39  * present in the texture's config. swizzleComponentMask indicates the channels present in the
     40  * shader swizzle.
     41  */
     42 inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
     43                                              uint32_t configComponentMask,
     44                                              uint32_t swizzleComponentMask) {
     45     if (caps.textureSwizzleSupport()) {
     46         // Any remapping is handled using texture swizzling not shader modifications.
     47         return false;
     48     }
     49     // check if the texture is alpha-only
     50     if (kA_GrColorComponentFlag == configComponentMask) {
     51         if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
     52             // we must map the swizzle 'a's to 'r'.
     53             return true;
     54         }
     55         if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
     56             // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
     57             // alpha-only textures smear alpha across all four channels when read.
     58             return true;
     59         }
     60     }
     61     return false;
     62 }
     63 
     64 void append_swizzle(SkString* outAppend,
     65                     const GrGLShaderBuilder::TextureSampler& texSampler,
     66                     const GrGLCaps& caps) {
     67     const char* swizzle = texSampler.swizzle();
     68     char mangledSwizzle[5];
     69 
     70     // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle
     71     // is available.
     72     if (!caps.textureSwizzleSupport() &&
     73         (kA_GrColorComponentFlag == texSampler.configComponentMask())) {
     74         char alphaChar = caps.textureRedSupport() ? 'r' : 'a';
     75         int i;
     76         for (i = 0; '\0' != swizzle[i]; ++i) {
     77             mangledSwizzle[i] = alphaChar;
     78         }
     79         mangledSwizzle[i] ='\0';
     80         swizzle = mangledSwizzle;
     81     }
     82     // For shader prettiness we omit the swizzle rather than appending ".rgba".
     83     if (memcmp(swizzle, "rgba", 4)) {
     84         outAppend->appendf(".%s", swizzle);
     85     }
     86 }
     87 
     88 }
     89 
     90 static const char kDstCopyColorName[] = "_dstColor";
     91 
     92 ///////////////////////////////////////////////////////////////////////////////
     93 
     94 GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
     95                                      GrGLUniformManager& uniformManager,
     96                                      const GrGLProgramDesc& desc)
     97     : fUniforms(kVarsPerBlock)
     98     , fVSAttrs(kVarsPerBlock)
     99     , fVSOutputs(kVarsPerBlock)
    100     , fGSInputs(kVarsPerBlock)
    101     , fGSOutputs(kVarsPerBlock)
    102     , fFSInputs(kVarsPerBlock)
    103     , fFSOutputs(kMaxFSOutputs)
    104     , fCtxInfo(ctxInfo)
    105     , fUniformManager(uniformManager)
    106     , fFSFeaturesAddedMask(0)
    107 #if GR_GL_EXPERIMENTAL_GS
    108     , fUsesGS(SkToBool(desc.getHeader().fExperimentalGS))
    109 #else
    110     , fUsesGS(false)
    111 #endif
    112     , fSetupFragPosition(false)
    113     , fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle)
    114     , fDstCopyTopLeftUniform (GrGLUniformManager::kInvalidUniformHandle)
    115     , fDstCopyScaleUniform (GrGLUniformManager::kInvalidUniformHandle)
    116     , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) {
    117 
    118     const GrGLProgramDesc::KeyHeader& header = desc.getHeader();
    119 
    120     fPositionVar = &fVSAttrs.push_back();
    121     fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
    122     if (-1 != header.fLocalCoordAttributeIndex) {
    123         fLocalCoordsVar = &fVSAttrs.push_back();
    124         fLocalCoordsVar->set(kVec2f_GrSLType,
    125                              GrGLShaderVar::kAttribute_TypeModifier,
    126                              "aLocalCoords");
    127     } else {
    128         fLocalCoordsVar = fPositionVar;
    129     }
    130     // Emit code to read the dst copy textue if necessary.
    131     if (kNoDstRead_DstReadKey != header.fDstReadKey &&
    132         GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) {
    133         bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
    134         const char* dstCopyTopLeftName;
    135         const char* dstCopyCoordScaleName;
    136         uint32_t configMask;
    137         if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
    138             configMask = kA_GrColorComponentFlag;
    139         } else {
    140             configMask = kRGBA_GrColorComponentFlags;
    141         }
    142         fDstCopySampler.init(this, configMask, "rgba", 0);
    143 
    144         fDstCopyTopLeftUniform = this->addUniform(kFragment_ShaderType,
    145                                                   kVec2f_GrSLType,
    146                                                   "DstCopyUpperLeft",
    147                                                   &dstCopyTopLeftName);
    148         fDstCopyScaleUniform     = this->addUniform(kFragment_ShaderType,
    149                                                     kVec2f_GrSLType,
    150                                                     "DstCopyCoordScale",
    151                                                     &dstCopyCoordScaleName);
    152         const char* fragPos = this->fragmentPosition();
    153         this->fsCodeAppend("\t// Read color from copy of the destination.\n");
    154         this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n",
    155                             fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
    156         if (!topDown) {
    157             this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n");
    158         }
    159         this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName);
    160         this->appendTextureLookup(kFragment_ShaderType, fDstCopySampler, "_dstTexCoord");
    161         this->fsCodeAppend(";\n\n");
    162     }
    163 }
    164 
    165 bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) {
    166     switch (feature) {
    167         case kStandardDerivatives_GLSLFeature:
    168             if (!fCtxInfo.caps()->shaderDerivativeSupport()) {
    169                 return false;
    170             }
    171             if (kES2_GrGLBinding == fCtxInfo.binding()) {
    172                 this->addFSFeature(1 << kStandardDerivatives_GLSLFeature,
    173                                    "GL_OES_standard_derivatives");
    174             }
    175             return true;
    176         default:
    177             GrCrash("Unexpected GLSLFeature requested.");
    178             return false;
    179     }
    180 }
    181 
    182 bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) {
    183     switch (feature) {
    184         case kFragCoordConventions_GLSLPrivateFeature:
    185             if (!fCtxInfo.caps()->fragCoordConventionsSupport()) {
    186                 return false;
    187             }
    188             if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) {
    189                 this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
    190                                    "GL_ARB_fragment_coord_conventions");
    191             }
    192             return true;
    193         case kEXTShaderFramebufferFetch_GLSLPrivateFeature:
    194             if (GrGLCaps::kEXT_FBFetchType != fCtxInfo.caps()->fbFetchType()) {
    195                 return false;
    196             }
    197             this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature,
    198                                "GL_EXT_shader_framebuffer_fetch");
    199             return true;
    200         case kNVShaderFramebufferFetch_GLSLPrivateFeature:
    201             if (GrGLCaps::kNV_FBFetchType != fCtxInfo.caps()->fbFetchType()) {
    202                 return false;
    203             }
    204             this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature,
    205                                "GL_NV_shader_framebuffer_fetch");
    206             return true;
    207         default:
    208             GrCrash("Unexpected GLSLPrivateFeature requested.");
    209             return false;
    210     }
    211 }
    212 
    213 void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) {
    214     if (!(featureBit & fFSFeaturesAddedMask)) {
    215         fFSExtensions.appendf("#extension %s: require\n", extensionName);
    216         fFSFeaturesAddedMask |= featureBit;
    217     }
    218 }
    219 
    220 void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) {
    221     if ('\0' == prefix) {
    222         *out = name;
    223     } else {
    224         out->printf("%c%s", prefix, name);
    225     }
    226     if (fCodeStage.inStageCode()) {
    227         if (out->endsWith('_')) {
    228             // Names containing "__" are reserved.
    229             out->append("x");
    230         }
    231         out->appendf("_Stage%d", fCodeStage.stageIndex());
    232     }
    233 }
    234 
    235 const char* GrGLShaderBuilder::dstColor() {
    236     if (fCodeStage.inStageCode()) {
    237         const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
    238         if (!effect->willReadDstColor()) {
    239             GrDebugCrash("GrGLEffect asked for dst color but its generating GrEffect "
    240                          "did not request access.");
    241             return "";
    242         }
    243     }
    244     static const char kFBFetchColorName[] = "gl_LastFragData[0]";
    245     GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType();
    246     if (GrGLCaps::kEXT_FBFetchType == fetchType) {
    247         SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature));
    248         return kFBFetchColorName;
    249     } else if (GrGLCaps::kNV_FBFetchType == fetchType) {
    250         SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature));
    251         return kFBFetchColorName;
    252     } else if (fDstCopySampler.isInitialized()) {
    253         return kDstCopyColorName;
    254     } else {
    255         return "";
    256     }
    257 }
    258 
    259 void GrGLShaderBuilder::codeAppendf(ShaderType type, const char format[], va_list args) {
    260     SkString* string = NULL;
    261     switch (type) {
    262         case kVertex_ShaderType:
    263             string = &fVSCode;
    264             break;
    265         case kGeometry_ShaderType:
    266             string = &fGSCode;
    267             break;
    268         case kFragment_ShaderType:
    269             string = &fFSCode;
    270             break;
    271         default:
    272             GrCrash("Invalid shader type");
    273     }
    274     string->appendf(format, args);
    275 }
    276 
    277 void GrGLShaderBuilder::codeAppend(ShaderType type, const char* str) {
    278     SkString* string = NULL;
    279     switch (type) {
    280         case kVertex_ShaderType:
    281             string = &fVSCode;
    282             break;
    283         case kGeometry_ShaderType:
    284             string = &fGSCode;
    285             break;
    286         case kFragment_ShaderType:
    287             string = &fFSCode;
    288             break;
    289         default:
    290             GrCrash("Invalid shader type");
    291     }
    292     string->append(str);
    293 }
    294 
    295 void GrGLShaderBuilder::appendTextureLookup(SkString* out,
    296                                             const GrGLShaderBuilder::TextureSampler& sampler,
    297                                             const char* coordName,
    298                                             GrSLType varyingType) const {
    299     GrAssert(NULL != coordName);
    300 
    301     out->appendf("%s(%s, %s)",
    302                  sample_function_name(varyingType, fCtxInfo.glslGeneration()),
    303                  this->getUniformCStr(sampler.fSamplerUniform),
    304                  coordName);
    305     append_swizzle(out, sampler, *fCtxInfo.caps());
    306 }
    307 
    308 void GrGLShaderBuilder::appendTextureLookup(ShaderType type,
    309                                             const GrGLShaderBuilder::TextureSampler& sampler,
    310                                             const char* coordName,
    311                                             GrSLType varyingType) {
    312     GrAssert(kFragment_ShaderType == type);
    313     this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType);
    314 }
    315 
    316 void GrGLShaderBuilder::appendTextureLookupAndModulate(
    317                                             ShaderType type,
    318                                             const char* modulation,
    319                                             const GrGLShaderBuilder::TextureSampler& sampler,
    320                                             const char* coordName,
    321                                             GrSLType varyingType) {
    322     GrAssert(kFragment_ShaderType == type);
    323     SkString lookup;
    324     this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
    325     GrGLSLModulatef<4>(&fFSCode, modulation, lookup.c_str());
    326 }
    327 
    328 GrBackendEffectFactory::EffectKey GrGLShaderBuilder::KeyForTextureAccess(
    329                                                             const GrTextureAccess& access,
    330                                                             const GrGLCaps& caps) {
    331     uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
    332     if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
    333         return 1;
    334     } else {
    335         return 0;
    336     }
    337 }
    338 
    339 GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
    340                                                                const GrGLCaps& caps) {
    341     uint32_t key = kYesDstRead_DstReadKeyBit;
    342     if (GrGLCaps::kNone_FBFetchType != caps.fbFetchType()) {
    343         return key;
    344     }
    345     GrAssert(NULL != dstCopy);
    346     if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) {
    347         // The fact that the config is alpha-only must be considered when generating code.
    348         key |= kUseAlphaConfig_DstReadKeyBit;
    349     }
    350     if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) {
    351         key |= kTopLeftOrigin_DstReadKeyBit;
    352     }
    353     GrAssert(static_cast<DstReadKey>(key) == key);
    354     return static_cast<DstReadKey>(key);
    355 }
    356 
    357 GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
    358                                                                         const GrGLCaps&) {
    359     if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
    360         return kTopLeftFragPosRead_FragPosKey;
    361     } else {
    362         return kBottomLeftFragPosRead_FragPosKey;
    363     }
    364 }
    365 
    366 
    367 const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) {
    368     if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) {
    369         if (caps.textureRedSupport()) {
    370             static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED };
    371             return gRedSmear;
    372         } else {
    373             static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
    374                                                     GR_GL_ALPHA, GR_GL_ALPHA };
    375             return gAlphaSmear;
    376         }
    377     } else {
    378         static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA };
    379         return gStraight;
    380     }
    381 }
    382 
    383 GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
    384                                                                      GrSLType type,
    385                                                                      const char* name,
    386                                                                      int count,
    387                                                                      const char** outName) {
    388     GrAssert(name && strlen(name));
    389     SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType);
    390     GrAssert(0 == (~kVisibilityMask & visibility));
    391     GrAssert(0 != visibility);
    392 
    393     BuilderUniform& uni = fUniforms.push_back();
    394     UniformHandle h = index_to_handle(fUniforms.count() - 1);
    395     GR_DEBUGCODE(UniformHandle h2 =)
    396     fUniformManager.appendUniform(type, count);
    397     // We expect the uniform manager to initially have no uniforms and that all uniforms are added
    398     // by this function. Therefore, the handles should match.
    399     GrAssert(h2 == h);
    400     uni.fVariable.setType(type);
    401     uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
    402     this->nameVariable(uni.fVariable.accessName(), 'u', name);
    403     uni.fVariable.setArrayCount(count);
    404     uni.fVisibility = visibility;
    405 
    406     // If it is visible in both the VS and FS, the precision must match.
    407     // We declare a default FS precision, but not a default VS. So set the var
    408     // to use the default FS precision.
    409     if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
    410         // the fragment and vertex precisions must match
    411         uni.fVariable.setPrecision(kDefaultFragmentPrecision);
    412     }
    413 
    414     if (NULL != outName) {
    415         *outName = uni.fVariable.c_str();
    416     }
    417 
    418     return h;
    419 }
    420 
    421 const GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const {
    422     return fUniforms[handle_to_index(u)].fVariable;
    423 }
    424 
    425 bool GrGLShaderBuilder::addAttribute(GrSLType type,
    426                                      const char* name) {
    427     for (int i = 0; i < fVSAttrs.count(); ++i) {
    428         const GrGLShaderVar& attr = fVSAttrs[i];
    429         // if attribute already added, don't add it again
    430         if (attr.getName().equals(name)) {
    431             GrAssert(attr.getType() == type);
    432             return false;
    433         }
    434     }
    435     fVSAttrs.push_back().set(type,
    436                              GrGLShaderVar::kAttribute_TypeModifier,
    437                              name);
    438     return true;
    439 }
    440 
    441 void GrGLShaderBuilder::addVarying(GrSLType type,
    442                                    const char* name,
    443                                    const char** vsOutName,
    444                                    const char** fsInName) {
    445     fVSOutputs.push_back();
    446     fVSOutputs.back().setType(type);
    447     fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
    448     this->nameVariable(fVSOutputs.back().accessName(), 'v', name);
    449 
    450     if (vsOutName) {
    451         *vsOutName = fVSOutputs.back().getName().c_str();
    452     }
    453     // input to FS comes either from VS or GS
    454     const SkString* fsName;
    455     if (fUsesGS) {
    456         // if we have a GS take each varying in as an array
    457         // and output as non-array.
    458         fGSInputs.push_back();
    459         fGSInputs.back().setType(type);
    460         fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
    461         fGSInputs.back().setUnsizedArray();
    462         *fGSInputs.back().accessName() = fVSOutputs.back().getName();
    463         fGSOutputs.push_back();
    464         fGSOutputs.back().setType(type);
    465         fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
    466         this->nameVariable(fGSOutputs.back().accessName(), 'g', name);
    467         fsName = fGSOutputs.back().accessName();
    468     } else {
    469         fsName = fVSOutputs.back().accessName();
    470     }
    471     fFSInputs.push_back();
    472     fFSInputs.back().setType(type);
    473     fFSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
    474     fFSInputs.back().setName(*fsName);
    475     if (fsInName) {
    476         *fsInName = fsName->c_str();
    477     }
    478 }
    479 
    480 const char* GrGLShaderBuilder::fragmentPosition() {
    481     if (fCodeStage.inStageCode()) {
    482         const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
    483         if (!effect->willReadFragmentPosition()) {
    484             GrDebugCrash("GrGLEffect asked for frag position but its generating GrEffect "
    485                          "did not request access.");
    486             return "";
    487         }
    488     }
    489     if (fTopLeftFragPosRead) {
    490         if (!fSetupFragPosition) {
    491             fFSInputs.push_back().set(kVec4f_GrSLType,
    492                                       GrGLShaderVar::kIn_TypeModifier,
    493                                       "gl_FragCoord",
    494                                       GrGLShaderVar::kDefault_Precision);
    495             fSetupFragPosition = true;
    496         }
    497         return "gl_FragCoord";
    498     } else if (fCtxInfo.caps()->fragCoordConventionsSupport()) {
    499         if (!fSetupFragPosition) {
    500             SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature));
    501             fFSInputs.push_back().set(kVec4f_GrSLType,
    502                                       GrGLShaderVar::kIn_TypeModifier,
    503                                       "gl_FragCoord",
    504                                       GrGLShaderVar::kDefault_Precision,
    505                                       GrGLShaderVar::kUpperLeft_Origin);
    506             fSetupFragPosition = true;
    507         }
    508         return "gl_FragCoord";
    509     } else {
    510         static const char* kCoordName = "fragCoordYDown";
    511         if (!fSetupFragPosition) {
    512             // temporarily change the stage index because we're inserting non-stage code.
    513             CodeStage::AutoStageRestore csar(&fCodeStage, NULL);
    514 
    515             GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform);
    516             const char* rtHeightName;
    517 
    518             fRTHeightUniform = this->addUniform(kFragment_ShaderType,
    519                                                 kFloat_GrSLType,
    520                                                 "RTHeight",
    521                                                 &rtHeightName);
    522 
    523             this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n",
    524                                    kCoordName, rtHeightName);
    525             fSetupFragPosition = true;
    526         }
    527         GrAssert(GrGLUniformManager::kInvalidUniformHandle != fRTHeightUniform);
    528         return kCoordName;
    529     }
    530 }
    531 
    532 
    533 void GrGLShaderBuilder::emitFunction(ShaderType shader,
    534                                      GrSLType returnType,
    535                                      const char* name,
    536                                      int argCnt,
    537                                      const GrGLShaderVar* args,
    538                                      const char* body,
    539                                      SkString* outName) {
    540     GrAssert(kFragment_ShaderType == shader);
    541     fFSFunctions.append(GrGLSLTypeString(returnType));
    542     this->nameVariable(outName, '\0', name);
    543     fFSFunctions.appendf(" %s", outName->c_str());
    544     fFSFunctions.append("(");
    545     for (int i = 0; i < argCnt; ++i) {
    546         args[i].appendDecl(fCtxInfo, &fFSFunctions);
    547         if (i < argCnt - 1) {
    548             fFSFunctions.append(", ");
    549         }
    550     }
    551     fFSFunctions.append(") {\n");
    552     fFSFunctions.append(body);
    553     fFSFunctions.append("}\n\n");
    554 }
    555 
    556 namespace {
    557 
    558 inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
    559                                                GrGLBinding binding,
    560                                                SkString* str) {
    561     // Desktop GLSL has added precision qualifiers but they don't do anything.
    562     if (kES2_GrGLBinding == binding) {
    563         switch (p) {
    564             case GrGLShaderVar::kHigh_Precision:
    565                 str->append("precision highp float;\n");
    566                 break;
    567             case GrGLShaderVar::kMedium_Precision:
    568                 str->append("precision mediump float;\n");
    569                 break;
    570             case GrGLShaderVar::kLow_Precision:
    571                 str->append("precision lowp float;\n");
    572                 break;
    573             case GrGLShaderVar::kDefault_Precision:
    574                 GrCrash("Default precision now allowed.");
    575             default:
    576                 GrCrash("Unknown precision value.");
    577         }
    578     }
    579 }
    580 }
    581 
    582 void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
    583     for (int i = 0; i < vars.count(); ++i) {
    584         vars[i].appendDecl(fCtxInfo, out);
    585         out->append(";\n");
    586     }
    587 }
    588 
    589 void GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const {
    590     for (int i = 0; i < fUniforms.count(); ++i) {
    591         if (fUniforms[i].fVisibility & stype) {
    592             fUniforms[i].fVariable.appendDecl(fCtxInfo, out);
    593             out->append(";\n");
    594         }
    595     }
    596 }
    597 
    598 void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
    599     const char* version = GrGetGLSLVersionDecl(fCtxInfo.binding(), fCtxInfo.glslGeneration());
    600 
    601     switch (type) {
    602         case kVertex_ShaderType:
    603             *shaderStr = version;
    604             this->appendUniformDecls(kVertex_ShaderType, shaderStr);
    605             this->appendDecls(fVSAttrs, shaderStr);
    606             this->appendDecls(fVSOutputs, shaderStr);
    607             shaderStr->append("void main() {\n");
    608             shaderStr->append(fVSCode);
    609             shaderStr->append("}\n");
    610             break;
    611         case kGeometry_ShaderType:
    612             if (fUsesGS) {
    613                 *shaderStr = version;
    614                 shaderStr->append(fGSHeader);
    615                 this->appendDecls(fGSInputs, shaderStr);
    616                 this->appendDecls(fGSOutputs, shaderStr);
    617                 shaderStr->append("void main() {\n");
    618                 shaderStr->append(fGSCode);
    619                 shaderStr->append("}\n");
    620             } else {
    621                 shaderStr->reset();
    622             }
    623             break;
    624         case kFragment_ShaderType:
    625             *shaderStr = version;
    626             shaderStr->append(fFSExtensions);
    627             append_default_precision_qualifier(kDefaultFragmentPrecision,
    628                                                fCtxInfo.binding(),
    629                                                shaderStr);
    630             this->appendUniformDecls(kFragment_ShaderType, shaderStr);
    631             this->appendDecls(fFSInputs, shaderStr);
    632             // We shouldn't have declared outputs on 1.10
    633             GrAssert(k110_GrGLSLGeneration != fCtxInfo.glslGeneration() || fFSOutputs.empty());
    634             this->appendDecls(fFSOutputs, shaderStr);
    635             shaderStr->append(fFSFunctions);
    636             shaderStr->append("void main() {\n");
    637             shaderStr->append(fFSCode);
    638             shaderStr->append("}\n");
    639             break;
    640     }
    641  }
    642 
    643 void GrGLShaderBuilder::finished(GrGLuint programID) {
    644     fUniformManager.getUniformLocations(programID, fUniforms);
    645 }
    646 
    647 void GrGLShaderBuilder::emitEffects(
    648                         const GrEffectStage* effectStages[],
    649                         const GrBackendEffectFactory::EffectKey effectKeys[],
    650                         int effectCnt,
    651                         SkString* fsInOutColor,
    652                         GrSLConstantVec* fsInOutColorKnownValue,
    653                         SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[],
    654                         GrGLEffect* glEffects[]) {
    655     bool effectEmitted = false;
    656 
    657     SkString inColor = *fsInOutColor;
    658     SkString outColor;
    659 
    660     for (int e = 0; e < effectCnt; ++e) {
    661         GrAssert(NULL != effectStages[e] && NULL != effectStages[e]->getEffect());
    662         const GrEffectStage& stage = *effectStages[e];
    663         const GrEffectRef& effect = *stage.getEffect();
    664 
    665         CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
    666 
    667         int numTextures = effect->numTextures();
    668         SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers;
    669         textureSamplers.push_back_n(numTextures);
    670         for (int t = 0; t < numTextures; ++t) {
    671             textureSamplers[t].init(this, &effect->textureAccess(t), t);
    672             effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform);
    673         }
    674         GrDrawEffect drawEffect(stage, this->hasExplicitLocalCoords());
    675 
    676         int numAttributes = stage.getVertexAttribIndexCount();
    677         const int* attributeIndices = stage.getVertexAttribIndices();
    678         SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames;
    679         for (int a = 0; a < numAttributes; ++a) {
    680             // TODO: Make addAttribute mangle the name.
    681             SkString attributeName("aAttr");
    682             attributeName.appendS32(attributeIndices[a]);
    683             if (this->addAttribute(effect->vertexAttribType(a), attributeName.c_str())) {
    684                 fEffectAttributes.push_back().set(attributeIndices[a], attributeName);
    685             }
    686         }
    687 
    688         glEffects[e] = effect->getFactory().createGLInstance(drawEffect);
    689 
    690         if (kZeros_GrSLConstantVec == *fsInOutColorKnownValue) {
    691             // Effects have no way to communicate zeros, they treat an empty string as ones.
    692             this->nameVariable(&inColor, '\0', "input");
    693             this->fsCodeAppendf("\tvec4 %s = %s;\n", inColor.c_str(), GrGLSLZerosVecf(4));
    694         }
    695 
    696         // create var to hold stage result
    697         this->nameVariable(&outColor, '\0', "output");
    698         this->fsCodeAppendf("\tvec4 %s;\n", outColor.c_str());
    699 
    700         // Enclose custom code in a block to avoid namespace conflicts
    701         SkString openBrace;
    702         openBrace.printf("\t{ // Stage %d: %s\n", fCodeStage.stageIndex(), glEffects[e]->name());
    703         this->fVSCode.append(openBrace);
    704         this->fFSCode.append(openBrace);
    705 
    706         glEffects[e]->emitCode(this,
    707                                drawEffect,
    708                                effectKeys[e],
    709                                outColor.c_str(),
    710                                inColor.isEmpty() ? NULL : inColor.c_str(),
    711                                textureSamplers);
    712         this->fVSCode.append("\t}\n");
    713         this->fFSCode.append("\t}\n");
    714 
    715         inColor = outColor;
    716         *fsInOutColorKnownValue = kNone_GrSLConstantVec;
    717         effectEmitted = true;
    718     }
    719 
    720     if (effectEmitted) {
    721         *fsInOutColor = outColor;
    722     }
    723 }
    724 
    725 const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const {
    726     const AttributePair* attribEnd = this->getEffectAttributes().end();
    727     for (const AttributePair* attrib = this->getEffectAttributes().begin();
    728          attrib != attribEnd;
    729          ++attrib) {
    730         if (attrib->fIndex == attributeIndex) {
    731             return &attrib->fName;
    732         }
    733     }
    734 
    735     return NULL;
    736 }
    737