Towards NV path rendering

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



git-svn-id: http://skia.googlecode.com/svn/trunk@4219 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index e56b98f..55bd04c 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -14,6 +14,7 @@
 #include "GrRefCnt.h"
 #include "GrSamplerState.h"
 #include "GrStencil.h"
+#include "GrTexture.h"
 
 #include "SkXfermode.h"
 
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index bc373ba..148dd19 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -830,6 +830,14 @@
     }
 }
 
+void GrDrawTarget::stencilPath(const GrPath& path, GrPathFill fill) {
+    // TODO: extract portions of checkDraw that are relevant to path stenciling.
+    GrAssert(fCaps.fPathStencilingSupport);
+    GrAssert(kHairLine_GrPathFill != fill);
+    GrAssert(!GrIsFillInverted(fill));
+    this->onStencilPath(path, fill);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 // Some blend modes allow folding a partial coverage value into the color's
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index a6ab675..6e5bc67 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -12,22 +12,17 @@
 #define GrDrawTarget_DEFINED
 
 #include "GrClip.h"
-#include "GrColor.h"
 #include "GrDrawState.h"
 #include "GrIndexBuffer.h"
 #include "GrMatrix.h"
 #include "GrRefCnt.h"
-#include "GrSamplerState.h"
-#include "GrStencil.h"
-#include "GrTexture.h"
 
 #include "SkXfermode.h"
 #include "SkTLazy.h"
 
-class GrTexture;
 class GrClipIterator;
+class GrPath;
 class GrVertexBuffer;
-class GrIndexBuffer;
 
 class GrDrawTarget : public GrRefCnt {
 public:
@@ -52,6 +47,7 @@
         bool fFSAASupport               : 1;
         bool fDualSourceBlendingSupport : 1;
         bool fBufferLockSupport         : 1;
+        bool fPathStencilingSupport     : 1;
         int fMaxRenderTargetSize;
         int fMaxTextureSize;
     };
@@ -436,7 +432,7 @@
      * Pops the vertex / index sources from the matching push.
      */
     void popGeometrySource();
-    
+
     /**
      * Draws indexed geometry using the current state and current vertex / index
      * sources.
@@ -470,6 +466,13 @@
                         int vertexCount);
 
     /**
+     * Draws path into the stencil buffer. The fill must be either even/odd or
+     * winding (not inverse or hairline). It will respect the HW antialias flag
+     * on the draw state (if possible in the 3D API).
+     */
+    void stencilPath(const GrPath& path, GrPathFill fill);
+
+    /**
      * Helper function for drawing rects. This does not use the current index
      * and vertex sources. After returning, the vertex and index sources may
      * have changed. They should be reestablished before the next drawIndexed
@@ -1042,6 +1045,8 @@
     virtual void onDrawNonIndexed(GrPrimitiveType type,
                                   int startVertex,
                                   int vertexCount) = 0;
+    virtual void onStencilPath(const GrPath& path, GrPathFill fill) = 0;
+
     // subclass overrides to be notified when clip is set. Must call
     // INHERITED::clipwillBeSet
     virtual void clipWillBeSet(const GrClip& clip) {}
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 9e26135..7765d24 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -226,6 +226,12 @@
     return this->onCreateIndexBuffer(size, dynamic);
 }
 
+GrPath* GrGpu::createPath(const SkPath& path) {
+    GrAssert(fCaps.fPathStencilingSupport);
+    this->handleDirtyContext();
+    return this->onCreatePath(path);
+}
+
 void GrGpu::clear(const GrIRect* rect, GrColor color) {
     if (NULL == this->getDrawState().getRenderTarget()) {
         return;
@@ -358,7 +364,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
+bool GrGpu::setupClipAndFlushState(DrawType type) {
 
     ScissoringSettings scissoringSettings;
 
@@ -410,7 +416,7 @@
 
     this->handleDirtyContext();
 
-    if (!this->setupClipAndFlushState(type)) {
+    if (!this->setupClipAndFlushState(PrimTypeToDrawType(type))) {
         return;
     }
 
@@ -423,11 +429,11 @@
 }
 
 void GrGpu::onDrawNonIndexed(GrPrimitiveType type,
-                           int startVertex,
-                           int vertexCount) {
+                             int startVertex,
+                             int vertexCount) {
     this->handleDirtyContext();
 
-    if (!this->setupClipAndFlushState(type)) {
+    if (!this->setupClipAndFlushState(PrimTypeToDrawType(type))) {
         return;
     }
 
@@ -437,6 +443,16 @@
     this->onGpuDrawNonIndexed(type, sVertex, vertexCount);
 }
 
+void GrGpu::onStencilPath(const GrPath& path, GrPathFill fill) {
+    this->handleDirtyContext();
+
+    if (!this->setupClipAndFlushState(kStencilPath_DrawType)) {
+        return;
+    }
+
+    this->onGpuStencilPath(path, fill);
+}
+
 void GrGpu::finalizeReservedVertices() {
     GrAssert(NULL != fVertexPool);
     fVertexPool->unlock();
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index d39ace0..9302393 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -13,11 +13,11 @@
 #include "GrDrawTarget.h"
 #include "GrRect.h"
 #include "GrRefCnt.h"
-#include "GrTexture.h"
 #include "GrClipMaskManager.h"
 
 class GrContext;
 class GrIndexBufferAllocPool;
+class GrPath;
 class GrPathRenderer;
 class GrPathRendererChain;
 class GrResource;
@@ -130,6 +130,12 @@
     GrIndexBuffer* createIndexBuffer(uint32_t size, bool dynamic);
 
     /**
+     * Creates a path object that can be stenciled using stencilPath(). It is
+     * only legal to call this if the caps report support for path stenciling.
+     */
+    GrPath* createPath(const SkPath& path);
+
+    /**
      * Returns an index buffer that can be used to render quads.
      * Six indices per quad: 0, 1, 2, 0, 2, 3, etc.
      * The max number of quads can be queried using GrIndexBuffer::maxQuads().
@@ -341,8 +347,32 @@
     }
 
 protected:
+    enum DrawType {
+        kDrawPoints_DrawType,
+        kDrawLines_DrawType,
+        kDrawTriangles_DrawType,
+        kStencilPath_DrawType,
+    };
+
+    DrawType PrimTypeToDrawType(GrPrimitiveType type) {
+        switch (type) {
+            case kTriangles_GrPrimitiveType:
+            case kTriangleStrip_GrPrimitiveType:
+            case kTriangleFan_GrPrimitiveType:
+                return kDrawTriangles_DrawType;
+            case kPoints_GrPrimitiveType:
+                return kDrawPoints_DrawType;
+            case kLines_GrPrimitiveType:
+            case kLineStrip_GrPrimitiveType:
+                return kDrawLines_DrawType;
+            default:
+                GrCrash("Unexpected primitive type");
+                return kDrawTriangles_DrawType;
+        }
+    }
+
     // prepares clip flushes gpu state before a draw
-    bool setupClipAndFlushState(GrPrimitiveType type);
+    bool setupClipAndFlushState(DrawType);
 
     // Functions used to map clip-respecting stencil tests into normal
     // stencil funcs supported by GPUs.
@@ -413,6 +443,7 @@
                                                  bool dynamic) = 0;
     virtual GrIndexBuffer* onCreateIndexBuffer(uint32_t size,
                                                bool dynamic) = 0;
+    virtual GrPath* onCreatePath(const SkPath& path) = 0;
 
     // overridden by API-specific derivated class to perform the clear and 
     // clearRect. NULL rect means clear whole target.
@@ -428,6 +459,8 @@
     virtual void onGpuDrawNonIndexed(GrPrimitiveType type,
                                      uint32_t vertexCount,
                                      uint32_t numVertices) = 0;
+    // overridden by API-specific derived class to perform the path stenciling.
+    virtual void onGpuStencilPath(const GrPath& path, GrPathFill fill) = 0;
 
     // overridden by API-specific derived class to perform flush
     virtual void onForceRenderTargetFlush() = 0;
@@ -472,7 +505,7 @@
     // deltas from previous state at draw time. This function does the
     // API-specific flush of the state
     // returns false if current state is unsupported.
-    virtual bool flushGraphicsState(GrPrimitiveType type) = 0;
+    virtual bool flushGraphicsState(DrawType) = 0;
 
     // clears the entire stencil buffer to 0
     virtual void clearStencil() = 0;
@@ -518,6 +551,7 @@
     virtual void onDrawNonIndexed(GrPrimitiveType type,
                                   int startVertex,
                                   int vertexCount) SK_OVERRIDE;
+    virtual void onStencilPath(const GrPath& path, GrPathFill fill) SK_OVERRIDE;
 
     // readies the pools to provide vertex/index data.
     void prepareVertexPool();
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 7abe941..907b4f1 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -439,6 +439,10 @@
     draw.fIndexBuffer = NULL;
 }
 
+void GrInOrderDrawBuffer::onStencilPath(const GrPath&, GrPathFill) {
+    GrCrash("Not implemented yet. Should not get here.");
+}
+
 void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) {
     GrIRect r;
     if (NULL == rect) {
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index a467f6c..ed7d97d 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -147,6 +147,7 @@
     virtual void onDrawNonIndexed(GrPrimitiveType primitiveType,
                                   int startVertex,
                                   int vertexCount) SK_OVERRIDE;
+    virtual void onStencilPath(const GrPath&, GrPathFill) SK_OVERRIDE;
     virtual bool onReserveVertexSpace(GrVertexLayout layout, 
                                       int vertexCount,
                                       void** vertices) SK_OVERRIDE;
diff --git a/src/gpu/GrPath.h b/src/gpu/GrPath.h
new file mode 100644
index 0000000..872859d
--- /dev/null
+++ b/src/gpu/GrPath.h
@@ -0,0 +1,28 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrPath_DEFINED
+#define GrPath_DEFINED
+
+#include "GrResource.h"
+#include "GrRect.h"
+
+class GrPath : public GrResource {
+public:
+    GrPath(GrGpu* gpu) : INHERITED(gpu) {}
+
+    const GrIRect& getBounds() const { return fBounds; }
+
+protected:
+    GrIRect fBounds;
+
+private:
+    typedef GrResource INHERITED;
+};
+
+#endif
diff --git a/src/gpu/gl/GrGLPath.cpp b/src/gpu/gl/GrGLPath.cpp
new file mode 100644
index 0000000..2fceaa3
--- /dev/null
+++ b/src/gpu/gl/GrGLPath.cpp
@@ -0,0 +1,101 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLPath.h"
+#include "GrGpuGL.h"
+
+#define GPUGL static_cast<GrGpuGL*>(this->getGpu())
+
+#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
+#define GL_CALL_RET(R, X) GR_GL_CALL_RET(GPUGL->glInterface(), R, X)
+
+namespace {
+inline GrGLubyte verb_to_gl_path_cmd(const SkPath::Verb verb) {
+    static const GrGLubyte gTable[] = {
+        GR_GL_MOVE_TO,
+        GR_GL_LINE_TO,
+        GR_GL_QUADRATIC_CURVE_TO,
+        GR_GL_CUBIC_CURVE_TO,
+        GR_GL_CLOSE_PATH,
+    };
+    GR_STATIC_ASSERT(0 == SkPath::kMove_Verb);
+    GR_STATIC_ASSERT(1 == SkPath::kLine_Verb);
+    GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb);
+    GR_STATIC_ASSERT(3 == SkPath::kCubic_Verb);
+    GR_STATIC_ASSERT(4 == SkPath::kClose_Verb);
+
+    GrAssert(verb >= 0 && verb < GR_ARRAY_COUNT(gTable));
+    return gTable[verb];
+}
+
+inline int num_pts(const SkPath::Verb verb) {
+    static const int gTable[] = {
+        1, // move
+        1, // line
+        2, // quad
+        3, // cubic
+        0, // close
+    };
+    GR_STATIC_ASSERT(0 == SkPath::kMove_Verb);
+    GR_STATIC_ASSERT(1 == SkPath::kLine_Verb);
+    GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb);
+    GR_STATIC_ASSERT(3 == SkPath::kCubic_Verb);
+    GR_STATIC_ASSERT(4 == SkPath::kClose_Verb);
+
+    GrAssert(verb >= 0 && verb < GR_ARRAY_COUNT(gTable));
+    return gTable[verb];
+}
+}
+
+GrGLPath::GrGLPath(GrGpuGL* gpu, const SkPath& path) : INHERITED(gpu) {
+    GL_CALL_RET(fPathID, GenPaths(1));
+    SkPath::Iter iter(path, true);
+
+    SkSTArray<16, GrGLubyte, true> pathCommands;
+    GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT); // assuming SkPoint is floats
+    SkSTArray<16, SkPoint, true> pathPoints;
+
+    int verbCnt = path.countVerbs();
+    int pointCnt = path.countPoints();
+    pathCommands.resize_back(verbCnt);
+    pathPoints.resize_back(pointCnt);
+
+    // TODO: Direct access to path points since we could pass them on directly.
+    path.getPoints(&pathPoints[0], pointCnt);
+    path.getVerbs(&pathCommands[0], verbCnt);
+    
+    GR_DEBUGCODE(int numPts = 0);
+    for (int i = 0; i < verbCnt; ++i) {
+        SkPath::Verb v = static_cast<SkPath::Verb>(pathCommands[i]);
+        pathCommands[i] = verb_to_gl_path_cmd(v);
+        GR_DEBUGCODE(numPts += num_pts(v));
+    }
+    GrAssert(pathPoints.count() == numPts);
+    
+    GL_CALL(PathCommands(fPathID,
+                         verbCnt, &pathCommands[0],
+                         2 * pointCnt, GR_GL_FLOAT, &pathPoints[0]));
+    GrRect bounds = path.getBounds();
+    bounds.roundOut(&fBounds);
+}
+
+GrGLPath::~GrGLPath() {
+    this->release();
+}
+
+void GrGLPath::onRelease() {
+    if (0 != fPathID) {
+        GL_CALL(DeletePaths(1, fPathID));
+        fPathID = 0;
+    }
+}
+
+void GrGLPath::onAbandon() {
+    fPathID = 0;
+}
+
diff --git a/src/gpu/gl/GrGLPath.h b/src/gpu/gl/GrGLPath.h
new file mode 100644
index 0000000..f9febb4
--- /dev/null
+++ b/src/gpu/gl/GrGLPath.h
@@ -0,0 +1,43 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLPath_DEFINED
+#define GrGLPath_DEFINED
+
+#include "../GrPath.h"
+#include "gl/GrGLFunctions.h"
+
+class GrGpuGL;
+class SkPath;
+
+/**
+ * Currently this represents a path built using GL_NV_path_rendering. If we
+ * support other GL path extensions then this would have to have a type enum
+ * and/or be subclassed.
+ */
+
+class GrGLPath : public GrPath {
+public:
+    GrGLPath(GrGpuGL* gpu, const SkPath& path);
+    virtual ~GrGLPath();
+    GrGLuint pathID() const { return fPathID; }
+    // TODO: Figure out how to get an approximate size of the path in Gpu 
+    // memory.
+    virtual size_t sizeInBytes() const SK_OVERRIDE { return 100; }
+
+protected:
+    virtual void onRelease() SK_OVERRIDE;
+    virtual void onAbandon() SK_OVERRIDE;
+
+private:
+    GrGLuint fPathID;
+
+    typedef GrPath INHERITED;
+};
+
+#endif
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index da168cd..77d8758 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -8,6 +8,7 @@
 
 #include "GrGpuGL.h"
 #include "GrGLStencilBuffer.h"
+#include "GrGLPath.h"
 #include "GrTypes.h"
 #include "SkTemplates.h"
 
@@ -1325,6 +1326,14 @@
     return NULL;
 }
 
