| /* |
| * 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 "src/gpu/KeyBuilder.h" |
| #include "src/gpu/ganesh/GrDynamicAtlas.h" |
| #include "src/gpu/ganesh/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(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 { |
| 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>(); |
| } |