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
This commit is contained in:
parent
b3915b5a9f
commit
e8232bc6f0
@ -49,14 +49,14 @@ static void convolve_gaussian(GrContext* context,
|
||||
Gr1DKernelEffect::Direction direction) {
|
||||
GrPaint paint;
|
||||
paint.reset();
|
||||
float cropRect[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
|
||||
float bounds[2] = { 0.0f, 1.0f };
|
||||
if (cropToSrcRect) {
|
||||
if (direction == Gr1DKernelEffect::kX_Direction) {
|
||||
cropRect[0] = SkScalarToFloat(srcRect.left()) / texture->width();
|
||||
cropRect[1] = SkScalarToFloat(srcRect.right()) / texture->width();
|
||||
bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
|
||||
bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width();
|
||||
} else {
|
||||
cropRect[2] = SkScalarToFloat(srcRect.top()) / texture->height();
|
||||
cropRect[3] = SkScalarToFloat(srcRect.bottom()) / texture->height();
|
||||
bounds[0] = SkScalarToFloat(srcRect.top()) / texture->height();
|
||||
bounds[1] = SkScalarToFloat(srcRect.bottom()) / texture->height();
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ static void convolve_gaussian(GrContext* context,
|
||||
radius,
|
||||
sigma,
|
||||
cropToSrcRect,
|
||||
cropRect));
|
||||
bounds));
|
||||
paint.addColorEffect(conv);
|
||||
context->drawRectToRect(paint, dstRect, srcRect);
|
||||
}
|
||||
|
@ -33,13 +33,15 @@ public:
|
||||
|
||||
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 @@ GrGLConvolutionEffect::GrGLConvolutionEffect(const GrBackendEffectFactory& facto
|
||||
: 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 @@ void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
|
||||
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 @@ 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");
|
||||
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 @@ void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman,
|
||||
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 @@ void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman,
|
||||
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 @@ GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
|
||||
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 @@ GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
|
||||
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 @@ 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)) &&
|
||||
this->useBounds() == s.useBounds() &&
|
||||
0 == memcmp(fBounds, s.fBounds, sizeof(fBounds)) &&
|
||||
0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float)));
|
||||
}
|
||||
|
||||
@ -224,19 +232,19 @@ 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();
|
||||
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);
|
||||
}
|
||||
|
@ -26,14 +26,14 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user