Reland 8459 with fix for #extension after default precision in FS.
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 2 Apr 2013 12:50:49 +0000 (12:50 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 2 Apr 2013 12:50:49 +0000 (12:50 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@8479 2bbb7eff-a529-9590-31e7-b0007b416f81

src/gpu/effects/GrEdgeEffect.cpp
src/gpu/gl/GrGLProgram.cpp
src/gpu/gl/GrGLSL.cpp
src/gpu/gl/GrGLShaderBuilder.cpp
src/gpu/gl/GrGLShaderBuilder.h

index dd7474f..6f56413 100644 (file)
@@ -38,7 +38,7 @@ public:
             builder->fsCodeAppendf("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
             break;
         case GrEdgeEffect::kQuad_EdgeType:
-            GrAssert(builder->ctxInfo().caps()->shaderDerivativeSupport());
+            SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
             builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName);
 
             // keep the derivative instructions outside the conditional
@@ -56,12 +56,9 @@ public:
                                    fsName);
             builder->fsCodeAppendf("\t\t\tedgeAlpha = "
                                    "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n\t\t}\n");
-            if (kES2_GrGLBinding == builder->ctxInfo().binding()) {
-                builder->fHeader.append("#extension GL_OES_standard_derivatives: enable\n");
-            }
             break;
         case GrEdgeEffect::kHairQuad_EdgeType:
-            GrAssert(builder->ctxInfo().caps()->shaderDerivativeSupport());
+            SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
             builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
 
             builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
@@ -73,9 +70,6 @@ public:
                                    fsName);
             builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
             builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
-            if (kES2_GrGLBinding == builder->ctxInfo().binding()) {
-                builder->fHeader.append("#extension GL_OES_standard_derivatives: enable\n");
-            }
             break;
         };
 
index e1fa3a2..51cae5c 100644 (file)
@@ -462,8 +462,6 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
     // the dual source output has no canonical var name, have to
     // declare an output, which is incompatible with gl_FragColor/gl_FragData.
     bool dualSourceOutputWritten = false;
-    builder.fHeader.append(GrGetGLSLVersionDecl(fContext.info().binding(),
-                                                fContext.info().glslGeneration()));
 
     GrGLShaderVar colorOutput;
     bool isColorDeclared = GrGLSLSetupFSColorOuput(fContext.info().glslGeneration(),
index b7946fc..3ec7fc4 100644 (file)
@@ -9,8 +9,7 @@
 #include "GrGLShaderVar.h"
 #include "SkString.h"
 
-GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding,
-                                   const GrGLInterface* gl) {
+GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding, const GrGLInterface* gl) {
     GrGLSLVersion ver = GrGLGetGLSLVersion(gl);
     switch (binding) {
         case kDesktop_GrGLBinding:
@@ -34,8 +33,7 @@ GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding,
     }
 }
 
