GPU-based Gaussian blur.

This is a first stab at implementing a GPU-based
Gaussian blur in Ganesh.  The convolution shader is implemented as a new
filtering mode.  There are several known issues:

- no support for blur types other than "normal"
- FBO truncation problem at high zoom values
- uses bilinear for upsampling instead of Mitchell

Review URL:  http://codereview.appspot.com/4645082/



git-svn-id: http://skia.googlecode.com/svn/trunk@1830 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrSamplerState.h b/gpu/include/GrSamplerState.h
index d10d8c4..c7a4f2b 100644
--- a/gpu/include/GrSamplerState.h
+++ b/gpu/include/GrSamplerState.h
@@ -21,6 +21,8 @@
 #include "GrTypes.h"
 #include "GrMatrix.h"
 
+#define MAX_KERNEL_WIDTH 25
+
 class GrSamplerState {
 public:
     enum Filter {
@@ -39,6 +41,10 @@
          * between texels in x and y spaced 4 texels apart.)
          */
         k4x4Downsample_Filter,
+        /**
+         * Apply a separable convolution kernel.
+         */
+        kConvolution_Filter
     };
 
     /**
@@ -148,6 +154,9 @@
     const GrRect& getTextureDomain() const { return fTextureDomain; }
     bool hasTextureDomain() const {return SkIntToScalar(0) != fTextureDomain.right();}
     Filter getFilter() const { return fFilter; }
+    int getKernelWidth() const { return fKernelWidth; }
+    const float* getKernel() const { return fKernel; }
+    const float* getImageIncrement() const { return fImageIncrement; }
 
     bool isGradient() const {
         return  kRadial_SampleMode == fSampleMode ||
@@ -220,6 +229,19 @@
         fRadial2PosRoot = posRoot;
     }
 
+    void setConvolutionParams(int kernelWidth, const float* kernel, float imageIncrement[2]) {
+        GrAssert(kernelWidth >= 0 && kernelWidth <= MAX_KERNEL_WIDTH);
+        fKernelWidth = kernelWidth;
+        if (NULL != kernel) {
+            memcpy(fKernel, kernel, kernelWidth * sizeof(float));
+        }
+        if (NULL != imageIncrement) {
+            memcpy(fImageIncrement, imageIncrement, sizeof(fImageIncrement));
+        } else {
+            memset(fImageIncrement, 0, sizeof(fImageIncrement));
+        }
+    }
+
     static const GrSamplerState& ClampNoFilter() {
         return gClampNoFilter;
     }
@@ -237,6 +259,11 @@
     GrScalar    fRadial2Radius0;
     bool        fRadial2PosRoot;
 
+    // These are undefined unless fFilter == kConvolution_Filter
+    int         fKernelWidth;
+    float       fKernel[MAX_KERNEL_WIDTH];
+    float       fImageIncrement[2];
+
     static const GrSamplerState gClampNoFilter;
 };