1/*
2 * Copyright 2021 Google LLC.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "src/gpu/effects/GrModulateAtlasCoverageEffect.h"
9
10#include "src/gpu/GrDynamicAtlas.h"
11#include "src/gpu/effects/GrTextureEffect.h"
12
13GrModulateAtlasCoverageEffect::GrModulateAtlasCoverageEffect(
14        Flags flags,
15        std::unique_ptr<GrFragmentProcessor> inputFP,
16        GrSurfaceProxyView atlasView,
17        const SkMatrix& devToAtlasMatrix,
18        const SkIRect& devIBounds)
19        : GrFragmentProcessor(kTessellate_GrModulateAtlasCoverageEffect_ClassID,
20                              kCompatibleWithCoverageAsAlpha_OptimizationFlag)
21        , fFlags(flags)
22        , fBounds((fFlags & Flags::kCheckBounds) ? devIBounds : SkIRect{0,0,0,0}) {
23    this->registerChild(std::move(inputFP));
24    this->registerChild(GrTextureEffect::Make(std::move(atlasView), kUnknown_SkAlphaType,
25                                              devToAtlasMatrix, GrSamplerState::Filter::kNearest),
26                        SkSL::SampleUsage::Explicit());
27}
28
29GrModulateAtlasCoverageEffect::GrModulateAtlasCoverageEffect(
30        const GrModulateAtlasCoverageEffect& that)
31        : GrFragmentProcessor(that)
32        , fFlags(that.fFlags)
33        , fBounds(that.fBounds) {}
34
35std::unique_ptr<GrFragmentProcessor::ProgramImpl>
36GrModulateAtlasCoverageEffect::onMakeProgramImpl() const {
37    class Impl : public ProgramImpl {
38        void emitCode(EmitArgs& args) override {
39            auto fp = args.fFp.cast<GrModulateAtlasCoverageEffect>();
40            auto f = args.fFragBuilder;
41            auto uniHandler = args.fUniformHandler;
42            SkString inputColor = this->invokeChild(0, args);
43            f->codeAppend("half coverage = 0;");
44            if (fp.fFlags & Flags::kCheckBounds) {
45                const char* boundsName;
46                fBoundsUniform = uniHandler->addUniform(&fp, kFragment_GrShaderFlag,
47                                                        kFloat4_GrSLType, "bounds", &boundsName);
48                // Are we inside the path's valid atlas bounds?
49                f->codeAppendf("if (all(greaterThan(sk_FragCoord.xy, %s.xy)) && "
50                                   "all(lessThan(sk_FragCoord.xy, %s.zw))) ",
51                               boundsName, boundsName);
52            }
53            f->codeAppendf("{");
54            SkString atlasCoverage = this->invokeChild(1, args, "sk_FragCoord.xy");
55            f->codeAppendf("coverage = %s.a;", atlasCoverage.c_str());
56            f->codeAppendf("}");
57            const char* coverageMaybeInvertName;
58            fCoverageMaybeInvertUniform = uniHandler->addUniform(&fp, kFragment_GrShaderFlag,
59                                                                 kHalf2_GrSLType, "coverageInvert",
60                                                                 &coverageMaybeInvertName);
61            // Invert coverage, if needed.
62            f->codeAppendf("coverage = coverage * %s.x + %s.y;",
63                           coverageMaybeInvertName, coverageMaybeInvertName);
64            f->codeAppendf("return %s * coverage;", inputColor.c_str());
65        }
66
67    private:
68        void onSetData(const GrGLSLProgramDataManager& pdman,
69                       const GrFragmentProcessor& processor) override {
70            auto fp = processor.cast<GrModulateAtlasCoverageEffect>();
71            if (fp.fFlags & Flags::kCheckBounds) {
72                pdman.set4fv(fBoundsUniform, 1, SkRect::Make(fp.fBounds).asScalars());
73            }
74            if (fp.fFlags & Flags::kInvertCoverage) {
75                pdman.set2f(fCoverageMaybeInvertUniform, -1, 1);  // -1*coverage + 1 = 1 - coverage.
76            } else {
77                pdman.set2f(fCoverageMaybeInvertUniform, 1, 0);  // 1*coverage + 0 = coverage.
78            }
79        }
80        UniformHandle fBoundsUniform;
81        UniformHandle fCoverageMaybeInvertUniform;
82    };
83
84    return std::make_unique<Impl>();
85}
86