Revert "Make GrBicubicEffect also support centripetal Catmull-Rom kernel."

This reverts commit f9a8688b4e.

Reason for revert: breaking processor unit tests

Original change's description:
> Make GrBicubicEffect also support centripetal Catmull-Rom kernel.
> 
> Use new kernel in async rescale APIs.
> 
> Bug: skia:8962
> Change-Id: Ife8f56f54b5df58cedd65b54083c7c0716b8c633
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/216352
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>

TBR=bsalomon@google.com,brianosman@google.com

Change-Id: Idf317e76b870407060113dc60dd3776abc07f810
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:8962
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/220751
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2019-06-13 20:22:10 +00:00 committed by Skia Commit-Bot
parent 26a75c4aa8
commit 1127c0b273
10 changed files with 57 additions and 94 deletions

View File

@ -1894,14 +1894,12 @@ sk_sp<GrRenderTargetContext> GrRenderTargetContext::rescale(const SkImageInfo& i
} else if (nextH == srcH) {
dir = GrBicubicEffect::Direction::kX;
}
static constexpr auto kKernel = GrBicubicEffect::Kernel::kCatmullRom;
if (srcW != texProxy->width() || srcH != texProxy->height()) {
auto domain = GrTextureDomain::MakeTexelDomain(
SkIRect::MakeXYWH(srcX, srcY, srcW, srcH), GrTextureDomain::kClamp_Mode);
fp = GrBicubicEffect::Make(texProxy, matrix, domain, kKernel, dir,
kPremul_SkAlphaType);
fp = GrBicubicEffect::Make(texProxy, matrix, domain, dir, kPremul_SkAlphaType);
} else {
fp = GrBicubicEffect::Make(texProxy, matrix, kKernel, dir, kPremul_SkAlphaType);
fp = GrBicubicEffect::Make(texProxy, matrix, dir, kPremul_SkAlphaType);
}
if (xform) {
fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform));

View File

@ -226,17 +226,16 @@ std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createFragmentProcessorF
GrSamplerState::WrapMode::kClampToBorder, GrSamplerState::WrapMode::kClampToBorder};
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
static constexpr auto kKernel = GrBicubicEffect::Kernel::kMitchell;
if (kDomain_DomainMode == domainMode || (fDomainNeedsDecal && !clampToBorderSupport)) {
GrTextureDomain::Mode wrapMode = fDomainNeedsDecal ? GrTextureDomain::kDecal_Mode
: GrTextureDomain::kClamp_Mode;
return GrBicubicEffect::Make(std::move(proxy), textureMatrix, kClampClamp, wrapMode,
wrapMode, kKernel, kDir, this->alphaType(),
wrapMode, kDir, this->alphaType(),
kDomain_DomainMode == domainMode ? &domain : nullptr);
} else {
return GrBicubicEffect::Make(std::move(proxy), textureMatrix,
fDomainNeedsDecal ? kDecalDecal : kClampClamp, kKernel,
kDir, this->alphaType());
fDomainNeedsDecal ? kDecalDecal : kClampClamp, kDir,
this->alphaType());
}
}
}

View File

