aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/effects
diff options
context:
space:
mode:
authorGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-22 20:03:22 +0000
committerGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-22 20:03:22 +0000
commitccf225cebb68f9dbd8e353ba0ded247f7e8915ec (patch)
tree1c92c05d4ff012766ca266d90496301772267553 /src/gpu/effects
parent49a07ad0977fb118fe91f5c908b6703e2d89dec6 (diff)
This patch implements a crop rect for SkImageFilter. It has been implemented for SkColorFilterImageFilter and SkBlurImageFilter as examples.
In order to preserve the immutability of SkImageFilters, the crop rect is passed as a constructor parameter. If NULL (the default), the bounds of the input image are used, as before. This also tightens up the boundary handling for SkImageBlurFilter on the GPU backend. Where we were previously using clamping semantics, we now respect decal semantics (so we don't oversaturate the edges). This brings the GPU and raster backends into closer alignment, but will require some new baselines for the GPU tests. At a minimum, the following tests will need new baselines: imageblur, imagefiltersbase, imagefilterscropped, spritebitmap. R=reed@google.com Review URL: https://codereview.chromium.org/19775006 git-svn-id: http://skia.googlecode.com/svn/trunk@10251 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/effects')
-rw-r--r--src/gpu/effects/GrConvolutionEffect.cpp35
-rw-r--r--src/gpu/effects/GrConvolutionEffect.h23
2 files changed, 47 insertions, 11 deletions
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 380581fae3..5682b9c65c 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,11 @@ 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 +103,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 +144,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 +153,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 +179,7 @@ GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
for (int i = 0; i < width; ++i) {
fKernel[i] *= scale;
}
+ memcpy(fCropRect, cropRect, sizeof(fCropRect));
}
GrConvolutionEffect::~GrConvolutionEffect() {
@@ -174,6 +194,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 +211,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);
}
diff --git a/src/gpu/effects/GrConvolutionEffect.h b/src/gpu/effects/GrConvolutionEffect.h
index e4faa945b8..f75cfe9155 100644
--- a/src/gpu/effects/GrConvolutionEffect.h
+++ b/src/gpu/effects/GrConvolutionEffect.h
@@ -22,11 +22,16 @@ class GrConvolutionEffect : public Gr1DKernelEffect {
public:
/// Convolve with an arbitrary user-specified kernel
- static GrEffectRef* Create(GrTexture* tex, Direction dir, int halfWidth, const float* kernel) {
+ static GrEffectRef* Create(GrTexture* tex,
+ Direction dir,
+ int halfWidth,
+ const float* kernel,
+ float cropRect[4]) {
AutoEffectUnref effect(SkNEW_ARGS(GrConvolutionEffect, (tex,
dir,
halfWidth,
- kernel)));
+ kernel,
+ cropRect)));
return CreateEffectRef(effect);
}
@@ -34,11 +39,13 @@ public:
static GrEffectRef* CreateGaussian(GrTexture* tex,
Direction dir,
int halfWidth,
- float gaussianSigma) {
+ float gaussianSigma,
+ float cropRect[4]) {
AutoEffectUnref effect(SkNEW_ARGS(GrConvolutionEffect, (tex,
dir,
halfWidth,
- gaussianSigma)));
+ gaussianSigma,
+ cropRect)));
return CreateEffectRef(effect);
}
@@ -46,6 +53,8 @@ public:
const float* kernel() const { return fKernel; }
+ const float* cropRect() const { return fCropRect; }
+
static const char* Name() { return "Convolution"; }
typedef GrGLConvolutionEffect GLEffect;
@@ -72,15 +81,17 @@ public:
protected:
float fKernel[kMaxKernelWidth];
+ float fCropRect[4];
private:
GrConvolutionEffect(GrTexture*, Direction,
- int halfWidth, const float* kernel);
+ int halfWidth, const float* kernel, float cropRect[4]);
/// Convolve with a Gaussian kernel
GrConvolutionEffect(GrTexture*, Direction,
int halfWidth,
- float gaussianSigma);
+ float gaussianSigma,
+ float cropRect[4]);
virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;