Replace GrAlphaThresholdFP with GrSkSLFP

This also introduces "IgnoreOptFlags", for child FPs that should not
influence the OptFlags of the parent.

Change-Id: I8f7ba2ca59f612bd7d6e226b96e9fd94d656150b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/421929
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2021-06-25 12:35:16 -04:00 committed by Skia Commit-Bot
parent 061aa81252
commit 9204ca678b
10 changed files with 82 additions and 238 deletions

View File

@ -308,8 +308,6 @@ skia_gpu_sources = [
"$_src/gpu/effects/GrTextureEffect.h",
"$_src/gpu/effects/GrYUVtoRGBEffect.cpp",
"$_src/gpu/effects/GrYUVtoRGBEffect.h",
"$_src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp",
"$_src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h",
"$_src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp",
"$_src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h",
"$_src/gpu/effects/generated/GrConfigConversionEffect.cpp",

View File

@ -207,7 +207,6 @@ skia_sksl_gpu_sources = [
]
skia_gpu_processor_sources = [
"$_src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp",
"$_src/gpu/effects/GrCircleBlurFragmentProcessor.fp",
"$_src/gpu/effects/GrConfigConversionEffect.fp",
"$_src/gpu/effects/GrDitherEffect.fp",

View File

@ -16,13 +16,14 @@
#if SK_SUPPORT_GPU
#include "include/gpu/GrRecordingContext.h"
#include "src/core/SkRuntimeEffectPriv.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/GrTextureProxy.h"
#include "src/gpu/effects/GrSkSLFP.h"
#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h"
#endif
namespace {
@ -124,6 +125,41 @@ GrSurfaceProxyView SkAlphaThresholdImageFilter::createMaskTexture(
return rtContext->readSurfaceView();
}
static std::unique_ptr<GrFragmentProcessor> make_alpha_threshold_fp(
std::unique_ptr<GrFragmentProcessor> inputFP,
std::unique_ptr<GrFragmentProcessor> maskFP,
float innerThreshold,
float outerThreshold) {
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
uniform shader maskFP;
uniform half innerThreshold;
uniform half outerThreshold;
half4 main(float2 xy, half4 color) {
half4 mask_color = sample(maskFP, xy);
if (mask_color.a < 0.5) {
if (color.a > outerThreshold) {
half scale = outerThreshold / color.a;
color.rgb *= scale;
color.a = outerThreshold;
}
} else if (color.a < innerThreshold) {
half scale = innerThreshold / max(0.001, color.a);
color.rgb *= scale;
color.a = innerThreshold;
}
return color;
}
)");
return GrSkSLFP::Make(effect, "AlphaThreshold", std::move(inputFP),
(outerThreshold >= 1.0f) ? GrSkSLFP::OptFlags::kPreservesOpaqueInput
: GrSkSLFP::OptFlags::kNone,
"maskFP", GrSkSLFP::IgnoreOptFlags(std::move(maskFP)),
"innerThreshold", innerThreshold,
"outerThreshold", outerThreshold);
}
#endif
sk_sp<SkSpecialImage> SkAlphaThresholdImageFilter::onFilterImage(const Context& ctx,
@ -176,7 +212,7 @@ sk_sp<SkSpecialImage> SkAlphaThresholdImageFilter::onFilterImage(const Context&
return nullptr;
}
auto thresholdFP = GrAlphaThresholdFragmentProcessor::Make(
auto thresholdFP = make_alpha_threshold_fp(
std::move(textureFP), std::move(maskFP), fInnerThreshold, fOuterThreshold);
if (!thresholdFP) {
return nullptr;

View File

@ -54,7 +54,6 @@ public:
kEllipticalRRectEffect_ClassID,
kGP_ClassID,
kVertexColorSpaceBenchGP_ClassID,
kGrAlphaThresholdFragmentProcessor_ClassID,
kGrBicubicEffect_ClassID,
kGrBitmapTextGeoProc_ClassID,
kGrCircleBlurFragmentProcessor_ClassID,

View File

@ -146,7 +146,7 @@ SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories()
* we verify the count is as expected. If a new factory is added, then these numbers must be
* manually adjusted.
*/
static constexpr int kFPFactoryCount = 22;
static constexpr int kFPFactoryCount = 21;
static constexpr int kGPFactoryCount = 14;
static constexpr int kXPFactoryCount = 4;

View File

@ -1,47 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
in fragmentProcessor inputFP;
in fragmentProcessor maskFP;
in uniform half innerThreshold;
in uniform half outerThreshold;
@optimizationFlags {
ProcessorOptimizationFlags(inputFP.get()) &
((outerThreshold >= 1.0) ? kPreservesOpaqueInput_OptimizationFlag : kNone_OptimizationFlags)
}
half4 main() {
half4 color = sample(inputFP);
half4 mask_color = sample(maskFP);
if (mask_color.a < 0.5) {
if (color.a > outerThreshold) {
half scale = outerThreshold / color.a;
color.rgb *= scale;
color.a = outerThreshold;
}
} else if (color.a < innerThreshold) {
half scale = innerThreshold / max(0.001, color.a);
color.rgb *= scale;
color.a = innerThreshold;
}
return color;
}
@test(testData) {
// Make the inner and outer thresholds be in [0, 1].
float outerThresh = testData->fRandom->nextUScalar1();
float innerThresh = testData->fRandom->nextUScalar1();
std::unique_ptr<GrFragmentProcessor> inputChild, maskChild;
if (testData->fRandom->nextBool()) {
inputChild = GrProcessorUnitTest::MakeChildFP(testData);
}
maskChild = GrProcessorUnitTest::MakeChildFP(testData);
return GrAlphaThresholdFragmentProcessor::Make(std::move(inputChild), std::move(maskChild),
innerThresh, outerThresh);
}

View File

@ -260,7 +260,7 @@ std::unique_ptr<GrSkSLFP> GrSkSLFP::MakeWithData(
GrSkSLFP(std::move(effect), name, OptFlags::kNone));
sk_careful_memcpy(fp->uniformData(), uniforms->data(), uniformSize);
for (auto& childFP : childFPs) {
fp->addChild(std::move(childFP));
fp->addChild(std::move(childFP), /*mergeOptFlags=*/true);
}
if (inputFP) {
fp->setInput(std::move(inputFP));
@ -309,11 +309,13 @@ GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
this->cloneAndRegisterAllChildProcessors(other);
}
void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child, bool mergeOptFlags) {
SkASSERTF(fInputChildIndex == -1, "all addChild calls must happen before setInput");
int childIndex = this->numChildProcessors();
SkASSERT((size_t)childIndex < fEffect->fSampleUsages.size());
this->mergeOptimizationFlags(ProcessorOptimizationFlags(child.get()));
if (mergeOptFlags) {
this->mergeOptimizationFlags(ProcessorOptimizationFlags(child.get()));
}
this->registerChild(std::move(child), fEffect->fSampleUsages[childIndex]);
}

View File

@ -59,6 +59,13 @@ public:
return {condition, value};
}
struct GrIgnoreOptFlags {
std::unique_ptr<GrFragmentProcessor> child;
};
static GrIgnoreOptFlags IgnoreOptFlags(std::unique_ptr<GrFragmentProcessor> child) {
return {std::move(child)};
}
enum class OptFlags : uint32_t {
kNone = kNone_OptimizationFlags,
kCompatibleWithCoverageAsAlpha = kCompatibleWithCoverageAsAlpha_OptimizationFlag,
@ -145,7 +152,7 @@ private:
GrSkSLFP(sk_sp<SkRuntimeEffect> effect, const char* name, OptFlags optFlags);
GrSkSLFP(const GrSkSLFP& other);
void addChild(std::unique_ptr<GrFragmentProcessor> child);
void addChild(std::unique_ptr<GrFragmentProcessor> child, bool mergeOptFlags);
void setInput(std::unique_ptr<GrFragmentProcessor> input);
std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;
@ -189,7 +196,19 @@ private:
Args&&... remainder) {
// Child FP case -- register the child, then continue processing the remaining arguments.
// Children aren't "uniforms" here, so the data & flags pointers don't advance.
this->addChild(std::move(child));
this->addChild(std::move(child), /*mergeOptFlags=*/true);
this->appendArgs(uniformDataPtr, uniformFlagsPtr, std::forward<Args>(remainder)...);
}
// As above, but we don't merge in the child's optimization flags
template <typename... Args>
void appendArgs(uint8_t* uniformDataPtr,
UniformFlags* uniformFlagsPtr,
const char* name,
GrIgnoreOptFlags&& child,
Args&&... remainder) {
// Child FP case -- register the child, then continue processing the remaining arguments.
// Children aren't "uniforms" here, so the data & flags pointers don't advance.
this->addChild(std::move(child.child), /*mergeOptFlags=*/false);
this->appendArgs(uniformDataPtr, uniformFlagsPtr, std::forward<Args>(remainder)...);
}
template <typename T, typename... Args>
@ -252,6 +271,23 @@ private:
cIter->name.c_str(), name);
checkArgs(uIter, uEnd, ++cIter, cEnd, std::forward<Args>(remainder)...);
}
template <typename... Args>
static void checkArgs(uniform_iterator uIter,
uniform_iterator uEnd,
child_iterator cIter,
child_iterator cEnd,
const char* name,
GrIgnoreOptFlags&& child,
Args&&... remainder) {
// NOTE: This function (necessarily) gets an rvalue reference to child, but deliberately
// does not use it. We leave it intact, and our caller (Make) will pass another rvalue
// reference to appendArgs, which will then move it to call addChild.
SkASSERTF(cIter != cEnd, "Too many children, wasn't expecting '%s'", name);
SkASSERTF(cIter->name.equals(name),
"Expected child '%s', got '%s' instead",
cIter->name.c_str(), name);
checkArgs(uIter, uEnd, ++cIter, cEnd, std::forward<Args>(remainder)...);
}
template <typename T, typename... Args>
static void checkArgs(uniform_iterator uIter,
uniform_iterator uEnd,

View File

@ -1,122 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/**************************************************************************************************
*** This file was autogenerated from GrAlphaThresholdFragmentProcessor.fp; do not modify.
**************************************************************************************************/
#include "GrAlphaThresholdFragmentProcessor.h"
#include "src/core/SkUtils.h"
#include "src/gpu/GrTexture.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
#include "src/sksl/SkSLCPP.h"
#include "src/sksl/SkSLUtil.h"
class GrGLSLAlphaThresholdFragmentProcessor : public GrGLSLFragmentProcessor {
public:
GrGLSLAlphaThresholdFragmentProcessor() {}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrAlphaThresholdFragmentProcessor& _outer =
args.fFp.cast<GrAlphaThresholdFragmentProcessor>();
(void)_outer;
auto innerThreshold = _outer.innerThreshold;
(void)innerThreshold;
auto outerThreshold = _outer.outerThreshold;
(void)outerThreshold;
innerThresholdVar = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "innerThreshold");
outerThresholdVar = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "outerThreshold");
SkString _sample0 = this->invokeChild(0, args);
fragBuilder->codeAppendf(
R"SkSL(half4 color = %s;)SkSL", _sample0.c_str());
SkString _sample1 = this->invokeChild(1, args);
fragBuilder->codeAppendf(
R"SkSL(
half4 mask_color = %s;
if (mask_color.w < 0.5) {
if (color.w > %s) {
half scale = %s / color.w;
color.xyz *= scale;
color.w = %s;
}
} else if (color.w < %s) {
half scale = %s / max(0.0010000000474974513, color.w);
color.xyz *= scale;
color.w = %s;
}
return color;
)SkSL",
_sample1.c_str(),
args.fUniformHandler->getUniformCStr(outerThresholdVar),
args.fUniformHandler->getUniformCStr(outerThresholdVar),
args.fUniformHandler->getUniformCStr(outerThresholdVar),
args.fUniformHandler->getUniformCStr(innerThresholdVar),
args.fUniformHandler->getUniformCStr(innerThresholdVar),
args.fUniformHandler->getUniformCStr(innerThresholdVar));
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& _proc) override {
const GrAlphaThresholdFragmentProcessor& _outer =
_proc.cast<GrAlphaThresholdFragmentProcessor>();
{
pdman.set1f(innerThresholdVar, _outer.innerThreshold);
pdman.set1f(outerThresholdVar, _outer.outerThreshold);
}
}
UniformHandle innerThresholdVar;
UniformHandle outerThresholdVar;
};
std::unique_ptr<GrGLSLFragmentProcessor> GrAlphaThresholdFragmentProcessor::onMakeProgramImpl()
const {
return std::make_unique<GrGLSLAlphaThresholdFragmentProcessor>();
}
void GrAlphaThresholdFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {}
bool GrAlphaThresholdFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const {
const GrAlphaThresholdFragmentProcessor& that = other.cast<GrAlphaThresholdFragmentProcessor>();
(void)that;
if (innerThreshold != that.innerThreshold) return false;
if (outerThreshold != that.outerThreshold) return false;
return true;
}
GrAlphaThresholdFragmentProcessor::GrAlphaThresholdFragmentProcessor(
const GrAlphaThresholdFragmentProcessor& src)
: INHERITED(kGrAlphaThresholdFragmentProcessor_ClassID, src.optimizationFlags())
, innerThreshold(src.innerThreshold)
, outerThreshold(src.outerThreshold) {
this->cloneAndRegisterAllChildProcessors(src);
}
std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::clone() const {
return std::make_unique<GrAlphaThresholdFragmentProcessor>(*this);
}
#if GR_TEST_UTILS
SkString GrAlphaThresholdFragmentProcessor::onDumpInfo() const {
return SkStringPrintf("(innerThreshold=%f, outerThreshold=%f)", innerThreshold, outerThreshold);
}
#endif
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrAlphaThresholdFragmentProcessor);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::TestCreate(
GrProcessorTestData* testData) {
// Make the inner and outer thresholds be in [0, 1].
float outerThresh = testData->fRandom->nextUScalar1();
float innerThresh = testData->fRandom->nextUScalar1();
std::unique_ptr<GrFragmentProcessor> inputChild, maskChild;
if (testData->fRandom->nextBool()) {
inputChild = GrProcessorUnitTest::MakeChildFP(testData);
}
maskChild = GrProcessorUnitTest::MakeChildFP(testData);
return GrAlphaThresholdFragmentProcessor::Make(
std::move(inputChild), std::move(maskChild), innerThresh, outerThresh);
}
#endif

