Small optimization for convolution shader: only apply the bounds check in direction of convolution, not both. This requires generating different versions of the shader depending on direction.
R=robertphillips@google.com
Review URL: https://codereview.chromium.org/20789003
git-svn-id: http://skia.googlecode.com/svn/trunk@10417 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 3fa1cb9..e7fb8e5 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -33,13 +33,15 @@
private:
int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); }
- bool useCropRect() const { return fUseCropRect; }
+ bool useBounds() const { return fUseBounds; }
+ Gr1DKernelEffect::Direction direction() const { return fDirection; }
int fRadius;
- bool fUseCropRect;
+ bool fUseBounds;
+ Gr1DKernelEffect::Direction fDirection;
UniformHandle fKernelUni;
UniformHandle fImageIncrementUni;
- UniformHandle fCropRectUni;
+ UniformHandle fBoundsUni;
GrGLEffectMatrix fEffectMatrix;
typedef GrGLEffect INHERITED;
@@ -50,11 +52,12 @@
: INHERITED(factory)
, fKernelUni(kInvalidUniformHandle)
, fImageIncrementUni(kInvalidUniformHandle)
- , fCropRectUni(kInvalidUniformHandle)
+ , fBoundsUni(kInvalidUniformHandle)
, fEffectMatrix(drawEffect.castEffect<GrConvolutionEffect>().coordsType()) {
const GrConvolutionEffect& c = drawEffect.castEffect<GrConvolutionEffect>();
fRadius = c.radius();
- fUseCropRect = c.useCropRect();
+ fUseBounds = c.useBounds();
+ fDirection = c.direction();
}
void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
@@ -67,9 +70,9 @@
fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords);
fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kVec2f_GrSLType, "ImageIncrement");
- if (this->useCropRect()) {
- fCropRectUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
- kVec4f_GrSLType, "CropRect");
+ if (this->useBounds()) {
+ fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+ kVec2f_GrSLType, "Bounds");
}
fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_ShaderType,
kFloat_GrSLType, "Kernel", this->width());
@@ -90,10 +93,11 @@
kernel.appendArrayAccess(index.c_str(), &kernelIndex);
builder->fsCodeAppendf("\t\t%s += ", outputColor);
builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, samplers[0], "coord");
- if (this->useCropRect()) {
- const char* cropRect = builder->getUniformCStr(fCropRectUni);
- builder->fsCodeAppendf(" * float(coord.x >= %s.x && coord.x <= %s.y && coord.y >= %s.z && coord.y <= %s.w)",
- cropRect, cropRect, cropRect, cropRect);
+ if (this->useBounds()) {
+ const char* bounds = builder->getUniformCStr(fBoundsUni);
+ const char* component = this->direction() == Gr1DKernelEffect::kY_Direction ? "y" : "x";
+ builder->fsCodeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.y)",
+ component, bounds, component, bounds);
}
builder->fsCodeAppendf(" * %s;\n", kernelIndex.c_str());
builder->fsCodeAppendf("\t\tcoord += %s;\n", imgInc);
@@ -123,15 +127,14 @@
GrCrash("Unknown filter direction.");
}
uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement);
- if (conv.useCropRect()) {
- 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;
+ if (conv.useBounds()) {
+ const float* bounds = conv.bounds();
+ if (Gr1DKernelEffect::kY_Direction == conv.direction() &&
+ texture.origin() != kTopLeft_GrSurfaceOrigin) {
+ uman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]);
+ } else {
+ uman.set2f(fBoundsUni, bounds[0], bounds[1]);
}
- uman.set4fv(fCropRectUni, 0, 1, c);
}
uman.set1fv(fKernelUni, 0, this->width(), conv.kernel());
fEffectMatrix.setData(uman, conv.getMatrix(), drawEffect, conv.texture(0));
@@ -140,8 +143,12 @@
GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrDrawEffect& drawEffect,
const GrGLCaps&) {
const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect>();
- EffectKey key = conv.radius() << 1;
- key |= conv.useCropRect() ? 0x1 : 0x0;
+ EffectKey key = conv.radius();
+ key <<= 2;
+ if (conv.useBounds()) {
+ key |= 0x2;
+ key |= GrConvolutionEffect::kY_Direction == conv.direction() ? 0x1 : 0x0;
+ }
key <<= GrGLEffectMatrix::kKeyBits;
EffectKey matrixKey = GrGLEffectMatrix::GenKey(conv.getMatrix(),
drawEffect,
@@ -156,25 +163,25 @@
Direction direction,
int radius,
const float* kernel,
- bool useCropRect,
- float cropRect[4])
- : Gr1DKernelEffect(texture, direction, radius), fUseCropRect(useCropRect) {
+ bool useBounds,
+ float bounds[2])
+ : Gr1DKernelEffect(texture, direction, radius), fUseBounds(useBounds) {
GrAssert(radius <= kMaxKernelRadius);
GrAssert(NULL != kernel);
int width = this->width();
for (int i = 0; i < width; i++) {
fKernel[i] = kernel[i];
}
- memcpy(fCropRect, cropRect, sizeof(fCropRect));
+ memcpy(fBounds, bounds, sizeof(fBounds));
}
GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
Direction direction,
int radius,
float gaussianSigma,
- bool useCropRect,
- float cropRect[4])
- : Gr1DKernelEffect(texture, direction, radius), fUseCropRect(useCropRect) {
+ bool useBounds,
+ float bounds[2])
+ : Gr1DKernelEffect(texture, direction, radius), fUseBounds(useBounds) {
GrAssert(radius <= kMaxKernelRadius);
int width = this->width();
@@ -192,7 +199,7 @@
for (int i = 0; i < width; ++i) {
fKernel[i] *= scale;
}
- memcpy(fCropRect, cropRect, sizeof(fCropRect));
+ memcpy(fBounds, bounds, sizeof(fBounds));
}
GrConvolutionEffect::~GrConvolutionEffect() {
@@ -207,7 +214,8 @@
return (this->texture(0) == s.texture(0) &&
this->radius() == s.radius() &&
this->direction() == s.direction() &&
- 0 == memcmp(fCropRect, s.fCropRect, sizeof(fCropRect)) &&
+ this->useBounds() == s.useBounds() &&
+ 0 == memcmp(fBounds, s.fBounds, sizeof(fBounds)) &&
0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float)));
}
@@ -224,19 +232,19 @@
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();
+ float bounds[2];
+ for (int i = 0; i < 2; ++i) {
+ bounds[i] = random->nextF();
}
- bool useCropRect = random->nextBool();
+ bool useBounds = random->nextBool();
return GrConvolutionEffect::Create(textures[texIdx],
dir,
radius,
kernel,
- useCropRect,
- cropRect);
+ useBounds,
+ bounds);
}
diff --git a/src/gpu/effects/GrConvolutionEffect.h b/src/gpu/effects/GrConvolutionEffect.h
index 265150a..56a54b4 100644
--- a/src/gpu/effects/GrConvolutionEffect.h
+++ b/src/gpu/effects/GrConvolutionEffect.h
@@ -26,14 +26,14 @@
Direction dir,
int halfWidth,
const float* kernel,
- bool useCropRect,
- float cropRect[4]) {
+ bool useBounds,
+ float bounds[2]) {
AutoEffectUnref effect(SkNEW_ARGS(GrConvolutionEffect, (tex,
dir,
halfWidth,
kernel,
- useCropRect,
- cropRect)));
+ useBounds,
+ bounds)));
return CreateEffectRef(effect);
}
@@ -42,14 +42,14 @@
Direction dir,
int halfWidth,
float gaussianSigma,
- bool useCropRect,
- float cropRect[4]) {
+ bool useBounds,
+ float bounds[2]) {
AutoEffectUnref effect(SkNEW_ARGS(GrConvolutionEffect, (tex,
dir,
halfWidth,
gaussianSigma,
- useCropRect,
- cropRect)));
+ useBounds,
+ bounds)));
return CreateEffectRef(effect);
}
@@ -57,8 +57,8 @@
const float* kernel() const { return fKernel; }
- const float* cropRect() const { return fCropRect; }
- bool useCropRect() const { return fUseCropRect; }
+ const float* bounds() const { return fBounds; }
+ bool useBounds() const { return fUseBounds; }
static const char* Name() { return "Convolution"; }
@@ -86,22 +86,22 @@
protected:
float fKernel[kMaxKernelWidth];
- bool fUseCropRect;
- float fCropRect[4];
+ bool fUseBounds;
+ float fBounds[2];
private:
GrConvolutionEffect(GrTexture*, Direction,
int halfWidth,
const float* kernel,
- bool useCropRect,
- float cropRect[4]);
+ bool useBounds,
+ float bounds[2]);
/// Convolve with a Gaussian kernel
GrConvolutionEffect(GrTexture*, Direction,
int halfWidth,
float gaussianSigma,
- bool useCropRect,
- float cropRect[4]);
+ bool useBounds,
+ float bounds[2]);
virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;