Revert "Drop support for unused MSAA extensions"

This reverts commit 7df27465c4ecc8a4a0cdd95e9785c342903c2de9.

Reason for revert: experimental revert to see if this is the cause of the tree redness

Original change's description:
> Drop support for unused MSAA extensions
> 
> Bug: skia:
> Change-Id: I113b80e3f991f195155148625ceb29242ea82776
> Reviewed-on: https://skia-review.googlesource.com/101403
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Chris Dalton <csmartdalton@google.com>

TBR=bsalomon@google.com,csmartdalton@google.com,ethannicholas@google.com

Change-Id: I4fa4123e2d176bef88cd76a09a14053d9ac5809f
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/101680
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index db252e3..6de545b 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -17,6 +17,18 @@
 
 const char* GrGLSLFragmentShaderBuilder::kDstColorName = "_dstColor";
 
+static const char* sample_offset_array_name(GrGLSLFPFragmentBuilder::Coordinates coords) {
+    static const char* kArrayNames[] = {
+        "deviceSpaceSampleOffsets",
+        "windowSpaceSampleOffsets"
+    };
+    return kArrayNames[coords];
+
+    GR_STATIC_ASSERT(0 == GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
+    GR_STATIC_ASSERT(1 == GrGLSLFPFragmentBuilder::kGLSLWindow_Coordinates);
+    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kArrayNames) == GrGLSLFPFragmentBuilder::kLast_Coordinates + 1);
+}
+
 static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
     SkASSERT(GrBlendEquationIsAdvanced(equation));
 
@@ -58,19 +70,47 @@
                      kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation);
 }
 
+uint8_t GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(GrSurfaceOrigin origin) {
+    SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin);
+    return origin + 1;
+
+    GR_STATIC_ASSERT(0 == kTopLeft_GrSurfaceOrigin);
+    GR_STATIC_ASSERT(1 == kBottomLeft_GrSurfaceOrigin);
+}
+
 GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program)
     : GrGLSLFragmentBuilder(program)
     , fSetupFragPosition(false)
     , fHasCustomColorOutput(false)
     , fCustomColorOutputIndex(-1)
     , fHasSecondaryOutput(false)
+    , fUsedSampleOffsetArrays(0)
+    , fHasInitializedSampleMask(false)
     , fForceHighPrecision(false) {
     fSubstageIndices.push_back(0);
 #ifdef SK_DEBUG
+    fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
     fHasReadDstColor = false;
 #endif
 }
 
+bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
+    const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
+    switch (feature) {
+        case kMultisampleInterpolation_GLSLFeature:
+            if (!shaderCaps.multisampleInterpolationSupport()) {
+                return false;
+            }
+            if (const char* extension = shaderCaps.multisampleInterpolationExtensionString()) {
+                this->addFeature(1 << kMultisampleInterpolation_GLSLFeature, extension);
+            }
+            return true;
+        default:
+            SK_ABORT("Unexpected GLSLFeature requested.");
+            return false;
+    }
+}
+
 SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords) {
     if (kFloat3_GrSLType != coords.getType() && kHalf3_GrSLType != coords.getType()) {
         SkASSERT(kFloat2_GrSLType == coords.getType() || kHalf2_GrSLType == coords.getType());
@@ -84,6 +124,57 @@
     return coords2D;
 }
 
+void GrGLSLFragmentShaderBuilder::appendOffsetToSample(const char* sampleIdx, Coordinates coords) {
+    SkASSERT(fProgramBuilder->header().fSamplePatternKey);
+    SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kSampleLocations_RequiredFeature);
+    if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) {
+        // With a top left origin, device and window space are equal, so we only use device coords.
+        coords = kSkiaDevice_Coordinates;
+    }
+    this->codeAppendf("%s[%s]", sample_offset_array_name(coords), sampleIdx);
+    fUsedSampleOffsetArrays |= (1 << coords);
+}
+
+void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool invert) {
+    const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
+    if (!shaderCaps.sampleVariablesSupport()) {
+        SkDEBUGFAIL("Attempted to mask sample coverage without support.");
+        return;
+    }
+    if (const char* extension = shaderCaps.sampleVariablesExtensionString()) {
+        this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension);
+    }
+    if (!fHasInitializedSampleMask) {
+        this->codePrependf("gl_SampleMask[0] = -1;");
+        fHasInitializedSampleMask = true;
+    }
+    if (invert) {
+        this->codeAppendf("gl_SampleMask[0] &= ~(%s);", mask);
+    } else {
+        this->codeAppendf("gl_SampleMask[0] &= %s;", mask);
+    }
+}
+
+void GrGLSLFragmentShaderBuilder::overrideSampleCoverage(const char* mask) {
+    const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
+    if (!shaderCaps.sampleMaskOverrideCoverageSupport()) {
+        SkDEBUGFAIL("Attempted to override sample coverage without support.");
+        return;
+    }
+    SkASSERT(shaderCaps.sampleVariablesSupport());
+    if (const char* extension = shaderCaps.sampleVariablesExtensionString()) {
+        this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension);
+    }
+    if (this->addFeature(1 << kSampleMaskOverrideCoverage_GLSLPrivateFeature,
+                         "GL_NV_sample_mask_override_coverage")) {
+        // Redeclare gl_SampleMask with layout(override_coverage) if we haven't already.
+        fOutputs.push_back().set(kInt_GrSLType, "gl_SampleMask", 1, GrShaderVar::kOut_TypeModifier,
+                                 kHigh_GrSLPrecision, "override_coverage");
+    }
+    this->codeAppendf("gl_SampleMask[0] = %s;", mask);
+    fHasInitializedSampleMask = true;
+}
+
 const char* GrGLSLFragmentShaderBuilder::dstColor() {
     SkDEBUGCODE(fHasReadDstColor = true;)
 
@@ -185,6 +276,33 @@
 
 void GrGLSLFragmentShaderBuilder::onFinalize() {
     fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
+    if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) {
+        this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coordinates),
+                                      SkMatrix::MakeTrans(-0.5f, -0.5f));
+    }
+    if (fUsedSampleOffsetArrays & (1 << kGLSLWindow_Coordinates)) {
+        // With a top left origin, device and window space are equal, so we only use device coords.
+        SkASSERT(kBottomLeft_GrSurfaceOrigin == this->getSurfaceOrigin());
+        SkMatrix m;
+        m.setScale(1, -1);
+        m.preTranslate(-0.5f, -0.5f);
+        this->defineSampleOffsetArray(sample_offset_array_name(kGLSLWindow_Coordinates), m);
+    }
+}
+
+void GrGLSLFragmentShaderBuilder::defineSampleOffsetArray(const char* name, const SkMatrix& m) {
+    SkASSERT(fProgramBuilder->caps()->sampleLocationsSupport());
+    const GrPipeline& pipeline = fProgramBuilder->pipeline();
+    const GrRenderTargetPriv& rtp = pipeline.renderTarget()->renderTargetPriv();
+    const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline);
+    SkSTArray<16, SkPoint, true> offsets;
+    offsets.push_back_n(specs.fEffectiveSampleCnt);
+    m.mapPoints(offsets.begin(), specs.fSampleLocations, specs.fEffectiveSampleCnt);
+    this->definitions().appendf("const float2 %s[] = float2[](", name);
+    for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
+        this->definitions().appendf("float2(%f, %f)", offsets[i].x(), offsets[i].y());
+        this->definitions().append(i + 1 != specs.fEffectiveSampleCnt ? ", " : ");\n");
+    }
 }
 
 void GrGLSLFragmentShaderBuilder::onBeforeChildProcEmitCode() {
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
index f5ed024..f124a44 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
@@ -25,6 +25,20 @@
     virtual ~GrGLSLFragmentBuilder() {}
 
     /**
+     * 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 {
+        kMultisampleInterpolation_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.
+     */
+    virtual bool enableFeature(GLSLFeature) = 0;
+
+    /**
      * This returns a variable name to access the 2D, perspective correct version of the coords in
      * the fragment shader. The passed in coordinates must either be of type kHalf2 or kHalf3. If
      * the coordinates are 3-dimensional, it a perspective divide into is emitted into the
@@ -47,6 +61,34 @@
     /** Appease the compiler; the derived class initializes GrGLSLFragmentBuilder. */
     GrGLSLFPFragmentBuilder() : GrGLSLFragmentBuilder(nullptr) {}
 
+    enum Coordinates {
+        kSkiaDevice_Coordinates,
+        kGLSLWindow_Coordinates,
+
+        kLast_Coordinates = kGLSLWindow_Coordinates
+    };
+
+    /**
+     * Appends the offset from the center of the pixel to a specified sample.
+     *
+     * @param sampleIdx      GLSL expression of the sample index.
+     * @param Coordinates    Coordinate space in which to emit the offset.
+     *
+     * A processor must call setWillUseSampleLocations in its constructor before using this method.
+     */
+    virtual void appendOffsetToSample(const char* sampleIdx, Coordinates) = 0;
+
+    /**
+     * Subtracts sample coverage from the fragment. Any sample whose corresponding bit is not found
+     * in the mask will not be written out to the framebuffer.
+     *
+     * @param mask      int that contains the sample mask. Bit N corresponds to the Nth sample.
+     * @param invert    perform a bit-wise NOT on the provided mask before applying it?
+     *
+     * Requires GLSL support for sample variables.
+     */
+    virtual void maskSampleCoverage(const char* mask, bool invert = false) = 0;
+
     /**
      * Fragment procs with child procs should call these functions before/after calling emitCode
      * on a child proc.
@@ -60,6 +102,29 @@
 };
 
 /*
+ * This class is used by primitive processors to build their fragment code.
+ */
+class GrGLSLPPFragmentBuilder : public GrGLSLFPFragmentBuilder {
+public:
+    /** Appease the compiler; the derived class initializes GrGLSLFragmentBuilder. */
+    GrGLSLPPFragmentBuilder() : GrGLSLFragmentBuilder(nullptr) {}
+
+    /**
+     * Overrides the fragment's sample coverage. The provided mask determines which samples will now
+     * be written out to the framebuffer. Note that this mask can be reduced by a future call to
+     * maskSampleCoverage.
+     *
+     * If a primitive processor uses this method, it must guarantee that every codepath through the
+     * shader overrides the sample mask at some point.
+     *
+     * @param mask    int that contains the new coverage mask. Bit N corresponds to the Nth sample.
+     *
+     * Requires NV_sample_mask_override_coverage.
+     */
+    virtual void overrideSampleCoverage(const char* mask) = 0;
+};
+
+/*
  * This class is used by Xfer processors to build their fragment code.
  */
 class GrGLSLXPFragmentBuilder : virtual public GrGLSLFragmentBuilder {
@@ -83,14 +148,22 @@
 /*
  * This class implements the various fragment builder interfaces.
  */
-class GrGLSLFragmentShaderBuilder : public GrGLSLFPFragmentBuilder, public GrGLSLXPFragmentBuilder {
+class GrGLSLFragmentShaderBuilder : public GrGLSLPPFragmentBuilder, public GrGLSLXPFragmentBuilder {
 public:
+   /** Returns a nonzero key for a surface's origin. This should only be called if a processor will
+       use the fragment position and/or sample locations. */
+    static uint8_t KeyForSurfaceOrigin(GrSurfaceOrigin);
+
     GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program);
 
     // Shared GrGLSLFragmentBuilder interface.
+    bool enableFeature(GLSLFeature) override;
     virtual SkString ensureCoords2D(const GrShaderVar&) override;
 
     // GrGLSLFPFragmentBuilder interface.
+    void appendOffsetToSample(const char* sampleIdx, Coordinates) override;
+    void maskSampleCoverage(const char* mask, bool invert = false) override;
+    void overrideSampleCoverage(const char* mask) override;
     const SkString& getMangleString() const override { return fMangleString; }
     void onBeforeChildProcEmitCode() override;
     void onAfterChildProcEmitCode() override;
@@ -112,8 +185,10 @@
 #ifdef SK_DEBUG
     // As GLSLProcessors emit code, there are some conditions we need to verify.  We use the below
     // state to track this.  The reset call is called per processor emitted.
+    GrProcessor::RequiredFeatures usedProcessorFeatures() const { return fUsedProcessorFeatures; }
     bool hasReadDstColor() const { return fHasReadDstColor; }
     void resetVerification() {
+        fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
         fHasReadDstColor = false;
     }
 #endif
@@ -124,6 +199,7 @@
     GrSurfaceOrigin getSurfaceOrigin() const;
 
     void onFinalize() override;
+    void defineSampleOffsetArray(const char* name, const SkMatrix&);
 
     static const char* kDstColorName;
 
@@ -151,11 +227,14 @@
     bool          fHasCustomColorOutput;
     int           fCustomColorOutputIndex;
     bool          fHasSecondaryOutput;
+    uint8_t       fUsedSampleOffsetArrays;
+    bool          fHasInitializedSampleMask;
     bool          fForceHighPrecision;
 
 #ifdef SK_DEBUG
     // some state to verify shaders and effects are consistent, this is reset between effects by
     // the program creator
+    GrProcessor::RequiredFeatures fUsedProcessorFeatures;
     bool fHasReadDstColor;
 #endif
 
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
index e31f7c2..02fa2e7 100644
--- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
@@ -36,7 +36,7 @@
     return combined;
 }
 
-void GrGLSLPrimitiveProcessor::setupUniformColor(GrGLSLFragmentBuilder* fragBuilder,
+void GrGLSLPrimitiveProcessor::setupUniformColor(GrGLSLPPFragmentBuilder* fragBuilder,
                                                  GrGLSLUniformHandler* uniformHandler,
                                                  const char* outputName,
                                                  UniformHandle* colorUniform) {
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
index dc398a4..30ca143 100644
--- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
@@ -14,7 +14,7 @@
 #include "glsl/GrGLSLUniformHandler.h"
 
 class GrPrimitiveProcessor;
-class GrGLSLFragmentBuilder;
+class GrGLSLPPFragmentBuilder;
 class GrGLSLGeometryBuilder;
 class GrGLSLGPBuilder;
 class GrGLSLVaryingHandler;
@@ -67,7 +67,7 @@
     struct EmitArgs {
         EmitArgs(GrGLSLVertexBuilder* vertBuilder,
                  GrGLSLGeometryBuilder* geomBuilder,
-                 GrGLSLFragmentBuilder* fragBuilder,
+                 GrGLSLPPFragmentBuilder* fragBuilder,
                  GrGLSLVaryingHandler* varyingHandler,
                  GrGLSLUniformHandler* uniformHandler,
                  const GrShaderCaps* caps,
@@ -93,7 +93,7 @@
             , fFPCoordTransformHandler(transformHandler) {}
         GrGLSLVertexBuilder* fVertBuilder;
         GrGLSLGeometryBuilder* fGeomBuilder;
-        GrGLSLFragmentBuilder* fFragBuilder;
+        GrGLSLPPFragmentBuilder* fFragBuilder;
         GrGLSLVaryingHandler* fVaryingHandler;
         GrGLSLUniformHandler* fUniformHandler;
         const GrShaderCaps* fShaderCaps;
@@ -129,7 +129,7 @@
     static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
 
 protected:
-    void setupUniformColor(GrGLSLFragmentBuilder* fragBuilder,
+    void setupUniformColor(GrGLSLPPFragmentBuilder* fragBuilder,
                            GrGLSLUniformHandler* uniformHandler,
                            const char* outputName,
                            UniformHandle* colorUniform);
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 914a958..04ebc6a 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -360,13 +360,16 @@
 
 #ifdef SK_DEBUG
 void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
+    SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());
 }
 
 void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
+    SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures());
     SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
 }
 
 void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
+    SkASSERT(fFS.usedProcessorFeatures() == fp.requiredFeatures());
 }
 #endif
 
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index 8459218..0708625 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -173,7 +173,9 @@
         kTexelBuffer_GLSLPrivateFeature,
         kFramebufferFetch_GLSLPrivateFeature,
         kNoPerspectiveInterpolation_GLSLPrivateFeature,
-        kLastGLSLPrivateFeature = kNoPerspectiveInterpolation_GLSLPrivateFeature
+        kSampleVariables_GLSLPrivateFeature,
+        kSampleMaskOverrideCoverage_GLSLPrivateFeature,
+        kLastGLSLPrivateFeature = kSampleMaskOverrideCoverage_GLSLPrivateFeature
     };
 
     /*