gfx/skia/trunk/src/gpu/effects/GrBicubicEffect.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/gpu/effects/GrBicubicEffect.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,179 @@
     1.4 +#include "GrBicubicEffect.h"
     1.5 +
     1.6 +#define DS(x) SkDoubleToScalar(x)
     1.7 +
     1.8 +const SkScalar GrBicubicEffect::gMitchellCoefficients[16] = {
     1.9 +    DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0),
    1.10 +    DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0),
    1.11 +    DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0),
    1.12 +    DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS(  7.0 / 18.0),
    1.13 +};
    1.14 +
    1.15 +
    1.16 +class GrGLBicubicEffect : public GrGLEffect {
    1.17 +public:
    1.18 +    GrGLBicubicEffect(const GrBackendEffectFactory& factory,
    1.19 +                      const GrDrawEffect&);
    1.20 +
    1.21 +    virtual void emitCode(GrGLShaderBuilder*,
    1.22 +                          const GrDrawEffect&,
    1.23 +                          EffectKey,
    1.24 +                          const char* outputColor,
    1.25 +                          const char* inputColor,
    1.26 +                          const TransformedCoordsArray&,
    1.27 +                          const TextureSamplerArray&) SK_OVERRIDE;
    1.28 +
    1.29 +    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
    1.30 +
    1.31 +    static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
    1.32 +        const GrTextureDomain& domain = drawEffect.castEffect<GrBicubicEffect>().domain();
    1.33 +        return GrTextureDomain::GLDomain::DomainKey(domain);
    1.34 +    }
    1.35 +
    1.36 +private:
    1.37 +    typedef GrGLUniformManager::UniformHandle        UniformHandle;
    1.38 +
    1.39 +    UniformHandle               fCoefficientsUni;
    1.40 +    UniformHandle               fImageIncrementUni;
    1.41 +    GrTextureDomain::GLDomain   fDomain;
    1.42 +
    1.43 +    typedef GrGLEffect INHERITED;
    1.44 +};
    1.45 +
    1.46 +GrGLBicubicEffect::GrGLBicubicEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
    1.47 +    : INHERITED(factory) {
    1.48 +}
    1.49 +
    1.50 +void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder,
    1.51 +                                 const GrDrawEffect& drawEffect,
    1.52 +                                 EffectKey key,
    1.53 +                                 const char* outputColor,
    1.54 +                                 const char* inputColor,
    1.55 +                                 const TransformedCoordsArray& coords,
    1.56 +                                 const TextureSamplerArray& samplers) {
    1.57 +    const GrTextureDomain& domain = drawEffect.castEffect<GrBicubicEffect>().domain();
    1.58 +
    1.59 +    SkString coords2D = builder->ensureFSCoords2D(coords, 0);
    1.60 +    fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
    1.61 +                                           kMat44f_GrSLType, "Coefficients");
    1.62 +    fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
    1.63 +                                             kVec2f_GrSLType, "ImageIncrement");
    1.64 +
    1.65 +    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
    1.66 +    const char* coeff = builder->getUniformCStr(fCoefficientsUni);
    1.67 +
    1.68 +    SkString cubicBlendName;
    1.69 +
    1.70 +    static const GrGLShaderVar gCubicBlendArgs[] = {
    1.71 +        GrGLShaderVar("coefficients",  kMat44f_GrSLType),
    1.72 +        GrGLShaderVar("t",             kFloat_GrSLType),
    1.73 +        GrGLShaderVar("c0",            kVec4f_GrSLType),
    1.74 +        GrGLShaderVar("c1",            kVec4f_GrSLType),
    1.75 +        GrGLShaderVar("c2",            kVec4f_GrSLType),
    1.76 +        GrGLShaderVar("c3",            kVec4f_GrSLType),
    1.77 +    };
    1.78 +    builder->fsEmitFunction(kVec4f_GrSLType,
    1.79 +                            "cubicBlend",
    1.80 +                            SK_ARRAY_COUNT(gCubicBlendArgs),
    1.81 +                            gCubicBlendArgs,
    1.82 +                            "\tvec4 ts = vec4(1.0, t, t * t, t * t * t);\n"
    1.83 +                            "\tvec4 c = coefficients * ts;\n"
    1.84 +                            "\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3;\n",
    1.85 +                            &cubicBlendName);
    1.86 +    builder->fsCodeAppendf("\tvec2 coord = %s - %s * vec2(0.5);\n", coords2D.c_str(), imgInc);
    1.87 +    // We unnormalize the coord in order to determine our fractional offset (f) within the texel
    1.88 +    // We then snap coord to a texel center and renormalize. The snap prevents cases where the
    1.89 +    // starting coords are near a texel boundary and accumulations of imgInc would cause us to skip/
    1.90 +    // double hit a texel.
    1.91 +    builder->fsCodeAppendf("\tcoord /= %s;\n", imgInc);
    1.92 +    builder->fsCodeAppend("\tvec2 f = fract(coord);\n");
    1.93 +    builder->fsCodeAppendf("\tcoord = (coord - f + vec2(0.5)) * %s;\n", imgInc);
    1.94 +    builder->fsCodeAppend("\tvec4 rowColors[4];\n");
    1.95 +    for (int y = 0; y < 4; ++y) {
    1.96 +        for (int x = 0; x < 4; ++x) {
    1.97 +            SkString coord;
    1.98 +            coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1);
    1.99 +            SkString sampleVar;
   1.100 +            sampleVar.printf("rowColors[%d]", x);
   1.101 +            fDomain.sampleTexture(builder, domain, sampleVar.c_str(), coord, samplers[0]);
   1.102 +        }
   1.103 +        builder->fsCodeAppendf("\tvec4 s%d = %s(%s, f.x, rowColors[0], rowColors[1], rowColors[2], rowColors[3]);\n", y, cubicBlendName.c_str(), coeff);
   1.104 +    }
   1.105 +    SkString bicubicColor;
   1.106 +    bicubicColor.printf("%s(%s, f.y, s0, s1, s2, s3)", cubicBlendName.c_str(), coeff);
   1.107 +    builder->fsCodeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(bicubicColor.c_str()) * GrGLSLExpr4(inputColor)).c_str());
   1.108 +}
   1.109 +
   1.110 +void GrGLBicubicEffect::setData(const GrGLUniformManager& uman,
   1.111 +                                const GrDrawEffect& drawEffect) {
   1.112 +    const GrBicubicEffect& effect = drawEffect.castEffect<GrBicubicEffect>();
   1.113 +    const GrTexture& texture = *effect.texture(0);
   1.114 +    float imageIncrement[2];
   1.115 +    imageIncrement[0] = 1.0f / texture.width();
   1.116 +    imageIncrement[1] = 1.0f / texture.height();
   1.117 +    uman.set2fv(fImageIncrementUni, 1, imageIncrement);
   1.118 +    uman.setMatrix4f(fCoefficientsUni, effect.coefficients());
   1.119 +    fDomain.setData(uman, effect.domain(), texture.origin());
   1.120 +}
   1.121 +
   1.122 +static inline void convert_row_major_scalar_coeffs_to_column_major_floats(float dst[16],
   1.123 +                                                                          const SkScalar src[16]) {
   1.124 +    for (int y = 0; y < 4; y++) {
   1.125 +        for (int x = 0; x < 4; x++) {
   1.126 +            dst[x * 4 + y] = SkScalarToFloat(src[y * 4 + x]);
   1.127 +        }
   1.128 +    }
   1.129 +}
   1.130 +
   1.131 +GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
   1.132 +                                 const SkScalar coefficients[16],
   1.133 +                                 const SkMatrix &matrix,
   1.134 +                                 const SkShader::TileMode tileModes[2])
   1.135 +  : INHERITED(texture, matrix, GrTextureParams(tileModes, GrTextureParams::kNone_FilterMode))
   1.136 +  , fDomain(GrTextureDomain::IgnoredDomain()) {
   1.137 +    convert_row_major_scalar_coeffs_to_column_major_floats(fCoefficients, coefficients);
   1.138 +}
   1.139 +
   1.140 +GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
   1.141 +                                 const SkScalar coefficients[16],
   1.142 +                                 const SkMatrix &matrix,
   1.143 +                                 const SkRect& domain)
   1.144 +  : INHERITED(texture, matrix, GrTextureParams(SkShader::kClamp_TileMode,
   1.145 +                                               GrTextureParams::kNone_FilterMode))
   1.146 +  , fDomain(domain, GrTextureDomain::kClamp_Mode) {
   1.147 +    convert_row_major_scalar_coeffs_to_column_major_floats(fCoefficients, coefficients);
   1.148 +}
   1.149 +
   1.150 +GrBicubicEffect::~GrBicubicEffect() {
   1.151 +}
   1.152 +
   1.153 +const GrBackendEffectFactory& GrBicubicEffect::getFactory() const {
   1.154 +    return GrTBackendEffectFactory<GrBicubicEffect>::getInstance();
   1.155 +}
   1.156 +
   1.157 +bool GrBicubicEffect::onIsEqual(const GrEffect& sBase) const {
   1.158 +    const GrBicubicEffect& s = CastEffect<GrBicubicEffect>(sBase);
   1.159 +    return this->textureAccess(0) == s.textureAccess(0) &&
   1.160 +           !memcmp(fCoefficients, s.coefficients(), 16);
   1.161 +}
   1.162 +
   1.163 +void GrBicubicEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
   1.164 +    // FIXME: Perhaps we can do better.
   1.165 +    *validFlags = 0;
   1.166 +    return;
   1.167 +}
   1.168 +
   1.169 +GR_DEFINE_EFFECT_TEST(GrBicubicEffect);
   1.170 +
   1.171 +GrEffectRef* GrBicubicEffect::TestCreate(SkRandom* random,
   1.172 +                                         GrContext* context,
   1.173 +                                         const GrDrawTargetCaps&,
   1.174 +                                         GrTexture* textures[]) {
   1.175 +    int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
   1.176 +                                      GrEffectUnitTest::kAlphaTextureIdx;
   1.177 +    SkScalar coefficients[16];
   1.178 +    for (int i = 0; i < 16; i++) {
   1.179 +        coefficients[i] = random->nextSScalar1();
   1.180 +    }
   1.181 +    return GrBicubicEffect::Create(textures[texIdx], coefficients);
   1.182 +}

mercurial