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;
 }