Move edgeAA shader gen code to its own function
Review URL:  http://codereview.appspot.com/5015048/


git-svn-id: http://skia.googlecode.com/svn/trunk@2271 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrGLProgram.cpp b/gpu/src/GrGLProgram.cpp
index a939d6e..0efb99f 100644
--- a/gpu/src/GrGLProgram.cpp
+++ b/gpu/src/GrGLProgram.cpp
@@ -321,6 +321,87 @@
     add_helper(outputVar, colorStr.c_str(), constStr.c_str(), fsCode);
 }
 
+void GrGLProgram::genEdgeCoverage(const GrGLInterface* gl,
+                                  GrVertexLayout layout,
+                                  CachedData* programData,
+                                  GrStringBuilder* coverageVar,
+                                  ShaderCodeSegments* segments) const {
+    if (fProgramDesc.fEdgeAANumEdges > 0) {
+        segments->fFSUnis.append("uniform vec3 " EDGES_UNI_NAME "[");
+        segments->fFSUnis.appendS32(fProgramDesc.fEdgeAANumEdges);
+        segments->fFSUnis.append("];\n");
+        programData->fUniLocations.fEdgesUni = kUseUniform;
+        int count = fProgramDesc.fEdgeAANumEdges;
+        segments->fFSCode.append(
+            "\tvec3 pos = vec3(gl_FragCoord.xy, 1);\n");
+        for (int i = 0; i < count; i++) {
+            segments->fFSCode.append("\tfloat a");
+            segments->fFSCode.appendS32(i);
+            segments->fFSCode.append(" = clamp(dot(" EDGES_UNI_NAME "[");
+            segments->fFSCode.appendS32(i);
+            segments->fFSCode.append("], pos), 0.0, 1.0);\n");
+        }
+        if (fProgramDesc.fEdgeAAConcave && (count & 0x01) == 0) {
+            // For concave polys, we consider the edges in pairs.
+            segments->fFSFunctions.append("float cross2(vec2 a, vec2 b) {\n");
+            segments->fFSFunctions.append("\treturn dot(a, vec2(b.y, -b.x));\n");
+            segments->fFSFunctions.append("}\n");
+            for (int i = 0; i < count; i += 2) {
+                segments->fFSCode.appendf("\tfloat eb%d;\n", i / 2);
+                segments->fFSCode.appendf("\tif (cross2(" EDGES_UNI_NAME "[%d].xy, " EDGES_UNI_NAME "[%d].xy) < 0.0) {\n", i, i + 1);
+                segments->fFSCode.appendf("\t\teb%d = a%d * a%d;\n", i / 2, i, i + 1);
+                segments->fFSCode.append("\t} else {\n");
+                segments->fFSCode.appendf("\t\teb%d = a%d + a%d - a%d * a%d;\n", i / 2, i, i + 1, i, i + 1);
+                segments->fFSCode.append("\t}\n");
+            }
+            segments->fFSCode.append("\tfloat edgeAlpha = ");
+            for (int i = 0; i < count / 2 - 1; i++) {
+                segments->fFSCode.appendf("min(eb%d, ", i);
+            }
+            segments->fFSCode.appendf("eb%d", count / 2 - 1);
+            for (int i = 0; i < count / 2 - 1; i++) {
+                segments->fFSCode.append(")");
+            }
+            segments->fFSCode.append(";\n");
+        } else {
+            segments->fFSCode.append("\tfloat edgeAlpha = ");
+            for (int i = 0; i < count - 1; i++) {
+                segments->fFSCode.appendf("min(a%d * a%d, ", i, i + 1);
+            }
+            segments->fFSCode.appendf("a%d * a0", count - 1);
+            for (int i = 0; i < count - 1; i++) {
+                segments->fFSCode.append(")");
+            }
+            segments->fFSCode.append(";\n");
+        }
+        *coverageVar = "edgeAlpha";
+    } else  if (layout & GrDrawTarget::kEdge_VertexLayoutBit) {
+        segments->fVSAttrs.append("attribute vec4 " EDGE_ATTR_NAME ";\n");
+        segments->fVaryings.append("varying vec4 vEdge;\n");
+        segments->fVSCode.append("\tvEdge = " EDGE_ATTR_NAME ";\n");
+        if (GrDrawTarget::kHairLine_EdgeType == fProgramDesc.fVertexEdgeType) {
+            segments->fFSCode.append("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), vEdge.xyz));\n");
+        } else {
+            GrAssert(GrDrawTarget::kHairQuad_EdgeType == fProgramDesc.fVertexEdgeType);
+            // for now we know we're not in perspective, so we could compute this
+            // per-quadratic rather than per pixel
+            segments->fFSCode.append("\tvec2 duvdx = dFdx(vEdge.xy);\n");
+            segments->fFSCode.append("\tvec2 duvdy = dFdy(vEdge.xy);\n");
+            segments->fFSCode.append("\tfloat dfdx = 2.0*vEdge.x*duvdx.x - duvdx.y;\n");
+            segments->fFSCode.append("\tfloat dfdy = 2.0*vEdge.x*duvdy.x - duvdy.y;\n");
+            segments->fFSCode.append("\tfloat edgeAlpha = (vEdge.x*vEdge.x - vEdge.y);\n");
+            segments->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / (dfdx*dfdx + dfdy*dfdy));\n");
+            if (gl->supportsES()) {
+                segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
+            }
+        }
+        segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
+        *coverageVar = "edgeAlpha";
+    } else {
+        coverageVar->reset();
+    }
+}
+
 bool GrGLProgram::genProgram(const GrGLInterface* gl, 
                              GrGLProgram::CachedData* programData) const {
 
@@ -491,78 +572,9 @@
     // output will be zero and we don't have a dual src blend output.
     if (!wroteFragColorZero ||
         ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
-        if (fProgramDesc.fEdgeAANumEdges > 0) {
-            segments.fFSUnis.append("uniform vec3 " EDGES_UNI_NAME "[");
-            segments.fFSUnis.appendS32(fProgramDesc.fEdgeAANumEdges);
-            segments.fFSUnis.append("];\n");
-            programData->fUniLocations.fEdgesUni = kUseUniform;
-            int count = fProgramDesc.fEdgeAANumEdges;
-            segments.fFSCode.append(
-                "\tvec3 pos = vec3(gl_FragCoord.xy, 1);\n");
-            for (int i = 0; i < count; i++) {
-                segments.fFSCode.append("\tfloat a");
-                segments.fFSCode.appendS32(i);
-                segments.fFSCode.append(" = clamp(dot(" EDGES_UNI_NAME "[");
-                segments.fFSCode.appendS32(i);
-                segments.fFSCode.append("], pos), 0.0, 1.0);\n");
-            }
-            if (fProgramDesc.fEdgeAAConcave && (count & 0x01) == 0) {
-                // For concave polys, we consider the edges in pairs.
-                segments.fFSFunctions.append("float cross2(vec2 a, vec2 b) {\n");
-                segments.fFSFunctions.append("\treturn dot(a, vec2(b.y, -b.x));\n");
-                segments.fFSFunctions.append("}\n");
-                for (int i = 0; i < count; i += 2) {
-                    segments.fFSCode.appendf("\tfloat eb%d;\n", i / 2);
-                    segments.fFSCode.appendf("\tif (cross2(" EDGES_UNI_NAME "[%d].xy, " EDGES_UNI_NAME "[%d].xy) < 0.0) {\n", i, i + 1);
-                    segments.fFSCode.appendf("\t\teb%d = a%d * a%d;\n", i / 2, i, i + 1);
-                    segments.fFSCode.append("\t} else {\n");
-                    segments.fFSCode.appendf("\t\teb%d = a%d + a%d - a%d * a%d;\n", i / 2, i, i + 1, i, i + 1);
-                    segments.fFSCode.append("\t}\n");
-                }
-                segments.fFSCode.append("\tfloat edgeAlpha = ");
-                for (int i = 0; i < count / 2 - 1; i++) {
-                    segments.fFSCode.appendf("min(eb%d, ", i);
-                }
-                segments.fFSCode.appendf("eb%d", count / 2 - 1);
-                for (int i = 0; i < count / 2 - 1; i++) {
-                    segments.fFSCode.append(")");
-                }
-                segments.fFSCode.append(";\n");
-            } else {
-                segments.fFSCode.append("\tfloat edgeAlpha = ");
-                for (int i = 0; i < count - 1; i++) {
-                    segments.fFSCode.appendf("min(a%d * a%d, ", i, i + 1);
-                }
-                segments.fFSCode.appendf("a%d * a0", count - 1);
-                for (int i = 0; i < count - 1; i++) {
-                    segments.fFSCode.append(")");
-                }
-                segments.fFSCode.append(";\n");
-            }
-            inCoverage = "edgeAlpha";
-        } else  if (layout & GrDrawTarget::kEdge_VertexLayoutBit) {
-            segments.fVSAttrs.append("attribute vec4 " EDGE_ATTR_NAME ";\n");
-            segments.fVaryings.append("varying vec4 vEdge;\n");
-            segments.fVSCode.append("\tvEdge = " EDGE_ATTR_NAME ";\n");
-            if (GrDrawTarget::kHairLine_EdgeType == fProgramDesc.fVertexEdgeType) {
-                segments.fFSCode.append("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), vEdge.xyz));\n");
-            } else {
-                GrAssert(GrDrawTarget::kHairQuad_EdgeType == fProgramDesc.fVertexEdgeType);
-                // for now we know we're not in perspective, so we could compute this
-                // per-quadratic rather than per pixel
-                segments.fFSCode.append("\tvec2 duvdx = dFdx(vEdge.xy);\n");
-                segments.fFSCode.append("\tvec2 duvdy = dFdy(vEdge.xy);\n");
-                segments.fFSCode.append("\tfloat dfdx = 2.0*vEdge.x*duvdx.x - duvdx.y;\n");
-                segments.fFSCode.append("\tfloat dfdy = 2.0*vEdge.x*duvdy.x - duvdy.y;\n");
-                segments.fFSCode.append("\tfloat edgeAlpha = (vEdge.x*vEdge.x - vEdge.y);\n");
-                segments.fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / (dfdx*dfdx + dfdy*dfdy));\n");
-                if (gl->supportsES()) {
-                    segments.fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
-                }
-            }
-            segments.fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
-            inCoverage = "edgeAlpha";
-        }
+
+        // get edge AA coverage and use it as inCoverage to first coverage stage
+        this->genEdgeCoverage(gl, layout, programData, &inCoverage, &segments);
 
         GrStringBuilder outCoverage;
         const int& startStage = fProgramDesc.fFirstCoverageStage;
diff --git a/gpu/src/GrGLProgram.h b/gpu/src/GrGLProgram.h
index 78d25b5..90e515f 100644
--- a/gpu/src/GrGLProgram.h
+++ b/gpu/src/GrGLProgram.h
@@ -286,6 +286,13 @@
                       const char* vsInCoord,
                       ShaderCodeSegments* segments,
                       StageUniLocations* locations) const;
+    
+    // generates code to compute coverage based on edge AA.
+    void genEdgeCoverage(const GrGLInterface* gl,
+                         GrVertexLayout layout,
+                         CachedData* programData,
+                         GrStringBuilder* coverageVar,
+                         ShaderCodeSegments* segments) const;
 
     static bool CompileFSAndVS(const GrGLInterface* gl,
                                const ShaderCodeSegments& segments,