diff options
author | senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-07-29 18:45:44 +0000 |
---|---|---|
committer | senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-07-29 18:45:44 +0000 |
commit | e8232bc6f0719f381d437483271ce3c78af3c819 (patch) | |
tree | 1394fdc20747312a885a7a31a8d2b51256e9d120 /src | |
parent | b3915b5a9f6a7c4ed9f36921ea82d5b3318654f6 (diff) |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/effects/SkGpuBlurUtils.cpp | 12 | ||||
-rw-r--r-- | src/gpu/effects/GrConvolutionEffect.cpp | 82 | ||||
-rw-r--r-- | src/gpu/effects/GrConvolutionEffect.h | 32 |
3 files changed, 67 insertions, 59 deletions
diff --git a/src/effects/SkGpuBlurUtils.cpp b/src/effects/SkGpuBlurUtils.cpp index 0769237353..28ccd4589b 100644 --- a/src/effects/SkGpuBlurUtils.cpp +++ b/src/effects/SkGpuBlurUtils.cpp @@ -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); } diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp index 3fa1cb9fea..e7fb8e5403 100644 --- a/src/gpu/effects/GrConvolutionEffect.cpp +++ b/src/gpu/effects/GrConvolutionEffect.cpp @@ -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); } diff --git a/src/gpu/effects/GrConvolutionEffect.h b/src/gpu/effects/GrConvolutionEffect.h index 265150a92c..56a54b4a6a 100644 --- a/src/gpu/effects/GrConvolutionEffect.h +++ b/src/gpu/effects/GrConvolutionEffect.h @@ -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; |