Add gl_SampleMask functionality to fragment builders

Adds methods for overriding and masking a fragment's sample mask.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1690963003

Committed: https://skia.googlesource.com/skia/+/533cefe5b9c7cec2592fc7ca00ee4cf69a26c094

Review URL: https://codereview.chromium.org/1690963003
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index 4277cf4..44db57e 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -74,6 +74,7 @@
     , fHasCustomColorOutput(false)
     , fCustomColorOutputIndex(-1)
     , fHasSecondaryOutput(false)
+    , fHasInitializedSampleMask(false)
     , fHasReadDstColor(false)
     , fHasReadFragmentPosition(false) {
     fSubstageIndices.push_back(0);
@@ -169,6 +170,47 @@
     }
 }
 
+void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool invert) {
+    const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps();
+    if (!glslCaps.sampleVariablesSupport()) {
+        SkDEBUGFAIL("Attempted to mask sample coverage without support.");
+        return;
+    }
+    if (const char* extension = glslCaps.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 GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps();
+    if (!glslCaps.sampleMaskOverrideCoverageSupport()) {
+        SkDEBUGFAIL("Attempted to override sample coverage without support.");
+        return;
+    }
+    SkASSERT(glslCaps.sampleVariablesSupport());
+    if (const char* extension = glslCaps.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, GrShaderVar::kOut_TypeModifier,
+                                 "gl_SampleMask", 1, kHigh_GrSLPrecision,
+                                 "override_coverage");
+    }
+    this->codeAppendf("gl_SampleMask[0] = %s;", mask);
+    fHasInitializedSampleMask = true;
+}
+
 const char* GrGLSLFragmentShaderBuilder::dstColor() {
     fHasReadDstColor = true;