| Index: src/gpu/effects/GrConvolutionEffect.cpp
|
| diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
|
| index 380581fae360795c6447725e701f00fcbb7bb173..90546758e4587828ff955b2f91521ec0fc5bb475 100644
|
| --- a/src/gpu/effects/GrConvolutionEffect.cpp
|
| +++ b/src/gpu/effects/GrConvolutionEffect.cpp
|
| @@ -37,6 +37,7 @@ private:
|
| int fRadius;
|
| UniformHandle fKernelUni;
|
| UniformHandle fImageIncrementUni;
|
| + UniformHandle fCropRectUni;
|
| GrGLEffectMatrix fEffectMatrix;
|
|
|
| typedef GrGLEffect INHERITED;
|
| @@ -47,6 +48,7 @@ GrGLConvolutionEffect::GrGLConvolutionEffect(const GrBackendEffectFactory& facto
|
| : INHERITED(factory)
|
| , fKernelUni(kInvalidUniformHandle)
|
| , fImageIncrementUni(kInvalidUniformHandle)
|
| + , fCropRectUni(kInvalidUniformHandle)
|
| , fEffectMatrix(drawEffect.castEffect<GrConvolutionEffect>().coordsType()) {
|
| const GrConvolutionEffect& c = drawEffect.castEffect<GrConvolutionEffect>();
|
| fRadius = c.radius();
|
| @@ -62,6 +64,8 @@ void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
|
| fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords);
|
| fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
| kVec2f_GrSLType, "ImageIncrement");
|
| + fCropRectUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
| + kVec4f_GrSLType, "CropRect");
|
| fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_ShaderType,
|
| kFloat_GrSLType, "Kernel", this->width());
|
|
|
| @@ -70,6 +74,7 @@ void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
|
| int width = this ->width();
|
| const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni);
|
| const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
|
| + const char* cropRect = builder->getUniformCStr(fCropRectUni);
|
|
|
| builder->fsCodeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords, fRadius, imgInc);
|
|
|
| @@ -81,9 +86,10 @@ void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
|
| kernel.appendArrayAccess(index.c_str(), &kernelIndex);
|
| builder->fsCodeAppendf("\t\t%s += ", outputColor);
|
| builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, samplers[0], "coord");
|
| - builder->fsCodeAppendf(" * %s;\n", kernelIndex.c_str());
|
| + builder->fsCodeAppendf(" * float(coord.x >= %s.x && coord.x <= %s.y && coord.y >= %s.z && coord.y <= %s.w) * %s;\n", cropRect, cropRect, cropRect, cropRect, kernelIndex.c_str());
|
| builder->fsCodeAppendf("\t\tcoord += %s;\n", imgInc);
|
| }
|
| +
|
| SkString modulate;
|
| GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
|
| builder->fsCodeAppend(modulate.c_str());
|
| @@ -96,17 +102,26 @@ void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman,
|
| // the code we generated was for a specific kernel radius
|
| GrAssert(conv.radius() == fRadius);
|
| float imageIncrement[2] = { 0 };
|
| + float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f;
|
| switch (conv.direction()) {
|
| case Gr1DKernelEffect::kX_Direction:
|
| imageIncrement[0] = 1.0f / texture.width();
|
| break;
|
| case Gr1DKernelEffect::kY_Direction:
|
| - imageIncrement[1] = 1.0f / texture.height();
|
| + imageIncrement[1] = ySign / texture.height();
|
| break;
|
| default:
|
| GrCrash("Unknown filter direction.");
|
| }
|
| uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement);
|
| + float c[4];
|
| + memcpy(c, conv.cropRect(), sizeof(c));
|
| + if (texture.origin() != kTopLeft_GrSurfaceOrigin) {
|
| + float tmp = 1.0f - c[2];
|
| + c[2] = 1.0f - c[3];
|
| + c[3] = tmp;
|
| + }
|
| + uman.set4fv(fCropRectUni, 0, 1, c);
|
| uman.set1fv(fKernelUni, 0, this->width(), conv.kernel());
|
| fEffectMatrix.setData(uman, conv.getMatrix(), drawEffect, conv.texture(0));
|
| }
|
| @@ -128,7 +143,8 @@ GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrDrawEffect& drawEffe
|
| GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
|
| Direction direction,
|
| int radius,
|
| - const float* kernel)
|
| + const float* kernel,
|
| + float cropRect[4])
|
| : Gr1DKernelEffect(texture, direction, radius) {
|
| GrAssert(radius <= kMaxKernelRadius);
|
| GrAssert(NULL != kernel);
|
| @@ -136,12 +152,14 @@ GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
|
| for (int i = 0; i < width; i++) {
|
| fKernel[i] = kernel[i];
|
| }
|
| + memcpy(fCropRect, cropRect, sizeof(fCropRect));
|
| }
|
|
|
| GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
|
| Direction direction,
|
| int radius,
|
| - float gaussianSigma)
|
| + float gaussianSigma,
|
| + float cropRect[4])
|
| : Gr1DKernelEffect(texture, direction, radius) {
|
| GrAssert(radius <= kMaxKernelRadius);
|
| int width = this->width();
|
| @@ -160,6 +178,7 @@ GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
|
| for (int i = 0; i < width; ++i) {
|
| fKernel[i] *= scale;
|
| }
|
| + memcpy(fCropRect, cropRect, sizeof(fCropRect));
|
| }
|
|
|
| GrConvolutionEffect::~GrConvolutionEffect() {
|
| @@ -174,6 +193,7 @@ bool GrConvolutionEffect::onIsEqual(const GrEffect& sBase) const {
|
| return (this->texture(0) == s.texture(0) &&
|
| this->radius() == s.radius() &&
|
| this->direction() == s.direction() &&
|
| + 0 == memcmp(fCropRect, s.fCropRect, sizeof(fCropRect)) &&
|
| 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float)));
|
| }
|
|
|
| @@ -190,9 +210,13 @@ GrEffectRef* GrConvolutionEffect::TestCreate(SkMWCRandom* random,
|
| Direction dir = random->nextBool() ? kX_Direction : kY_Direction;
|
| int radius = random->nextRangeU(1, kMaxKernelRadius);
|
| float kernel[kMaxKernelRadius];
|
| + float cropRect[4];
|
| for (int i = 0; i < kMaxKernelRadius; ++i) {
|
| kernel[i] = random->nextSScalar1();
|
| }
|
| + for (int i = 0; i < 4; ++i) {
|
| + cropRect[i] = random->nextF();
|
| + }
|
|
|
| - return GrConvolutionEffect::Create(textures[texIdx], dir, radius,kernel);
|
| + return GrConvolutionEffect::Create(textures[texIdx], dir, radius, kernel, cropRect);
|
| }
|
|
|