@ -970,7 +970,6 @@ void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap,
// the rest from the SkPaint.
std::unique_ptr<GrFragmentProcessor> fp;
static constexpr auto kBicubicKernel = GrBicubicEffect::Kernel::kMitchell;
if (needsTextureDomain && (SkCanvas::kStrict_SrcRectConstraint == constraint)) {
// Use a constrained texture domain to avoid color bleeding
SkRect domain;
@ -988,7 +987,7 @@ void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap,
}
if (bicubic) {
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
fp = GrBicubicEffect::Make(std::move(proxy), texMatrix, domain, kBicubicKernel, kDir,
fp = GrBicubicEffect::Make(std::move(proxy), texMatrix, domain, kDir,
bitmap.alphaType());
} else {
fp = GrTextureDomainEffect::Make(std::move(proxy), texMatrix, domain,
@ -998,8 +997,7 @@ void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap,
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(proxy), texMatrix, wrapMode, kBicubicKernel, kDir,
bitmap.alphaType());
fp = GrBicubicEffect::Make(std::move(proxy), texMatrix, wrapMode, kDir, bitmap.alphaType());
} else {
fp = GrSimpleTextureEffect::Make(std::move(proxy), texMatrix, samplerState);
}

View File

@ -20,10 +20,8 @@ public:
GrProcessorKeyBuilder* b) {
const GrBicubicEffect& bicubicEffect = effect.cast<GrBicubicEffect>();
b->add32(GrTextureDomain::GLDomain::DomainKey(bicubicEffect.domain()));
auto kernel = static_cast<uint32_t>(bicubicEffect.kernel());
SkASSERT((kernel & ~0b1U) == 0);
uint32_t bidir = bicubicEffect.direction() == GrBicubicEffect::Direction::kXY ? 0b10 : 0b00;
b->add32(kernel | bidir | (bicubicEffect.alphaType() << 2));
uint32_t bidir = bicubicEffect.direction() == GrBicubicEffect::Direction::kXY ? 1 : 0;
b->add32(bidir | (bicubicEffect.alphaType() << 1));
}
protected:
@ -33,7 +31,7 @@ private:
typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
UniformHandle fDimensions;
GrTextureDomain::GLDomain fDomain;
GrTextureDomain::GLDomain fDomain;
typedef GrGLSLFragmentProcessor INHERITED;
};
@ -49,48 +47,29 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
if (bicubicEffect.kernel() == GrBicubicEffect::Kernel::kMitchell) {
/*
* Filter weights come from Don Mitchell & Arun Netravali's 'Reconstruction Filters in\
* Computer * Graphics', ACM SIGGRAPH Computer Graphics 22, 4 (Aug. 1988).
* ACM DL: http://dl.acm.org/citation.cfm?id=378514
* Free:
* http://www.cs.utexas.edu/users/fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf
*
* The authors define a family of cubic filters with two free parameters (B and C):
*
* { (12 - 9B - 6C)|x|^3 + (-18 + 12B + 6C)|x|^2 + (6 - 2B) if |x| < 1
* k(x) = 1/6 { (-B - 6C)|x|^3 + (6B + 30C)|x|^2 + (-12B - 48C)|x| + (8B + 24C) if 1 <= |x| < 2
* { 0 otherwise
*
* Various well-known cubic splines can be generated, and the authors select (1/3, 1/3) as
* their favorite overall spline - this is now commonly known as the Mitchell filter, and
* is the source of the specific weights below.
*
* This is SkSL, so the matrix is column-major (transposed from standard matrix notation).
*/
fragBuilder->codeAppend(
"half4x4 kCoefficients = half4x4("
" 1.0 / 18.0, 16.0 / 18.0, 1.0 / 18.0, 0.0 / 18.0,"
"-9.0 / 18.0, 0.0 / 18.0, 9.0 / 18.0, 0.0 / 18.0,"
"15.0 / 18.0, -36.0 / 18.0, 27.0 / 18.0, -6.0 / 18.0,"
"-7.0 / 18.0, 21.0 / 18.0, -21.0 / 18.0, 7.0 / 18.0);");
} else {
/*
* Centripetal variant of the Catmull-Rom spline.
*
* Catmull, Edwin; Rom, Raphael (1974). "A class of local interpolating splines". In
* Barnhill, Robert E.; Riesenfeld, Richard F. (eds.). Computer Aided Geometric Design.
* pp. 317326.
*/
SkASSERT(bicubicEffect.kernel() == GrBicubicEffect::Kernel::kCatmullRom);
fragBuilder->codeAppend(
"half4x4 kCoefficients = 0.5 * half4x4("
" 0, 2, 0, 0,"
"-1, 0, 1, 0,"
" 2, -5, 4, -1,"
"-1, 3, -3, 1);");
}
/*
* Filter weights come from Don Mitchell & Arun Netravali's 'Reconstruction Filters in Computer
* Graphics', ACM SIGGRAPH Computer Graphics 22, 4 (Aug. 1988).
* ACM DL: http://dl.acm.org/citation.cfm?id=378514
* Free : http://www.cs.utexas.edu/users/fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf
*
* The authors define a family of cubic filters with two free parameters (B and C):
*
* { (12 - 9B - 6C)|x|^3 + (-18 + 12B + 6C)|x|^2 + (6 - 2B) if |x| < 1
* k(x) = 1/6 { (-B - 6C)|x|^3 + (6B + 30C)|x|^2 + (-12B - 48C)|x| + (8B + 24C) if 1 <= |x| < 2
* { 0 otherwise
*
* Various well-known cubic splines can be generated, and the authors select (1/3, 1/3) as their
* 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).
*/
fragBuilder->codeAppend("half4x4 kMitchellCoefficients = half4x4("
" 1.0 / 18.0, 16.0 / 18.0, 1.0 / 18.0, 0.0 / 18.0,"
"-9.0 / 18.0, 0.0 / 18.0, 9.0 / 18.0, 0.0 / 18.0,"
"15.0 / 18.0, -36.0 / 18.0, 27.0 / 18.0, -6.0 / 18.0,"
"-7.0 / 18.0, 21.0 / 18.0, -21.0 / 18.0, 7.0 / 18.0);");
fragBuilder->codeAppendf("float2 coord = %s - %s.xy * float2(0.5);", coords2D.c_str(), dims);
// We unnormalize the coord in order to determine our fractional offset (f) within the texel
// We then snap coord to a texel center and renormalize. The snap prevents cases where the
@ -100,9 +79,9 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
fragBuilder->codeAppendf("coord = coord + (half2(0.5) - f) * %s.xy;", dims);
if (bicubicEffect.direction() == GrBicubicEffect::Direction::kXY) {
fragBuilder->codeAppend(
"half4 wx = kCoefficients * half4(1.0, f.x, f.x * f.x, f.x * f.x * f.x);");
"half4 wx = kMitchellCoefficients * half4(1.0, f.x, f.x * f.x, f.x * f.x * f.x);");
fragBuilder->codeAppend(
"half4 wy = kCoefficients * half4(1.0, f.y, f.y * f.y, f.y * f.y * f.y);");
"half4 wy = kMitchellCoefficients * half4(1.0, f.y, f.y * f.y, f.y * f.y * f.y);");
fragBuilder->codeAppend("half4 rowColors[4];");
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
@ -129,7 +108,7 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
// One of the dims.xy values will be zero. So v here selects the nonzero value of f.
fragBuilder->codeAppend("half v = f.x + f.y;");
fragBuilder->codeAppend("half v2 = v * v;");
fragBuilder->codeAppend("half4 w = kCoefficients * half4(1.0, v, v2, v2 * v);");
fragBuilder->codeAppend("half4 w = kMitchellCoefficients * half4(1.0, v, v2, v2 * v);");
fragBuilder->codeAppend("half4 c[4];");
for (int i = 0; i < 4; ++i) {
SkString coord;
@ -185,7 +164,7 @@ void GrGLBicubicEffect::onSetData(const GrGLSLProgramDataManager& pdman,
GrBicubicEffect::GrBicubicEffect(sk_sp<GrTextureProxy> proxy, const SkMatrix& matrix,
const SkRect& domain, const GrSamplerState::WrapMode wrapModes[2],
GrTextureDomain::Mode modeX, GrTextureDomain::Mode modeY,
Kernel kernel, Direction direction, SkAlphaType alphaType)
Direction direction, SkAlphaType alphaType)
: INHERITED{kGrBicubicEffect_ClassID,
ModulateForSamplerOptFlags(
proxy->config(),
@ -195,7 +174,6 @@ GrBicubicEffect::GrBicubicEffect(sk_sp<GrTextureProxy> proxy, const SkMatrix& ma
, fTextureSampler(std::move(proxy),
GrSamplerState(wrapModes, GrSamplerState::Filter::kNearest))
, fAlphaType(alphaType)
, fKernel(kernel)
, fDirection(direction) {
this->addCoordTransform(&fCoordTransform);
this->setTextureSamplerCnt(1);
@ -207,7 +185,6 @@ GrBicubicEffect::GrBicubicEffect(const GrBicubicEffect& that)
, fDomain(that.fDomain)
, fTextureSampler(that.fTextureSampler)
, fAlphaType(that.fAlphaType)
, fKernel(that.fKernel)
, fDirection(that.fDirection) {
this->addCoordTransform(&fCoordTransform);
this->setTextureSamplerCnt(1);
@ -237,8 +214,6 @@ std::unique_ptr<GrFragmentProcessor> GrBicubicEffect::TestCreate(GrProcessorTest
GrSamplerState::WrapMode::kClamp};
SkAlphaType alphaType = d->fRandom->nextBool() ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
Direction direction = Direction::kX;
auto kernel = d->fRandom->nextBool() ? GrBicubicEffect::Kernel::kMitchell
: GrBicubicEffect::Kernel::kCatmullRom;
switch (d->fRandom->nextULessThan(3)) {
case 0:
direction = Direction::kX;
@ -250,8 +225,8 @@ std::unique_ptr<GrFragmentProcessor> GrBicubicEffect::TestCreate(GrProcessorTest
direction = Direction::kXY;
break;
}
return GrBicubicEffect::Make(d->textureProxy(texIdx), SkMatrix::I(), kClampClamp, kernel,
direction, alphaType);
return GrBicubicEffect::Make(d->textureProxy(texIdx), SkMatrix::I(), kClampClamp, direction,
alphaType);
}
#endif

View File

@ -11,6 +11,8 @@
#include "src/gpu/effects/GrTextureDomain.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
class GrInvariantOutput;
class GrBicubicEffect : public GrFragmentProcessor {
public:
enum {
@ -18,11 +20,6 @@ public:
// surrounding texels are needed by the kernel in x and y.
};
enum class Kernel {
kMitchell,
kCatmullRom,
};
enum class Direction {
/** Apply bicubic kernel in local coord x, nearest neighbor in y. */
kX,
@ -44,39 +41,35 @@ public:
SkAlphaType alphaType() const { return fAlphaType; }
Kernel kernel() const { return fKernel; }
/**
* Create a bicubic filter effect with specified texture matrix with clamp wrap mode.
* Create a Mitchell filter effect with specified texture matrix with clamp wrap mode.
*/
static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
const SkMatrix& matrix,
Kernel kernel,
Direction direction,
SkAlphaType alphaType) {
static constexpr GrSamplerState::WrapMode kClampClamp[] = {
GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp};
return Make(std::move(proxy), matrix, kClampClamp, GrTextureDomain::kIgnore_Mode,
GrTextureDomain::kIgnore_Mode, kernel, direction, alphaType);
GrTextureDomain::kIgnore_Mode, direction, alphaType);
}
/**
* Create a bicubic filter effect with specified texture matrix and x/y tile modes.
* Create a Mitchell filter effect with specified texture matrix and x/y tile modes.
*/
static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
const SkMatrix& matrix,
const GrSamplerState::WrapMode wrapModes[2],
Kernel kernel,
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(proxy), matrix, wrapModes, GrTextureDomain::kIgnore_Mode,
GrTextureDomain::kIgnore_Mode, kernel, direction, alphaType);
GrTextureDomain::kIgnore_Mode, direction, alphaType);
}
/**
* Create a bicubic filter effect with specified texture matrix and x/y tile modes. This
* 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).
*/
@ -85,7 +78,6 @@ public:
const GrSamplerState::WrapMode wrapModes[2],
GrTextureDomain::Mode modeX,
GrTextureDomain::Mode modeY,
Kernel kernel,
Direction direction,
SkAlphaType alphaType,
const SkRect* domain = nullptr) {
@ -93,22 +85,21 @@ public:
SkIRect::MakeWH(proxy->width(), proxy->height()), modeX, modeY);
return std::unique_ptr<GrFragmentProcessor>(
new GrBicubicEffect(std::move(proxy), matrix, resolvedDomain, wrapModes, modeX,
modeY, kernel, direction, alphaType));
modeY, direction, alphaType));
}
/**
* Create a bicubic filter effect with a texture matrix and a domain.
* Create a Mitchell filter effect with a texture matrix and a domain.
*/
static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
const SkMatrix& matrix,
const SkRect& domain,
Kernel kernel,
Direction direction,
SkAlphaType alphaType) {
static const GrSamplerState::WrapMode kClampClamp[] = {
GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp};
return Make(std::move(proxy), matrix, kClampClamp, GrTextureDomain::kClamp_Mode,
GrTextureDomain::kClamp_Mode, kernel, direction, alphaType, &domain);
GrTextureDomain::kClamp_Mode, direction, alphaType, &domain);
}
/**
@ -122,9 +113,9 @@ public:
GrSamplerState::Filter* filterMode);
private:
GrBicubicEffect(sk_sp<GrTextureProxy>, const SkMatrix&, const SkRect& domain,
const GrSamplerState::WrapMode[2], GrTextureDomain::Mode modeX,
GrTextureDomain::Mode modeY, Kernel, Direction, SkAlphaType);
GrBicubicEffect(sk_sp<GrTextureProxy>, const SkMatrix& matrix, const SkRect& domain,
const GrSamplerState::WrapMode wrapModes[2], GrTextureDomain::Mode modeX,
GrTextureDomain::Mode modeY, Direction direction, SkAlphaType alphaType);
explicit GrBicubicEffect(const GrBicubicEffect&);
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
@ -139,7 +130,6 @@ private:
GrTextureDomain fDomain;
TextureSampler fTextureSampler;
SkAlphaType fAlphaType;
Kernel fKernel;
Direction fDirection;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST

View File

@ -12,6 +12,7 @@
#include "src/gpu/GrProcessor.h"
class GrGLBitmapTextGeoProc;
class GrInvariantOutput;
/**
* The output color of this effect is a modulation of the input color and a sample from a texture.

View File

@ -13,6 +13,7 @@
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrProcessor.h"
class GrInvariantOutput;
class SkPath;
/**

View File

@ -14,6 +14,7 @@
class GrGLDistanceFieldA8TextGeoProc;
class GrGLDistanceFieldPathGeoProc;
class GrGLDistanceFieldLCDTextGeoProc;
class GrInvariantOutput;
enum GrDistanceFieldEffectFlags {
kSimilarity_DistanceFieldEffectFlag = 0x01, // ctm is similarity matrix

View File

@ -15,6 +15,7 @@
class GrGLProgramBuilder;
class GrGLSLShaderBuilder;
class GrInvariantOutput;
class GrGLSLUniformHandler;
struct SkRect;

View File

@ -240,9 +240,8 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
// domainX and domainY will properly apply the decal effect with the texture domain used in
// the bicubic filter if clamp to border was unsupported in hardware
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
static constexpr auto kKernel = GrBicubicEffect::Kernel::kMitchell;
inner = GrBicubicEffect::Make(std::move(proxy), lmInverse, wrapModes, domainX, domainY,
kKernel, kDir, fImage->alphaType());
kDir, fImage->alphaType());
} else {
if (domainX != GrTextureDomain::kIgnore_Mode || domainY != GrTextureDomain::kIgnore_Mode) {
SkRect domain = GrTextureDomain::MakeTexelDomain(