| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 The Android Open Source Project | 2 * Copyright 2013 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBicubicImageFilter.h" | 8 #include "SkBicubicImageFilter.h" |
| 9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| 11 #include "SkFlattenableBuffers.h" | 11 #include "SkFlattenableBuffers.h" |
| 12 #include "SkMatrix.h" | 12 #include "SkMatrix.h" |
| 13 #include "SkRect.h" | 13 #include "SkRect.h" |
| 14 #include "SkUnPreMultiply.h" | 14 #include "SkUnPreMultiply.h" |
| 15 | 15 |
| 16 #if SK_SUPPORT_GPU | 16 #if SK_SUPPORT_GPU |
| 17 #include "gl/GrGLEffectMatrix.h" | 17 #include "effects/GrBicubicEffect.h" |
| 18 #include "effects/GrSingleTextureEffect.h" | |
| 19 #include "GrTBackendEffectFactory.h" | |
| 20 #include "GrContext.h" | 18 #include "GrContext.h" |
| 21 #include "GrTexture.h" | 19 #include "GrTexture.h" |
| 22 #include "SkImageFilterUtils.h" | 20 #include "SkImageFilterUtils.h" |
| 23 #endif | 21 #endif |
| 24 | 22 |
| 23 #define DS(x) SkDoubleToScalar(x) |
| 24 |
| 25 static const SkScalar gMitchellCoefficients[16] = { |
| 26 DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0), |
| 27 DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0), |
| 28 DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0), |
| 29 DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0), |
| 30 }; |
| 31 |
| 25 SkBicubicImageFilter::SkBicubicImageFilter(const SkSize& scale, const SkScalar c
oefficients[16], SkImageFilter* input) | 32 SkBicubicImageFilter::SkBicubicImageFilter(const SkSize& scale, const SkScalar c
oefficients[16], SkImageFilter* input) |
| 26 : INHERITED(input), | 33 : INHERITED(input), |
| 27 fScale(scale) { | 34 fScale(scale) { |
| 28 memcpy(fCoefficients, coefficients, sizeof(fCoefficients)); | 35 memcpy(fCoefficients, coefficients, sizeof(fCoefficients)); |
| 29 } | 36 } |
| 30 | 37 |
| 31 #define DS(x) SkDoubleToScalar(x) | |
| 32 | |
| 33 SkBicubicImageFilter* SkBicubicImageFilter::CreateMitchell(const SkSize& scale, | 38 SkBicubicImageFilter* SkBicubicImageFilter::CreateMitchell(const SkSize& scale, |
| 34 SkImageFilter* input)
{ | 39 SkImageFilter* input)
{ |
| 35 static const SkScalar coefficients[16] = { | 40 return SkNEW_ARGS(SkBicubicImageFilter, (scale, gMitchellCoefficients, input
)); |
| 36 DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0), | |
| 37 DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0), | |
| 38 DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0), | |
| 39 DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0), | |
| 40 }; | |
| 41 return SkNEW_ARGS(SkBicubicImageFilter, (scale, coefficients, input)); | |
| 42 } | 41 } |
| 43 | 42 |
| 44 SkBicubicImageFilter::SkBicubicImageFilter(SkFlattenableReadBuffer& buffer) : IN
HERITED(buffer) { | 43 SkBicubicImageFilter::SkBicubicImageFilter(SkFlattenableReadBuffer& buffer) : IN
HERITED(buffer) { |
| 45 SkDEBUGCODE(uint32_t readSize =) buffer.readScalarArray(fCoefficients); | 44 SkDEBUGCODE(uint32_t readSize =) buffer.readScalarArray(fCoefficients); |
| 46 SkASSERT(readSize == 16); | 45 SkASSERT(readSize == 16); |
| 47 fScale.fWidth = buffer.readScalar(); | 46 fScale.fWidth = buffer.readScalar(); |
| 48 fScale.fHeight = buffer.readScalar(); | 47 fScale.fHeight = buffer.readScalar(); |
| 49 } | 48 } |
| 50 | 49 |
| 51 void SkBicubicImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { | 50 void SkBicubicImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 SkPMColor s3 = cubicBlend(fCoefficients, fractx, s03, s13, s23, s33)
; | 149 SkPMColor s3 = cubicBlend(fCoefficients, fractx, s03, s13, s23, s33)
; |
| 151 *dptr++ = cubicBlend(fCoefficients, fracty, s0, s1, s2, s3); | 150 *dptr++ = cubicBlend(fCoefficients, fracty, s0, s1, s2, s3); |
| 152 } | 151 } |
| 153 } | 152 } |
| 154 return true; | 153 return true; |
| 155 } | 154 } |
| 156 | 155 |
| 157 /////////////////////////////////////////////////////////////////////////////// | 156 /////////////////////////////////////////////////////////////////////////////// |
| 158 | 157 |
| 159 #if SK_SUPPORT_GPU | 158 #if SK_SUPPORT_GPU |
| 160 class GrGLBicubicEffect; | |
| 161 | |
| 162 class GrBicubicEffect : public GrSingleTextureEffect { | |
| 163 public: | |
| 164 virtual ~GrBicubicEffect(); | |
| 165 | |
| 166 static const char* Name() { return "Bicubic"; } | |
| 167 const float* coefficients() const { return fCoefficients; } | |
| 168 | |
| 169 typedef GrGLBicubicEffect GLEffect; | |
| 170 | |
| 171 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | |
| 172 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; | |
| 173 | |
| 174 static GrEffectRef* Create(GrTexture* tex, const SkScalar coefficients[16])
{ | |
| 175 AutoEffectUnref effect(SkNEW_ARGS(GrBicubicEffect, (tex, coefficients)))
; | |
| 176 return CreateEffectRef(effect); | |
| 177 } | |
| 178 | |
| 179 private: | |
| 180 GrBicubicEffect(GrTexture*, const SkScalar coefficients[16]); | |
| 181 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; | |
| 182 float fCoefficients[16]; | |
| 183 | |
| 184 GR_DECLARE_EFFECT_TEST; | |
| 185 | |
| 186 typedef GrSingleTextureEffect INHERITED; | |
| 187 }; | |
| 188 | |
| 189 class GrGLBicubicEffect : public GrGLEffect { | |
| 190 public: | |
| 191 GrGLBicubicEffect(const GrBackendEffectFactory& factory, | |
| 192 const GrDrawEffect&); | |
| 193 virtual void emitCode(GrGLShaderBuilder*, | |
| 194 const GrDrawEffect&, | |
| 195 EffectKey, | |
| 196 const char* outputColor, | |
| 197 const char* inputColor, | |
| 198 const TextureSamplerArray&) SK_OVERRIDE; | |
| 199 | |
| 200 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); | |
| 201 | |
| 202 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; | |
| 203 | |
| 204 private: | |
| 205 typedef GrGLUniformManager::UniformHandle UniformHandle; | |
| 206 | |
| 207 UniformHandle fCoefficientsUni; | |
| 208 UniformHandle fImageIncrementUni; | |
| 209 | |
| 210 GrGLEffectMatrix fEffectMatrix; | |
| 211 | |
| 212 typedef GrGLEffect INHERITED; | |
| 213 }; | |
| 214 | |
| 215 GrGLBicubicEffect::GrGLBicubicEffect(const GrBackendEffectFactory& factory, | |
| 216 const GrDrawEffect& drawEffect) | |
| 217 : INHERITED(factory) | |
| 218 , fEffectMatrix(drawEffect.castEffect<GrBicubicEffect>().coordsType()) { | |
| 219 } | |
| 220 | |
| 221 void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder, | |
| 222 const GrDrawEffect&, | |
| 223 EffectKey key, | |
| 224 const char* outputColor, | |
| 225 const char* inputColor, | |
| 226 const TextureSamplerArray& samplers) { | |
| 227 SkString coords; | |
| 228 fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords); | |
| 229 fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili
ty, | |
| 230 kMat44f_GrSLType, "Coefficients"); | |
| 231 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibi
lity, | |
| 232 kVec2f_GrSLType, "ImageIncrement"); | |
| 233 | |
| 234 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); | |
| 235 const char* coeff = builder->getUniformCStr(fCoefficientsUni); | |
| 236 | |
| 237 SkString cubicBlendName; | |
| 238 | |
| 239 static const GrGLShaderVar gCubicBlendArgs[] = { | |
| 240 GrGLShaderVar("coefficients", kMat44f_GrSLType), | |
| 241 GrGLShaderVar("t", kFloat_GrSLType), | |
| 242 GrGLShaderVar("c0", kVec4f_GrSLType), | |
| 243 GrGLShaderVar("c1", kVec4f_GrSLType), | |
| 244 GrGLShaderVar("c2", kVec4f_GrSLType), | |
| 245 GrGLShaderVar("c3", kVec4f_GrSLType), | |
| 246 }; | |
| 247 builder->fsEmitFunction(kVec4f_GrSLType, | |
| 248 "cubicBlend", | |
| 249 SK_ARRAY_COUNT(gCubicBlendArgs), | |
| 250 gCubicBlendArgs, | |
| 251 "\tvec4 ts = vec4(1.0, t, t * t, t * t * t);\n" | |
| 252 "\tvec4 c = coefficients * ts;\n" | |
| 253 "\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3;
\n", | |
| 254 &cubicBlendName); | |
| 255 builder->fsCodeAppendf("\tvec2 coord = %s - %s * vec2(0.5, 0.5);\n", coords.
c_str(), imgInc); | |
| 256 builder->fsCodeAppendf("\tvec2 f = fract(coord / %s);\n", imgInc); | |
| 257 for (int y = 0; y < 4; ++y) { | |
| 258 for (int x = 0; x < 4; ++x) { | |
| 259 SkString coord; | |
| 260 coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1); | |
| 261 builder->fsCodeAppendf("\tvec4 s%d%d = ", x, y); | |
| 262 builder->fsAppendTextureLookup(samplers[0], coord.c_str()); | |
| 263 builder->fsCodeAppend(";\n"); | |
| 264 } | |
| 265 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); | |
| 266 } | |
| 267 builder->fsCodeAppendf("\t%s = %s(%s, f.y, s0, s1, s2, s3);\n", outputColor,
cubicBlendName.c_str(), coeff); | |
| 268 } | |
| 269 | |
| 270 GrGLEffect::EffectKey GrGLBicubicEffect::GenKey(const GrDrawEffect& drawEffect,
const GrGLCaps&) { | |
| 271 const GrBicubicEffect& bicubic = drawEffect.castEffect<GrBicubicEffect>(); | |
| 272 EffectKey matrixKey = GrGLEffectMatrix::GenKey(bicubic.getMatrix(), | |
| 273 drawEffect, | |
| 274 bicubic.coordsType(), | |
| 275 bicubic.texture(0)); | |
| 276 return matrixKey; | |
| 277 } | |
| 278 | |
| 279 void GrGLBicubicEffect::setData(const GrGLUniformManager& uman, | |
| 280 const GrDrawEffect& drawEffect) { | |
| 281 const GrBicubicEffect& effect = drawEffect.castEffect<GrBicubicEffect>(); | |
| 282 GrTexture& texture = *effect.texture(0); | |
| 283 float imageIncrement[2]; | |
| 284 imageIncrement[0] = 1.0f / texture.width(); | |
| 285 imageIncrement[1] = 1.0f / texture.height(); | |
| 286 uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement); | |
| 287 uman.setMatrix4f(fCoefficientsUni, effect.coefficients()); | |
| 288 fEffectMatrix.setData(uman, | |
| 289 effect.getMatrix(), | |
| 290 drawEffect, | |
| 291 effect.texture(0)); | |
| 292 } | |
| 293 | |
| 294 GrBicubicEffect::GrBicubicEffect(GrTexture* texture, | |
| 295 const SkScalar coefficients[16]) | |
| 296 : INHERITED(texture, MakeDivByTextureWHMatrix(texture)) { | |
| 297 for (int y = 0; y < 4; y++) { | |
| 298 for (int x = 0; x < 4; x++) { | |
| 299 // Convert from row-major scalars to column-major floats. | |
| 300 fCoefficients[x * 4 + y] = SkScalarToFloat(coefficients[y * 4 + x]); | |
| 301 } | |
| 302 } | |
| 303 } | |
| 304 | |
| 305 GrBicubicEffect::~GrBicubicEffect() { | |
| 306 } | |
| 307 | |
| 308 const GrBackendEffectFactory& GrBicubicEffect::getFactory() const { | |
| 309 return GrTBackendEffectFactory<GrBicubicEffect>::getInstance(); | |
| 310 } | |
| 311 | |
| 312 bool GrBicubicEffect::onIsEqual(const GrEffect& sBase) const { | |
| 313 const GrBicubicEffect& s = CastEffect<GrBicubicEffect>(sBase); | |
| 314 return this->texture(0) == s.texture(0) && | |
| 315 !memcmp(fCoefficients, s.coefficients(), 16); | |
| 316 } | |
| 317 | |
| 318 void GrBicubicEffect::getConstantColorComponents(GrColor* color, uint32_t* valid
Flags) const { | |
| 319 // FIXME: Perhaps we can do better. | |
| 320 *validFlags = 0; | |
| 321 return; | |
| 322 } | |
| 323 | |
| 324 GR_DEFINE_EFFECT_TEST(GrBicubicEffect); | |
| 325 | |
| 326 GrEffectRef* GrBicubicEffect::TestCreate(SkMWCRandom* random, | |
| 327 GrContext* context, | |
| 328 const GrDrawTargetCaps&, | |
| 329 GrTexture* textures[]) { | |
| 330 int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : | |
| 331 GrEffectUnitTest::kAlphaTextureIdx; | |
| 332 SkScalar coefficients[16]; | |
| 333 for (int i = 0; i < 16; i++) { | |
| 334 coefficients[i] = random->nextSScalar1(); | |
| 335 } | |
| 336 return GrBicubicEffect::Create(textures[texIdx], coefficients); | |
| 337 } | |
| 338 | 159 |
| 339 bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, con
st SkMatrix& ctm, | 160 bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, con
st SkMatrix& ctm, |
| 340 SkBitmap* result, SkIPoint* offset) { | 161 SkBitmap* result, SkIPoint* offset) { |
| 341 SkBitmap srcBM; | 162 SkBitmap srcBM; |
| 342 if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &sr
cBM, offset)) { | 163 if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &sr
cBM, offset)) { |
| 343 return false; | 164 return false; |
| 344 } | 165 } |
| 345 GrTexture* srcTexture = srcBM.getTexture(); | 166 GrTexture* srcTexture = srcBM.getTexture(); |
| 346 GrContext* context = srcTexture->getContext(); | 167 GrContext* context = srcTexture->getContext(); |
| 347 | 168 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 363 GrPaint paint; | 184 GrPaint paint; |
| 364 paint.addColorEffect(GrBicubicEffect::Create(srcTexture, fCoefficients))->un
ref(); | 185 paint.addColorEffect(GrBicubicEffect::Create(srcTexture, fCoefficients))->un
ref(); |
| 365 SkRect srcRect; | 186 SkRect srcRect; |
| 366 srcBM.getBounds(&srcRect); | 187 srcBM.getBounds(&srcRect); |
| 367 context->drawRectToRect(paint, dstRect, srcRect); | 188 context->drawRectToRect(paint, dstRect, srcRect); |
| 368 return SkImageFilterUtils::WrapTexture(dst, desc.fWidth, desc.fHeight, resul
t); | 189 return SkImageFilterUtils::WrapTexture(dst, desc.fWidth, desc.fHeight, resul
t); |
| 369 } | 190 } |
| 370 #endif | 191 #endif |
| 371 | 192 |
| 372 /////////////////////////////////////////////////////////////////////////////// | 193 /////////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |