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