GPU-based blur cleanup. Clean up some issues raised in code review:
- convolveRect() is too low-level; made it private and exposed convolveInX() and
convolveInY() instead
- added GrAutoTextureEntry to automatically unlock a texture entry
- the clipping and bounder checks were returning false from
drawWithGPUMaskFilter(), causing the software blur to kick in; return true
instead
- the Windows build was giving a spurious warning about reading an uninitialized
variable; rearrange the code to fix it
Review URL: http://codereview.appspot.com/4710042/
git-svn-id: http://skia.googlecode.com/svn/trunk@1842 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 0c873ee..d80aef2 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -491,20 +491,30 @@
GrPixelConfig, const void* buffer, size_t stride);
/**
- * Performs a 1D convolution over a rectangle of pixels. Set
- * imageIncrement to (1/w, 0) for a convolution in X, (0, 1/h) for a
- * convolution in Y, where w, h are the texture dimensions.
- * @param srcTexture the texture to read from
- * @param dstRect the destination rectangle
- * @param imageIncrement the displacement between pixel samples
+ * Applies a 1D convolution kernel in the X direction to a rectangle of
+ * pixels from a given texture.
+ * @param texture the texture to read from
+ * @param rect the destination rectangle
* @param kernel the convolution kernel (kernelWidth elements)
* @param kernelWidth the width of the convolution kernel
*/
- void convolveRect(GrTexture* srcTexture,
- const SkRect& dstRect,
- float imageIncrement[2],
- const float* kernel,
- int kernelWidth);
+ void convolveInX(GrTexture* texture,
+ const SkRect& rect,
+ const float* kernel,
+ int kernelWidth);
+ /**
+ * Applies a 1D convolution kernel in the Y direction to a rectangle of
+ * pixels from a given texture.
+ * direction.
+ * @param texture the texture to read from
+ * @param rect the destination rectangle
+ * @param kernel the convolution kernel (kernelWidth elements)
+ * @param kernelWidth the width of the convolution kernel
+ */
+ void convolveInY(GrTexture* texture,
+ const SkRect& rect,
+ const float* kernel,
+ int kernelWidth);
///////////////////////////////////////////////////////////////////////////
// Helpers
@@ -630,6 +640,12 @@
void cleanupOffscreenAA(GrDrawTarget* target,
GrPathRenderer* pr,
OffscreenRecord* record);
+
+ void convolve(GrTexture* texture,
+ const SkRect& rect,
+ float imageIncrement[2],
+ const float* kernel,
+ int kernelWidth);
// computes vertex layout bits based on the paint. If paint expresses
// a texture for a stage, the stage coords will be bound to postitions
@@ -663,6 +679,25 @@
GrMatrix fMatrix;
};
+/**
+ * Unlocks a texture entry when this goes out of scope. Entry may be NULL.
+ */
+class GrAutoUnlockTextureEntry : ::GrNoncopyable {
+public:
+ GrAutoUnlockTextureEntry(GrContext* context, GrTextureEntry* entry)
+ : fContext(context)
+ , fEntry(entry) {
+ }
+ ~GrAutoUnlockTextureEntry() {
+ if (fContext && fEntry) {
+ fContext->unlockTexture(fEntry);
+ }
+ }
+private:
+ GrContext* fContext;
+ GrTextureEntry* fEntry;
+};
+
#endif
#include "GrContext_impl.h"
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 092b0ba..dc4bac8 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -1699,22 +1699,38 @@
}
}
-void GrContext::convolveRect(GrTexture* srcTexture,
- const SkRect& rect,
- float imageIncrement[2],
- const float* kernel,
- int kernelWidth) {
+void GrContext::convolveInX(GrTexture* texture,
+ const SkRect& rect,
+ const float* kernel,
+ int kernelWidth) {
+ float imageIncrement[2] = {1.0f / texture->width(), 0.0f};
+ convolve(texture, rect, imageIncrement, kernel, kernelWidth);
+}
+
+void GrContext::convolveInY(GrTexture* texture,
+ const SkRect& rect,
+ const float* kernel,
+ int kernelWidth) {
+ float imageIncrement[2] = {0.0f, 1.0f / texture->height()};
+ convolve(texture, rect, imageIncrement, kernel, kernelWidth);
+}
+
+void GrContext::convolve(GrTexture* texture,
+ const SkRect& rect,
+ float imageIncrement[2],
+ const float* kernel,
+ int kernelWidth) {
GrDrawTarget::AutoStateRestore asr(fGpu);
GrMatrix sampleM;
GrSamplerState sampler(GrSamplerState::kClamp_WrapMode,
GrSamplerState::kClamp_WrapMode,
GrSamplerState::kConvolution_Filter);
sampler.setConvolutionParams(kernelWidth, kernel, imageIncrement);
- sampleM.setScale(GR_Scalar1 / srcTexture->width(),
- GR_Scalar1 / srcTexture->height());
+ sampleM.setScale(GR_Scalar1 / texture->width(),
+ GR_Scalar1 / texture->height());
sampler.setMatrix(sampleM);
fGpu->setSamplerState(0, sampler);
fGpu->setViewMatrix(GrMatrix::I());
- fGpu->setTexture(0, srcTexture);
+ fGpu->setTexture(0, texture);
fGpu->drawSimpleRect(rect, NULL, 1 << 0);
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index ae7f86f..f0e7d61 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -836,12 +836,11 @@
SkMaskFilter* filter, const SkMatrix& matrix,
const SkRegion& clip, SkBounder* bounder,
GrPaint* grp) {
- SkMaskFilter::BlurInfo info;
-#if USE_GPU_BLUR
- SkMaskFilter::BlurType blurType = filter->asABlur(&info);
-#else
- SkMaskFilter::BlurType blurType = SkMaskFilter::kNone_BlurType;
+#if !USE_GPU_BLUR
+ return false;
#endif
+ SkMaskFilter::BlurInfo info;
+ SkMaskFilter::BlurType blurType = filter->asABlur(&info);
if (SkMaskFilter::kNone_BlurType == blurType) {
return false;
}
@@ -871,10 +870,10 @@
SkIRect finalIRect;
finalRect.roundOut(&finalIRect);
if (clip.quickReject(finalIRect)) {
- return false;
+ return true;
}
if (bounder && !bounder->doIRect(finalIRect)) {
- return false;
+ return true;
}
GrPoint offset = GrPoint::Make(-srcRect.fLeft, -srcRect.fTop);
srcRect.offset(-srcRect.fLeft, -srcRect.fTop);
@@ -890,6 +889,8 @@
GrTextureEntry* srcEntry = context->findApproximateKeylessTexture(desc);
GrTextureEntry* dstEntry = context->findApproximateKeylessTexture(desc);
+ GrAutoUnlockTextureEntry srcLock(context, srcEntry),
+ dstLock(context, dstEntry);
if (NULL == srcEntry || NULL == dstEntry) {
return false;
}
@@ -940,6 +941,7 @@
paint.setTexture(0, srcTexture);
context->drawRect(paint, srcRect);
}
+ GrAutoUnlockTextureEntry origLock(context, origEntry);
for (int i = 1; i < scaleFactor; i *= 2) {
context->setRenderTarget(dstTexture->asRenderTarget());
SkRect dstRect(srcRect);
@@ -957,18 +959,14 @@
float* kernel = kernelStorage.get();
buildKernel(sigma, kernel, kernelWidth);
- float imageIncrementX[2] = {1.0f / srcTexture->width(), 0.0f};
context->setRenderTarget(dstTexture->asRenderTarget());
context->clear(NULL, 0);
- context->convolveRect(srcTexture, srcRect, imageIncrementX, kernel,
- kernelWidth);
+ context->convolveInX(srcTexture, srcRect, kernel, kernelWidth);
SkTSwap(srcTexture, dstTexture);
- float imageIncrementY[2] = {0.0f, 1.0f / srcTexture->height()};
context->setRenderTarget(dstTexture->asRenderTarget());
context->clear(NULL, 0);
- context->convolveRect(srcTexture, srcRect, imageIncrementY, kernel,
- kernelWidth);
+ context->convolveInY(srcTexture, srcRect, kernel, kernelWidth);
SkTSwap(srcTexture, dstTexture);
if (scaleFactor > 1) {
@@ -1036,13 +1034,6 @@
m.postIDiv(srcTexture->width(), srcTexture->height());
grp->getMaskSampler(MASK_IDX)->setMatrix(m);
context->drawRect(*grp, finalRect);
- // FIXME: these unlockTexture() calls could be more safely done with
- // an RAII guard class.
- context->unlockTexture(srcEntry);
- context->unlockTexture(dstEntry);
- if (origEntry) {
- context->unlockTexture(origEntry);
- }
return true;
}