Make GrMorphologyEffect use GrTextureEffect

Bug: skia:10139

Change-Id: I11de91c243ac1eeb0ad1ea580670add6229dbe41
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/296041
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2020-06-12 09:11:32 -04:00 committed by Skia Commit-Bot
parent 637838d20a
commit ac16760df4

View File

@ -228,13 +228,6 @@ public:
new GrMorphologyEffect(std::move(view), srcAlphaType, dir, radius, type, bounds));
}
MorphType type() const { return fType; }
bool useRange() const { return fUseRange; }
const float* range() const { return fRange; }
MorphDirection direction() const { return fDirection; }
int radius() const { return fRadius; }
int width() const { return 2 * fRadius + 1; }
const char* name() const override { return "Morphology"; }
std::unique_ptr<GrFragmentProcessor> clone() const override {
@ -242,8 +235,9 @@ public:
}
private:
GrCoordTransform fCoordTransform;
TextureSampler fTextureSampler;
// We really just want the unaltered local coords, but the only way to get that right now is
// an identity coord transform.
GrCoordTransform fCoordTransform = {};
MorphDirection fDirection;
int fRadius;
MorphType fType;
@ -255,9 +249,6 @@ private:
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
const TextureSampler& onTextureSampler(int i) const override { return fTextureSampler; }
GrMorphologyEffect(GrSurfaceProxyView, SkAlphaType srcAlphaType, MorphDirection, int radius,
MorphType, const float range[2]);
explicit GrMorphologyEffect(const GrMorphologyEffect&);
@ -267,138 +258,81 @@ private:
typedef GrFragmentProcessor INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
GrGLSLFragmentProcessor* GrMorphologyEffect::onCreateGLSLInstance() const {
class Impl : public GrGLSLFragmentProcessor {
public:
void emitCode(EmitArgs& args) override {
const GrMorphologyEffect& me = args.fFp.cast<GrMorphologyEffect>();
class GrGLMorphologyEffect : public GrGLSLFragmentProcessor {
public:
void emitCode(EmitArgs&) override;
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
fRangeUni = uniformHandler->addUniform(&me, kFragment_GrShaderFlag, kFloat2_GrSLType,
"Range");
const char* range = uniformHandler->getUniformCStr(fRangeUni);
static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
SkString coords2D = fragBuilder->ensureCoords2D(
args.fTransformedCoords[0].fVaryingPoint, args.fFp.sampleMatrix());
protected:
void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
const char* func = me.fType == MorphType::kErode ? "min" : "max";
private:
GrGLSLProgramDataManager::UniformHandle fPixelSizeUni;
GrGLSLProgramDataManager::UniformHandle fRangeUni;
char initialValue = me.fType == MorphType::kErode ? '1' : '0';
fragBuilder->codeAppendf("%s = half4(%c);", args.fOutputColor, initialValue);
typedef GrGLSLFragmentProcessor INHERITED;
};
char dir = me.fDirection == MorphDirection::kX ? 'x' : 'y';
void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
const GrMorphologyEffect& me = args.fFp.cast<GrMorphologyEffect>();
int width = 2 * me.fRadius + 1;
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
fPixelSizeUni = uniformHandler->addUniform(&me, kFragment_GrShaderFlag, kHalf_GrSLType,
"PixelSize");
const char* pixelSizeInc = uniformHandler->getUniformCStr(fPixelSizeUni);
fRangeUni = uniformHandler->addUniform(&me, kFragment_GrShaderFlag, kFloat2_GrSLType, "Range");
const char* range = uniformHandler->getUniformCStr(fRangeUni);
// float2 coord = coord2D;
fragBuilder->codeAppendf("float2 coord = %s;", coords2D.c_str());
// coord.x -= radius;
fragBuilder->codeAppendf("coord.%c -= %d;", dir, me.fRadius);
if (me.fUseRange) {
// highBound = min(highBound, coord.x + (width-1));
fragBuilder->codeAppendf("float highBound = min(%s.y, coord.%c + %f);", range, dir,
float(width - 1));
// coord.x = max(lowBound, coord.x);
fragBuilder->codeAppendf("coord.%c = max(%s.x, coord.%c);", dir, range, dir);
}
fragBuilder->codeAppendf("for (int i = 0; i < %d; i++) {", width);
SkString sample = this->invokeChild(0, args, "coord");
fragBuilder->codeAppendf(" %s = %s(%s, %s);", args.fOutputColor, func,
args.fOutputColor, sample.c_str());
// coord.x += 1;
fragBuilder->codeAppendf(" coord.%c += 1;", dir);
if (me.fUseRange) {
// coord.x = min(highBound, coord.x);
fragBuilder->codeAppendf(" coord.%c = min(highBound, coord.%c);", dir, dir);
}
fragBuilder->codeAppend("}");
fragBuilder->codeAppendf("%s *= %s;", args.fOutputColor, args.fInputColor);
}
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
args.fFp.sampleMatrix());
const char* func;
switch (me.type()) {
case MorphType::kErode:
fragBuilder->codeAppendf("\t\t%s = half4(1, 1, 1, 1);\n", args.fOutputColor);
func = "min";
break;
case MorphType::kDilate:
fragBuilder->codeAppendf("\t\t%s = half4(0, 0, 0, 0);\n", args.fOutputColor);
func = "max";
break;
default:
SK_ABORT("Unexpected type");
func = ""; // suppress warning
break;
}
protected:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& proc) override {
const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>();
if (m.fUseRange) {
pdman.set2f(fRangeUni, m.fRange[0], m.fRange[1]);
}
}
const char* dir;
switch (me.direction()) {
case MorphDirection::kX:
dir = "x";
break;
case MorphDirection::kY:
dir = "y";
break;
default:
SK_ABORT("Unknown filter direction.");
dir = ""; // suppress warning
}
int width = me.width();
// float2 coord = coord2D;
fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str());
// coord.x -= radius * pixelSize;
fragBuilder->codeAppendf("\t\tcoord.%s -= %d.0 * %s; \n", dir, me.radius(), pixelSizeInc);
if (me.useRange()) {
// highBound = min(highBound, coord.x + (width-1) * pixelSize);
fragBuilder->codeAppendf("\t\tfloat highBound = min(%s.y, coord.%s + %f * %s);",
range, dir, float(width - 1), pixelSizeInc);
// coord.x = max(lowBound, coord.x);
fragBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, range, dir);
}
fragBuilder->codeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", width);
fragBuilder->codeAppendf("\t\t\t%s = %s(%s, ", args.fOutputColor, func, args.fOutputColor);
fragBuilder->appendTextureLookup(args.fTexSamplers[0], "coord");
fragBuilder->codeAppend(");\n");
// coord.x += pixelSize;
fragBuilder->codeAppendf("\t\t\tcoord.%s += %s;\n", dir, pixelSizeInc);
if (me.useRange()) {
// coord.x = min(highBound, coord.x);
fragBuilder->codeAppendf("\t\t\tcoord.%s = min(highBound, coord.%s);", dir, dir);
}
fragBuilder->codeAppend("\t\t}\n");
fragBuilder->codeAppendf("%s *= %s;\n", args.fOutputColor, args.fInputColor);
private:
GrGLSLProgramDataManager::UniformHandle fRangeUni;
};
return new Impl;
}
void GrGLMorphologyEffect::GenKey(const GrProcessor& proc,
const GrShaderCaps&, GrProcessorKeyBuilder* b) {
const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>();
uint32_t key = static_cast<uint32_t>(m.radius());
key |= (static_cast<uint32_t>(m.type()) << 8);
key |= (static_cast<uint32_t>(m.direction()) << 9);
if (m.useRange()) {
void GrMorphologyEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {
uint32_t key = static_cast<uint32_t>(fRadius);
key |= (static_cast<uint32_t>(fType) << 8);
key |= (static_cast<uint32_t>(fDirection) << 9);
if (fUseRange) {
key |= 1 << 10;
}
b->add32(key);
}
void GrGLMorphologyEffect::onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& proc) {
const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>();
const auto& view = m.textureSampler(0).view();
GrSurfaceProxy* proxy = view.proxy();
GrTexture& texture = *proxy->peekTexture();
float pixelSize = 0.0f;
switch (m.direction()) {
case MorphDirection::kX:
pixelSize = 1.0f / texture.width();
break;
case MorphDirection::kY:
pixelSize = 1.0f / texture.height();
break;
default:
SK_ABORT("Unknown filter direction.");
}
pdman.set1f(fPixelSizeUni, pixelSize);
if (m.useRange()) {
const float* range = m.range();
if (MorphDirection::kY == m.direction() &&
view.origin() == kBottomLeft_GrSurfaceOrigin) {
pdman.set2f(fRangeUni, 1.0f - (range[1]*pixelSize), 1.0f - (range[0]*pixelSize));
} else {
pdman.set2f(fRangeUni, range[0] * pixelSize, range[1] * pixelSize);
}
}
}
///////////////////////////////////////////////////////////////////////////////
GrMorphologyEffect::GrMorphologyEffect(GrSurfaceProxyView view,
SkAlphaType srcAlphaType,
MorphDirection direction,
@ -406,17 +340,14 @@ GrMorphologyEffect::GrMorphologyEffect(GrSurfaceProxyView view,
MorphType type,
const float range[2])
: INHERITED(kGrMorphologyEffect_ClassID, ModulateForClampedSamplerOptFlags(srcAlphaType))
, fCoordTransform(view.proxy(), view.origin())
, fTextureSampler(std::move(view))
, fDirection(direction)
, fRadius(radius)
, fType(type)
, fUseRange(SkToBool(range)) {
// Make sure the sampler's ctor uses the clamp wrap mode
SkASSERT(fTextureSampler.samplerState().wrapModeX() == GrSamplerState::WrapMode::kClamp &&
fTextureSampler.samplerState().wrapModeY() == GrSamplerState::WrapMode::kClamp);
this->addCoordTransform(&fCoordTransform);
this->setTextureSamplerCnt(1);
auto te = GrTextureEffect::Make(std::move(view), srcAlphaType);
te->setSampledWithExplicitCoords();
this->registerChildProcessor(std::move(te));
if (fUseRange) {
fRange[0] = range[0];
fRange[1] = range[1];
@ -425,34 +356,26 @@ GrMorphologyEffect::GrMorphologyEffect(GrSurfaceProxyView view,
GrMorphologyEffect::GrMorphologyEffect(const GrMorphologyEffect& that)
: INHERITED(kGrMorphologyEffect_ClassID, that.optimizationFlags())
, fCoordTransform(that.fCoordTransform)
, fTextureSampler(that.fTextureSampler)
, fDirection(that.fDirection)
, fRadius(that.fRadius)
, fType(that.fType)
, fUseRange(that.fUseRange) {
this->addCoordTransform(&fCoordTransform);
this->setTextureSamplerCnt(1);
auto child = that.childProcessor(0).clone();
child->setSampledWithExplicitCoords();
this->registerChildProcessor(std::move(child));
if (that.fUseRange) {
fRange[0] = that.fRange[0];
fRange[1] = that.fRange[1];
}
}
void GrMorphologyEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {
GrGLMorphologyEffect::GenKey(*this, caps, b);
}
GrGLSLFragmentProcessor* GrMorphologyEffect::onCreateGLSLInstance() const {
return new GrGLMorphologyEffect;
}
bool GrMorphologyEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
const GrMorphologyEffect& s = sBase.cast<GrMorphologyEffect>();
return (this->radius() == s.radius() &&
this->direction() == s.direction() &&
this->useRange() == s.useRange() &&
this->type() == s.type());
return this->fRadius == s.fRadius &&
this->fDirection == s.fDirection &&
this->fUseRange == s.fUseRange &&
this->fType == s.fType;
}
///////////////////////////////////////////////////////////////////////////////