| /* | |
| * 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/ganesh/effects/GrModulateAtlasCoverageEffect.h" | |
| #include "include/core/SkAlphaType.h" | |
| #include "include/core/SkSamplingOptions.h" | |
| #include "include/core/SkString.h" | |
| #include "include/private/SkSLSampleUsage.h" | |
| #include "include/private/gpu/ganesh/GrTypesPriv.h" | |
| #include "src/core/SkSLTypeShared.h" | |
| #include "src/gpu/KeyBuilder.h" | |
| #include "src/gpu/ganesh/GrSamplerState.h" | |
| #include "src/gpu/ganesh/GrSurfaceProxyView.h" | |
| #include "src/gpu/ganesh/effects/GrTextureEffect.h" | |
| #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h" | |
| #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h" | |
| #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h" | |
| #include <utility> | |
| class SkMatrix; | |
| struct GrShaderCaps; | |
| 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(that) | |
| , fFlags(that.fFlags) | |
| , fBounds(that.fBounds) {} | |
| void GrModulateAtlasCoverageEffect::onAddToKey(const GrShaderCaps&, | |
| skgpu::KeyBuilder* b) const { | |
| b->add32(fFlags & Flags::kCheckBounds); | |
| } | |
| std::unique_ptr<GrFragmentProcessor::ProgramImpl> | |
| GrModulateAtlasCoverageEffect::onMakeProgramImpl() const { | |
| class Impl : public ProgramImpl { | |
| 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, | |
| SkSLType::kFloat4, "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, | |
| SkSLType::kHalf2, "coverageInvert", | |
| &coverageMaybeInvertName); | |
| // Invert coverage, if needed. | |
| f->codeAppendf("coverage = coverage * %s.x + %s.y;", | |
| coverageMaybeInvertName, coverageMaybeInvertName); | |
| f->codeAppendf("return %s * coverage;", inputColor.c_str()); | |
| } | |
| private: | |
| void onSetData(const GrGLSLProgramDataManager& pdman, | |
| const GrFragmentProcessor& processor) override { | |
| const 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>(); | |
| } |