#include "glsl/GrGLSLUniformHandler.h"
#include "../private/GrGLSL.h"
-#define DS(x) SkDoubleToScalar(x)
-
/*
* Filter weights come from Don Mitchell & Arun Netravali's 'Reconstruction Filters in Computer
* Graphics', ACM SIGGRAPH Computer Graphics 22, 4 (Aug. 1988).
* 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.
+ *
+ * These weights are in column-major order (ie this matrix is transposed from what you'd expect),
+ * so we can upload them directly via setMatrix4f.
*/
-const SkScalar GrBicubicEffect::gMitchellCoefficients[16] = {
- DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0),
- DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0),
- DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0),
- DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0),
+static constexpr float kMitchellCoefficients[16] = {
+ 1.0f / 18.0f, 16.0f / 18.0f, 1.0f / 18.0f, 0.0f / 18.0f,
+ -9.0f / 18.0f, 0.0f / 18.0f, 9.0f / 18.0f, 0.0f / 18.0f,
+ 15.0f / 18.0f, -36.0f / 18.0f, 27.0f / 18.0f, -6.0f / 18.0f,
+ -7.0f / 18.0f, 21.0f / 18.0f, -21.0f / 18.0f, 7.0f / 18.0f,
};
-
class GrGLBicubicEffect : public GrGLSLFragmentProcessor {
public:
void emitCode(EmitArgs&) override;
imageIncrement[0] = 1.0f / texture->width();
imageIncrement[1] = 1.0f / texture->height();
pdman.set2fv(fImageIncrementUni, 1, imageIncrement);
- pdman.setMatrix4f(fCoefficientsUni, bicubicEffect.coefficients());
+ pdman.setMatrix4f(fCoefficientsUni, kMitchellCoefficients);
fDomain.setData(pdman, bicubicEffect.domain(), texture->origin());
if (SkToBool(bicubicEffect.colorSpaceXform())) {
pdman.setSkMatrix44(fColorSpaceXformUni, bicubicEffect.colorSpaceXform()->srcToDst());
}
}
-static inline void convert_row_major_scalar_coeffs_to_column_major_floats(float dst[16],
- const SkScalar src[16]) {
- for (int y = 0; y < 4; y++) {
- for (int x = 0; x < 4; x++) {
- dst[x * 4 + y] = SkScalarToFloat(src[y * 4 + x]);
- }
- }
-}
-
GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkScalar coefficients[16],
const SkMatrix &matrix,
const SkShader::TileMode tileModes[2])
- : INHERITED(texture, nullptr, matrix,
+ : INHERITED(texture, std::move(colorSpaceXform), matrix,
GrSamplerParams(tileModes, GrSamplerParams::kNone_FilterMode))
- , fDomain(GrTextureDomain::IgnoredDomain())
- , fColorSpaceXform(std::move(colorSpaceXform)) {
+ , fDomain(GrTextureDomain::IgnoredDomain()) {
this->initClassID<GrBicubicEffect>();
- convert_row_major_scalar_coeffs_to_column_major_floats(fCoefficients, coefficients);
}
GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkScalar coefficients[16],
const SkMatrix &matrix,
const SkRect& domain)
- : INHERITED(texture, nullptr, matrix,
+ : INHERITED(texture, std::move(colorSpaceXform), matrix,
GrSamplerParams(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode))
- , fDomain(domain, GrTextureDomain::kClamp_Mode)
- , fColorSpaceXform(std::move(colorSpaceXform)) {
+ , fDomain(domain, GrTextureDomain::kClamp_Mode) {
this->initClassID<GrBicubicEffect>();
- convert_row_major_scalar_coeffs_to_column_major_floats(fCoefficients, coefficients);
}
GrBicubicEffect::~GrBicubicEffect() {
bool GrBicubicEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
const GrBicubicEffect& s = sBase.cast<GrBicubicEffect>();
- return !memcmp(fCoefficients, s.coefficients(), 16) &&
- fDomain == s.fDomain;
+ return fDomain == s.fDomain;
}
void GrBicubicEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
sk_sp<GrFragmentProcessor> GrBicubicEffect::TestCreate(GrProcessorTestData* d) {
int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
GrProcessorUnitTest::kAlphaTextureIdx;
- SkScalar coefficients[16];
- for (int i = 0; i < 16; i++) {
- coefficients[i] = d->fRandom->nextSScalar1();
- }
auto colorSpaceXform = GrTest::TestColorXform(d->fRandom);
- return GrBicubicEffect::Make(d->fTextures[texIdx], colorSpaceXform, coefficients);
+ static const SkShader::TileMode kClampClamp[] =
+ { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode };
+ return GrBicubicEffect::Make(d->fTextures[texIdx], colorSpaceXform,
+ GrCoordTransform::MakeDivByTextureWHMatrix(d->fTextures[texIdx]),
+ kClampClamp);
}
//////////////////////////////////////////////////////////////////////////////
#include "GrTextureDomain.h"
#include "glsl/GrGLSLFragmentProcessor.h"
-class GrGLBicubicEffect;
class GrInvariantOutput;
class GrBicubicEffect : public GrSingleTextureEffect {
};
virtual ~GrBicubicEffect();
- const float* coefficients() const { return fCoefficients; }
-
const char* name() const override { return "Bicubic"; }
const GrTextureDomain& domain() const { return fDomain; }
- GrColorSpaceXform* colorSpaceXform() const { return fColorSpaceXform.get(); }
-
- /**
- * Create a simple filter effect with custom bicubic coefficients and optional domain.
- */
- static sk_sp<GrFragmentProcessor> Make(GrTexture* tex,
- sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkScalar coefficients[16],
- const SkRect* domain = nullptr) {
- if (nullptr == domain) {
- static const SkShader::TileMode kTileModes[] = { SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode };
- return Make(tex, std::move(colorSpaceXform), coefficients,
- GrCoordTransform::MakeDivByTextureWHMatrix(tex), kTileModes);
- } else {
- return sk_sp<GrFragmentProcessor>(
- new GrBicubicEffect(tex, std::move(colorSpaceXform), coefficients,
- GrCoordTransform::MakeDivByTextureWHMatrix(tex), *domain));
- }
- }
-
/**
* Create a Mitchell filter effect with specified texture matrix and x/y tile modes.
*/
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& matrix,
const SkShader::TileMode tileModes[2]) {
- return Make(tex, std::move(colorSpaceXform), gMitchellCoefficients, matrix, tileModes);
- }
-
- /**
- * Create a filter effect with custom bicubic coefficients, the texture matrix, and the x/y
- * tilemodes.
- */
- static sk_sp<GrFragmentProcessor> Make(GrTexture* tex,
- sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkScalar coefficients[16],
- const SkMatrix& matrix,
- const SkShader::TileMode tileModes[2]) {
return sk_sp<GrFragmentProcessor>(new GrBicubicEffect(tex, std::move(colorSpaceXform),
- coefficients, matrix, tileModes));
+ matrix, tileModes));
}
/**
const SkMatrix& matrix,
const SkRect& domain) {
return sk_sp<GrFragmentProcessor>(new GrBicubicEffect(tex, std::move(colorSpaceXform),
- gMitchellCoefficients, matrix,
- domain));
+ matrix, domain));
}
/**
GrSamplerParams::FilterMode* filterMode);
private:
- GrBicubicEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkScalar coefficients[16],
- const SkMatrix &matrix, const SkShader::TileMode tileModes[2]);
- GrBicubicEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkScalar coefficients[16],
- const SkMatrix &matrix, const SkRect& domain);
+ GrBicubicEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkMatrix &matrix,
+ const SkShader::TileMode tileModes[2]);
+ GrBicubicEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkMatrix &matrix,
+ const SkRect& domain);
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
- float fCoefficients[16];
GrTextureDomain fDomain;
- sk_sp<GrColorSpaceXform> fColorSpaceXform;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
- static const SkScalar gMitchellCoefficients[16];
-
typedef GrSingleTextureEffect INHERITED;
};