blob: cd32a477d41c373a555bb7ee126b6b104f593092 [file] [log] [blame]
/*
* 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>();
}