Allow FPs to elevate default precision for the entire fragment program

Currently, GrConfigConversionEffect is able to round-trip on many
mobile GPUs because it uses highp for all intermediate variables
(including the texture fetch result). Separating the texture sample
into a different processor breaks that.

This is a blunt instrument, not to be used lightly.

This reverts commit dffe9827b18444d1426859d9035f9f0087201f44.

Bug: skia:
Change-Id: I940af3256c47e6672a008d516db9e55669672ca3
Reviewed-on: https://skia-review.googlesource.com/11345
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h
index 2711b9a..e5222bf 100644
--- a/src/gpu/GrGeometryProcessor.h
+++ b/src/gpu/GrGeometryProcessor.h
@@ -51,6 +51,7 @@
      */
     const Attribute& addVertexAttrib(const char* name, GrVertexAttribType type,
                                      GrSLPrecision precision = kDefault_GrSLPrecision) {
+        precision = (kDefault_GrSLPrecision == precision) ? kMedium_GrSLPrecision : precision;
         fAttribs.emplace_back(name, type, precision);
         fVertexStride += fAttribs.back().fOffset;
         return fAttribs.back();
diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp
index e3e6b07..636b955 100644
--- a/src/gpu/GrShaderCaps.cpp
+++ b/src/gpu/GrShaderCaps.cpp
@@ -32,8 +32,10 @@
         return "medium";
     case kHigh_GrSLPrecision:
         return "high";
+    default:
+        SkFAIL("Unexpected precision type.");
+        return "";
     }
-    return "";
 }
 
 GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
@@ -201,7 +203,7 @@
         }
 
         uint8_t* table = fSamplerPrecisions[visibility];
-        table[kUnknown_GrPixelConfig]        = kDefault_GrSLPrecision;
+        table[kUnknown_GrPixelConfig]        = lowp;
         table[kAlpha_8_GrPixelConfig]        = lowp;
         table[kGray_8_GrPixelConfig]         = lowp;
         table[kRGB_565_GrPixelConfig]        = lowp;
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 1a41a5b..6b3e3a7 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1257,9 +1257,10 @@
         return GR_GL_MEDIUM_FLOAT;
     case kHigh_GrSLPrecision:
         return GR_GL_HIGH_FLOAT;
+    default:
+        SkFAIL("Unexpected precision type.");
+        return -1;
     }
-    SkFAIL("Unknown precision.");
-    return -1;
 }
 
 static GrGLenum shader_type_to_gl_shader(GrShaderType type) {
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 3af3ed2..714ded0 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3578,7 +3578,7 @@
         fshaderTxt.appendf("#extension %s : require\n",
                            shaderCaps->externalTextureExtensionString());
     }
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, *shaderCaps,
+    GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps,
                                                  &fshaderTxt);
     vTexCoord.setTypeModifier(GrShaderVar::kIn_TypeModifier);
     vTexCoord.appendDecl(shaderCaps, &fshaderTxt);
@@ -3716,7 +3716,7 @@
             fshaderTxt.appendf("#extension %s : require\n", extension);
         }
     }
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, *shaderCaps,
+    GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *shaderCaps,
                                                  &fshaderTxt);
     for (int i = 0; i < numTaps; ++i) {
         vTexCoords[i].setTypeModifier(GrShaderVar::kIn_TypeModifier);
@@ -3831,7 +3831,7 @@
     GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
 
     SkString fshaderTxt(version);
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision,
+    GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision,
                                                  *this->caps()->shaderCaps(),
                                                  &fshaderTxt);
     uColor.appendDecl(this->caps()->shaderCaps(), &fshaderTxt);
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index a1f5173..484bd78 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -85,7 +85,8 @@
     , fCustomColorOutputIndex(-1)
     , fHasSecondaryOutput(false)
     , fUsedSampleOffsetArrays(0)
-    , fHasInitializedSampleMask(false) {
+    , fHasInitializedSampleMask(false)
+    , fDefaultPrecision(kMedium_GrSLPrecision) {
     fSubstageIndices.push_back(0);
 #ifdef SK_DEBUG
     fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
@@ -178,6 +179,10 @@
     fHasInitializedSampleMask = true;
 }
 
+void GrGLSLFragmentShaderBuilder::elevateDefaultPrecision(GrSLPrecision precision) {
+    fDefaultPrecision = SkTMax(fDefaultPrecision, precision);
+}
+
 const char* GrGLSLFragmentShaderBuilder::dstColor() {
     SkDEBUGCODE(fHasReadDstColor = true;)
 
@@ -279,7 +284,7 @@
 
 void GrGLSLFragmentShaderBuilder::onFinalize() {
     fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision,
+    GrGLSLAppendDefaultFloatPrecisionDeclaration(fDefaultPrecision,
                                                  *fProgramBuilder->shaderCaps(),
                                                  &this->precisionQualifier());
     if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) {
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
index 764f3bd..65bcb8d 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
@@ -94,6 +94,13 @@
     virtual const char* distanceVectorName() const = 0;
 
     /**
+     * Overrides the default precision for the entire fragment program. Processors that require
+     * high precision input (eg from incoming texture samples) may use this. For calculations that
+     * are limited to a single processor's code, it is better to annotate individual declarations.
+     */
+    virtual void elevateDefaultPrecision(GrSLPrecision) = 0;
+
+    /**
      * Fragment procs with child procs should call these functions before/after calling emitCode
      * on a child proc.
      */
@@ -167,6 +174,7 @@
     void appendOffsetToSample(const char* sampleIdx, Coordinates) override;
     void maskSampleCoverage(const char* mask, bool invert = false) override;
     void overrideSampleCoverage(const char* mask) override;
+    void elevateDefaultPrecision(GrSLPrecision) override;
     const SkString& getMangleString() const override { return fMangleString; }
     void onBeforeChildProcEmitCode() override;
     void onAfterChildProcEmitCode() override;
@@ -225,13 +233,14 @@
      */
     SkString fMangleString;
 
-    bool       fSetupFragPosition;
-    bool       fHasCustomColorOutput;
-    int        fCustomColorOutputIndex;
-    bool       fHasSecondaryOutput;
-    uint8_t    fUsedSampleOffsetArrays;
-    bool       fHasInitializedSampleMask;
-    SkString   fDistanceVectorOutput;
+    bool          fSetupFragPosition;
+    bool          fHasCustomColorOutput;
+    int           fCustomColorOutputIndex;
+    bool          fHasSecondaryOutput;
+    uint8_t       fUsedSampleOffsetArrays;
+    bool          fHasInitializedSampleMask;
+    SkString      fDistanceVectorOutput;
+    GrSLPrecision fDefaultPrecision;
 
 #ifdef SK_DEBUG
     // some state to verify shaders and effects are consistent, this is reset between effects by
diff --git a/src/gpu/glsl/GrGLSLVarying.cpp b/src/gpu/glsl/GrGLSLVarying.cpp
index 7d841f5..ef3fe8a 100644
--- a/src/gpu/glsl/GrGLSLVarying.cpp
+++ b/src/gpu/glsl/GrGLSLVarying.cpp
@@ -42,7 +42,7 @@
 
     SkASSERT(varying);
     v.fType = varying->fType;
-    v.fPrecision = precision;
+    v.fPrecision = (kDefault_GrSLPrecision == precision) ? kMedium_GrSLPrecision : precision;
     v.fIsFlat = flat;
     fProgramBuilder->nameVariable(&v.fVsOut, 'v', name);
     v.fVisibility = kNone_GrShaderFlags;