View File

@ -1,57 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/**************************************************************************************************
*** This file was autogenerated from GrAlphaThresholdFragmentProcessor.fp; do not modify.
**************************************************************************************************/
#ifndef GrAlphaThresholdFragmentProcessor_DEFINED
#define GrAlphaThresholdFragmentProcessor_DEFINED
#include "include/core/SkM44.h"
#include "include/core/SkTypes.h"
#include "src/gpu/GrFragmentProcessor.h"
class GrAlphaThresholdFragmentProcessor : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
std::unique_ptr<GrFragmentProcessor> maskFP,
float innerThreshold,
float outerThreshold) {
return std::unique_ptr<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor(
std::move(inputFP), std::move(maskFP), innerThreshold, outerThreshold));
}
GrAlphaThresholdFragmentProcessor(const GrAlphaThresholdFragmentProcessor& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "AlphaThresholdFragmentProcessor"; }
float innerThreshold;
float outerThreshold;
private:
GrAlphaThresholdFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP,
std::unique_ptr<GrFragmentProcessor> maskFP,
float innerThreshold,
float outerThreshold)
: INHERITED(kGrAlphaThresholdFragmentProcessor_ClassID,
(OptimizationFlags)ProcessorOptimizationFlags(inputFP.get()) &
((outerThreshold >= 1.0) ? kPreservesOpaqueInput_OptimizationFlag
: kNone_OptimizationFlags))
, innerThreshold(innerThreshold)
, outerThreshold(outerThreshold) {
this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
this->registerChild(std::move(maskFP), SkSL::SampleUsage::PassThrough());
}
std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
#if GR_TEST_UTILS
SkString onDumpInfo() const override;
#endif
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
using INHERITED = GrFragmentProcessor;
};
#endif