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:
parent
061aa81252
commit
9204ca678b
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -54,7 +54,6 @@ public:
|
||||
kEllipticalRRectEffect_ClassID,
|
||||
kGP_ClassID,
|
||||
kVertexColorSpaceBenchGP_ClassID,
|
||||
kGrAlphaThresholdFragmentProcessor_ClassID,
|
||||
kGrBicubicEffect_ClassID,
|
||||
kGrBitmapTextGeoProc_ClassID,
|
||||
kGrCircleBlurFragmentProcessor_ClassID,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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]);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
@ -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
|
Loading…
Reference in New Issue
Block a user