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 +}