gfx/skia/trunk/src/gpu/gl/GrGLShaderBuilder.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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  */
     8 #include "gl/GrGLShaderBuilder.h"
     9 #include "gl/GrGLProgram.h"
    10 #include "gl/GrGLUniformHandle.h"
    11 #include "GrCoordTransform.h"
    12 #include "GrDrawEffect.h"
    13 #include "GrGpuGL.h"
    14 #include "GrTexture.h"
    15 #include "SkRTConf.h"
    16 #include "SkTrace.h"
    18 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
    19 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
    21 // number of each input/output type in a single allocation block
    22 static const int kVarsPerBlock = 8;
    24 // except FS outputs where we expect 2 at most.
    25 static const int kMaxFSOutputs = 2;
    27 // ES2 FS only guarantees mediump and lowp support
    28 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
    30 typedef GrGLUniformManager::UniformHandle UniformHandle;
    32 SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false,
    33                 "Print the source code for all shaders generated.");
    35 ///////////////////////////////////////////////////////////////////////////////
    37 namespace {
    39 inline const char* color_attribute_name() { return "aColor"; }
    40 inline const char* coverage_attribute_name() { return "aCoverage"; }
    41 inline const char* declared_color_output_name() { return "fsColorOut"; }
    42 inline const char* dual_source_output_name() { return "dualSourceOut"; }
    43 inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) {
    44     if (kVec2f_GrSLType == type) {
    45         return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D";
    46     } else {
    47         SkASSERT(kVec3f_GrSLType == type);
    48         return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj";
    49     }
    50 }
    52 void append_texture_lookup(SkString* out,
    53                            GrGpuGL* gpu,
    54                            const char* samplerName,
    55                            const char* coordName,
    56                            uint32_t configComponentMask,
    57                            const char* swizzle,
    58                            GrSLType varyingType = kVec2f_GrSLType) {
    59     SkASSERT(NULL != coordName);
    61     out->appendf("%s(%s, %s)",
    62                  sample_function_name(varyingType, gpu->glslGeneration()),
    63                  samplerName,
    64                  coordName);
    66     char mangledSwizzle[5];
    68     // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle
    69     // is available.
    70     if (!gpu->glCaps().textureSwizzleSupport() &&
    71         (kA_GrColorComponentFlag == configComponentMask)) {
    72         char alphaChar = gpu->glCaps().textureRedSupport() ? 'r' : 'a';
    73         int i;
    74         for (i = 0; '\0' != swizzle[i]; ++i) {
    75             mangledSwizzle[i] = alphaChar;
    76         }
    77         mangledSwizzle[i] ='\0';
    78         swizzle = mangledSwizzle;
    79     }
    80     // For shader prettiness we omit the swizzle rather than appending ".rgba".
    81     if (memcmp(swizzle, "rgba", 4)) {
    82         out->appendf(".%s", swizzle);
    83     }
    84 }
    86 }
    88 static const char kDstCopyColorName[] = "_dstColor";
    90 ///////////////////////////////////////////////////////////////////////////////
    92 GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
    93                                      GrGLUniformManager& uniformManager,
    94                                      const GrGLProgramDesc& desc)
    95     : fGpu(gpu)
    96     , fUniformManager(uniformManager)
    97     , fFSFeaturesAddedMask(0)
    98     , fFSInputs(kVarsPerBlock)
    99     , fFSOutputs(kMaxFSOutputs)
   100     , fUniforms(kVarsPerBlock)
   101     , fSetupFragPosition(false)
   102     , fHasCustomColorOutput(false)
   103     , fHasSecondaryOutput(false)
   104     , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) {
   106     const GrGLProgramDesc::KeyHeader& header = desc.getHeader();
   108     // Emit code to read the dst copy textue if necessary.
   109     if (kNoDstRead_DstReadKey != header.fDstReadKey &&
   110         GrGLCaps::kNone_FBFetchType == fGpu->glCaps().fbFetchType()) {
   111         bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
   112         const char* dstCopyTopLeftName;
   113         const char* dstCopyCoordScaleName;
   114         uint32_t configMask;
   115         if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
   116             configMask = kA_GrColorComponentFlag;
   117         } else {
   118             configMask = kRGBA_GrColorComponentFlags;
   119         }
   120         fDstCopySamplerUniform = this->addUniform(kFragment_Visibility,
   121                                                   kSampler2D_GrSLType,
   122                                                   "DstCopySampler");
   123         fDstCopyTopLeftUniform = this->addUniform(kFragment_Visibility,
   124                                                   kVec2f_GrSLType,
   125                                                   "DstCopyUpperLeft",
   126                                                   &dstCopyTopLeftName);
   127         fDstCopyScaleUniform     = this->addUniform(kFragment_Visibility,
   128                                                     kVec2f_GrSLType,
   129                                                     "DstCopyCoordScale",
   130                                                     &dstCopyCoordScaleName);
   131         const char* fragPos = this->fragmentPosition();
   132         this->fsCodeAppend("\t// Read color from copy of the destination.\n");
   133         this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n",
   134                             fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
   135         if (!topDown) {
   136             this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n");
   137         }
   138         this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName);
   139         append_texture_lookup(&fFSCode,
   140                               fGpu,
   141                               this->getUniformCStr(fDstCopySamplerUniform),
   142                               "_dstTexCoord",
   143                               configMask,
   144                               "rgba");
   145         this->fsCodeAppend(";\n\n");
   146     }
   148     if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
   149         const char* name;
   150         fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   151                                          kVec4f_GrSLType, "Color", &name);
   152         fInputColor = GrGLSLExpr4(name);
   153     } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fColorInput) {
   154         fInputColor = GrGLSLExpr4(1);
   155     } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fColorInput) {
   156         fInputColor = GrGLSLExpr4(0);
   157     }
   159     if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
   160         const char* name;
   161         fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   162                                             kVec4f_GrSLType, "Coverage", &name);
   163         fInputCoverage = GrGLSLExpr4(name);
   164     } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) {
   165         fInputCoverage = GrGLSLExpr4(1);
   166     } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fCoverageInput) {
   167         fInputCoverage = GrGLSLExpr4(0);
   168     }
   170     if (k110_GrGLSLGeneration != fGpu->glslGeneration()) {
   171         fFSOutputs.push_back().set(kVec4f_GrSLType,
   172                                    GrGLShaderVar::kOut_TypeModifier,
   173                                    declared_color_output_name());
   174         fHasCustomColorOutput = true;
   175     }
   176 }
   178 bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) {
   179     switch (feature) {
   180         case kStandardDerivatives_GLSLFeature:
   181             if (!fGpu->glCaps().shaderDerivativeSupport()) {
   182                 return false;
   183             }
   184             if (kGLES_GrGLStandard == fGpu->glStandard()) {
   185                 this->addFSFeature(1 << kStandardDerivatives_GLSLFeature,
   186                                    "GL_OES_standard_derivatives");
   187             }
   188             return true;
   189         default:
   190             GrCrash("Unexpected GLSLFeature requested.");
   191             return false;
   192     }
   193 }
   195 bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) {
   196     switch (feature) {
   197         case kFragCoordConventions_GLSLPrivateFeature:
   198             if (!fGpu->glCaps().fragCoordConventionsSupport()) {
   199                 return false;
   200             }
   201             if (fGpu->glslGeneration() < k150_GrGLSLGeneration) {
   202                 this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
   203                                    "GL_ARB_fragment_coord_conventions");
   204             }
   205             return true;
   206         case kEXTShaderFramebufferFetch_GLSLPrivateFeature:
   207             if (GrGLCaps::kEXT_FBFetchType != fGpu->glCaps().fbFetchType()) {
   208                 return false;
   209             }
   210             this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature,
   211                                "GL_EXT_shader_framebuffer_fetch");
   212             return true;
   213         case kNVShaderFramebufferFetch_GLSLPrivateFeature:
   214             if (GrGLCaps::kNV_FBFetchType != fGpu->glCaps().fbFetchType()) {
   215                 return false;
   216             }
   217             this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature,
   218                                "GL_NV_shader_framebuffer_fetch");
   219             return true;
   220         default:
   221             GrCrash("Unexpected GLSLPrivateFeature requested.");
   222             return false;
   223     }
   224 }
   226 void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) {
   227     if (!(featureBit & fFSFeaturesAddedMask)) {
   228         fFSExtensions.appendf("#extension %s: require\n", extensionName);
   229         fFSFeaturesAddedMask |= featureBit;
   230     }
   231 }
   233 void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) {
   234     if ('\0' == prefix) {
   235         *out = name;
   236     } else {
   237         out->printf("%c%s", prefix, name);
   238     }
   239     if (fCodeStage.inStageCode()) {
   240         if (out->endsWith('_')) {
   241             // Names containing "__" are reserved.
   242             out->append("x");
   243         }
   244         out->appendf("_Stage%d", fCodeStage.stageIndex());
   245     }
   246 }
   248 const char* GrGLShaderBuilder::dstColor() {
   249     if (fCodeStage.inStageCode()) {
   250         const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
   251         if (!effect->willReadDstColor()) {
   252             GrDebugCrash("GrGLEffect asked for dst color but its generating GrEffect "
   253                          "did not request access.");
   254             return "";
   255         }
   256     }
   257     static const char kFBFetchColorName[] = "gl_LastFragData[0]";
   258     GrGLCaps::FBFetchType fetchType = fGpu->glCaps().fbFetchType();
   259     if (GrGLCaps::kEXT_FBFetchType == fetchType) {
   260         SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature));
   261         return kFBFetchColorName;
   262     } else if (GrGLCaps::kNV_FBFetchType == fetchType) {
   263         SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature));
   264         return kFBFetchColorName;
   265     } else if (fDstCopySamplerUniform.isValid()) {
   266         return kDstCopyColorName;
   267     } else {
   268         return "";
   269     }
   270 }
   272 void GrGLShaderBuilder::appendTextureLookup(SkString* out,
   273                                             const GrGLShaderBuilder::TextureSampler& sampler,
   274                                             const char* coordName,
   275                                             GrSLType varyingType) const {
   276     append_texture_lookup(out,
   277                           fGpu,
   278                           this->getUniformCStr(sampler.samplerUniform()),
   279                           coordName,
   280                           sampler.configComponentMask(),
   281                           sampler.swizzle(),
   282                           varyingType);
   283 }
   285 void GrGLShaderBuilder::fsAppendTextureLookup(const GrGLShaderBuilder::TextureSampler& sampler,
   286                                               const char* coordName,
   287                                               GrSLType varyingType) {
   288     this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType);
   289 }
   291 void GrGLShaderBuilder::fsAppendTextureLookupAndModulate(
   292                                             const char* modulation,
   293                                             const GrGLShaderBuilder::TextureSampler& sampler,
   294                                             const char* coordName,
   295                                             GrSLType varyingType) {
   296     SkString lookup;
   297     this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
   298     fFSCode.append((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str());
   299 }
   301 GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
   302                                                                const GrGLCaps& caps) {
   303     uint32_t key = kYesDstRead_DstReadKeyBit;
   304     if (GrGLCaps::kNone_FBFetchType != caps.fbFetchType()) {
   305         return key;
   306     }
   307     SkASSERT(NULL != dstCopy);
   308     if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) {
   309         // The fact that the config is alpha-only must be considered when generating code.
   310         key |= kUseAlphaConfig_DstReadKeyBit;
   311     }
   312     if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) {
   313         key |= kTopLeftOrigin_DstReadKeyBit;
   314     }
   315     SkASSERT(static_cast<DstReadKey>(key) == key);
   316     return static_cast<DstReadKey>(key);
   317 }
   319 GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
   320                                                                         const GrGLCaps&) {
   321     if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
   322         return kTopLeftFragPosRead_FragPosKey;
   323     } else {
   324         return kBottomLeftFragPosRead_FragPosKey;
   325     }
   326 }
   329 const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) {
   330     if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) {
   331         if (caps.textureRedSupport()) {
   332             static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED };
   333             return gRedSmear;
   334         } else {
   335             static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
   336                                                     GR_GL_ALPHA, GR_GL_ALPHA };
   337             return gAlphaSmear;
   338         }
   339     } else {
   340         static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA };
   341         return gStraight;
   342     }
   343 }
   345 GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
   346                                                                      GrSLType type,
   347                                                                      const char* name,
   348                                                                      int count,
   349                                                                      const char** outName) {
   350     SkASSERT(name && strlen(name));
   351     SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
   352     SkASSERT(0 == (~kVisibilityMask & visibility));
   353     SkASSERT(0 != visibility);
   355     BuilderUniform& uni = fUniforms.push_back();
   356     UniformHandle h = GrGLUniformManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
   357     SkDEBUGCODE(UniformHandle h2 =)
   358     fUniformManager.appendUniform(type, count);
   359     // We expect the uniform manager to initially have no uniforms and that all uniforms are added
   360     // by this function. Therefore, the handles should match.
   361     SkASSERT(h2 == h);
   362     uni.fVariable.setType(type);
   363     uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
   364     this->nameVariable(uni.fVariable.accessName(), 'u', name);
   365     uni.fVariable.setArrayCount(count);
   366     uni.fVisibility = visibility;
   368     // If it is visible in both the VS and FS, the precision must match.
   369     // We declare a default FS precision, but not a default VS. So set the var
   370     // to use the default FS precision.
   371     if ((kVertex_Visibility | kFragment_Visibility) == visibility) {
   372         // the fragment and vertex precisions must match
   373         uni.fVariable.setPrecision(kDefaultFragmentPrecision);
   374     }
   376     if (NULL != outName) {
   377         *outName = uni.fVariable.c_str();
   378     }
   380     return h;
   381 }
   383 SkString GrGLShaderBuilder::ensureFSCoords2D(const TransformedCoordsArray& coords, int index) {
   384     if (kVec3f_GrSLType != coords[index].type()) {
   385         SkASSERT(kVec2f_GrSLType == coords[index].type());
   386         return coords[index].getName();
   387     }
   389     SkString coords2D("coords2D");
   390     if (0 != index) {
   391         coords2D.appendf("_%i", index);
   392     }
   393     this->fsCodeAppendf("\tvec2 %s = %s.xy / %s.z;",
   394                         coords2D.c_str(), coords[index].c_str(), coords[index].c_str());
   395     return coords2D;
   396 }
   398 const char* GrGLShaderBuilder::fragmentPosition() {
   399     if (fCodeStage.inStageCode()) {
   400         const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
   401         if (!effect->willReadFragmentPosition()) {
   402             GrDebugCrash("GrGLEffect asked for frag position but its generating GrEffect "
   403                          "did not request access.");
   404             return "";
   405         }
   406     }
   407     // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
   408     // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
   409     // declaration varies in earlier GLSL specs. So it is simpler to omit it.
   410     if (fTopLeftFragPosRead) {
   411         fSetupFragPosition = true;
   412         return "gl_FragCoord";
   413     } else if (fGpu->glCaps().fragCoordConventionsSupport()) {
   414         if (!fSetupFragPosition) {
   415             SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature));
   416             fFSInputs.push_back().set(kVec4f_GrSLType,
   417                                       GrGLShaderVar::kIn_TypeModifier,
   418                                       "gl_FragCoord",
   419                                       GrGLShaderVar::kDefault_Precision,
   420                                       GrGLShaderVar::kUpperLeft_Origin);
   421             fSetupFragPosition = true;
   422         }
   423         return "gl_FragCoord";
   424     } else {
   425         static const char* kCoordName = "fragCoordYDown";
   426         if (!fSetupFragPosition) {
   427             // temporarily change the stage index because we're inserting non-stage code.
   428             CodeStage::AutoStageRestore csar(&fCodeStage, NULL);
   430             SkASSERT(!fRTHeightUniform.isValid());
   431             const char* rtHeightName;
   433             fRTHeightUniform = this->addUniform(kFragment_Visibility,
   434                                                 kFloat_GrSLType,
   435                                                 "RTHeight",
   436                                                 &rtHeightName);
   438             this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n",
   439                                    kCoordName, rtHeightName);
   440             fSetupFragPosition = true;
   441         }
   442         SkASSERT(fRTHeightUniform.isValid());
   443         return kCoordName;
   444     }
   445 }
   447 void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType,
   448                                        const char* name,
   449                                        int argCnt,
   450                                        const GrGLShaderVar* args,
   451                                        const char* body,
   452                                        SkString* outName) {
   453     fFSFunctions.append(GrGLSLTypeString(returnType));
   454     this->nameVariable(outName, '\0', name);
   455     fFSFunctions.appendf(" %s", outName->c_str());
   456     fFSFunctions.append("(");
   457     for (int i = 0; i < argCnt; ++i) {
   458         args[i].appendDecl(this->ctxInfo(), &fFSFunctions);
   459         if (i < argCnt - 1) {
   460             fFSFunctions.append(", ");
   461         }
   462     }
   463     fFSFunctions.append(") {\n");
   464     fFSFunctions.append(body);
   465     fFSFunctions.append("}\n\n");
   466 }
   468 namespace {
   470 inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
   471                                                GrGLStandard standard,
   472                                                SkString* str) {
   473     // Desktop GLSL has added precision qualifiers but they don't do anything.
   474     if (kGLES_GrGLStandard == standard) {
   475         switch (p) {
   476             case GrGLShaderVar::kHigh_Precision:
   477                 str->append("precision highp float;\n");
   478                 break;
   479             case GrGLShaderVar::kMedium_Precision:
   480                 str->append("precision mediump float;\n");
   481                 break;
   482             case GrGLShaderVar::kLow_Precision:
   483                 str->append("precision lowp float;\n");
   484                 break;
   485             case GrGLShaderVar::kDefault_Precision:
   486                 GrCrash("Default precision now allowed.");
   487             default:
   488                 GrCrash("Unknown precision value.");
   489         }
   490     }
   491 }
   492 }
   494 void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
   495     for (int i = 0; i < vars.count(); ++i) {
   496         vars[i].appendDecl(this->ctxInfo(), out);
   497         out->append(";\n");
   498     }
   499 }
   501 void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility,
   502                                            SkString* out) const {
   503     for (int i = 0; i < fUniforms.count(); ++i) {
   504         if (fUniforms[i].fVisibility & visibility) {
   505             fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
   506             out->append(";\n");
   507         }
   508     }
   509 }
   511 void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder,
   512                                              const GrEffectStage* effectStages[],
   513                                              const EffectKey effectKeys[],
   514                                              int effectCnt,
   515                                              GrGLSLExpr4* fsInOutColor) {
   516     bool effectEmitted = false;
   518     GrGLSLExpr4 inColor = *fsInOutColor;
   519     GrGLSLExpr4 outColor;
   521     for (int e = 0; e < effectCnt; ++e) {
   522         SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect());
   523         const GrEffectStage& stage = *effectStages[e];
   525         CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
   527         if (inColor.isZeros()) {
   528             SkString inColorName;
   530             // Effects have no way to communicate zeros, they treat an empty string as ones.
   531             this->nameVariable(&inColorName, '\0', "input");
   532             this->fsCodeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str());
   533             inColor = inColorName;
   534         }
   536         // create var to hold stage result
   537         SkString outColorName;
   538         this->nameVariable(&outColorName, '\0', "output");
   539         this->fsCodeAppendf("\tvec4 %s;\n", outColorName.c_str());
   540         outColor = outColorName;
   543         programEffectsBuilder->emitEffect(stage,
   544                                           effectKeys[e],
   545                                           outColor.c_str(),
   546                                           inColor.isOnes() ? NULL : inColor.c_str(),
   547                                           fCodeStage.stageIndex());
   549         inColor = outColor;
   550         effectEmitted = true;
   551     }
   553     if (effectEmitted) {
   554         *fsInOutColor = outColor;
   555     }
   556 }
   558 const char* GrGLShaderBuilder::getColorOutputName() const {
   559     return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
   560 }
   562 const char* GrGLShaderBuilder::enableSecondaryOutput() {
   563     if (!fHasSecondaryOutput) {
   564         fFSOutputs.push_back().set(kVec4f_GrSLType,
   565                                    GrGLShaderVar::kOut_TypeModifier,
   566                                    dual_source_output_name());
   567         fHasSecondaryOutput = true;
   568     }
   569     return dual_source_output_name();
   570 }
   572 bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) {
   573     SK_TRACE_EVENT0("GrGLShaderBuilder::finish");
   575     GrGLuint programId = 0;
   576     GL_CALL_RET(programId, CreateProgram());
   577     if (!programId) {
   578         return false;
   579     }
   581     SkTDArray<GrGLuint> shadersToDelete;
   583     if (!this->compileAndAttachShaders(programId, &shadersToDelete)) {
   584         GL_CALL(DeleteProgram(programId));
   585         return false;
   586     }
   588     this->bindProgramLocations(programId);
   589     if (fUniformManager.isUsingBindUniform()) {
   590       fUniformManager.getUniformLocations(programId, fUniforms);
   591     }
   593     GL_CALL(LinkProgram(programId));
   595     // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
   596     bool checkLinked = !fGpu->ctxInfo().isChromium();
   597 #ifdef SK_DEBUG
   598     checkLinked = true;
   599 #endif
   600     if (checkLinked) {
   601         GrGLint linked = GR_GL_INIT_ZERO;
   602         GL_CALL(GetProgramiv(programId, GR_GL_LINK_STATUS, &linked));
   603         if (!linked) {
   604             GrGLint infoLen = GR_GL_INIT_ZERO;
   605             GL_CALL(GetProgramiv(programId, GR_GL_INFO_LOG_LENGTH, &infoLen));
   606             SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
   607             if (infoLen > 0) {
   608                 // retrieve length even though we don't need it to workaround
   609                 // bug in chrome cmd buffer param validation.
   610                 GrGLsizei length = GR_GL_INIT_ZERO;
   611                 GL_CALL(GetProgramInfoLog(programId,
   612                                           infoLen+1,
   613                                           &length,
   614                                           (char*)log.get()));
   615                 GrPrintf((char*)log.get());
   616             }
   617             SkDEBUGFAIL("Error linking program");
   618             GL_CALL(DeleteProgram(programId));
   619             return false;
   620         }
   621     }
   623     if (!fUniformManager.isUsingBindUniform()) {
   624       fUniformManager.getUniformLocations(programId, fUniforms);
   625     }
   627     for (int i = 0; i < shadersToDelete.count(); ++i) {
   628       GL_CALL(DeleteShader(shadersToDelete[i]));
   629     }
   631     *outProgramId = programId;
   632     return true;
   633 }
   635 // Compiles a GL shader and attaches it to a program. Returns the shader ID if
   636 // successful, or 0 if not.
   637 static GrGLuint attach_shader(const GrGLContext& glCtx,
   638                               GrGLuint programId,
   639                               GrGLenum type,
   640                               const SkString& shaderSrc) {
   641     const GrGLInterface* gli = glCtx.interface();
   643     GrGLuint shaderId;
   644     GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
   645     if (0 == shaderId) {
   646         return 0;
   647     }
   649     const GrGLchar* sourceStr = shaderSrc.c_str();
   650     GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size());
   651     GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength));
   652     GR_GL_CALL(gli, CompileShader(shaderId));
   654     // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds.
   655     bool checkCompiled = !glCtx.isChromium();
   656 #ifdef SK_DEBUG
   657     checkCompiled = true;
   658 #endif
   659     if (checkCompiled) {
   660         GrGLint compiled = GR_GL_INIT_ZERO;
   661         GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
   663         if (!compiled) {
   664             GrGLint infoLen = GR_GL_INIT_ZERO;
   665             GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
   666             SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
   667             if (infoLen > 0) {
   668                 // retrieve length even though we don't need it to workaround bug in Chromium cmd
   669                 // buffer param validation.
   670                 GrGLsizei length = GR_GL_INIT_ZERO;
   671                 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1,
   672                                                  &length, (char*)log.get()));
   673                 GrPrintf(shaderSrc.c_str());
   674                 GrPrintf("\n%s", log.get());
   675             }
   676             SkDEBUGFAIL("Shader compilation failed!");
   677             GR_GL_CALL(gli, DeleteShader(shaderId));
   678             return 0;
   679         }
   680     }
   681     if (c_PrintShaders) {
   682         GrPrintf(shaderSrc.c_str());
   683         GrPrintf("\n");
   684     }
   686     // Attach the shader, but defer deletion until after we have linked the program.
   687     // This works around a bug in the Android emulator's GLES2 wrapper which
   688     // will immediately delete the shader object and free its memory even though it's
   689     // attached to a program, which then causes glLinkProgram to fail.
   690     GR_GL_CALL(gli, AttachShader(programId, shaderId));
   692     return shaderId;
   693 }
   695 bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const {
   696     SkString fragShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
   697     fragShaderSrc.append(fFSExtensions);
   698     append_default_precision_qualifier(kDefaultFragmentPrecision,
   699                                        fGpu->glStandard(),
   700                                        &fragShaderSrc);
   701     this->appendUniformDecls(kFragment_Visibility, &fragShaderSrc);
   702     this->appendDecls(fFSInputs, &fragShaderSrc);
   703     // We shouldn't have declared outputs on 1.10
   704     SkASSERT(k110_GrGLSLGeneration != fGpu->glslGeneration() || fFSOutputs.empty());
   705     this->appendDecls(fFSOutputs, &fragShaderSrc);
   706     fragShaderSrc.append(fFSFunctions);
   707     fragShaderSrc.append("void main() {\n");
   708     fragShaderSrc.append(fFSCode);
   709     fragShaderSrc.append("}\n");
   711     GrGLuint fragShaderId = attach_shader(fGpu->glContext(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc);
   712     if (!fragShaderId) {
   713         return false;
   714     }
   716     *shaderIds->append() = fragShaderId;
   718     return true;
   719 }
   721 void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) const {
   722     if (fHasCustomColorOutput) {
   723         GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()));
   724     }
   725     if (fHasSecondaryOutput) {
   726         GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name()));
   727     }
   728 }
   730 const GrGLContextInfo& GrGLShaderBuilder::ctxInfo() const {
   731     return fGpu->ctxInfo();
   732 }
   734 ////////////////////////////////////////////////////////////////////////////////
   736 GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu,
   737                                              GrGLUniformManager& uniformManager,
   738                                              const GrGLProgramDesc& desc)
   739     : INHERITED(gpu, uniformManager, desc)
   740     , fDesc(desc)
   741     , fVSAttrs(kVarsPerBlock)
   742     , fVSOutputs(kVarsPerBlock)
   743     , fGSInputs(kVarsPerBlock)
   744     , fGSOutputs(kVarsPerBlock) {
   746     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
   748     fPositionVar = &fVSAttrs.push_back();
   749     fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
   750     if (-1 != header.fLocalCoordAttributeIndex) {
   751         fLocalCoordsVar = &fVSAttrs.push_back();
   752         fLocalCoordsVar->set(kVec2f_GrSLType,
   753                              GrGLShaderVar::kAttribute_TypeModifier,
   754                              "aLocalCoords");
   755     } else {
   756         fLocalCoordsVar = fPositionVar;
   757     }
   759     const char* viewMName;
   760     fViewMatrixUniform = this->addUniform(GrGLShaderBuilder::kVertex_Visibility,
   761                                           kMat33f_GrSLType, "ViewM", &viewMName);
   763     this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
   764                         "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
   765                         viewMName, fPositionVar->c_str());
   767     // we output point size in the GS if present
   768     if (header.fEmitsPointSize
   769 #if GR_GL_EXPERIMENTAL_GS
   770         && !header.fExperimentalGS
   771 #endif
   772         ) {
   773         this->vsCodeAppend("\tgl_PointSize = 1.0;\n");
   774     }
   776     if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
   777         this->addAttribute(kVec4f_GrSLType, color_attribute_name());
   778         const char *vsName, *fsName;
   779         this->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
   780         this->vsCodeAppendf("\t%s = %s;\n", vsName, color_attribute_name());
   781         this->setInputColor(fsName);
   782     }
   784     if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
   785         this->addAttribute(kVec4f_GrSLType, coverage_attribute_name());
   786         const char *vsName, *fsName;
   787         this->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
   788         this->vsCodeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name());
   789         this->setInputCoverage(fsName);
   790     }
   791 }
   793 bool GrGLFullShaderBuilder::addAttribute(GrSLType type, const char* name) {
   794     for (int i = 0; i < fVSAttrs.count(); ++i) {
   795         const GrGLShaderVar& attr = fVSAttrs[i];
   796         // if attribute already added, don't add it again
   797         if (attr.getName().equals(name)) {
   798             SkASSERT(attr.getType() == type);
   799             return false;
   800         }
   801     }
   802     fVSAttrs.push_back().set(type,
   803                              GrGLShaderVar::kAttribute_TypeModifier,
   804                              name);
   805     return true;
   806 }
   808 bool GrGLFullShaderBuilder::addEffectAttribute(int attributeIndex,
   809                                                GrSLType type,
   810                                                const SkString& name) {
   811     if (!this->addAttribute(type, name.c_str())) {
   812         return false;
   813     }
   815     fEffectAttributes.push_back().set(attributeIndex, name);
   816     return true;
   817 }
   819 void GrGLFullShaderBuilder::addVarying(GrSLType type,
   820                                        const char* name,
   821                                        const char** vsOutName,
   822                                        const char** fsInName) {
   823     fVSOutputs.push_back();
   824     fVSOutputs.back().setType(type);
   825     fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
   826     this->nameVariable(fVSOutputs.back().accessName(), 'v', name);
   828     if (vsOutName) {
   829         *vsOutName = fVSOutputs.back().getName().c_str();
   830     }
   831     // input to FS comes either from VS or GS
   832     const SkString* fsName;
   833 #if GR_GL_EXPERIMENTAL_GS
   834     if (fDesc.getHeader().fExperimentalGS) {
   835         // if we have a GS take each varying in as an array
   836         // and output as non-array.
   837         fGSInputs.push_back();
   838         fGSInputs.back().setType(type);
   839         fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
   840         fGSInputs.back().setUnsizedArray();
   841         *fGSInputs.back().accessName() = fVSOutputs.back().getName();
   842         fGSOutputs.push_back();
   843         fGSOutputs.back().setType(type);
   844         fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
   845         this->nameVariable(fGSOutputs.back().accessName(), 'g', name);
   846         fsName = fGSOutputs.back().accessName();
   847     } else
   848 #endif
   849     {
   850         fsName = fVSOutputs.back().accessName();
   851     }
   852     this->fsInputAppend().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, *fsName);
   853     if (fsInName) {
   854         *fsInName = fsName->c_str();
   855     }
   856 }
   858 const SkString* GrGLFullShaderBuilder::getEffectAttributeName(int attributeIndex) const {
   859     const AttributePair* attribEnd = fEffectAttributes.end();
   860     for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) {
   861         if (attrib->fIndex == attributeIndex) {
   862             return &attrib->fName;
   863         }
   864     }
   866     return NULL;
   867 }
   869 GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects(
   870         const GrEffectStage* effectStages[],
   871         const EffectKey effectKeys[],
   872         int effectCnt,
   873         GrGLSLExpr4* inOutFSColor) {
   875     GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
   876     this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
   877                                           effectStages,
   878                                           effectKeys,
   879                                           effectCnt,
   880                                           inOutFSColor);
   881     return programEffectsBuilder.finish();
   882 }
   884 bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const {
   885     const GrGLContext& glCtx = this->gpu()->glContext();
   886     SkString vertShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
   887     this->appendUniformDecls(kVertex_Visibility, &vertShaderSrc);
   888     this->appendDecls(fVSAttrs, &vertShaderSrc);
   889     this->appendDecls(fVSOutputs, &vertShaderSrc);
   890     vertShaderSrc.append("void main() {\n");
   891     vertShaderSrc.append(fVSCode);
   892     vertShaderSrc.append("}\n");
   893     GrGLuint vertShaderId = attach_shader(glCtx, programId, GR_GL_VERTEX_SHADER, vertShaderSrc);
   894     if (!vertShaderId) {
   895         return false;
   896     }
   897     *shaderIds->append() = vertShaderId;
   899 #if GR_GL_EXPERIMENTAL_GS
   900     if (fDesc.getHeader().fExperimentalGS) {
   901         SkASSERT(this->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration);
   902         SkString geomShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
   903         geomShaderSrc.append("layout(triangles) in;\n"
   904                              "layout(triangle_strip, max_vertices = 6) out;\n");
   905         this->appendDecls(fGSInputs, &geomShaderSrc);
   906         this->appendDecls(fGSOutputs, &geomShaderSrc);
   907         geomShaderSrc.append("void main() {\n");
   908         geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n"
   909                              "\t\tgl_Position = gl_in[i].gl_Position;\n");
   910         if (fDesc.getHeader().fEmitsPointSize) {
   911             geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n");
   912         }
   913         SkASSERT(fGSInputs.count() == fGSOutputs.count());
   914         for (int i = 0; i < fGSInputs.count(); ++i) {
   915             geomShaderSrc.appendf("\t\t%s = %s[i];\n",
   916                                   fGSOutputs[i].getName().c_str(),
   917                                   fGSInputs[i].getName().c_str());
   918         }
   919         geomShaderSrc.append("\t\tEmitVertex();\n"
   920                              "\t}\n"
   921                              "\tEndPrimitive();\n");
   922         geomShaderSrc.append("}\n");
   923         GrGLuint geomShaderId = attach_shader(glCtx, programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc);
   924         if (!geomShaderId) {
   925             return false;
   926         }
   927         *shaderIds->append() = geomShaderId;
   928     }
   929 #endif
   931     return this->INHERITED::compileAndAttachShaders(programId, shaderIds);
   932 }
   934 void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) const {
   935     this->INHERITED::bindProgramLocations(programId);
   937     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
   939     // Bind the attrib locations to same values for all shaders
   940     SkASSERT(-1 != header.fPositionAttributeIndex);
   941     GL_CALL(BindAttribLocation(programId,
   942                                header.fPositionAttributeIndex,
   943                                fPositionVar->c_str()));
   944     if (-1 != header.fLocalCoordAttributeIndex) {
   945         GL_CALL(BindAttribLocation(programId,
   946                                    header.fLocalCoordAttributeIndex,
   947                                    fLocalCoordsVar->c_str()));
   948     }
   949     if (-1 != header.fColorAttributeIndex) {
   950         GL_CALL(BindAttribLocation(programId,
   951                                    header.fColorAttributeIndex,
   952                                    color_attribute_name()));
   953     }
   954     if (-1 != header.fCoverageAttributeIndex) {
   955         GL_CALL(BindAttribLocation(programId,
   956                                    header.fCoverageAttributeIndex,
   957                                    coverage_attribute_name()));
   958     }
   960     const AttributePair* attribEnd = fEffectAttributes.end();
   961     for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) {
   962          GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str()));
   963     }
   964 }
   966 ////////////////////////////////////////////////////////////////////////////////
   968 GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu,
   969                                                              GrGLUniformManager& uniformManager,
   970                                                              const GrGLProgramDesc& desc)
   971     : INHERITED(gpu, uniformManager, desc)
   972     , fNumTexCoordSets(0) {
   974     SkASSERT(!desc.getHeader().fHasVertexCode);
   975     SkASSERT(gpu->glCaps().fixedFunctionSupport());
   976     SkASSERT(gpu->glCaps().pathRenderingSupport());
   977     SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
   978     SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
   979 }
   981 int GrGLFragmentOnlyShaderBuilder::addTexCoordSets(int count) {
   982     int firstFreeCoordSet = fNumTexCoordSets;
   983     fNumTexCoordSets += count;
   984     SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fNumTexCoordSets);
   985     return firstFreeCoordSet;
   986 }
   988 GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects(
   989         const GrEffectStage* effectStages[],
   990         const EffectKey effectKeys[],
   991         int effectCnt,
   992         GrGLSLExpr4* inOutFSColor) {
   994     GrGLTexGenProgramEffectsBuilder texGenEffectsBuilder(this, effectCnt);
   995     this->INHERITED::createAndEmitEffects(&texGenEffectsBuilder,
   996                                           effectStages,
   997                                           effectKeys,
   998                                           effectCnt,
   999                                           inOutFSColor);
  1000     return texGenEffectsBuilder.finish();

mercurial