Reland 8459 with fix for #extension after default precision in FS.



git-svn-id: http://skia.googlecode.com/svn/trunk@8479 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 0e91df2..f7ecf36 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -104,6 +104,7 @@
     , fCtxInfo(ctxInfo)
     , fUniformManager(uniformManager)
     , fCurrentStageIdx(kNonStageIdx)
+    , fFSFeaturesAddedMask(0)
 #if GR_GL_EXPERIMENTAL_GS
     , fUsesGS(desc.fExperimentalGS)
 #else
@@ -157,6 +158,47 @@
     }
 }
 
+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 @@
 #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::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 @@
             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 @@
             }
             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