Add 4x4 downsample filter with 4 bilinear texture reads, use for ssaa.

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

git-svn-id: http://skia.googlecode.com/svn/trunk@1250 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext_impl.h b/gpu/include/GrContext_impl.h
index 0fa3b8d..fae4e92 100644
--- a/gpu/include/GrContext_impl.h
+++ b/gpu/include/GrContext_impl.h
@@ -21,6 +21,11 @@
     OffscreenRecord() { fEntry0 = NULL; fEntry1 = NULL; }
     ~OffscreenRecord() { GrAssert(NULL == fEntry0 && NULL == fEntry1); }
 
+    enum Downsample {
+        k4x4TwoPass_Downsample,
+        k4x4SinglePass_Downsample,
+        kFSAA_Downsample
+    }                              fDownsample;
     GrTextureEntry*                fEntry0;
     GrTextureEntry*                fEntry1;
     GrDrawTarget::SavedDrawState   fSavedState;
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index 5602d1a..e44956f 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -199,6 +199,11 @@
     bool supportsAALines() const { return fAALineSupport; }
 
     /**
+     * Does the subclass support GrSamplerState::k4x4Downsample_Filter
+     */
+    bool supports4x4DownsampleFilter() const { return f4X4DownsampleFilterSupport; }
+
+    /**
      * Gets the minimum width of a render target. If a texture/rt is created
      * with a width less than this size the GrGpu object will clamp it to this
      * value.
@@ -379,6 +384,7 @@
     bool fStencilWrapOpsSupport;
     bool fAALineSupport;
     bool fFSAASupport;
+    bool f4X4DownsampleFilterSupport; // supports GrSamplerState::k4x4Downsample_Filter
 
     // set by subclass to true if index and vertex buffers can be locked, false
     // otherwise.
diff --git a/gpu/include/GrSamplerState.h b/gpu/include/GrSamplerState.h
index 910bc74..dd47c53 100644
--- a/gpu/include/GrSamplerState.h
+++ b/gpu/include/GrSamplerState.h
@@ -23,6 +23,24 @@
 
 class GrSamplerState {
 public:
+    enum Filter {
+        /**
+         * Read the closest src texel to the sample position
+         */
+        kNearest_Filter,
+        /**
+         * Blend between closest 4 src texels to sample position (tent filter)
+         */
+        kBilinear_Filter,
+        /**
+         * Average of 4 bilinear filterings spaced +/- 1 texel from sample
+         * position in x and y. Intended for averaging 16 texels in a downsample
+         * pass. (rasterizing such that texture samples fall exactly halfway
+         * between texels in x and y spaced 4 texels apart.)
+         */
+        k4x4Downsample_Filter,
+    };
+
     /**
      * The intepretation of the texture matrix depends on the sample mode. The
      * texture matrix is applied both when the texture coordinates are explicit
@@ -70,7 +88,7 @@
         this->setClampNoFilter();
     }
 
-    explicit GrSamplerState(bool filter) {
+    explicit GrSamplerState(Filter filter) {
         fWrapX = kClamp_WrapMode;
         fWrapY = kClamp_WrapMode;
         fSampleMode = kNormal_SampleMode;
@@ -78,7 +96,7 @@
         fMatrix.setIdentity();
     }
 
-    GrSamplerState(WrapMode wx, WrapMode wy, bool filter) {
+    GrSamplerState(WrapMode wx, WrapMode wy, Filter filter) {
         fWrapX = wx;
         fWrapY = wy;
         fSampleMode = kNormal_SampleMode;
@@ -86,7 +104,8 @@
         fMatrix.setIdentity();
     }
 
-    GrSamplerState(WrapMode wx, WrapMode wy, const GrMatrix& matrix, bool filter) {
+    GrSamplerState(WrapMode wx, WrapMode wy, 
+                   const GrMatrix& matrix, Filter filter) {
         fWrapX = wx;
         fWrapY = wy;
         fSampleMode = kNormal_SampleMode;
@@ -94,7 +113,8 @@
         fMatrix = matrix;
     }
 
-    GrSamplerState(WrapMode wx, WrapMode wy, SampleMode sample, const GrMatrix& matrix, bool filter) {
+    GrSamplerState(WrapMode wx, WrapMode wy, SampleMode sample, 
+                   const GrMatrix& matrix, Filter filter) {
         fWrapX = wx;
         fWrapY = wy;
         fSampleMode = sample;
@@ -106,7 +126,7 @@
     WrapMode getWrapY() const { return fWrapY; }
     SampleMode getSampleMode() const { return fSampleMode; }
     const GrMatrix& getMatrix() const { return fMatrix; }
-    bool isFilter() const { return fFilter; }
+    Filter getFilter() const { return fFilter; }
 
     bool isGradient() const {
         return  kRadial_SampleMode == fSampleMode ||
@@ -138,16 +158,16 @@
     void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }
 
     /**
-     * Enables or disables filtering.
-     * @param filter    indicates whether filtering is applied.
+     * Sets filtering type.
+     * @param filter    type of filtering to apply
      */
-    void setFilter(bool filter) { fFilter = filter; }
+    void setFilter(Filter filter) { fFilter = filter; }
 
     void setClampNoFilter() {
         fWrapX = kClamp_WrapMode;
         fWrapY = kClamp_WrapMode;
         fSampleMode = kNormal_SampleMode;
-        fFilter = false;
+        fFilter = kNearest_Filter;
         fMatrix.setIdentity();
     }
 
@@ -176,7 +196,7 @@
     WrapMode    fWrapX;
     WrapMode    fWrapY;
     SampleMode  fSampleMode;
-    bool        fFilter;
+    Filter      fFilter;
     GrMatrix    fMatrix;
 
     // these are undefined unless fSampleMode == kRadial2_SampleMode