Move alpha-ramp AA to GrContext, detect cases when AA is applied via other methods (smooth lines, MSAA) or rect falls on integer coords and skip the alpha ramp path. Use pre-fab index buffer for alpha-ramped fill rects and stroke rects.

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

git-svn-id: http://skia.googlecode.com/svn/trunk@1169 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 5eda2b7..07d76f8 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -568,8 +568,26 @@
     GrIndexBufferAllocPool*     fDrawBufferIBAllocPool;
     GrInOrderDrawBuffer*        fDrawBuffer;
 
+    GrIndexBuffer*              fAAFillRectIndexBuffer;
+    GrIndexBuffer*              fAAStrokeRectIndexBuffer;
+
     GrContext(GrGpu* gpu);
 
+    void fillAARect(GrDrawTarget* target,
+                    const GrPaint& paint,
+                    const GrRect& devRect);
+
+    void strokeAARect(GrDrawTarget* target,
+                      const GrPaint& paint,
+                      const GrRect& devRect,
+                      const GrVec& devStrokeSize);
+
+    inline int aaFillRectIndexCount() const;
+    GrIndexBuffer* aaFillRectIndexBuffer();
+
+    inline int aaStrokeRectIndexCount() const;
+    GrIndexBuffer* aaStrokeRectIndexBuffer();
+
     void setupDrawBuffer();
 
     void flushDrawBuffer();
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index 7dd9959..5bbe85d 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -273,6 +273,12 @@
     bool supportsBufferLocking() const { return fBufferLockSupport; }
 
     /**
+     * Does the 3D API support anti-aliased lines. If so then line primitive
+     * types will use this functionality when the AA state flag is set.
+     */
+    bool supportsAALines() const { return fAALineSupport; }
+
+    /**
      * 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.
@@ -445,6 +451,7 @@
     bool fNPOTRenderTargetSupport;
     bool fTwoSidedStencilSupport;
     bool fStencilWrapOpsSupport;
+    bool fAALineSupport;
 
     // set by subclass to true if index and vertex buffers can be locked, false
     // otherwise.
diff --git a/gpu/include/GrMatrix.h b/gpu/include/GrMatrix.h
index 9a2e660..1ebc0b4 100644
--- a/gpu/include/GrMatrix.h
+++ b/gpu/include/GrMatrix.h
@@ -135,7 +135,7 @@
                 GrScalar scaleY,
                 GrScalar transY,
                 GrScalar persp0,
-                GrScalar persp1,                
+                GrScalar persp1,
                 GrScalar persp2) {
         fM[kScaleX] = scaleX;
         fM[kSkewX]  = skewX;
@@ -253,6 +253,21 @@
             start = (GrPoint*)((intptr_t)start + stride);
         }
     }
+
+    /**
+     * Transforms a vector by the matrix. Doesn't handle cases when a
+     * homogeneous vector maps to a point (i.e. perspective transform).
+     * In this case the desired answer is dependent on where the tail of
+     * the vector is in space.
+     */
+    void mapVec(GrVec* vec) {
+        GrAssert(!this->hasPerspective());
+        if (!this->isIdentity()) {
+            GrScalar x = vec->fX;
+            vec->fX = (*this)[kScaleX] * x + (*this)[kSkewX]  * vec->fY;
+            vec->fY = (*this)[kSkewY ] * x + (*this)[kScaleY] * vec->fY;
+        }
+    }
     
     /**
      *  Transform the 4 corners of the src rect, and return the bounding rect
@@ -278,7 +293,12 @@
      * @return true if matrix is idenity
      */
     bool isIdentity() const;
-    
+
+    /**
+     * Do axis-aligned lines stay axis aligned? May do 90 degree rotation / mirroring.
+     */
+    bool preservesAxisAlignment() const;
+
     /**
      * Calculates the maximum stretching factor of the matrix. Only defined if
      * the matrix does not have perspective.
diff --git a/gpu/include/GrPoint.h b/gpu/include/GrPoint.h
index c07543b..8c540f0 100644
--- a/gpu/include/GrPoint.h
+++ b/gpu/include/GrPoint.h
@@ -153,6 +153,14 @@
         fX = x;
         fY = y;
     }
+
+    /**
+     * set this to (abs(v.x), abs(v.y))
+     */
+    void setAbs(const GrVec& v) {
+        fX = GrScalarAbs(v.fX);
+        fY = GrScalarAbs(v.fY);
+    }
     
     /**
      * set vector to point from a to b.
diff --git a/gpu/include/GrRect.h b/gpu/include/GrRect.h
index 67e366c..a9ff6ec 100644
--- a/gpu/include/GrRect.h
+++ b/gpu/include/GrRect.h
@@ -206,6 +206,14 @@
     }
 
     /**
+     * Returns true if the rects edges are integer-aligned.
+     */
+    bool isIRect() const {
+        return GrScalarIsInt(fLeft) && GrScalarIsInt(fTop) && 
+               GrScalarIsInt(fRight) && GrScalarIsInt(fBottom);
+    }
+
+    /**
      * Does this rect contain a point.
      */
     bool contains(const GrPoint& point) const {
@@ -363,6 +371,22 @@
         return pts + 4;
     }
 
+    /**
+     * Swaps (left and right) and/or (top and bottom) if they are inverted
+     */
+    void sort() {
+        if (fLeft > fRight) {
+            GrScalar temp = fLeft;
+            fLeft = fRight;
+            fRight = temp;
+        }
+        if (fTop > fBottom) {
+            GrScalar temp = fTop;
+            fTop = fBottom;
+            fBottom = temp;
+        }
+    }
+
     bool operator ==(const GrRect& r) const {
         return fLeft == r.fLeft     &&
                fTop == r.fTop       &&
diff --git a/gpu/include/GrScalar.h b/gpu/include/GrScalar.h
index 1353fb2..7aaa43d 100644
--- a/gpu/include/GrScalar.h
+++ b/gpu/include/GrScalar.h
@@ -56,11 +56,19 @@
  */
 #define GrFloatToFixed(x)      ((GrFixed)((x) * GR_Fixed1))
 
-inline GrFixed GrFixedAbs(GrFixed x) {
+static inline GrFixed GrFixedAbs(GrFixed x) {
     int32_t s = (x & 0x80000000) >> 31;
     return (GrFixed)(((int32_t)x ^ s) - s);  
 }
 
+static inline bool GrFixedIsInt(GrFixed x) {
+    return 0 == (x & 0xffff);
+}
+
+static inline bool GrFloatIsInt(float x) {
+    return x == (float)(int)x;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 #if GR_SCALAR_IS_FIXED
@@ -72,6 +80,7 @@
     #define GrScalarHalf(x)         ((x) >> 1)
     #define GrScalarAve(x,y)        (((x)+(y)) >> 1)
     #define GrScalarAbs(x)          GrFixedAbs(x)
+    #define GrScalarIsInt           GrFixedIsInt
     #define GR_Scalar1              GR_Fixed1
     #define GR_ScalarHalf           GR_FixedHalf
     #define GR_ScalarMax            GR_FixedMax
@@ -85,6 +94,7 @@
     #define GrScalarHalf(x)         ((x) * 0.5f)
     #define GrScalarAbs(x)          fabsf(x)
     #define GrScalarAve(x,y)        (((x) + (y)) * 0.5f)
+    #define GrScalarIsInt           GrFloatIsInt
     #define GR_Scalar1              1.f    
     #define GR_ScalarHalf           0.5f
     #define GR_ScalarMax            (FLT_MAX)