GrBicubicEffect.cpp revision 77af6805e5faea1e2a5c0220098aec9082f3a6e5
13aad3b01afc77993ff051c02e49186294e312980humper@google.com#include "GrBicubicEffect.h"
23aad3b01afc77993ff051c02e49186294e312980humper@google.com
33aad3b01afc77993ff051c02e49186294e312980humper@google.com#define DS(x) SkDoubleToScalar(x)
43aad3b01afc77993ff051c02e49186294e312980humper@google.com
53aad3b01afc77993ff051c02e49186294e312980humper@google.comconst SkScalar GrBicubicEffect::gMitchellCoefficients[16] = {
63aad3b01afc77993ff051c02e49186294e312980humper@google.com    DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0),
73aad3b01afc77993ff051c02e49186294e312980humper@google.com    DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0),
83aad3b01afc77993ff051c02e49186294e312980humper@google.com    DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0),
93aad3b01afc77993ff051c02e49186294e312980humper@google.com    DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS(  7.0 / 18.0),
103aad3b01afc77993ff051c02e49186294e312980humper@google.com};
113aad3b01afc77993ff051c02e49186294e312980humper@google.com
123aad3b01afc77993ff051c02e49186294e312980humper@google.com
133aad3b01afc77993ff051c02e49186294e312980humper@google.comclass GrGLBicubicEffect : public GrGLEffect {
143aad3b01afc77993ff051c02e49186294e312980humper@google.compublic:
153aad3b01afc77993ff051c02e49186294e312980humper@google.com    GrGLBicubicEffect(const GrBackendEffectFactory& factory,
163aad3b01afc77993ff051c02e49186294e312980humper@google.com                      const GrDrawEffect&);
173aad3b01afc77993ff051c02e49186294e312980humper@google.com    virtual void emitCode(GrGLShaderBuilder*,
183aad3b01afc77993ff051c02e49186294e312980humper@google.com                          const GrDrawEffect&,
193aad3b01afc77993ff051c02e49186294e312980humper@google.com                          EffectKey,
203aad3b01afc77993ff051c02e49186294e312980humper@google.com                          const char* outputColor,
213aad3b01afc77993ff051c02e49186294e312980humper@google.com                          const char* inputColor,
2277af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                          const TransformedCoordsArray&,
233aad3b01afc77993ff051c02e49186294e312980humper@google.com                          const TextureSamplerArray&) SK_OVERRIDE;
243aad3b01afc77993ff051c02e49186294e312980humper@google.com
253aad3b01afc77993ff051c02e49186294e312980humper@google.com    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
263aad3b01afc77993ff051c02e49186294e312980humper@google.com
273aad3b01afc77993ff051c02e49186294e312980humper@google.comprivate:
283aad3b01afc77993ff051c02e49186294e312980humper@google.com    typedef GrGLUniformManager::UniformHandle        UniformHandle;
293aad3b01afc77993ff051c02e49186294e312980humper@google.com
303aad3b01afc77993ff051c02e49186294e312980humper@google.com    UniformHandle       fCoefficientsUni;
313aad3b01afc77993ff051c02e49186294e312980humper@google.com    UniformHandle       fImageIncrementUni;
323aad3b01afc77993ff051c02e49186294e312980humper@google.com
333aad3b01afc77993ff051c02e49186294e312980humper@google.com    typedef GrGLEffect INHERITED;
343aad3b01afc77993ff051c02e49186294e312980humper@google.com};
353aad3b01afc77993ff051c02e49186294e312980humper@google.com
3677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.comGrGLBicubicEffect::GrGLBicubicEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
3777af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com    : INHERITED(factory) {
383aad3b01afc77993ff051c02e49186294e312980humper@google.com}
393aad3b01afc77993ff051c02e49186294e312980humper@google.com
403aad3b01afc77993ff051c02e49186294e312980humper@google.comvoid GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder,
413aad3b01afc77993ff051c02e49186294e312980humper@google.com                                 const GrDrawEffect&,
423aad3b01afc77993ff051c02e49186294e312980humper@google.com                                 EffectKey key,
433aad3b01afc77993ff051c02e49186294e312980humper@google.com                                 const char* outputColor,
443aad3b01afc77993ff051c02e49186294e312980humper@google.com                                 const char* inputColor,
4577af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                                 const TransformedCoordsArray& coords,
463aad3b01afc77993ff051c02e49186294e312980humper@google.com                                 const TextureSamplerArray& samplers) {
4777af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com    SkString coords2D = builder->ensureFSCoords2D(coords, 0);
483aad3b01afc77993ff051c02e49186294e312980humper@google.com    fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
493aad3b01afc77993ff051c02e49186294e312980humper@google.com                                           kMat44f_GrSLType, "Coefficients");
503aad3b01afc77993ff051c02e49186294e312980humper@google.com    fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
513aad3b01afc77993ff051c02e49186294e312980humper@google.com                                             kVec2f_GrSLType, "ImageIncrement");
523aad3b01afc77993ff051c02e49186294e312980humper@google.com
533aad3b01afc77993ff051c02e49186294e312980humper@google.com    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
543aad3b01afc77993ff051c02e49186294e312980humper@google.com    const char* coeff = builder->getUniformCStr(fCoefficientsUni);
553aad3b01afc77993ff051c02e49186294e312980humper@google.com
563aad3b01afc77993ff051c02e49186294e312980humper@google.com    SkString cubicBlendName;
573aad3b01afc77993ff051c02e49186294e312980humper@google.com
583aad3b01afc77993ff051c02e49186294e312980humper@google.com    static const GrGLShaderVar gCubicBlendArgs[] = {
593aad3b01afc77993ff051c02e49186294e312980humper@google.com        GrGLShaderVar("coefficients",  kMat44f_GrSLType),
603aad3b01afc77993ff051c02e49186294e312980humper@google.com        GrGLShaderVar("t",             kFloat_GrSLType),
613aad3b01afc77993ff051c02e49186294e312980humper@google.com        GrGLShaderVar("c0",            kVec4f_GrSLType),
623aad3b01afc77993ff051c02e49186294e312980humper@google.com        GrGLShaderVar("c1",            kVec4f_GrSLType),
633aad3b01afc77993ff051c02e49186294e312980humper@google.com        GrGLShaderVar("c2",            kVec4f_GrSLType),
643aad3b01afc77993ff051c02e49186294e312980humper@google.com        GrGLShaderVar("c3",            kVec4f_GrSLType),
653aad3b01afc77993ff051c02e49186294e312980humper@google.com    };
663aad3b01afc77993ff051c02e49186294e312980humper@google.com    builder->fsEmitFunction(kVec4f_GrSLType,
673aad3b01afc77993ff051c02e49186294e312980humper@google.com                            "cubicBlend",
683aad3b01afc77993ff051c02e49186294e312980humper@google.com                            SK_ARRAY_COUNT(gCubicBlendArgs),
693aad3b01afc77993ff051c02e49186294e312980humper@google.com                            gCubicBlendArgs,
703aad3b01afc77993ff051c02e49186294e312980humper@google.com                            "\tvec4 ts = vec4(1.0, t, t * t, t * t * t);\n"
713aad3b01afc77993ff051c02e49186294e312980humper@google.com                            "\tvec4 c = coefficients * ts;\n"
723aad3b01afc77993ff051c02e49186294e312980humper@google.com                            "\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3;\n",
733aad3b01afc77993ff051c02e49186294e312980humper@google.com                            &cubicBlendName);
7477af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com    builder->fsCodeAppendf("\tvec2 coord = %s - %s * vec2(0.5, 0.5);\n", coords2D.c_str(), imgInc);
753aad3b01afc77993ff051c02e49186294e312980humper@google.com    builder->fsCodeAppendf("\tvec2 f = fract(coord / %s);\n", imgInc);
763aad3b01afc77993ff051c02e49186294e312980humper@google.com    for (int y = 0; y < 4; ++y) {
773aad3b01afc77993ff051c02e49186294e312980humper@google.com        for (int x = 0; x < 4; ++x) {
783aad3b01afc77993ff051c02e49186294e312980humper@google.com            SkString coord;
793aad3b01afc77993ff051c02e49186294e312980humper@google.com            coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1);
803aad3b01afc77993ff051c02e49186294e312980humper@google.com            builder->fsCodeAppendf("\tvec4 s%d%d = ", x, y);
813aad3b01afc77993ff051c02e49186294e312980humper@google.com            builder->fsAppendTextureLookup(samplers[0], coord.c_str());
823aad3b01afc77993ff051c02e49186294e312980humper@google.com            builder->fsCodeAppend(";\n");
833aad3b01afc77993ff051c02e49186294e312980humper@google.com        }
843aad3b01afc77993ff051c02e49186294e312980humper@google.com        builder->fsCodeAppendf("\tvec4 s%d = %s(%s, f.x, s0%d, s1%d, s2%d, s3%d);\n", y, cubicBlendName.c_str(), coeff, y, y, y, y);
853aad3b01afc77993ff051c02e49186294e312980humper@google.com    }
863aad3b01afc77993ff051c02e49186294e312980humper@google.com    builder->fsCodeAppendf("\t%s = %s(%s, f.y, s0, s1, s2, s3);\n", outputColor, cubicBlendName.c_str(), coeff);
873aad3b01afc77993ff051c02e49186294e312980humper@google.com}
883aad3b01afc77993ff051c02e49186294e312980humper@google.com
893aad3b01afc77993ff051c02e49186294e312980humper@google.comvoid GrGLBicubicEffect::setData(const GrGLUniformManager& uman,
903aad3b01afc77993ff051c02e49186294e312980humper@google.com                                const GrDrawEffect& drawEffect) {
913aad3b01afc77993ff051c02e49186294e312980humper@google.com    const GrBicubicEffect& effect = drawEffect.castEffect<GrBicubicEffect>();
923aad3b01afc77993ff051c02e49186294e312980humper@google.com    GrTexture& texture = *effect.texture(0);
933aad3b01afc77993ff051c02e49186294e312980humper@google.com    float imageIncrement[2];
943aad3b01afc77993ff051c02e49186294e312980humper@google.com    imageIncrement[0] = 1.0f / texture.width();
953aad3b01afc77993ff051c02e49186294e312980humper@google.com    imageIncrement[1] = 1.0f / texture.height();
963aad3b01afc77993ff051c02e49186294e312980humper@google.com    uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement);
973aad3b01afc77993ff051c02e49186294e312980humper@google.com    uman.setMatrix4f(fCoefficientsUni, effect.coefficients());
983aad3b01afc77993ff051c02e49186294e312980humper@google.com}
993aad3b01afc77993ff051c02e49186294e312980humper@google.com
1003aad3b01afc77993ff051c02e49186294e312980humper@google.comGrBicubicEffect::GrBicubicEffect(GrTexture* texture,
1013aad3b01afc77993ff051c02e49186294e312980humper@google.com                                 const SkScalar coefficients[16])
1023aad3b01afc77993ff051c02e49186294e312980humper@google.com  : INHERITED(texture, MakeDivByTextureWHMatrix(texture)) {
1033aad3b01afc77993ff051c02e49186294e312980humper@google.com    for (int y = 0; y < 4; y++) {
1043aad3b01afc77993ff051c02e49186294e312980humper@google.com        for (int x = 0; x < 4; x++) {
1053aad3b01afc77993ff051c02e49186294e312980humper@google.com            // Convert from row-major scalars to column-major floats.
1063aad3b01afc77993ff051c02e49186294e312980humper@google.com            fCoefficients[x * 4 + y] = SkScalarToFloat(coefficients[y * 4 + x]);
1073aad3b01afc77993ff051c02e49186294e312980humper@google.com        }
1083aad3b01afc77993ff051c02e49186294e312980humper@google.com    }
1093aad3b01afc77993ff051c02e49186294e312980humper@google.com}
1103aad3b01afc77993ff051c02e49186294e312980humper@google.com
1113aad3b01afc77993ff051c02e49186294e312980humper@google.comGrBicubicEffect::GrBicubicEffect(GrTexture* texture,
1123aad3b01afc77993ff051c02e49186294e312980humper@google.com                                 const SkScalar coefficients[16],
1133aad3b01afc77993ff051c02e49186294e312980humper@google.com                                 const SkMatrix &matrix,
1143aad3b01afc77993ff051c02e49186294e312980humper@google.com                                 const GrTextureParams &params,
11577af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                                 GrCoordSet coordSet)
11677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com  : INHERITED(texture, MakeDivByTextureWHMatrix(texture), params, coordSet) {
1173aad3b01afc77993ff051c02e49186294e312980humper@google.com    for (int y = 0; y < 4; y++) {
1183aad3b01afc77993ff051c02e49186294e312980humper@google.com        for (int x = 0; x < 4; x++) {
1193aad3b01afc77993ff051c02e49186294e312980humper@google.com            // Convert from row-major scalars to column-major floats.
1203aad3b01afc77993ff051c02e49186294e312980humper@google.com            fCoefficients[x * 4 + y] = SkScalarToFloat(coefficients[y * 4 + x]);
1213aad3b01afc77993ff051c02e49186294e312980humper@google.com        }
1223aad3b01afc77993ff051c02e49186294e312980humper@google.com    }
1233aad3b01afc77993ff051c02e49186294e312980humper@google.com}
1243aad3b01afc77993ff051c02e49186294e312980humper@google.com
1253aad3b01afc77993ff051c02e49186294e312980humper@google.comGrBicubicEffect::~GrBicubicEffect() {
1263aad3b01afc77993ff051c02e49186294e312980humper@google.com}
1273aad3b01afc77993ff051c02e49186294e312980humper@google.com
1283aad3b01afc77993ff051c02e49186294e312980humper@google.comconst GrBackendEffectFactory& GrBicubicEffect::getFactory() const {
1293aad3b01afc77993ff051c02e49186294e312980humper@google.com    return GrTBackendEffectFactory<GrBicubicEffect>::getInstance();
1303aad3b01afc77993ff051c02e49186294e312980humper@google.com}
1313aad3b01afc77993ff051c02e49186294e312980humper@google.com
1323aad3b01afc77993ff051c02e49186294e312980humper@google.combool GrBicubicEffect::onIsEqual(const GrEffect& sBase) const {
1333aad3b01afc77993ff051c02e49186294e312980humper@google.com    const GrBicubicEffect& s = CastEffect<GrBicubicEffect>(sBase);
134d1af237d7d52e23bc08ccaf73eddaadddeab6758humper@google.com    return this->textureAccess(0) == s.textureAccess(0) &&
1353aad3b01afc77993ff051c02e49186294e312980humper@google.com           !memcmp(fCoefficients, s.coefficients(), 16);
1363aad3b01afc77993ff051c02e49186294e312980humper@google.com}
1373aad3b01afc77993ff051c02e49186294e312980humper@google.com
1383aad3b01afc77993ff051c02e49186294e312980humper@google.comvoid GrBicubicEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
1393aad3b01afc77993ff051c02e49186294e312980humper@google.com    // FIXME:  Perhaps we can do better.
1403aad3b01afc77993ff051c02e49186294e312980humper@google.com    *validFlags = 0;
1413aad3b01afc77993ff051c02e49186294e312980humper@google.com    return;
1423aad3b01afc77993ff051c02e49186294e312980humper@google.com}
1433aad3b01afc77993ff051c02e49186294e312980humper@google.com
1443aad3b01afc77993ff051c02e49186294e312980humper@google.comGR_DEFINE_EFFECT_TEST(GrBicubicEffect);
1453aad3b01afc77993ff051c02e49186294e312980humper@google.com
146e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.orgGrEffectRef* GrBicubicEffect::TestCreate(SkRandom* random,
1473aad3b01afc77993ff051c02e49186294e312980humper@google.com                                         GrContext* context,
1483aad3b01afc77993ff051c02e49186294e312980humper@google.com                                         const GrDrawTargetCaps&,
1493aad3b01afc77993ff051c02e49186294e312980humper@google.com                                         GrTexture* textures[]) {
1503aad3b01afc77993ff051c02e49186294e312980humper@google.com    int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
1513aad3b01afc77993ff051c02e49186294e312980humper@google.com                                      GrEffectUnitTest::kAlphaTextureIdx;
1523aad3b01afc77993ff051c02e49186294e312980humper@google.com    SkScalar coefficients[16];
1533aad3b01afc77993ff051c02e49186294e312980humper@google.com    for (int i = 0; i < 16; i++) {
1543aad3b01afc77993ff051c02e49186294e312980humper@google.com        coefficients[i] = random->nextSScalar1();
1553aad3b01afc77993ff051c02e49186294e312980humper@google.com    }
1563aad3b01afc77993ff051c02e49186294e312980humper@google.com    return GrBicubicEffect::Create(textures[texIdx], coefficients);
1573aad3b01afc77993ff051c02e49186294e312980humper@google.com}
158