-const char* GrGetGLSLVersionDecl(GrGLBinding binding,
-                                   GrGLSLGeneration gen) {
+const char* GrGetGLSLVersionDecl(GrGLBinding binding, GrGLSLGeneration gen) {
     switch (gen) {
         case k110_GrGLSLGeneration:
             if (kES2_GrGLBinding == binding) {
@@ -61,9 +59,7 @@ const char* GrGetGLSLVersionDecl(GrGLBinding binding,
     }
 }
 
-bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen,
-                             const char* nameIfDeclared,
-                             GrGLShaderVar* var) {
+bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen, const char* nameIfDeclared, GrGLShaderVar* var) {
     bool declaredOutput = k110_GrGLSLGeneration != gen;
     var->set(kVec4f_GrSLType,
              GrGLShaderVar::kOut_TypeModifier,
index 0e91df2..f7ecf36 100644 (file)
@@ -104,6 +104,7 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
     , fCtxInfo(ctxInfo)
     , fUniformManager(uniformManager)
     , fCurrentStageIdx(kNonStageIdx)
+    , fFSFeaturesAddedMask(0)
 #if GR_GL_EXPERIMENTAL_GS
     , fUsesGS(desc.fExperimentalGS)
 #else
@@ -157,6 +158,47 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
     }
 }
 
+bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) {
+    switch (feature) {
+        case kStandardDerivatives_GLSLFeature:
+            if (!fCtxInfo.caps()->shaderDerivativeSupport()) {
+                return false;
+            }
+            if (kES2_GrGLBinding == fCtxInfo.binding()) {
+                this->addFSFeature(1 << kStandardDerivatives_GLSLFeature,
+                                   "GL_OES_standard_derivatives");
+            }
+            return true;
+        default:
+            GrCrash("Unexpected GLSLFeature requested.");
+            return false;
+    }
+}
+
+bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) {
+    switch (feature) {
+        case kFragCoordConventions_GLSLPrivateFeature:
+            if (!fCtxInfo.caps()->fragCoordConventionsSupport()) {
+                return false;
+            }
+            if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) {
+                this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
+                                   "GL_ARB_fragment_coord_conventions");
+            }
+            return true;
+        default:
+            GrCrash("Unexpected GLSLPrivateFeature requested.");
+            return false;
+    }
+}
+
+void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) {
+    if (!(featureBit & fFSFeaturesAddedMask)) {
+        fFSExtensions.appendf("#extension %s: require\n", extensionName);
+        fFSFeaturesAddedMask |= featureBit;
+    }
+}
+
 const char* GrGLShaderBuilder::dstColor() const {
     if (fDstCopySampler.isInitialized()) {
         return kDstColorName;
@@ -388,9 +430,7 @@ const char* GrGLShaderBuilder::fragmentPosition() {
 #if 1
     if (fCtxInfo.caps()->fragCoordConventionsSupport()) {
         if (!fSetupFragPosition) {
-            if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) {
-                fFSHeader.append("#extension GL_ARB_fragment_coord_conventions: require\n");
-            }
+            SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature));
             fFSInputs.push_back().set(kVec4f_GrSLType,
                                       GrGLShaderVar::kIn_TypeModifier,
                                       "gl_FragCoord",
@@ -507,9 +547,11 @@ void GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) cons
 }
 
 void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
+    const char* version = GrGetGLSLVersionDecl(fCtxInfo.binding(), fCtxInfo.glslGeneration());
+
     switch (type) {
         case kVertex_ShaderType:
-            *shaderStr = fHeader;
+            *shaderStr = version;
             this->appendUniformDecls(kVertex_ShaderType, shaderStr);
             this->appendDecls(fVSAttrs, shaderStr);
             this->appendDecls(fVSOutputs, shaderStr);
@@ -519,7 +561,7 @@ void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
             break;
         case kGeometry_ShaderType:
             if (fUsesGS) {
-                *shaderStr = fHeader;
+                *shaderStr = version;
                 shaderStr->append(fGSHeader);
                 this->appendDecls(fGSInputs, shaderStr);
                 this->appendDecls(fGSOutputs, shaderStr);
@@ -531,11 +573,11 @@ void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
             }
             break;
         case kFragment_ShaderType:
-            *shaderStr = fHeader;
+            *shaderStr = version;
+            shaderStr->append(fFSExtensions);
             append_default_precision_qualifier(kDefaultFragmentPrecision,
                                                fCtxInfo.binding(),
                                                shaderStr);
-            shaderStr->append(fFSHeader);
             this->appendUniformDecls(kFragment_ShaderType, shaderStr);
             this->appendDecls(fFSInputs, shaderStr);
             // We shouldn't have declared outputs on 1.10
index 4e39f91..ab093fb 100644 (file)
@@ -107,6 +107,22 @@ public:
     GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&, const GrGLProgramDesc&);
 
     /**
+     * Use of these features may require a GLSL extension to be enabled. Shaders may not compile
+     * if code is added that uses one of these features without calling enableFeature()
+     */
+    enum GLSLFeature {
+        kStandardDerivatives_GLSLFeature = 0,
+
+        kLastGLSLFeature = kStandardDerivatives_GLSLFeature
+    };
+
+    /**
+     * If the feature is supported then true is returned and any necessary #extension declarations
+     * are added to the shaders. If the feature is not supported then false will be returned.
+     */
+    bool enableFeature(GLSLFeature);
+
+    /**
      * Called by GrGLEffects to add code to one of the shaders.
      */
     void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
@@ -313,7 +329,6 @@ private:
     // TODO: Everything below here private.
 public:
 
-    SkString    fHeader; // VS+FS, GLSL version, etc
     VarArray    fVSAttrs;
     VarArray    fVSOutputs;
     VarArray    fGSInputs;
@@ -327,6 +342,18 @@ private:
         kNonStageIdx = -1,
     };
 
+    /**
+     * Features that should only be enabled by GrGLShaderBuilder itself.
+     */
+    enum GLSLPrivateFeature {
+        kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1
+    };
+    bool enablePrivateFeature(GLSLPrivateFeature);
+
+    // If we ever have VS/GS features we can expand this to take a bitmask of ShaderType and track
+    // the enables separately for each shader.
+    void addFSFeature(uint32_t featureBit, const char* extensionName);
+
     // Interpretation of DstReadKey when generating code
     enum {
         kNoDstRead_DstReadKey         = 0,
@@ -338,8 +365,9 @@ private:
     const GrGLContextInfo&              fCtxInfo;
     GrGLUniformManager&                 fUniformManager;
     int                                 fCurrentStageIdx;
+    uint32_t                            fFSFeaturesAddedMask;
     SkString                            fFSFunctions;
-    SkString                            fFSHeader;
+    SkString                            fFSExtensions;
 
     bool                                fUsesGS;