+GrPath* GrGpuGL::onCreatePath(const SkPath& inPath) {
+    GrPath* path = NULL;
+    if (fCaps.fPathStencilingSupport) {
+        path = new GrGLPath(this, inPath);
+    }
+    return path;
+}
+
 void GrGpuGL::enableScissoring(const GrIRect& rect) {
     const GrDrawState& drawState = this->getDrawState();
     const GrGLRenderTarget* rt =
@@ -1718,6 +1727,10 @@
 #endif
 }
 
+void GrGpuGL::onGpuStencilPath(const GrPath&, GrPathFill) {
+    GrCrash("Not implemented yet. Should not get here.");
+}
+
 void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
 
     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
@@ -1955,7 +1968,7 @@
     }
 }
 
-void GrGpuGL::flushAAState(GrPrimitiveType type) {
+void GrGpuGL::flushAAState(bool isLines) {
     const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
     if (kDesktop_GrGLBinding == this->glBinding()) {
         // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
@@ -1963,7 +1976,7 @@
         // we prefer smooth lines over multisampled lines
         bool smoothLines = false;
 
-        if (GrIsPrimTypeLines(type)) {
+        if (isLines) {
             smoothLines = this->willUseHWAALines();
             if (smoothLines) {
                 if (kYes_TriState != fHWAAState.fSmoothLineEnabled) {
@@ -1999,10 +2012,10 @@
     }
 }
 
-void GrGpuGL::flushBlend(GrPrimitiveType type,
+void GrGpuGL::flushBlend(bool isLines,
                          GrBlendCoeff srcCoeff,
                          GrBlendCoeff dstCoeff) {
-    if (GrIsPrimTypeLines(type) && this->willUseHWAALines()) {
+    if (isLines && this->willUseHWAALines()) {
         if (kYes_TriState != fHWBlendState.fEnabled) {
             GL_CALL(Enable(GR_GL_BLEND));
             fHWBlendState.fEnabled = kYes_TriState;
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 2906170..51e49ec 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -67,6 +67,7 @@
                                                  bool dynamic) SK_OVERRIDE;
     virtual GrIndexBuffer* onCreateIndexBuffer(uint32_t size,
                                                bool dynamic) SK_OVERRIDE;
+    virtual GrPath* onCreatePath(const SkPath&) SK_OVERRIDE;
     virtual GrTexture* onCreatePlatformTexture(
         const GrPlatformTextureDesc& desc) SK_OVERRIDE;
     virtual GrRenderTarget* onCreatePlatformRenderTarget(
@@ -106,13 +107,14 @@
     virtual void onGpuDrawNonIndexed(GrPrimitiveType type,
                                      uint32_t vertexCount,
                                      uint32_t numVertices) SK_OVERRIDE;
+    virtual void onGpuStencilPath(const GrPath&, GrPathFill) SK_OVERRIDE;
     virtual void enableScissoring(const GrIRect& rect) SK_OVERRIDE;
     virtual void disableScissor() SK_OVERRIDE;
 
     virtual void clearStencil() SK_OVERRIDE;
     virtual void clearStencilClip(const GrIRect& rect,
                                   bool insideClip) SK_OVERRIDE;
-    virtual bool flushGraphicsState(GrPrimitiveType type) SK_OVERRIDE;
+    virtual bool flushGraphicsState(DrawType) SK_OVERRIDE;
     virtual void setupGeometry(int* startVertex,
                                int* startIndex,
                                int vertexCount,
@@ -135,7 +137,7 @@
     // The params should be the final coeffecients to apply
     // (after any blending optimizations or dual source blending considerations
     // have been accounted for).
-    void flushBlend(GrPrimitiveType type,
+    void flushBlend(bool isLines,
                     GrBlendCoeff srcCoeff,
                     GrBlendCoeff dstCoeff);
 
@@ -233,7 +235,7 @@
     static void DeleteProgram(const GrGLInterface* gl,
                               CachedData* programData);
 
-    void buildProgram(GrPrimitiveType typeBlend,
+    void buildProgram(bool isPoints,
                       BlendOptFlags blendOpts,
                       GrBlendCoeff dstCoeff,
                       GrCustomStage** customStages);
@@ -261,7 +263,7 @@
     // NULL means whole target. Can be an empty rect.
     void flushRenderTarget(const GrIRect* bound);
     void flushStencil();
-    void flushAAState(GrPrimitiveType type);
+    void flushAAState(bool isLines);
 
     bool configToGLFormats(GrPixelConfig config,
                            bool getSizedInternal,
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index a38ae2d..97f9b6d 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -370,7 +370,7 @@
     }
 }
 
-bool GrGpuGL::flushGraphicsState(GrPrimitiveType type) {
+bool GrGpuGL::flushGraphicsState(DrawType type) {
     const GrDrawState& drawState = this->getDrawState();
 
     // GrGpu::setupClipAndFlushState should have already checked this
@@ -379,7 +379,7 @@
 
     this->flushMiscFixedFunctionState();
     this->flushStencil();
-    this->flushAAState(type);
+    this->flushAAState(kDrawLines_DrawType == type);
 
     GrBlendCoeff srcCoeff;
     GrBlendCoeff dstCoeff;
@@ -389,7 +389,8 @@
     }
 
     GrCustomStage* customStages [GrDrawState::kNumStages];
-    this->buildProgram(type, blendOpts, dstCoeff, customStages);
+    this->buildProgram(kDrawPoints_DrawType == type,
+                       blendOpts, dstCoeff, customStages);
     fProgramData = fProgramCache->getProgramData(fCurrentProgram,
                                                  customStages);
     if (NULL == fProgramData) {
@@ -402,7 +403,7 @@
         fHWProgramID = fProgramData->fProgramID;
     }
     fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff);
-    this->flushBlend(type, srcCoeff, dstCoeff);
+    this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
 
     GrColor color;
     GrColor coverage;
@@ -635,7 +636,7 @@
 
 }
 
-void GrGpuGL::buildProgram(GrPrimitiveType type,
+void GrGpuGL::buildProgram(bool isPoints,
                            BlendOptFlags blendOpts,
                            GrBlendCoeff dstCoeff,
                            GrCustomStage** customStages) {
@@ -658,7 +659,7 @@
     // Must initialize all fields or cache will have false negatives!
     desc.fVertexLayout = this->getVertexLayout();
 
-    desc.fEmitsPointSize = kPoints_GrPrimitiveType == type;
+    desc.fEmitsPointSize = isPoints;
 
     bool requiresAttributeColors = 
         !skipColor && SkToBool(desc.fVertexLayout & kColor_VertexLayoutBit);