Lift the tessellation atlas into its own path renderer

Creates a new path renderer, GrAtlasPathRenderer, that handles all the
atlasing. Managing the atlas in its own path renderer gives us more
control over when atlasing happens in the chain, will allow us to more
easily use the atlas in kCoverage mode, and makes the clipping code
cleaner.

Bug: skia:12258
Change-Id: Ie0b669974936c23895c8ab794e2d97206ed140f8
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/431896
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/effects/GrModulateAtlasCoverageEffect.cpp b/src/gpu/effects/GrModulateAtlasCoverageEffect.cpp
new file mode 100644
index 0000000..c23e1e6
--- /dev/null
+++ b/src/gpu/effects/GrModulateAtlasCoverageEffect.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2021 Google LLC.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/effects/GrModulateAtlasCoverageEffect.h"
+
+#include "src/gpu/GrDynamicAtlas.h"
+#include "src/gpu/effects/GrTextureEffect.h"
+
+GrModulateAtlasCoverageEffect::GrModulateAtlasCoverageEffect(
+        Flags flags,
+        std::unique_ptr<GrFragmentProcessor> inputFP,
+        GrSurfaceProxyView atlasView,
+        const SkMatrix& devToAtlasMatrix,
+        const SkIRect& devIBounds)
+        : GrFragmentProcessor(kTessellate_GrModulateAtlasCoverageEffect_ClassID,
+                              kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+        , fFlags(flags)
+        , fBounds((fFlags & Flags::kCheckBounds) ? devIBounds : SkIRect{0,0,0,0}) {
+    this->registerChild(std::move(inputFP));
+    this->registerChild(GrTextureEffect::Make(std::move(atlasView), kUnknown_SkAlphaType,
+                                              devToAtlasMatrix, GrSamplerState::Filter::kNearest),
+                        SkSL::SampleUsage::Explicit());
+}
+
+GrModulateAtlasCoverageEffect::GrModulateAtlasCoverageEffect(
+        const GrModulateAtlasCoverageEffect& that)
+        : GrFragmentProcessor(kTessellate_GrModulateAtlasCoverageEffect_ClassID,
+                              kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+        , fFlags(that.fFlags)
+        , fBounds(that.fBounds) {
+    this->cloneAndRegisterAllChildProcessors(that);
+}
+
+std::unique_ptr<GrGLSLFragmentProcessor> GrModulateAtlasCoverageEffect::onMakeProgramImpl() const {
+    class Impl : public GrGLSLFragmentProcessor {
+        void emitCode(EmitArgs& args) override {
+            auto fp = args.fFp.cast<GrModulateAtlasCoverageEffect>();
+            auto f = args.fFragBuilder;
+            auto uniHandler = args.fUniformHandler;
+            SkString inputColor = this->invokeChild(0, args);
+            f->codeAppend("half coverage = 0;");
+            if (fp.fFlags & Flags::kCheckBounds) {
+                const char* boundsName;
+                fBoundsUniform = uniHandler->addUniform(&fp, kFragment_GrShaderFlag,
+                                                        kFloat4_GrSLType, "bounds", &boundsName);
+                // Are we inside the path's valid atlas bounds?
+                f->codeAppendf("if (all(greaterThan(sk_FragCoord.xy, %s.xy)) && "
+                                   "all(lessThan(sk_FragCoord.xy, %s.zw))) ",
+                               boundsName, boundsName);
+            }
+            f->codeAppendf("{");
+            SkString atlasCoverage = this->invokeChild(1, args, "sk_FragCoord.xy");
+            f->codeAppendf("coverage = %s.a;", atlasCoverage.c_str());
+            f->codeAppendf("}");
+            const char* coverageMaybeInvertName;
+            fCoverageMaybeInvertUniform = uniHandler->addUniform(&fp, kFragment_GrShaderFlag,
+                                                                 kHalf2_GrSLType, "coverageInvert",
+                                                                 &coverageMaybeInvertName);
+            // Invert coverage, if needed.
+            f->codeAppendf("coverage = coverage * %s.x + %s.y;",
+                           coverageMaybeInvertName, coverageMaybeInvertName);
+            f->codeAppendf("return %s * coverage;", inputColor.c_str());
+        }
+        void onSetData(const GrGLSLProgramDataManager& pdman,
+                       const GrFragmentProcessor& processor) override {
+            auto fp = processor.cast<GrModulateAtlasCoverageEffect>();
+            if (fp.fFlags & Flags::kCheckBounds) {
+                pdman.set4fv(fBoundsUniform, 1, SkRect::Make(fp.fBounds).asScalars());
+            }
+            if (fp.fFlags & Flags::kInvertCoverage) {
+                pdman.set2f(fCoverageMaybeInvertUniform, -1, 1);  // -1*coverage + 1 = 1 - coverage.
+            } else {
+                pdman.set2f(fCoverageMaybeInvertUniform, 1, 0);  // 1*coverage + 0 = coverage.
+            }
+        }
+        UniformHandle fBoundsUniform;
+        UniformHandle fCoverageMaybeInvertUniform;
+    };
+    return std::make_unique<Impl>();
+}