GrBicubicEffect uses GrTextureEffect.
This opens the door to, but doesn't add support for, applying this effect to other child processor types. Fixes issue when applying effect to rectangle textures where steps were done using increments of 1/w and 1/h instead of 1. Change-Id: I74e20d6c96931c337b22b156a61c8e279c6fbc62 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/259420 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
parent
cfdfb229fc
commit
d0d033a125
@ -637,13 +637,10 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(
|
||||
} else if (nextH == srcH) {
|
||||
dir = GrBicubicEffect::Direction::kX;
|
||||
}
|
||||
if (srcW != texView.proxy()->width() || srcH != texView.proxy()->height()) {
|
||||
auto domain = GrTextureDomain::MakeTexelDomain(
|
||||
SkIRect::MakeXYWH(srcX, srcY, srcW, srcH), GrTextureDomain::kClamp_Mode);
|
||||
fp = GrBicubicEffect::Make(std::move(texView), matrix, domain, dir, prevAlphaType);
|
||||
} else {
|
||||
fp = GrBicubicEffect::Make(std::move(texView), matrix, dir, prevAlphaType);
|
||||
}
|
||||
static constexpr GrSamplerState::WrapMode kWM = GrSamplerState::WrapMode::kClamp;
|
||||
auto subset = SkRect::MakeXYWH(srcX, srcY, srcW, srcH);
|
||||
fp = GrBicubicEffect::MakeSubset(std::move(texView), prevAlphaType, matrix, kWM, kWM,
|
||||
subset, dir, *this->caps());
|
||||
if (xform) {
|
||||
fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform));
|
||||
}
|
||||
|
@ -193,11 +193,10 @@ std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createFragmentProcessorF
|
||||
SkASSERT(view.asTextureProxy());
|
||||
const auto& caps = *fContext->priv().caps();
|
||||
SkAlphaType srcAlphaType = this->alphaType();
|
||||
auto wm = fDomainNeedsDecal ? GrSamplerState::WrapMode::kClampToBorder
|
||||
: GrSamplerState::WrapMode::kClamp;
|
||||
if (filterOrNullForBicubic) {
|
||||
GrSamplerState::WrapMode wrapMode = fDomainNeedsDecal
|
||||
? GrSamplerState::WrapMode::kClampToBorder
|
||||
: GrSamplerState::WrapMode::kClamp;
|
||||
GrSamplerState samplerState(wrapMode, *filterOrNullForBicubic);
|
||||
GrSamplerState samplerState(wm, *filterOrNullForBicubic);
|
||||
if (kNoDomain_DomainMode == domainMode) {
|
||||
return GrTextureEffect::Make(std::move(view), srcAlphaType, textureMatrix, samplerState,
|
||||
caps);
|
||||
@ -205,23 +204,15 @@ std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createFragmentProcessorF
|
||||
return GrTextureEffect::MakeSubset(std::move(view), srcAlphaType, textureMatrix,
|
||||
samplerState, domain, caps);
|
||||
} else {
|
||||
static const GrSamplerState::WrapMode kClampClamp[] = {
|
||||
GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp};
|
||||
static const GrSamplerState::WrapMode kDecalDecal[] = {
|
||||
GrSamplerState::WrapMode::kClampToBorder, GrSamplerState::WrapMode::kClampToBorder};
|
||||
|
||||
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
|
||||
bool clampToBorderSupport = caps.clampToBorderSupport();
|
||||
if (kDomain_DomainMode == domainMode || (fDomainNeedsDecal && !clampToBorderSupport)) {
|
||||
GrTextureDomain::Mode wrapMode = fDomainNeedsDecal ? GrTextureDomain::kDecal_Mode
|
||||
: GrTextureDomain::kClamp_Mode;
|
||||
return GrBicubicEffect::Make(std::move(view), textureMatrix, kClampClamp, wrapMode,
|
||||
wrapMode, kDir, srcAlphaType,
|
||||
kDomain_DomainMode == domainMode ? &domain : nullptr);
|
||||
const auto& caps = *fContext->priv().caps();
|
||||
if (kDomain_DomainMode == domainMode) {
|
||||
return GrBicubicEffect::MakeSubset(std::move(view), srcAlphaType, textureMatrix, wm, wm,
|
||||
domain, kDir, caps);
|
||||
} else {
|
||||
return GrBicubicEffect::Make(std::move(view), textureMatrix,
|
||||
fDomainNeedsDecal ? kDecalDecal : kClampClamp, kDir,
|
||||
srcAlphaType);
|
||||
return GrBicubicEffect::Make(std::move(view), srcAlphaType, textureMatrix, wm, wm, kDir,
|
||||
caps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -938,16 +938,18 @@ void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap,
|
||||
if (needsTextureDomain && (SkCanvas::kStrict_SrcRectConstraint == constraint)) {
|
||||
if (bicubic) {
|
||||
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
|
||||
fp = GrBicubicEffect::Make(std::move(view), texMatrix, srcRect, kDir, srcAlphaType);
|
||||
fp = GrBicubicEffect::MakeSubset(std::move(view), srcAlphaType, texMatrix,
|
||||
samplerState.wrapModeX(), samplerState.wrapModeY(),
|
||||
srcRect, kDir, caps);
|
||||
} else {
|
||||
fp = GrTextureEffect::MakeSubset(std::move(view), srcAlphaType, texMatrix,
|
||||
samplerState, srcRect, caps);
|
||||
}
|
||||
} else if (bicubic) {
|
||||
SkASSERT(GrSamplerState::Filter::kNearest == samplerState.filter());
|
||||
GrSamplerState::WrapMode wrapMode[2] = {samplerState.wrapModeX(), samplerState.wrapModeY()};
|
||||
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
|
||||
fp = GrBicubicEffect::Make(std::move(view), texMatrix, wrapMode, kDir, srcAlphaType);
|
||||
fp = GrBicubicEffect::Make(std::move(view), srcAlphaType, texMatrix,
|
||||
samplerState.wrapModeX(), samplerState.wrapModeY(), kDir, caps);
|
||||
} else {
|
||||
fp = GrTextureEffect::Make(std::move(view), srcAlphaType, texMatrix, samplerState, caps);
|
||||
}
|
||||
|
@ -5,31 +5,21 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/core/SkMatrixPriv.h"
|
||||
#include "src/gpu/effects/GrBicubicEffect.h"
|
||||
|
||||
#include "include/gpu/GrTexture.h"
|
||||
#include "src/core/SkMatrixPriv.h"
|
||||
#include "src/gpu/effects/GrTextureEffect.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
|
||||
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
|
||||
|
||||
class GrGLBicubicEffect : public GrGLSLFragmentProcessor {
|
||||
class GrBicubicEffect::Impl : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
void emitCode(EmitArgs&) override;
|
||||
|
||||
static inline void GenKey(const GrProcessor& effect, const GrShaderCaps&,
|
||||
GrProcessorKeyBuilder* b) {
|
||||
const GrBicubicEffect& bicubicEffect = effect.cast<GrBicubicEffect>();
|
||||
b->add32(GrTextureDomain::GLDomain::DomainKey(bicubicEffect.domain()));
|
||||
uint32_t bidir = bicubicEffect.direction() == GrBicubicEffect::Direction::kXY ? 1 : 0;
|
||||
b->add32(bidir | (bicubicEffect.alphaType() << 1));
|
||||
}
|
||||
|
||||
protected:
|
||||
void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
|
||||
|
||||
private:
|
||||
typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
|
||||
void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
|
||||
|
||||
UniformHandle fDimensions;
|
||||
GrTextureDomain::GLDomain fDomain;
|
||||
@ -37,7 +27,7 @@ private:
|
||||
typedef GrGLSLFragmentProcessor INHERITED;
|
||||
};
|
||||
|
||||
void GrGLBicubicEffect::emitCode(EmitArgs& args) {
|
||||
void GrBicubicEffect::Impl::emitCode(EmitArgs& args) {
|
||||
const GrBicubicEffect& bicubicEffect = args.fFp.cast<GrBicubicEffect>();
|
||||
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
@ -64,7 +54,7 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
|
||||
* favorite overall spline - this is now commonly known as the Mitchell filter, and is the
|
||||
* source of the specific weights below.
|
||||
*
|
||||
* This is GLSL, so the matrix is column-major (transposed from standard matrix notation).
|
||||
* This is SkSL, so the matrix is column-major (transposed from standard matrix notation).
|
||||
*/
|
||||
fragBuilder->codeAppend("half4x4 kMitchellCoefficients = half4x4("
|
||||
" 1.0 / 18.0, 16.0 / 18.0, 1.0 / 18.0, 0.0 / 18.0,"
|
||||
@ -78,7 +68,7 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
|
||||
// double hit a texel.
|
||||
fragBuilder->codeAppendf("half2 f = half2(fract(coord * %s.zw));", dims);
|
||||
fragBuilder->codeAppendf("coord = coord + (half2(0.5) - f) * %s.xy;", dims);
|
||||
if (bicubicEffect.direction() == GrBicubicEffect::Direction::kXY) {
|
||||
if (bicubicEffect.fDirection == GrBicubicEffect::Direction::kXY) {
|
||||
fragBuilder->codeAppend(
|
||||
"half4 wx = kMitchellCoefficients * half4(1.0, f.x, f.x * f.x, f.x * f.x * f.x);");
|
||||
fragBuilder->codeAppend(
|
||||
@ -88,15 +78,9 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
SkString coord;
|
||||
coord.printf("coord + %s.xy * float2(%d, %d)", dims, x - 1, y - 1);
|
||||
SkString sampleVar;
|
||||
sampleVar.printf("rowColors[%d]", x);
|
||||
fDomain.sampleTexture(fragBuilder,
|
||||
args.fUniformHandler,
|
||||
args.fShaderCaps,
|
||||
bicubicEffect.domain(),
|
||||
sampleVar.c_str(),
|
||||
coord,
|
||||
args.fTexSamplers[0]);
|
||||
auto childStr =
|
||||
this->invokeChild(0, args, SkSL::String(coord.c_str(), coord.size()));
|
||||
fragBuilder->codeAppendf("rowColors[%d] = %s;", x, childStr.c_str());
|
||||
}
|
||||
fragBuilder->codeAppendf(
|
||||
"half4 s%d = wx.x * rowColors[0] + wx.y * rowColors[1] + wx.z * rowColors[2] + "
|
||||
@ -114,102 +98,139 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
SkString coord;
|
||||
coord.printf("coord + %s.xy * half(%d)", dims, i - 1);
|
||||
SkString samplerVar;
|
||||
samplerVar.printf("c[%d]", i);
|
||||
// With added complexity we could apply the domain once in X or Y depending on
|
||||
// direction rather than for each of the four lookups, but then we might not be
|
||||
// be able to share code for Direction::kX and ::kY.
|
||||
fDomain.sampleTexture(fragBuilder,
|
||||
args.fUniformHandler,
|
||||
args.fShaderCaps,
|
||||
bicubicEffect.domain(),
|
||||
samplerVar.c_str(),
|
||||
coord,
|
||||
args.fTexSamplers[0]);
|
||||
auto childStr = this->invokeChild(0, args, SkSL::String(coord.c_str(), coord.size()));
|
||||
fragBuilder->codeAppendf("c[%d] = %s;", i, childStr.c_str());
|
||||
}
|
||||
fragBuilder->codeAppend(
|
||||
"half4 bicubicColor = c[0] * w.x + c[1] * w.y + c[2] * w.z + c[3] * w.w;");
|
||||
}
|
||||
// Bicubic can send colors out of range, so clamp to get them back in (source) gamut.
|
||||
// The kind of clamp we have to do depends on the alpha type.
|
||||
if (kPremul_SkAlphaType == bicubicEffect.alphaType()) {
|
||||
fragBuilder->codeAppend("bicubicColor.a = saturate(bicubicColor.a);");
|
||||
fragBuilder->codeAppend(
|
||||
"bicubicColor.rgb = max(half3(0.0), min(bicubicColor.rgb, bicubicColor.aaa));");
|
||||
} else {
|
||||
fragBuilder->codeAppend("bicubicColor = saturate(bicubicColor);");
|
||||
switch (bicubicEffect.fClamp) {
|
||||
case Clamp::kUnpremul:
|
||||
fragBuilder->codeAppend("bicubicColor = saturate(bicubicColor);");
|
||||
break;
|
||||
case Clamp::kPremul:
|
||||
fragBuilder->codeAppend(
|
||||
"bicubicColor.rgb = max(half3(0.0), min(bicubicColor.rgb, bicubicColor.aaa));");
|
||||
break;
|
||||
}
|
||||
fragBuilder->codeAppendf("%s = bicubicColor * %s;", args.fOutputColor, args.fInputColor);
|
||||
}
|
||||
|
||||
void GrGLBicubicEffect::onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& processor) {
|
||||
void GrBicubicEffect::Impl::onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& processor) {
|
||||
const GrBicubicEffect& bicubicEffect = processor.cast<GrBicubicEffect>();
|
||||
const auto& view = processor.textureSampler(0).view();
|
||||
SkISize textureDims = view.proxy()->backingStoreDimensions();
|
||||
// Currently we only ever construct with GrTextureEffect and always take its
|
||||
// coord transform as our own.
|
||||
SkASSERT(bicubicEffect.fCoordTransform.peekTexture());
|
||||
SkISize textureDims = bicubicEffect.fCoordTransform.peekTexture()->dimensions();
|
||||
|
||||
float dims[4] = {0, 0, 0, 0};
|
||||
if (bicubicEffect.direction() != GrBicubicEffect::Direction::kY) {
|
||||
dims[0] = 1.0f / textureDims.width();
|
||||
dims[2] = textureDims.width();
|
||||
if (bicubicEffect.fDirection != GrBicubicEffect::Direction::kY) {
|
||||
if (bicubicEffect.fCoordTransform.normalize()) {
|
||||
dims[0] = 1.f / textureDims.width();
|
||||
dims[2] = textureDims.width();
|
||||
} else {
|
||||
dims[0] = dims[2] = 1.f;
|
||||
}
|
||||
}
|
||||
if (bicubicEffect.direction() != GrBicubicEffect::Direction::kX) {
|
||||
dims[1] = 1.0f / textureDims.height();
|
||||
dims[3] = textureDims.height();
|
||||
if (bicubicEffect.fDirection != GrBicubicEffect::Direction::kX) {
|
||||
if (bicubicEffect.fCoordTransform.normalize()) {
|
||||
dims[1] = 1.f / textureDims.height();
|
||||
dims[3] = textureDims.height();
|
||||
} else {
|
||||
dims[1] = dims[3] = 1.f;
|
||||
}
|
||||
}
|
||||
pdman.set4fv(fDimensions, 1, dims);
|
||||
fDomain.setData(pdman, bicubicEffect.domain(), view,
|
||||
processor.textureSampler(0).samplerState());
|
||||
}
|
||||
|
||||
GrBicubicEffect::GrBicubicEffect(GrSurfaceProxyView view, const SkMatrix& matrix,
|
||||
const SkRect& domain, const GrSamplerState::WrapMode wrapModes[2],
|
||||
GrTextureDomain::Mode modeX, GrTextureDomain::Mode modeY,
|
||||
Direction direction, SkAlphaType alphaType)
|
||||
: INHERITED{kGrBicubicEffect_ClassID,
|
||||
ModulateForSamplerOptFlags(
|
||||
alphaType, GrTextureDomain::IsDecalSampled(wrapModes, modeX, modeY))}
|
||||
, fCoordTransform(matrix, view.proxy(), view.origin())
|
||||
, fDomain(view.proxy(), domain, modeX, modeY)
|
||||
, fTextureSampler(std::move(view),
|
||||
GrSamplerState(wrapModes, GrSamplerState::Filter::kNearest))
|
||||
, fAlphaType(alphaType)
|
||||
, fDirection(direction) {
|
||||
std::unique_ptr<GrFragmentProcessor> GrBicubicEffect::Make(GrSurfaceProxyView view,
|
||||
SkAlphaType alphaType,
|
||||
const SkMatrix& matrix,
|
||||
Direction direction) {
|
||||
auto fp = GrTextureEffect::Make(std::move(view), alphaType, matrix);
|
||||
auto clamp = kPremul_SkAlphaType == alphaType ? Clamp::kPremul : Clamp::kUnpremul;
|
||||
return std::unique_ptr<GrFragmentProcessor>(
|
||||
new GrBicubicEffect(std::move(fp), direction, clamp));
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrBicubicEffect::Make(GrSurfaceProxyView view,
|
||||
SkAlphaType alphaType,
|
||||
const SkMatrix& matrix,
|
||||
const GrSamplerState::WrapMode wrapX,
|
||||
const GrSamplerState::WrapMode wrapY,
|
||||
Direction direction,
|
||||
const GrCaps& caps) {
|
||||
GrSamplerState sampler(wrapX, wrapY, GrSamplerState::Filter::kNearest);
|
||||
std::unique_ptr<GrFragmentProcessor> fp;
|
||||
fp = GrTextureEffect::Make(std::move(view), alphaType, matrix, sampler, caps);
|
||||
auto clamp = kPremul_SkAlphaType == alphaType ? Clamp::kPremul : Clamp::kUnpremul;
|
||||
return std::unique_ptr<GrFragmentProcessor>(
|
||||
new GrBicubicEffect(std::move(fp), direction, clamp));
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrBicubicEffect::MakeSubset(
|
||||
GrSurfaceProxyView view,
|
||||
SkAlphaType alphaType,
|
||||
const SkMatrix& matrix,
|
||||
const GrSamplerState::WrapMode wrapX,
|
||||
const GrSamplerState::WrapMode wrapY,
|
||||
const SkRect& subset,
|
||||
Direction direction,
|
||||
const GrCaps& caps) {
|
||||
GrSamplerState sampler(wrapX, wrapY, GrSamplerState::Filter::kNearest);
|
||||
std::unique_ptr<GrFragmentProcessor> fp;
|
||||
fp = GrTextureEffect::MakeSubset(std::move(view), alphaType, matrix, sampler, subset, caps);
|
||||
auto clamp = kPremul_SkAlphaType == alphaType ? Clamp::kPremul : Clamp::kUnpremul;
|
||||
return std::unique_ptr<GrFragmentProcessor>(
|
||||
new GrBicubicEffect(std::move(fp), direction, clamp));
|
||||
}
|
||||
|
||||
GrBicubicEffect::GrBicubicEffect(std::unique_ptr<GrFragmentProcessor> fp,
|
||||
Direction direction,
|
||||
Clamp clamp)
|
||||
: INHERITED(kGrBicubicEffect_ClassID, ProcessorOptimizationFlags(fp.get()))
|
||||
, fDirection(direction)
|
||||
, fClamp(clamp) {
|
||||
SkASSERT(fp->numCoordTransforms() == 1);
|
||||
fCoordTransform = fp->coordTransform(0);
|
||||
this->addCoordTransform(&fCoordTransform);
|
||||
this->setTextureSamplerCnt(1);
|
||||
fp->coordTransform(0) = {};
|
||||
fp->setSampledWithExplicitCoords(true);
|
||||
this->registerChildProcessor(std::move(fp));
|
||||
}
|
||||
|
||||
GrBicubicEffect::GrBicubicEffect(const GrBicubicEffect& that)
|
||||
: INHERITED(kGrBicubicEffect_ClassID, that.optimizationFlags())
|
||||
, fCoordTransform(that.fCoordTransform)
|
||||
, fDomain(that.fDomain)
|
||||
, fTextureSampler(that.fTextureSampler)
|
||||
, fAlphaType(that.fAlphaType)
|
||||
, fDirection(that.fDirection) {
|
||||
, fDirection(that.fDirection)
|
||||
, fClamp(that.fClamp) {
|
||||
this->addCoordTransform(&fCoordTransform);
|
||||
this->setTextureSamplerCnt(1);
|
||||
auto child = that.childProcessor(0).clone();
|
||||
child->setSampledWithExplicitCoords(true);
|
||||
this->registerChildProcessor(std::move(child));
|
||||
}
|
||||
|
||||
void GrBicubicEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {
|
||||
GrGLBicubicEffect::GenKey(*this, caps, b);
|
||||
uint32_t key = (fDirection == GrBicubicEffect::Direction::kXY)
|
||||
| (static_cast<uint32_t>(fClamp) << 1);
|
||||
b->add32(key);
|
||||
}
|
||||
|
||||
GrGLSLFragmentProcessor* GrBicubicEffect::onCreateGLSLInstance() const {
|
||||
return new GrGLBicubicEffect;
|
||||
}
|
||||
GrGLSLFragmentProcessor* GrBicubicEffect::onCreateGLSLInstance() const { return new Impl(); }
|
||||
|
||||
bool GrBicubicEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
|
||||
const GrBicubicEffect& s = sBase.cast<GrBicubicEffect>();
|
||||
return fDomain == s.fDomain && fDirection == s.fDirection && fAlphaType == s.fAlphaType;
|
||||
bool GrBicubicEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
const auto& that = other.cast<GrBicubicEffect>();
|
||||
return fDirection == that.fDirection && fClamp == that.fClamp;
|
||||
}
|
||||
|
||||
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrBicubicEffect);
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
std::unique_ptr<GrFragmentProcessor> GrBicubicEffect::TestCreate(GrProcessorTestData* d) {
|
||||
static const GrSamplerState::WrapMode kClampClamp[] = {GrSamplerState::WrapMode::kClamp,
|
||||
GrSamplerState::WrapMode::kClamp};
|
||||
Direction direction = Direction::kX;
|
||||
switch (d->fRandom->nextULessThan(3)) {
|
||||
case 0:
|
||||
@ -223,8 +244,24 @@ std::unique_ptr<GrFragmentProcessor> GrBicubicEffect::TestCreate(GrProcessorTest
|
||||
break;
|
||||
}
|
||||
auto [view, ct, at] = d->randomView();
|
||||
auto m = GrTest::TestMatrix(d->fRandom);
|
||||
if (d->fRandom->nextBool()) {
|
||||
GrSamplerState::WrapMode wm[2];
|
||||
GrTest::TestWrapModes(d->fRandom, wm);
|
||||
|
||||
return GrBicubicEffect::Make(std::move(view), SkMatrix::I(), kClampClamp, direction, at);
|
||||
if (d->fRandom->nextBool()) {
|
||||
SkRect subset;
|
||||
subset.fLeft = d->fRandom->nextSScalar1() * view.width();
|
||||
subset.fTop = d->fRandom->nextSScalar1() * view.height();
|
||||
subset.fRight = d->fRandom->nextSScalar1() * view.width();
|
||||
subset.fBottom = d->fRandom->nextSScalar1() * view.height();
|
||||
subset.sort();
|
||||
return MakeSubset(std::move(view), at, m, wm[0], wm[1], subset, direction, *d->caps());
|
||||
}
|
||||
return Make(std::move(view), at, m, wm[0], wm[1], direction, *d->caps());
|
||||
} else {
|
||||
return Make(std::move(view), at, m, direction);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -35,78 +35,37 @@ public:
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrBicubicEffect(*this));
|
||||
}
|
||||
|
||||
const GrTextureDomain& domain() const { return fDomain; }
|
||||
|
||||
Direction direction() const { return fDirection; }
|
||||
|
||||
SkAlphaType alphaType() const { return fAlphaType; }
|
||||
|
||||
/**
|
||||
* Create a Mitchell filter effect with specified texture matrix with clamp wrap mode.
|
||||
*/
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView view,
|
||||
const SkMatrix& matrix,
|
||||
Direction direction,
|
||||
SkAlphaType alphaType) {
|
||||
static constexpr GrSamplerState::WrapMode kClampClamp[] = {
|
||||
GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp};
|
||||
return Make(std::move(view), matrix, kClampClamp, GrTextureDomain::kIgnore_Mode,
|
||||
GrTextureDomain::kIgnore_Mode, direction, alphaType);
|
||||
}
|
||||
SkAlphaType,
|
||||
const SkMatrix&,
|
||||
Direction direction);
|
||||
|
||||
/**
|
||||
* Create a Mitchell filter effect with specified texture matrix and x/y tile modes.
|
||||
* Create a Mitchell filter effect for a texture with arbitrary wrap modes.
|
||||
*/
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView view,
|
||||
const SkMatrix& matrix,
|
||||
const GrSamplerState::WrapMode wrapModes[2],
|
||||
Direction direction,
|
||||
SkAlphaType alphaType) {
|
||||
// Ignore the domain on x and y, since this factory relies solely on the wrap mode of the
|
||||
// sampler to constrain texture coordinates
|
||||
return Make(std::move(view), matrix, wrapModes, GrTextureDomain::kIgnore_Mode,
|
||||
GrTextureDomain::kIgnore_Mode, direction, alphaType);
|
||||
}
|
||||
SkAlphaType,
|
||||
const SkMatrix&,
|
||||
const GrSamplerState::WrapMode wrapX,
|
||||
const GrSamplerState::WrapMode wrapY,
|
||||
Direction,
|
||||
const GrCaps&);
|
||||
|
||||
/**
|
||||
* Create a Mitchell filter effect with specified texture matrix and x/y tile modes. This
|
||||
* supports providing modes for the texture domain explicitly, in the event that it should
|
||||
* override the behavior of the sampler's tile mode (e.g. clamp to border unsupported).
|
||||
* Create a Mitchell filter effect for a subset of a texture, specified by a texture coordinate
|
||||
* rectangle subset. The WrapModes apply to the subset.
|
||||
*/
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView view,
|
||||
const SkMatrix& matrix,
|
||||
const GrSamplerState::WrapMode wrapModes[2],
|
||||
GrTextureDomain::Mode modeX,
|
||||
GrTextureDomain::Mode modeY,
|
||||
Direction direction,
|
||||
SkAlphaType alphaType,
|
||||
const SkRect* domain = nullptr) {
|
||||
SkRect resolvedDomain;
|
||||
if (domain) {
|
||||
resolvedDomain = *domain;
|
||||
} else {
|
||||
resolvedDomain = GrTextureDomain::MakeTexelDomain(
|
||||
SkIRect::MakeSize(view.proxy()->dimensions()), modeX, modeY);
|
||||
}
|
||||
return std::unique_ptr<GrFragmentProcessor>(
|
||||
new GrBicubicEffect(std::move(view), matrix, resolvedDomain, wrapModes, modeX,
|
||||
modeY, direction, alphaType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Mitchell filter effect with a texture matrix and a domain.
|
||||
*/
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView view,
|
||||
const SkMatrix& matrix,
|
||||
const SkRect& domain,
|
||||
Direction direction,
|
||||
SkAlphaType alphaType) {
|
||||
static const GrSamplerState::WrapMode kClampClamp[] = {
|
||||
GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp};
|
||||
return Make(std::move(view), matrix, kClampClamp, GrTextureDomain::kClamp_Mode,
|
||||
GrTextureDomain::kClamp_Mode, direction, alphaType, &domain);
|
||||
}
|
||||
|
||||
static std::unique_ptr<GrFragmentProcessor> MakeSubset(GrSurfaceProxyView view,
|
||||
SkAlphaType,
|
||||
const SkMatrix&,
|
||||
const GrSamplerState::WrapMode wrapX,
|
||||
const GrSamplerState::WrapMode wrapY,
|
||||
const SkRect& subset,
|
||||
Direction,
|
||||
const GrCaps&);
|
||||
/**
|
||||
* Determines whether the bicubic effect should be used based on the transformation from the
|
||||
* local coords to the device. Returns true if the bicubic effect should be used. filterMode
|
||||
@ -118,9 +77,14 @@ public:
|
||||
GrSamplerState::Filter* filterMode);
|
||||
|
||||
private:
|
||||
GrBicubicEffect(GrSurfaceProxyView, const SkMatrix& matrix, const SkRect& domain,
|
||||
const GrSamplerState::WrapMode wrapModes[2], GrTextureDomain::Mode modeX,
|
||||
GrTextureDomain::Mode modeY, Direction direction, SkAlphaType);
|
||||
class Impl;
|
||||
|
||||
enum class Clamp {
|
||||
kUnpremul, // clamps rgba to 0..1
|
||||
kPremul, // clamps a to 0..1 and rgb to 0..a
|
||||
};
|
||||
|
||||
GrBicubicEffect(std::unique_ptr<GrFragmentProcessor> fp, Direction direction, Clamp clamp);
|
||||
explicit GrBicubicEffect(const GrBicubicEffect&);
|
||||
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
@ -129,13 +93,9 @@ private:
|
||||
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||
|
||||
const TextureSampler& onTextureSampler(int) const override { return fTextureSampler; }
|
||||
|
||||
GrCoordTransform fCoordTransform;
|
||||
GrTextureDomain fDomain;
|
||||
TextureSampler fTextureSampler;
|
||||
SkAlphaType fAlphaType;
|
||||
Direction fDirection;
|
||||
Clamp fClamp;
|
||||
|
||||
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
|
||||
|
||||
|
@ -201,8 +201,8 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrSamplerState::WrapMode wrapModes[] = {tile_mode_to_wrap_mode(fTileModeX),
|
||||
tile_mode_to_wrap_mode(fTileModeY)};
|
||||
GrSamplerState::WrapMode wm[] = {tile_mode_to_wrap_mode(fTileModeX),
|
||||
tile_mode_to_wrap_mode(fTileModeY)};
|
||||
|
||||
// Must set wrap and filter on the sampler before requesting a texture. In two places below
|
||||
// we check the matrix scale factors to determine how to interpret the filter quality setting.
|
||||
@ -212,7 +212,7 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
|
||||
GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode(
|
||||
fImage->width(), fImage->height(), args.fFilterQuality, *args.fViewMatrix, *lm,
|
||||
args.fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
|
||||
GrSamplerState samplerState(wrapModes, textureFilterMode);
|
||||
GrSamplerState samplerState(wm, textureFilterMode);
|
||||
SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
|
||||
GrSurfaceProxyView view = as_IB(fImage)->refView(args.fContext, samplerState, scaleAdjust);
|
||||
if (!view) {
|
||||
@ -227,24 +227,9 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> inner;
|
||||
if (doBicubic) {
|
||||
// If either domainX or domainY are un-ignored, a texture domain effect has to be used to
|
||||
// implement the decal mode (while leaving non-decal axes alone). The wrap mode originally
|
||||
// clamp-to-border is reset to clamp since the hw cannot implement it directly.
|
||||
GrTextureDomain::Mode domainX = GrTextureDomain::kIgnore_Mode;
|
||||
GrTextureDomain::Mode domainY = GrTextureDomain::kIgnore_Mode;
|
||||
if (!caps.clampToBorderSupport()) {
|
||||
if (wrapModes[0] == GrSamplerState::WrapMode::kClampToBorder) {
|
||||
domainX = GrTextureDomain::kDecal_Mode;
|
||||
wrapModes[0] = GrSamplerState::WrapMode::kClamp;
|
||||
}
|
||||
if (wrapModes[1] == GrSamplerState::WrapMode::kClampToBorder) {
|
||||
domainY = GrTextureDomain::kDecal_Mode;
|
||||
wrapModes[1] = GrSamplerState::WrapMode::kClamp;
|
||||
}
|
||||
}
|
||||
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
|
||||
inner = GrBicubicEffect::Make(std::move(view), lmInverse, wrapModes, domainX, domainY, kDir,
|
||||
srcAlphaType);
|
||||
inner = GrBicubicEffect::Make(std::move(view), srcAlphaType, lmInverse, wm[0], wm[1], kDir,
|
||||
caps);
|
||||
} else {
|
||||
inner = GrTextureEffect::Make(std::move(view), srcAlphaType, lmInverse, samplerState, caps);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user