Hoist matrix transform out of GrRectBlurEffect
Change-Id: I3da5112801d244e3200ce05b6a288f75882f7ef3 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/423297 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
e1f72377e5
commit
e5926135cc
@ -18,15 +18,12 @@
|
||||
#include "src/gpu/GrShaderCaps.h"
|
||||
#include "src/gpu/GrThreadSafeCache.h"
|
||||
#include "src/gpu/SkGr.h"
|
||||
#include "src/gpu/effects/GrMatrixEffect.h"
|
||||
#include "src/gpu/effects/GrTextureEffect.h"
|
||||
}
|
||||
|
||||
in fragmentProcessor inputFP;
|
||||
in uniform float4 rect;
|
||||
|
||||
layout(key) in bool applyInvVM;
|
||||
layout(when=applyInvVM) in uniform float3x3 invVM;
|
||||
|
||||
// Effect that is a LUT for integral of normal distribution. The value at x:[0,6*sigma] is the
|
||||
// integral from -inf to (3*sigma - x). I.e. x is mapped from [0, 6*sigma] to [3*sigma to -3*sigma].
|
||||
// The flip saves a reversal in the shader.
|
||||
@ -37,7 +34,7 @@ in fragmentProcessor integral;
|
||||
layout(key) in bool isFast;
|
||||
|
||||
@optimizationFlags {
|
||||
ProcessorOptimizationFlags(inputFP.get()) & kCompatibleWithCoverageAsAlpha_OptimizationFlag
|
||||
kCompatibleWithCoverageAsAlpha_OptimizationFlag
|
||||
}
|
||||
|
||||
@class {
|
||||
@ -158,22 +155,19 @@ static std::unique_ptr<GrFragmentProcessor> MakeIntegralFP(GrRecordingContext* r
|
||||
// less than 6 sigma wide then things aren't so simple and we have to consider both the
|
||||
// left and right edge of the rectangle (and similar in y).
|
||||
bool isFast = insetRect.isSorted();
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(std::move(inputFP),
|
||||
insetRect,
|
||||
!invM.isIdentity(),
|
||||
invM,
|
||||
std::unique_ptr<GrFragmentProcessor> fp(new GrRectBlurEffect(insetRect,
|
||||
std::move(integral),
|
||||
isFast));
|
||||
if (!invM.isIdentity()) {
|
||||
fp = GrMatrixEffect::Make(invM, std::move(fp));
|
||||
}
|
||||
fp = GrFragmentProcessor::DeviceSpace(std::move(fp));
|
||||
return GrFragmentProcessor::MulInputByChildAlpha(std::move(fp));
|
||||
}
|
||||
}
|
||||
|
||||
half4 main() {
|
||||
half4 main(float2 pos) {
|
||||
half xCoverage, yCoverage;
|
||||
float2 pos = sk_FragCoord.xy;
|
||||
@if (applyInvVM) {
|
||||
// It'd be great if we could lift this to the VS.
|
||||
pos = (invVM*float3(pos,1)).xy;
|
||||
}
|
||||
@if (isFast) {
|
||||
// Get the smaller of the signed distance from the frag coord to the left and right
|
||||
// edges and similar for y.
|
||||
@ -205,7 +199,7 @@ half4 main() {
|
||||
yCoverage = 1 - sample(integral, half2(rect.T, 0.5)).a
|
||||
- sample(integral, half2(rect.B, 0.5)).a;
|
||||
}
|
||||
return sample(inputFP) * xCoverage * yCoverage;
|
||||
return half4(xCoverage * yCoverage);
|
||||
}
|
||||
|
||||
@test(data) {
|
||||
|
@ -26,137 +26,101 @@ public:
|
||||
(void)_outer;
|
||||
auto rect = _outer.rect;
|
||||
(void)rect;
|
||||
auto applyInvVM = _outer.applyInvVM;
|
||||
(void)applyInvVM;
|
||||
auto invVM = _outer.invVM;
|
||||
(void)invVM;
|
||||
auto isFast = _outer.isFast;
|
||||
(void)isFast;
|
||||
rectVar = args.fUniformHandler->addUniform(
|
||||
&_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "rect");
|
||||
if (applyInvVM) {
|
||||
invVMVar = args.fUniformHandler->addUniform(
|
||||
&_outer, kFragment_GrShaderFlag, kFloat3x3_GrSLType, "invVM");
|
||||
}
|
||||
fragBuilder->codeAppendf(
|
||||
R"SkSL(half xCoverage;
|
||||
half yCoverage;
|
||||
|
||||
float2 pos = sk_FragCoord.xy;
|
||||
@if (%s) {
|
||||
pos = (%s * float3(pos, 1.0)).xy;
|
||||
}
|
||||
@if (%s) {
|
||||
half2 xy = max(half2(%s.xy - pos), half2(pos - %s.zw));)SkSL",
|
||||
(_outer.applyInvVM ? "true" : "false"),
|
||||
invVMVar.isValid() ? args.fUniformHandler->getUniformCStr(invVMVar) : "float3x3(1)",
|
||||
half2 xy = max(half2(%s.xy - %s), half2(%s - %s.zw));)SkSL",
|
||||
(_outer.isFast ? "true" : "false"),
|
||||
args.fUniformHandler->getUniformCStr(rectVar),
|
||||
args.fSampleCoord,
|
||||
args.fSampleCoord,
|
||||
args.fUniformHandler->getUniformCStr(rectVar));
|
||||
SkString _coords0("float2(half2(xy.x, 0.5))");
|
||||
SkString _sample0 = this->invokeChild(1, args, _coords0.c_str());
|
||||
SkString _sample0 = this->invokeChild(0, args, _coords0.c_str());
|
||||
fragBuilder->codeAppendf(
|
||||
R"SkSL(
|
||||
xCoverage = %s.w;)SkSL",
|
||||
_sample0.c_str());
|
||||
SkString _coords1("float2(half2(xy.y, 0.5))");
|
||||
SkString _sample1 = this->invokeChild(1, args, _coords1.c_str());
|
||||
SkString _sample1 = this->invokeChild(0, args, _coords1.c_str());
|
||||
fragBuilder->codeAppendf(
|
||||
R"SkSL(
|
||||
yCoverage = %s.w;
|
||||
} else {
|
||||
half4 rect = half4(half2(%s.xy - pos), half2(pos - %s.zw));)SkSL",
|
||||
half4 rect = half4(half2(%s.xy - %s), half2(%s - %s.zw));)SkSL",
|
||||
_sample1.c_str(),
|
||||
args.fUniformHandler->getUniformCStr(rectVar),
|
||||
args.fSampleCoord,
|
||||
args.fSampleCoord,
|
||||
args.fUniformHandler->getUniformCStr(rectVar));
|
||||
SkString _coords2("float2(half2(rect.x, 0.5))");
|
||||
SkString _sample2 = this->invokeChild(1, args, _coords2.c_str());
|
||||
SkString _sample2 = this->invokeChild(0, args, _coords2.c_str());
|
||||
SkString _coords3("float2(half2(rect.z, 0.5))");
|
||||
SkString _sample3 = this->invokeChild(1, args, _coords3.c_str());
|
||||
SkString _sample3 = this->invokeChild(0, args, _coords3.c_str());
|
||||
fragBuilder->codeAppendf(
|
||||
R"SkSL(
|
||||
xCoverage = (1.0 - %s.w) - %s.w;)SkSL",
|
||||
_sample2.c_str(),
|
||||
_sample3.c_str());
|
||||
SkString _coords4("float2(half2(rect.y, 0.5))");
|
||||
SkString _sample4 = this->invokeChild(1, args, _coords4.c_str());
|
||||
SkString _sample4 = this->invokeChild(0, args, _coords4.c_str());
|
||||
SkString _coords5("float2(half2(rect.w, 0.5))");
|
||||
SkString _sample5 = this->invokeChild(1, args, _coords5.c_str());
|
||||
SkString _sample5 = this->invokeChild(0, args, _coords5.c_str());
|
||||
fragBuilder->codeAppendf(
|
||||
R"SkSL(
|
||||
yCoverage = (1.0 - %s.w) - %s.w;
|
||||
})SkSL",
|
||||
}
|
||||
return half4(xCoverage * yCoverage);
|
||||
)SkSL",
|
||||
_sample4.c_str(),
|
||||
_sample5.c_str());
|
||||
SkString _sample6 = this->invokeChild(0, args);
|
||||
fragBuilder->codeAppendf(
|
||||
R"SkSL(
|
||||
return (%s * xCoverage) * yCoverage;
|
||||
)SkSL",
|
||||
_sample6.c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& _proc) override {
|
||||
const GrRectBlurEffect& _outer = _proc.cast<GrRectBlurEffect>();
|
||||
{
|
||||
pdman.set4fv(rectVar, 1, reinterpret_cast<const float*>(&_outer.rect));
|
||||
if (invVMVar.isValid()) {
|
||||
pdman.setSkMatrix(invVMVar, _outer.invVM);
|
||||
}
|
||||
}
|
||||
{ pdman.set4fv(rectVar, 1, reinterpret_cast<const float*>(&_outer.rect)); }
|
||||
}
|
||||
UniformHandle rectVar;
|
||||
UniformHandle invVMVar;
|
||||
};
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> GrRectBlurEffect::onMakeProgramImpl() const {
|
||||
return std::make_unique<GrGLSLRectBlurEffect>();
|
||||
}
|
||||
void GrRectBlurEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {
|
||||
b->addBool(applyInvVM, "applyInvVM");
|
||||
b->addBool(isFast, "isFast");
|
||||
}
|
||||
bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
const GrRectBlurEffect& that = other.cast<GrRectBlurEffect>();
|
||||
(void)that;
|
||||
if (rect != that.rect) return false;
|
||||
if (applyInvVM != that.applyInvVM) return false;
|
||||
if (invVM != that.invVM) return false;
|
||||
if (isFast != that.isFast) return false;
|
||||
return true;
|
||||
}
|
||||
GrRectBlurEffect::GrRectBlurEffect(const GrRectBlurEffect& src)
|
||||
: INHERITED(kGrRectBlurEffect_ClassID, src.optimizationFlags())
|
||||
, rect(src.rect)
|
||||
, applyInvVM(src.applyInvVM)
|
||||
, invVM(src.invVM)
|
||||
, isFast(src.isFast) {
|
||||
this->cloneAndRegisterAllChildProcessors(src);
|
||||
this->setUsesSampleCoordsDirectly();
|
||||
}
|
||||
std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::clone() const {
|
||||
return std::make_unique<GrRectBlurEffect>(*this);
|
||||
}
|
||||
#if GR_TEST_UTILS
|
||||
SkString GrRectBlurEffect::onDumpInfo() const {
|
||||
return SkStringPrintf(
|
||||
"(rect=float4(%f, %f, %f, %f), applyInvVM=%s, invVM=float3x3(%f, %f, %f, %f, %f, %f, "
|
||||
"%f, %f, %f), isFast=%s)",
|
||||
return SkStringPrintf("(rect=float4(%f, %f, %f, %f), isFast=%s)",
|
||||
rect.left(),
|
||||
rect.top(),
|
||||
rect.right(),
|
||||
rect.bottom(),
|
||||
(applyInvVM ? "true" : "false"),
|
||||
invVM.rc(0, 0),
|
||||
invVM.rc(1, 0),
|
||||
invVM.rc(2, 0),
|
||||
invVM.rc(0, 1),
|
||||
invVM.rc(1, 1),
|
||||
invVM.rc(2, 1),
|
||||
invVM.rc(0, 2),
|
||||
invVM.rc(1, 2),
|
||||
invVM.rc(2, 2),
|
||||
(isFast ? "true" : "false"));
|
||||
}
|
||||
#endif
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "src/gpu/GrShaderCaps.h"
|
||||
#include "src/gpu/GrThreadSafeCache.h"
|
||||
#include "src/gpu/SkGr.h"
|
||||
#include "src/gpu/effects/GrMatrixEffect.h"
|
||||
#include "src/gpu/effects/GrTextureEffect.h"
|
||||
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
@ -145,36 +146,27 @@ public:
|
||||
// less than 6 sigma wide then things aren't so simple and we have to consider both the
|
||||
// left and right edge of the rectangle (and similar in y).
|
||||
bool isFast = insetRect.isSorted();
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(std::move(inputFP),
|
||||
insetRect,
|
||||
!invM.isIdentity(),
|
||||
invM,
|
||||
std::move(integral),
|
||||
isFast));
|
||||
std::unique_ptr<GrFragmentProcessor> fp(
|
||||
new GrRectBlurEffect(insetRect, std::move(integral), isFast));
|
||||
if (!invM.isIdentity()) {
|
||||
fp = GrMatrixEffect::Make(invM, std::move(fp));
|
||||
}
|
||||
fp = GrFragmentProcessor::DeviceSpace(std::move(fp));
|
||||
return GrFragmentProcessor::MulInputByChildAlpha(std::move(fp));
|
||||
}
|
||||
GrRectBlurEffect(const GrRectBlurEffect& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "RectBlurEffect"; }
|
||||
SkRect rect;
|
||||
bool applyInvVM;
|
||||
SkMatrix invVM;
|
||||
bool isFast;
|
||||
|
||||
private:
|
||||
GrRectBlurEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
|
||||
SkRect rect,
|
||||
bool applyInvVM,
|
||||
SkMatrix invVM,
|
||||
std::unique_ptr<GrFragmentProcessor> integral,
|
||||
bool isFast)
|
||||
GrRectBlurEffect(SkRect rect, std::unique_ptr<GrFragmentProcessor> integral, bool isFast)
|
||||
: INHERITED(kGrRectBlurEffect_ClassID,
|
||||
(OptimizationFlags)ProcessorOptimizationFlags(inputFP.get()) &
|
||||
kCompatibleWithCoverageAsAlpha_OptimizationFlag)
|
||||
(OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
|
||||
, rect(rect)
|
||||
, applyInvVM(applyInvVM)
|
||||
, invVM(invVM)
|
||||
, isFast(isFast) {
|
||||
this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
|
||||
this->setUsesSampleCoordsDirectly();
|
||||
this->registerChild(std::move(integral), SkSL::SampleUsage::Explicit());
|
||||
}
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;
|
||||
|
Loading…
Reference in New Issue
Block a user