Revert of Cleanup of shader building system (patchset #25 id:470001 of https://codere...
authorjoshualitt <joshualitt@chromium.org>
Tue, 7 Oct 2014 19:42:26 +0000 (12:42 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 7 Oct 2014 19:42:26 +0000 (12:42 -0700)
Reason for revert:
Seems to have messed up windows 7 gms

Original issue's description:
> Cleanup of shader building system
>
> this is a huge refactor and cleanup of the gl shader building system in
> Skia.  The entire shader building pipeline is now part of
> GrGLProgramCreator, which takes a gp, and some fps, and creates a
> program.  I added some subclasses of GrGLProgram to handle the
> eccentricities of Nvpr/Nvpres.  Outside of the builders folder
> and GrGLPrograms, this change is basically just a rename
>
>
> solo gp
>
> BUG=skia:
>
> Committed: https://skia.googlesource.com/skia/+/fe1233c3f12f81bb675718516bbb32f72af726ec

TBR=bsalomon@google.com
NOTREECHECKS=true
NOTRY=true
BUG=skia:

Review URL: https://codereview.chromium.org/635533005

45 files changed:
gyp/gpu.gypi
include/gpu/GrPaint.h
include/gpu/GrProcessorStage.h
include/gpu/GrTBackendProcessorFactory.h
src/gpu/GrAAConvexPathRenderer.cpp
src/gpu/GrAARectRenderer.cpp
src/gpu/GrDrawState.cpp
src/gpu/GrDrawTarget.cpp
src/gpu/GrOptDrawState.cpp
src/gpu/GrOvalRenderer.cpp
src/gpu/effects/GrBezierEffect.cpp
src/gpu/effects/GrCustomCoordsTextureEffect.cpp
src/gpu/effects/GrDashingEffect.cpp
src/gpu/effects/GrDistanceFieldTextureEffect.cpp
src/gpu/gl/GrGLGeometryProcessor.h
src/gpu/gl/GrGLProcessor.h
src/gpu/gl/GrGLProgram.cpp
src/gpu/gl/GrGLProgram.h
src/gpu/gl/GrGLProgramDataManager.cpp
src/gpu/gl/GrGLProgramDataManager.h
src/gpu/gl/GrGLProgramDesc.cpp
src/gpu/gl/GrGLProgramDesc.h
src/gpu/gl/GrGLProgramEffects.cpp [new file with mode: 0644]
src/gpu/gl/GrGLProgramEffects.h [new file with mode: 0644]
src/gpu/gl/GrGpuGL.h
src/gpu/gl/GrGpuGL_program.cpp
src/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.cpp [new file with mode: 0644]
src/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.h [new file with mode: 0644]
src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
src/gpu/gl/builders/GrGLFragmentShaderBuilder.h
src/gpu/gl/builders/GrGLFullProgramBuilder.cpp [new file with mode: 0644]
src/gpu/gl/builders/GrGLFullProgramBuilder.h [new file with mode: 0644]
src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp
src/gpu/gl/builders/GrGLGeometryShaderBuilder.h
src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp [deleted file]
src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h [deleted file]
src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp [deleted file]
src/gpu/gl/builders/GrGLNvprProgramBuilder.h [deleted file]
src/gpu/gl/builders/GrGLProgramBuilder.cpp
src/gpu/gl/builders/GrGLProgramBuilder.h
src/gpu/gl/builders/GrGLShaderBuilder.cpp
src/gpu/gl/builders/GrGLShaderBuilder.h
src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
src/gpu/gl/builders/GrGLVertexShaderBuilder.h
tests/GLProgramsTest.cpp

index eb520b524095df66b6c34e400a61db299d3cf70a..074c932506f229671a764f697ee10696c96bdcc3 100644 (file)
       '<(skia_src_path)/gpu/gl/GrGLProgram.h',
       '<(skia_src_path)/gpu/gl/GrGLProgramDesc.cpp',
       '<(skia_src_path)/gpu/gl/GrGLProgramDesc.h',
+      '<(skia_src_path)/gpu/gl/GrGLProgramEffects.cpp',
+      '<(skia_src_path)/gpu/gl/GrGLProgramEffects.h',
       '<(skia_src_path)/gpu/gl/GrGLProgramDataManager.cpp',
       '<(skia_src_path)/gpu/gl/GrGLProgramDataManager.h',
       '<(skia_src_path)/gpu/gl/GrGLRenderTarget.cpp',
       '<(skia_src_path)/gpu/gl/GrGpuGL_program.cpp',
 
       # Files for building GLSL shaders
-      '<(skia_src_path)/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp',
-      '<(skia_src_path)/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h',
-      '<(skia_src_path)/gpu/gl/builders/GrGLNvprProgramBuilder.cpp',
-      '<(skia_src_path)/gpu/gl/builders/GrGLNvprProgramBuilder.h',
-      '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.cpp',
-      '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.h',
+      '<(skia_src_path)/gpu/gl/builders/GrGLSLPrettyPrint.cpp',
       '<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.cpp',
       '<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.h',
+      '<(skia_src_path)/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.cpp',
+      '<(skia_src_path)/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.h',
+      '<(skia_src_path)/gpu/gl/builders/GrGLFullProgramBuilder.cpp',
+      '<(skia_src_path)/gpu/gl/builders/GrGLFullProgramBuilder.h',
+      '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.cpp',
+      '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.h',
       '<(skia_src_path)/gpu/gl/builders/GrGLShaderStringBuilder.cpp',
       '<(skia_src_path)/gpu/gl/builders/GrGLShaderStringBuilder.h',
-      '<(skia_src_path)/gpu/gl/builders/GrGLSLPrettyPrint.cpp',
       '<(skia_src_path)/gpu/gl/builders/GrGLVertexShaderBuilder.cpp',
       '<(skia_src_path)/gpu/gl/builders/GrGLVertexShaderBuilder.h',
       '<(skia_src_path)/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp',
index ff37fcfee899d9f4728d94006208b02f508ed12a..d0531a3024de190c00d37846c8bfab6c0484a988 100644 (file)
@@ -92,7 +92,7 @@ public:
         if (!fp->willUseInputColor()) {
             fColorStages.reset();
         }
-        SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (fp));
+        SkNEW_APPEND_TO_TARRAY(&fColorStages, GrProcessorStage, (fp));
         return fp;
     }
 
@@ -104,7 +104,7 @@ public:
         if (!fp->willUseInputColor()) {
             fCoverageStages.reset();
         }
-        SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (fp));
+        SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrProcessorStage, (fp));
         return fp;
     }
 
index 5cc06e78db3c298568535bb1aaf4ee523bf564ba..1485ca7cd197805a301f3bb7c402e9f3dc84c4b6 100644 (file)
@@ -31,8 +31,6 @@ public:
         fCoordChangeMatrixSet = false;
     }
 
-    virtual ~GrProcessorStage() {}
-
     GrProcessorStage(const GrProcessorStage& other) {
         fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
         if (other.fCoordChangeMatrixSet) {
@@ -149,11 +147,11 @@ public:
         }
     }
 
-    virtual const GrProcessor* getProcessor() const = 0;
+    const GrProcessor* getProcessor() const { return fProc.get(); }
 
     void convertToPendingExec() { fProc.convertToPendingExec(); }
 
-protected:
+private:
     bool                                   fCoordChangeMatrixSet;
     SkMatrix                               fCoordChangeMatrix;
     GrProgramElementRef<const GrProcessor> fProc;
@@ -163,24 +161,18 @@ class GrFragmentStage : public GrProcessorStage {
 public:
     GrFragmentStage(const GrFragmentProcessor* fp) : GrProcessorStage(fp) {}
 
-    virtual const GrFragmentProcessor* getProcessor() const {
-        return static_cast<const GrFragmentProcessor*>(fProc.get());
+    const GrFragmentProcessor* getFragmentProcessor() const {
+        return static_cast<const GrFragmentProcessor*>(this->getProcessor());
     }
-
-    typedef GrFragmentProcessor   Processor;
-    typedef GrGLFragmentProcessor GLProcessor;
 };
 
 class GrGeometryStage : public GrProcessorStage {
 public:
     GrGeometryStage(const GrGeometryProcessor* gp) : GrProcessorStage(gp) {}
 
-    virtual const GrGeometryProcessor* getProcessor() const {
-        return static_cast<const GrGeometryProcessor*>(fProc.get());
+    const GrGeometryProcessor* getGeometryProcessor() const {
+        return static_cast<const GrGeometryProcessor*>(this->getProcessor());
     }
-
-    typedef GrGeometryProcessor   Processor;
-    typedef GrGLGeometryProcessor GLProcessor;
 };
 
 #endif
index 78a6332d116fc09d21d710ca90a4ea5f445b2b32..c67f508f5d5da6cb9209eb2066a23b64e87d8e29 100644 (file)
@@ -9,6 +9,7 @@
 #define GrTBackendProcessorFactory_DEFINED
 
 #include "GrBackendProcessorFactory.h"
+#include "gl/GrGLProgramEffects.h"
 
 /**
  * Implements GrBackendEffectFactory for a GrProcessor subclass as a singleton. This can be used by
index 550d7ae79909d9e32362e430e1a8e0f57f3ccbbf..1aa90c3f2b9cc3b3d317f79d267ad2e9f1966fdc 100644 (file)
@@ -18,7 +18,7 @@
 #include "SkStrokeRec.h"
 #include "SkTraceEvent.h"
 
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLGeometryProcessor.h"
@@ -528,7 +528,7 @@ public:
         GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
             : INHERITED (factory) {}
 
-        virtual void emitCode(GrGLGPBuilder* builder,
+        virtual void emitCode(GrGLFullProgramBuilder* builder,
                               const GrGeometryProcessor& geometryProcessor,
                               const GrProcessorKey& key,
                               const char* outputColor,
@@ -538,7 +538,7 @@ public:
             const char *vsName, *fsName;
             builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName);
 
-            GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+            GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
 
             SkAssertResult(fsBuilder->enableFeature(
                     GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
@@ -565,7 +565,7 @@ public:
                                    (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
 
             const GrShaderVar& inQuadEdge = geometryProcessor.cast<QuadEdgeEffect>().inQuadEdge();
-            GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+            GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
             vsBuilder->codeAppendf("\t%s = %s;\n", vsName, inQuadEdge.c_str());
         }
 
index 88b0306a53fb9fcca3c1a2115c962c4f24d0ebeb..0b895d1d335f76c48041853332a7ed5b206b23f1 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "GrAARectRenderer.h"
 #include "GrGpu.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLGeometryProcessor.h"
 #include "GrTBackendProcessorFactory.h"
@@ -41,7 +41,7 @@ public:
         GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
         : INHERITED (factory) {}
 
-        virtual void emitCode(GrGLGPBuilder* builder,
+        virtual void emitCode(GrGLFullProgramBuilder* builder,
                               const GrGeometryProcessor& geometryProcessor,
                               const GrProcessorKey& key,
                               const char* outputColor,
@@ -55,10 +55,10 @@ public:
             builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName);
 
             const GrShaderVar& inRect = geometryProcessor.cast<GrAlignedRectEffect>().inRect();
-            GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+            GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
             vsBuilder->codeAppendf("\t%s = %s;\n", vsRectName, inRect.c_str());
 
-            GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+            GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
             // TODO: compute all these offsets, spans, and scales in the VS
             fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName);
             fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", fsRectName);
@@ -167,7 +167,7 @@ public:
         GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
         : INHERITED (factory) {}
 
-        virtual void emitCode(GrGLGPBuilder* builder,
+        virtual void emitCode(GrGLFullProgramBuilder* builder,
                               const GrGeometryProcessor& geometryProcessor,
                               const GrProcessorKey& key,
                               const char* outputColor,
@@ -181,7 +181,7 @@ public:
                                 &vsRectEdgeName, &fsRectEdgeName);
 
             const GrRectEffect& rectEffect = geometryProcessor.cast<GrRectEffect>();
-            GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+            GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
             vsBuilder->codeAppendf("%s = %s;", vsRectEdgeName, rectEffect.inRectEdge().c_str());
 
             // setup the varying for width/2+.5 and height/2+.5
@@ -192,7 +192,7 @@ public:
                                    vsWidthHeightName,
                                    rectEffect.inWidthHeight().c_str());
 
-            GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+            GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
             // TODO: compute all these offsets, spans, and scales in the VS
             fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName);
             fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName);
index 6831fad1f9a016d1b29178ad3291b961103e41b4..f967a6fa76182d536bd9aba26221c685335c7896 100644 (file)
@@ -266,7 +266,7 @@ bool GrDrawState::validateVertexAttribs() const {
 
     if (this->hasGeometryProcessor()) {
         const GrGeometryStage& stage = *this->getGeometryProcessor();
-        const GrGeometryProcessor* gp = stage.getProcessor();
+        const GrGeometryProcessor* gp = stage.getGeometryProcessor();
         SkASSERT(gp);
         // make sure that any attribute indices have the correct binding type, that the attrib
         // type and effect's shader lang type are compatible, and that attributes shared by
@@ -410,7 +410,7 @@ bool GrDrawState::hasSolidCoverage() const {
 
     // Run through the coverage stages and see if the coverage will be all ones at the end.
     if (this->hasGeometryProcessor()) {
-        const GrGeometryProcessor* gp = fGeometryProcessor->getProcessor();
+        const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
         gp->computeInvariantOutput(&inout);
     }
     for (int s = 0; s < this->numCoverageStages(); ++s) {
@@ -436,13 +436,13 @@ GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawS
 bool GrDrawState::willEffectReadDstColor() const {
     if (!this->isColorWriteDisabled()) {
         for (int s = 0; s < this->numColorStages(); ++s) {
-            if (this->getColorStage(s).getProcessor()->willReadDstColor()) {
+            if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) {
                 return true;
             }
         }
     }
     for (int s = 0; s < this->numCoverageStages(); ++s) {
-        if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) {
+        if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
             return true;
         }
     }
index 7265f4d23ab0f388e537625880f376032e6f2af3..d8848bc4d50b22c6609ff2d6edb0f6829cecf6ed 100644 (file)
@@ -391,7 +391,7 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
     SkASSERT(drawState.getRenderTarget());
 
     if (drawState.hasGeometryProcessor()) {
-        const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getProcessor();
+        const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getGeometryProcessor();
         int numTextures = gp->numTextures();
         for (int t = 0; t < numTextures; ++t) {
             GrTexture* texture = gp->texture(t);
index 19507c07e54ea7ce781a3ec797eed88800911e63..802713e21bdc10a1960ededb548aca707eb1f57c 100644 (file)
@@ -222,7 +222,7 @@ void GrOptDrawState::copyEffectiveColorStages(const GrDrawState& ds) {
     }
 
     for (int i = 0; i < ds.numColorStages(); ++i) {
-        const GrFragmentProcessor* fp = ds.getColorStage(i).getProcessor();
+        const GrFragmentProcessor* fp = ds.getColorStage(i).getFragmentProcessor();
         if (!fp->willUseInputColor()) {
             firstColorStage = i;
             fInputColorIsUsed = false;
@@ -270,10 +270,10 @@ void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
 }
 
 static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
-    if (stage.getProcessor()->willReadDstColor()) {
+    if (stage.getFragmentProcessor()->willReadDstColor()) {
         *readsDst = true;
     }
-    if (stage.getProcessor()->willReadFragmentPosition()) {
+    if (stage.getFragmentProcessor()->willReadFragmentPosition()) {
         *readsFragPosition = true;
     }
 }
index 4dda3b5113c7816a8104bd5d40fea15d1d79cf73..7a84f80805d9bf5cc6ab8c1b3d205f4525634343 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "GrOvalRenderer.h"
 
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLGeometryProcessor.h"
@@ -92,7 +92,7 @@ public:
         GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
         : INHERITED (factory) {}
 
-        virtual void emitCode(GrGLGPBuilder* builder,
+        virtual void emitCode(GrGLFullProgramBuilder* builder,
                               const GrGeometryProcessor& geometryProcessor,
                               const GrProcessorKey& key,
                               const char* outputColor,
@@ -103,10 +103,10 @@ public:
             const char *vsName, *fsName;
             builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName);
 
-            GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();;
+            GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();;
             vsBuilder->codeAppendf("\t%s = %s;\n", vsName, circleEffect.inCircleEdge().c_str());
 
-            GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+            GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
             fsBuilder->codeAppendf("\tfloat d = length(%s.xy);\n", fsName);
             fsBuilder->codeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName);
             if (circleEffect.isStroked()) {
@@ -210,7 +210,7 @@ public:
         GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
         : INHERITED (factory) {}
 
-        virtual void emitCode(GrGLGPBuilder* builder,
+        virtual void emitCode(GrGLFullProgramBuilder* builder,
                               const GrGeometryProcessor& geometryProcessor,
                               const GrProcessorKey& key,
                               const char* outputColor,
@@ -224,7 +224,7 @@ public:
 
             builder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName, &fsOffsetName);
 
-            GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+            GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
             vsBuilder->codeAppendf("%s = %s;", vsOffsetName,
                                    ellipseEffect.inEllipseOffset().c_str());
 
@@ -232,7 +232,7 @@ public:
             vsBuilder->codeAppendf("%s = %s;", vsRadiiName, ellipseEffect.inEllipseRadii().c_str());
 
             // for outer curve
-            GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+            GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
             fsBuilder->codeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffsetName, fsRadiiName);
             fsBuilder->codeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n");
             fsBuilder->codeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fsRadiiName);
@@ -359,7 +359,7 @@ public:
         GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
         : INHERITED (factory) {}
 
-        virtual void emitCode(GrGLGPBuilder* builder,
+        virtual void emitCode(GrGLFullProgramBuilder* builder,
                               const GrGeometryProcessor& geometryProcessor,
                               const GrProcessorKey& key,
                               const char* outputColor,
@@ -373,7 +373,7 @@ public:
             builder->addVarying(kVec2f_GrSLType, "EllipseOffsets0",
                                       &vsOffsetName0, &fsOffsetName0);
 
-            GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+            GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
             vsBuilder->codeAppendf("%s = %s;", vsOffsetName0,
                                    ellipseEffect.inEllipseOffsets0().c_str());
             const char *vsOffsetName1, *fsOffsetName1;
@@ -382,7 +382,7 @@ public:
             vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName1,
                                    ellipseEffect.inEllipseOffsets1().c_str());
 
-            GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+            GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
             SkAssertResult(fsBuilder->enableFeature(
                     GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
             // for outer curve
index d6044cb34ab72e9fb4e53194ac9039c9318d3a17..fe509b60a4ba6412f374e33d6a6602693de77576 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "GrBezierEffect.h"
 
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLGeometryProcessor.h"
@@ -17,7 +17,7 @@ class GrGLConicEffect : public GrGLGeometryProcessor {
 public:
     GrGLConicEffect(const GrBackendProcessorFactory&, const GrProcessor&);
 
-    virtual void emitCode(GrGLGPBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrGeometryProcessor& geometryProcessor,
                           const GrProcessorKey& key,
                           const char* outputColor,
@@ -42,7 +42,7 @@ GrGLConicEffect::GrGLConicEffect(const GrBackendProcessorFactory& factory,
     fEdgeType = ce.getEdgeType();
 }
 
-void GrGLConicEffect::emitCode(GrGLGPBuilder* builder,
+void GrGLConicEffect::emitCode(GrGLFullProgramBuilder* builder,
                                const GrGeometryProcessor& geometryProcessor,
                                const GrProcessorKey& key,
                                const char* outputColor,
@@ -55,10 +55,10 @@ void GrGLConicEffect::emitCode(GrGLGPBuilder* builder,
                               &vsName, &fsName);
 
     const GrShaderVar& inConicCoeffs = geometryProcessor.cast<GrConicEffect>().inConicCoeffs();
-    GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
     vsBuilder->codeAppendf("%s = %s;", vsName, inConicCoeffs.c_str());
 
-    GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
     fsBuilder->codeAppend("float edgeAlpha;");
 
     switch (fEdgeType) {
@@ -171,7 +171,7 @@ class GrGLQuadEffect : public GrGLGeometryProcessor {
 public:
     GrGLQuadEffect(const GrBackendProcessorFactory&, const GrProcessor&);
 
-    virtual void emitCode(GrGLGPBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrGeometryProcessor& geometryProcessor,
                           const GrProcessorKey& key,
                           const char* outputColor,
@@ -196,7 +196,7 @@ GrGLQuadEffect::GrGLQuadEffect(const GrBackendProcessorFactory& factory,
     fEdgeType = ce.getEdgeType();
 }
 
-void GrGLQuadEffect::emitCode(GrGLGPBuilder* builder,
+void GrGLQuadEffect::emitCode(GrGLFullProgramBuilder* builder,
                               const GrGeometryProcessor& geometryProcessor,
                               const GrProcessorKey& key,
                               const char* outputColor,
@@ -206,11 +206,11 @@ void GrGLQuadEffect::emitCode(GrGLGPBuilder* builder,
     const char *vsName, *fsName;
     builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
 
-    GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
     const GrShaderVar& inHairQuadEdge = geometryProcessor.cast<GrQuadEffect>().inHairQuadEdge();
     vsBuilder->codeAppendf("%s = %s;", vsName, inHairQuadEdge.c_str());
 
-    GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
     fsBuilder->codeAppendf("float edgeAlpha;");
 
     switch (fEdgeType) {
@@ -309,7 +309,7 @@ class GrGLCubicEffect : public GrGLGeometryProcessor {
 public:
     GrGLCubicEffect(const GrBackendProcessorFactory&, const GrProcessor&);
 
-    virtual void emitCode(GrGLGPBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrGeometryProcessor& geometryProcessor,
                           const GrProcessorKey& key,
                           const char* outputColor,
@@ -334,7 +334,7 @@ GrGLCubicEffect::GrGLCubicEffect(const GrBackendProcessorFactory& factory,
     fEdgeType = ce.getEdgeType();
 }
 
-void GrGLCubicEffect::emitCode(GrGLGPBuilder* builder,
+void GrGLCubicEffect::emitCode(GrGLFullProgramBuilder* builder,
                                const GrGeometryProcessor& geometryProcessor,
                                const GrProcessorKey& key,
                                const char* outputColor,
@@ -346,11 +346,11 @@ void GrGLCubicEffect::emitCode(GrGLGPBuilder* builder,
     builder->addVarying(kVec4f_GrSLType, "CubicCoeffs",
                               &vsName, &fsName, GrGLShaderVar::kHigh_Precision);
 
-    GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
     const GrShaderVar& inCubicCoeffs = geometryProcessor.cast<GrCubicEffect>().inCubicCoeffs();
     vsBuilder->codeAppendf("%s = %s;", vsName, inCubicCoeffs.c_str());
 
-    GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
 
     GrGLShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, GrGLShaderVar::kHigh_Precision);
     GrGLShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, GrGLShaderVar::kHigh_Precision);
index e89e46cb5a34022eb5674dd8f9b09f086241033b..7362ba98a63eb249d15297ee03af8a3ee378170e 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #include "GrCustomCoordsTextureEffect.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
@@ -19,7 +19,7 @@ public:
     GrGLCustomCoordsTextureEffect(const GrBackendProcessorFactory& factory, const GrProcessor&)
         : INHERITED (factory) {}
 
-    virtual void emitCode(GrGLGPBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrGeometryProcessor& geometryProcessor,
                           const GrProcessorKey& key,
                           const char* outputColor,
@@ -36,11 +36,11 @@ public:
         builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsVaryingNamePtr);
         fsCoordName = fsVaryingNamePtr;
 
-        GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+        GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
         const GrShaderVar& inTextureCoords = customCoordsTextureEffect.inTextureCoords();
         vsBuilder->codeAppendf("\t%s = %s;\n", vsVaryingName, inTextureCoords.c_str());
 
-        GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+        GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
         fsBuilder->codeAppendf("\t%s = ", outputColor);
         fsBuilder->appendTextureLookupAndModulate(inputColor,
                                                   samplers[0],
index d7a2f402da06424cbeb076976b2e7eb53fc5999b..4df1f02558e9a1d5ea1cc629c09b87f66fb388a6 100644 (file)
@@ -10,7 +10,7 @@
 #include "../GrAARectRenderer.h"
 
 #include "GrGeometryProcessor.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLGeometryProcessor.h"
 #include "gl/GrGLSL.h"
@@ -482,7 +482,7 @@ class GLDashingCircleEffect : public GrGLGeometryProcessor {
 public:
     GLDashingCircleEffect(const GrBackendProcessorFactory&, const GrProcessor&);
 
-    virtual void emitCode(GrGLGPBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrGeometryProcessor& geometryProcessor,
                           const GrProcessorKey& key,
                           const char* outputColor,
@@ -510,7 +510,7 @@ GLDashingCircleEffect::GLDashingCircleEffect(const GrBackendProcessorFactory& fa
     fPrevIntervalLength = SK_ScalarMax;
 }
 
-void GLDashingCircleEffect::emitCode(GrGLGPBuilder* builder,
+void GLDashingCircleEffect::emitCode(GrGLFullProgramBuilder* builder,
                                     const GrGeometryProcessor& geometryProcessor,
                                     const GrProcessorKey& key,
                                     const char* outputColor,
@@ -529,11 +529,11 @@ void GLDashingCircleEffect::emitCode(GrGLGPBuilder* builder,
     const char *vsCoordName, *fsCoordName;
     builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
 
-    GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
     vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dce.inCoord().c_str());
 
     // transforms all points so that we can compare them to our test circle
-    GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
     fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s.z;\n",
                            fsCoordName, fsCoordName, paramName, paramName);
     fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
@@ -694,7 +694,7 @@ class GLDashingLineEffect : public GrGLGeometryProcessor {
 public:
     GLDashingLineEffect(const GrBackendProcessorFactory&, const GrProcessor&);
 
-    virtual void emitCode(GrGLGPBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrGeometryProcessor& geometryProcessor,
                           const GrProcessorKey& key,
                           const char* outputColor,
@@ -721,7 +721,7 @@ GLDashingLineEffect::GLDashingLineEffect(const GrBackendProcessorFactory& factor
     fPrevIntervalLength = SK_ScalarMax;
 }
 
-void GLDashingLineEffect::emitCode(GrGLGPBuilder* builder,
+void GLDashingLineEffect::emitCode(GrGLFullProgramBuilder* builder,
                                    const GrGeometryProcessor& geometryProcessor,
                                    const GrProcessorKey& key,
                                    const char* outputColor,
@@ -745,11 +745,11 @@ void GLDashingLineEffect::emitCode(GrGLGPBuilder* builder,
 
     const char *vsCoordName, *fsCoordName;
     builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
-    GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
     vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, de.inCoord().c_str());
 
     // transforms all points so that we can compare them to our test rect
-    GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
     fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n",
                            fsCoordName, fsCoordName, intervalName, intervalName);
     fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
index c8ed5c9edadf1a72b804d45ecd52c31fa978b9e8..265f112c2bb4a44d38491597ca12c5f3c0b8d95c 100755 (executable)
@@ -6,7 +6,7 @@
  */
 
 #include "GrDistanceFieldTextureEffect.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
@@ -40,7 +40,7 @@ public:
 #endif
         {}
 
-    virtual void emitCode(GrGLGPBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrGeometryProcessor& geometryProcessor,
                           const GrProcessorKey& key,
                           const char* outputColor,
@@ -51,7 +51,7 @@ public:
                 geometryProcessor.cast<GrDistanceFieldTextureEffect>();
         SkASSERT(1 == dfTexEffect.getVertexAttribs().count());
 
-        GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+        GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
         SkAssertResult(fsBuilder->enableFeature(
                 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
 
@@ -61,7 +61,7 @@ public:
         builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
         fsCoordName = fsCoordNamePtr;
 
-        GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+        GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
         vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextureCoords().c_str());
 
         const char* textureSizeUniName = NULL;
@@ -267,7 +267,7 @@ public:
         : INHERITED(factory)
         , fTextureSize(SkISize::Make(-1, -1)) {}
 
-    virtual void emitCode(GrGLGPBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrGeometryProcessor& effect,
                           const GrProcessorKey& key,
                           const char* outputColor,
@@ -278,7 +278,7 @@ public:
                                                 effect.cast<GrDistanceFieldNoGammaTextureEffect>();
         SkASSERT(1 == dfTexEffect.getVertexAttribs().count());
 
-        GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+        GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
         SkAssertResult(fsBuilder->enableFeature(
                                      GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
 
@@ -288,7 +288,7 @@ public:
         builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
         fsCoordName = fsCoordNamePtr;
 
-        GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+        GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
         vsBuilder->codeAppendf("%s = %s;", vsCoordName, dfTexEffect.inTextureCoords().c_str());
 
         const char* textureSizeUniName = NULL;
@@ -439,7 +439,7 @@ public:
     , fTextureSize(SkISize::Make(-1,-1))
     , fTextColor(GrColor_ILLEGAL) {}
 
-    virtual void emitCode(GrGLGPBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrGeometryProcessor& geometryProcessor,
                           const GrProcessorKey& key,
                           const char* outputColor,
@@ -456,7 +456,7 @@ public:
         builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
         fsCoordName = fsCoordNamePtr;
 
-        GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+        GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
         vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextureCoords().c_str());
 
         const char* textureSizeUniName = NULL;
@@ -465,7 +465,7 @@ public:
                                               kVec3f_GrSLType, "TextureSize",
                                               &textureSizeUniName);
 
-        GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+        GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
 
         SkAssertResult(fsBuilder->enableFeature(
                 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
index ce1c7c988a574a0f5b74bd7bc051b5c968186def..b879e12dacc84f566a96fa3c02bd9c04b5454650 100644 (file)
@@ -24,7 +24,7 @@ public:
      * This is similar to emitCode() in the base class, except it takes a full shader builder.
      * This allows the effect subclass to emit vertex code.
      */
-    virtual void emitCode(GrGLGPBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrGeometryProcessor& geometryProcessor,
                           const GrProcessorKey& key,
                           const char* outputColor,
index 393bb87cb33d4b11cd590b6c74954df5a60a2f56..8455305b033abe4ee5c810d2ffb6b87d8acdc083 100644 (file)
@@ -9,8 +9,9 @@
 #define GrGLProcessor_DEFINED
 
 #include "GrBackendProcessorFactory.h"
-#include "GrGLProgramDataManager.h"
-#include "GrTextureAccess.h"
+#include "GrGLProgramEffects.h"
+#include "GrGLShaderVar.h"
+#include "GrGLSL.h"
 
 /** @file
     This file contains specializations for OpenGL of the shader stages declared in
index a464a8bbdec8bde1ad7e3640e5c95db081cabebf..480e1b77352c99b59fbf33a84357d0b293e0153d 100644 (file)
@@ -7,6 +7,8 @@
 
 #include "GrGLProgram.h"
 
+#include "builders/GrGLFullProgramBuilder.h"
+#include "builders/GrGLFragmentOnlyProgramBuilder.h"
 #include "GrAllocator.h"
 #include "GrProcessor.h"
 #include "GrCoordTransform.h"
 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
 
-/**
- * Retrieves the final matrix that a transform needs to apply to its source coords.
- */
-static SkMatrix get_transform_matrix(const GrProcessorStage& processorStage,
-                                     bool useExplicitLocalCoords,
-                                     int transformIdx) {
-    const GrCoordTransform& coordTransform =
-            processorStage.getProcessor()->coordTransform(transformIdx);
-    SkMatrix combined;
-
-    if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
-        // If we have explicit local coords then we shouldn't need a coord change.
-        const SkMatrix& ccm =
-                useExplicitLocalCoords ? SkMatrix::I() : processorStage.getCoordChangeMatrix();
-        combined.setConcat(coordTransform.getMatrix(), ccm);
+GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
+                                 const GrOptDrawState& optState,
+                                 const GrGLProgramDesc& desc,
+                                 const GrGeometryStage* geometryProcessor,
+                                 const GrFragmentStage* colorStages[],
+                                 const GrFragmentStage* coverageStages[]) {
+    SkAutoTDelete<GrGLProgramBuilder> builder;
+    if (desc.getHeader().fUseFragShaderOnly) {
+        SkASSERT(gpu->glCaps().pathRenderingSupport());
+        SkASSERT(gpu->glPathRendering()->texturingMode() ==
+                 GrGLPathRendering::FixedFunction_TexturingMode);
+        SkASSERT(NULL == geometryProcessor);
+        builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, optState, desc)));
     } else {
-        combined = coordTransform.getMatrix();
+        builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, optState, desc)));
     }
-    if (coordTransform.reverseY()) {
-        // combined.postScale(1,-1);
-        // combined.postTranslate(0,1);
-        combined.set(SkMatrix::kMSkewY,
-            combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
-        combined.set(SkMatrix::kMScaleY,
-            combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
-        combined.set(SkMatrix::kMTransY,
-            combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
+    if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) {
+        SkASSERT(0 != builder->getProgramID());
+        return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder));
     }
-    return combined;
+    return NULL;
 }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
 GrGLProgram::GrGLProgram(GrGpuGL* gpu,
                          const GrGLProgramDesc& desc,
-                         const BuiltinUniformHandles& builtinUniforms,
-                         GrGLuint programID,
-                         const UniformInfoArray& uniforms,
-                         GrGLInstalledProcessors* geometryProcessor,
-                         GrGLInstalledProcessors* colorProcessors,
-                         GrGLInstalledProcessors* coverageProcessors)
+                         const GrGLProgramBuilder& builder)
     : fColor(GrColor_ILLEGAL)
     , fCoverage(GrColor_ILLEGAL)
     , fDstCopyTexUnit(-1)
-    , fBuiltinUniformHandles(builtinUniforms)
-    , fProgramID(programID)
-    , fGeometryProcessor(SkSafeRef(geometryProcessor))
-    , fColorEffects(SkRef(colorProcessors))
-    , fCoverageEffects(SkRef(coverageProcessors))
+    , fBuiltinUniformHandles(builder.getBuiltinUniformHandles())
+    , fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor()))
+    , fColorEffects(SkRef(builder.getColorEffects()))
+    , fCoverageEffects(SkRef(builder.getCoverageEffects()))
+    , fProgramID(builder.getProgramID())
+    , fHasVertexShader(builder.hasVertexShader())
+    , fTexCoordSetCnt(builder.getTexCoordSetCount())
     , fDesc(desc)
     , fGpu(gpu)
-    , fProgramDataManager(gpu, uniforms) {
+    , fProgramDataManager(gpu, this, builder) {
     this->initSamplerUniforms();
 }
 
@@ -94,42 +83,12 @@ void GrGLProgram::initSamplerUniforms() {
         fDstCopyTexUnit = texUnitIdx++;
     }
     if (fGeometryProcessor.get()) {
-        this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
-    }
-    this->initSamplers(fColorEffects.get(), &texUnitIdx);
-    this->initSamplers(fCoverageEffects.get(), &texUnitIdx);
-}
-
-void GrGLProgram::initSamplers(GrGLInstalledProcessors* ip, int* texUnitIdx) {
-    int numEffects = ip->fGLProcessors.count();
-    SkASSERT(numEffects == ip->fSamplers.count());
-    for (int e = 0; e < numEffects; ++e) {
-        SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[e];
-        int numSamplers = samplers.count();
-        for (int s = 0; s < numSamplers; ++s) {
-            SkASSERT(samplers[s].fUniform.isValid());
-            fProgramDataManager.setSampler(samplers[s].fUniform, *texUnitIdx);
-            samplers[s].fTextureUnit = (*texUnitIdx)++;
-        }
-    }
-}
-
-void GrGLProgram::bindTextures(const GrGLInstalledProcessors* ip,
-                               const GrProcessor& processor,
-                               int effectIdx) {
-    const SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[effectIdx];
-    int numSamplers = samplers.count();
-    SkASSERT(numSamplers == processor.numTextures());
-    for (int s = 0; s < numSamplers; ++s) {
-        SkASSERT(samplers[s].fTextureUnit >= 0);
-        const GrTextureAccess& textureAccess = processor.textureAccess(s);
-        fGpu->bindTexture(samplers[s].fTextureUnit,
-                          textureAccess.getParams(),
-                          static_cast<GrGLTexture*>(textureAccess.getTexture()));
+        fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx);
     }
+    fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx);
+    fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx);
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 
 void GrGLProgram::setData(const GrOptDrawState& optState,
@@ -167,39 +126,21 @@ void GrGLProgram::setData(const GrOptDrawState& optState,
         SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
     }
 
-    // we set the textures, and uniforms for installed processors in a generic way, but subclasses
-    // of GLProgram determine how to set coord transforms
     if (fGeometryProcessor.get()) {
         SkASSERT(geometryProcessor);
-        this->setData<GrGeometryStage>(&geometryProcessor, fGeometryProcessor.get());
+        fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor);
     }
-    this->setData<GrFragmentStage>(colorStages, fColorEffects.get());
-    this->setData<GrFragmentStage>(coverageStages, fCoverageEffects.get());
-
-    // Some of GrGLProgram subclasses need to update state here
-    this->didSetData(drawType);
-}
+    fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages);
+    fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages);
 
-void GrGLProgram::setTransformData(const GrProcessorStage& processor,
-                                   int effectIdx,
-                                   GrGLInstalledProcessors* ip) {
-    SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx];
-    int numTransforms = transforms.count();
-    SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
-    for (int t = 0; t < numTransforms; ++t) {
-        SkASSERT(transforms[t].fHandle.isValid());
-        const SkMatrix& matrix = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t);
-        if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
-            fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix);
-            transforms[t].fCurrentValue = matrix;
-        }
+    // PathTexGen state applies to the the fixed function vertex shader. For
+    // custom shaders, it's ignored, so we don't need to change the texgen
+    // settings in that case.
+    if (!fHasVertexShader) {
+        fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
     }
 }
 
-void GrGLProgram::didSetData(GrGpu::DrawType drawType) {
-    SkASSERT(!GrGpu::IsPathRenderingDrawType(drawType));
-}
-
 void GrGLProgram::setColor(const GrOptDrawState& optState,
                            GrColor color,
                            SharedGLState* sharedState) {
@@ -279,25 +220,22 @@ void GrGLProgram::setCoverage(const GrOptDrawState& optState,
 
 void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
                                                  const GrOptDrawState& optState) {
+    const GrRenderTarget* rt = optState.getRenderTarget();
+    SkISize size;
+    size.set(rt->width(), rt->height());
+
     // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
     if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
-        fMatrixState.fRenderTargetSize.fHeight != optState.getRenderTarget()->width()) {
+        fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
         fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
-                                   SkIntToScalar(optState.getRenderTarget()->height()));
+                                   SkIntToScalar(size.fHeight));
     }
 
-    // call subclasses to set the actual view matrix
-    this->onSetMatrixAndRenderTargetHeight(drawType, optState);
-}
-
-void GrGLProgram::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
-                                                   const GrOptDrawState& optState) {
-    const GrRenderTarget* rt = optState.getRenderTarget();
-    SkISize size;
-    size.set(rt->width(), rt->height());
-    if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
-        fMatrixState.fRenderTargetSize != size ||
-        !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
+    if (GrGpu::IsPathRenderingDrawType(drawType)) {
+        fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
+    } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
+               fMatrixState.fRenderTargetSize != size ||
+               !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
         SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
 
         fMatrixState.fViewMatrix = optState.getViewMatrix();
@@ -313,115 +251,3 @@ void GrGLProgram::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
         fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
     }
 }
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu,
-                                         const GrGLProgramDesc& desc,
-                                         const BuiltinUniformHandles& builtinUniforms,
-                                         GrGLuint programID,
-                                         const UniformInfoArray& uniforms,
-                                         GrGLInstalledProcessors* colorProcessors,
-                                         GrGLInstalledProcessors* coverageProcessors)
-    : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, colorProcessors,
-                coverageProcessors) {
-}
-
-void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
-                                                           const GrOptDrawState& optState) {
-    SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
-    const GrRenderTarget* rt = optState.getRenderTarget();
-    SkISize size;
-    size.set(rt->width(), rt->height());
-    fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu,
-                                 const GrGLProgramDesc& desc,
-                                 const BuiltinUniformHandles& builtinUniforms,
-                                 GrGLuint programID,
-                                 const UniformInfoArray& uniforms,
-                                 GrGLInstalledProcessors* colorProcessors,
-                                 GrGLInstalledProcessors* coverageProcessors,
-                                 const SeparableVaryingInfoArray& separableVaryings)
-    : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors,
-                coverageProcessors) {
-    int count = separableVaryings.count();
-    fVaryings.push_back_n(count);
-    for (int i = 0; i < count; i++) {
-        Varying& varying = fVaryings[i];
-        const SeparableVaryingInfo& builderVarying = separableVaryings[i];
-        SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
-        SkDEBUGCODE(
-            varying.fType = builderVarying.fVariable.getType();
-        );
-        varying.fLocation = builderVarying.fLocation;
-    }
-}
-
-void GrGLNvprProgram::didSetData(GrGpu::DrawType drawType) {
-    SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
-}
-
-void GrGLNvprProgram::setTransformData(const GrProcessorStage& processor,
-                                       int effectIdx,
-                                       GrGLInstalledProcessors* ip) {
-    SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx];
-    int numTransforms = transforms.count();
-    SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
-    for (int t = 0; t < numTransforms; ++t) {
-        SkASSERT(transforms[t].fHandle.isValid());
-        const SkMatrix& transform = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t);
-        if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
-            continue;
-        }
-        transforms[t].fCurrentValue = transform;
-        const Varying& fragmentInput = fVaryings[transforms[t].fHandle.handle()];
-        SkASSERT(transforms[t].fType == kVec2f_GrSLType || transforms[t].fType == kVec3f_GrSLType);
-        unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
-        fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID,
-                                                                      fragmentInput.fLocation,
-                                                                      GR_GL_OBJECT_LINEAR,
-                                                                      components,
-                                                                      transform);
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////
-
-GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu,
-                                 const GrGLProgramDesc& desc,
-                                 const BuiltinUniformHandles& builtinUniforms,
-                                 GrGLuint programID,
-                                 const UniformInfoArray& uniforms,
-                                 GrGLInstalledProcessors* colorProcessors,
-                                 GrGLInstalledProcessors* coverageProcessors,
-                                 int texCoordSetCnt)
-    : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors,
-                coverageProcessors)
-    , fTexCoordSetCnt(texCoordSetCnt) {
-}
-
-void GrGLLegacyNvprProgram::didSetData(GrGpu::DrawType drawType) {
-    SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
-    fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
-}
-
-void GrGLLegacyNvprProgram::setTransformData(const GrProcessorStage& processorStage,
-                                       int effectIdx,
-                                       GrGLInstalledProcessors* ip) {
-    // We've hidden the texcoord index in the first entry of the transforms array for each effect
-    int texCoordIndex = ip->fTransforms[effectIdx][0].fHandle.handle();
-    int numTransforms = processorStage.getProcessor()->numTransforms();
-    for (int t = 0; t < numTransforms; ++t) {
-        const SkMatrix& transform = get_transform_matrix(processorStage, false, t);
-        GrGLPathRendering::PathTexGenComponents components =
-                GrGLPathRendering::kST_PathTexGenComponents;
-        if (processorStage.isPerspectiveCoordTransform(t, false)) {
-            components = GrGLPathRendering::kSTR_PathTexGenComponents;
-        }
-        fGpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
-    }
-}
index fc441e5d76f9fe3e123fc5dad53ae078e4ffc9db..21593e351f2528523fec8bb2919dfa317bd789b8 100644 (file)
@@ -10,7 +10,6 @@
 #define GrGLProgram_DEFINED
 
 #include "builders/GrGLProgramBuilder.h"
-#include "builders/GrGLNvprProgramBuilder.h"
 #include "GrDrawState.h"
 #include "GrGLContext.h"
 #include "GrGLProgramDesc.h"
@@ -22,7 +21,7 @@
 #include "SkXfermode.h"
 
 class GrGLProcessor;
-class GrGLInstalledProcessors;
+class GrGLProgramEffects;
 class GrGLProgramBuilder;
 
 /**
@@ -40,6 +39,13 @@ public:
 
     typedef GrGLProgramBuilder::BuiltinUniformHandles BuiltinUniformHandles;
 
+    static GrGLProgram* Create(GrGpuGL* gpu,
+                               const GrOptDrawState& optState,
+                               const GrGLProgramDesc& desc,
+                               const GrGeometryStage* geometryProcessor,
+                               const GrFragmentStage* colorStages[],
+                               const GrFragmentStage* coverageStages[]);
+
     virtual ~GrGLProgram();
 
     /**
@@ -54,10 +60,7 @@ public:
      */
     GrGLuint programID() const { return fProgramID; }
 
-    /*
-     * The base class always has a vertex shader, only the NVPR variants may omit a vertex shader
-     */
-    virtual bool hasVertexShader() const { return true; }
+    bool hasVertexShader() const { return fHasVertexShader; }
 
     /**
      * Some GL state that is relevant to programs is not stored per-program. In particular color
@@ -158,22 +161,15 @@ public:
                  const GrDeviceCoordTexture* dstCopy, // can be NULL
                  SharedGLState*);
 
-protected:
+private:
     typedef GrGLProgramDataManager::UniformHandle UniformHandle;
-    typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
 
     GrGLProgram(GrGpuGL*,
                 const GrGLProgramDesc&,
-                const BuiltinUniformHandles&,
-                GrGLuint programID,
-                const UniformInfoArray&,
-                GrGLInstalledProcessors* geometryProcessor,
-                GrGLInstalledProcessors* colorProcessors,
-                GrGLInstalledProcessors* coverageProcessors);
+                const GrGLProgramBuilder&);
 
     // Sets the texture units for samplers.
     void initSamplerUniforms();
-    void initSamplers(GrGLInstalledProcessors* processors, int* texUnitIdx);
 
     // Helper for setData(). Makes GL calls to specify the initial color when there is not
     // per-vertex colors.
@@ -183,134 +179,29 @@ protected:
     // per-vertex coverages.
     void setCoverage(const GrOptDrawState&, GrColor coverage, SharedGLState*);
 
-    // A templated helper to loop over effects, set the transforms(via subclass) and bind textures
-    template <class ProcessorStage>
-    void setData(const ProcessorStage* effectStages[],
-                 GrGLInstalledProcessors* installedProcessors) {
-        int numEffects = installedProcessors->fGLProcessors.count();
-        SkASSERT(numEffects == installedProcessors->fTransforms.count());
-        SkASSERT(numEffects == installedProcessors->fSamplers.count());
-        for (int e = 0; e < numEffects; ++e) {
-            const GrProcessor& effect = *effectStages[e]->getProcessor();
-            installedProcessors->fGLProcessors[e]->setData(fProgramDataManager, effect);
-            this->setTransformData(*effectStages[e], e, installedProcessors);
-            this->bindTextures(installedProcessors, effect, e);
-        }
-    }
-    virtual void setTransformData(const GrProcessorStage& effectStage,
-                                  int effectIdx,
-                                  GrGLInstalledProcessors* pe);
-    void bindTextures(const GrGLInstalledProcessors*, const GrProcessor&, int effectIdx);
-
-    /*
-     * Legacy NVPR needs a hook here to flush path tex gen settings.
-     * TODO when legacy nvpr is removed, remove this call.
-     */
-    virtual void didSetData(GrGpu::DrawType);
-
     // Helper for setData() that sets the view matrix and loads the render target height uniform
-    void setMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
-    virtual void onSetMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
+    void setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrOptDrawState&);
 
     // these reflect the current values of uniforms (GL uniform values travel with program)
-    MatrixState fMatrixState;
-    GrColor fColor;
-    GrColor fCoverage;
-    int fDstCopyTexUnit;
-    BuiltinUniformHandles fBuiltinUniformHandles;
-    GrGLuint fProgramID;
+    MatrixState                         fMatrixState;
+    GrColor                             fColor;
+    GrColor                             fCoverage;
+    int                                 fDstCopyTexUnit;
 
-    // the installed effects
-    SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
-    SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
-    SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
+    BuiltinUniformHandles               fBuiltinUniformHandles;
+    SkAutoTUnref<GrGLProgramEffects>    fGeometryProcessor;
+    SkAutoTUnref<GrGLProgramEffects>    fColorEffects;
+    SkAutoTUnref<GrGLProgramEffects>    fCoverageEffects;
+    GrGLuint                            fProgramID;
+    bool                                fHasVertexShader;
+    int                                 fTexCoordSetCnt;
 
-    GrGLProgramDesc fDesc;
-    GrGpuGL* fGpu;
-    GrGLProgramDataManager fProgramDataManager;
+    GrGLProgramDesc                     fDesc;
+    GrGpuGL*                            fGpu;
 
-    friend class GrGLProgramBuilder;
+    GrGLProgramDataManager              fProgramDataManager;
 
     typedef SkRefCnt INHERITED;
 };
 
-/*
- * Below are slight specializations of the program object for the different types of programs
- * The default GrGL programs consist of at the very least a vertex and fragment shader.
- * Legacy Nvpr only has a fragment shader, 1.3+ Nvpr ignores the vertex shader, but both require
- * specialized methods for setting transform data. Both types of NVPR also require setting the
- * projection matrix through a special function call
- */
-class GrGLNvprProgramBase : public GrGLProgram {
-protected:
-    GrGLNvprProgramBase(GrGpuGL*,
-                        const GrGLProgramDesc&,
-                        const BuiltinUniformHandles&,
-                        GrGLuint programID,
-                        const UniformInfoArray&,
-                        GrGLInstalledProcessors* colorProcessors,
-                        GrGLInstalledProcessors* coverageProcessors);
-    virtual void onSetMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
-
-    typedef GrGLProgram INHERITED;
-};
-
-class GrGLNvprProgram : public GrGLNvprProgramBase {
-public:
-      virtual bool hasVertexShader() const SK_OVERRIDE { return true; }
-
-private:
-    typedef GrGLNvprProgramBuilder::SeparableVaryingInfo SeparableVaryingInfo;
-    typedef GrGLNvprProgramBuilder::SeparableVaryingInfoArray SeparableVaryingInfoArray;
-    GrGLNvprProgram(GrGpuGL*,
-                    const GrGLProgramDesc&,
-                    const BuiltinUniformHandles&,
-                    GrGLuint programID,
-                    const UniformInfoArray&,
-                    GrGLInstalledProcessors* colorProcessors,
-                    GrGLInstalledProcessors* coverageProcessors,
-                    const SeparableVaryingInfoArray& separableVaryings);
-    virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
-    virtual void setTransformData(const GrProcessorStage&,
-                                  int effectIdx,
-                                  GrGLInstalledProcessors*) SK_OVERRIDE;
-
-    struct Varying {
-        GrGLint     fLocation;
-        SkDEBUGCODE(
-            GrSLType    fType;
-        );
-    };
-    SkTArray<Varying, true> fVaryings;
-
-    friend class GrGLNvprProgramBuilder;
-
-    typedef GrGLNvprProgramBase INHERITED;
-};
-
-class GrGLLegacyNvprProgram : public GrGLNvprProgramBase {
-public:
-    virtual bool hasVertexShader() const SK_OVERRIDE { return false; }
-
-private:
-    GrGLLegacyNvprProgram(GrGpuGL* gpu,
-                          const GrGLProgramDesc& desc,
-                          const BuiltinUniformHandles&,
-                          GrGLuint programID,
-                          const UniformInfoArray&,
-                          GrGLInstalledProcessors* colorProcessors,
-                          GrGLInstalledProcessors* coverageProcessors,
-                          int texCoordSetCnt);
-    virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
-    virtual void setTransformData(const GrProcessorStage&,
-                                  int effectIdx,
-                                  GrGLInstalledProcessors*) SK_OVERRIDE;
-
-    int fTexCoordSetCnt;
-
-    friend class GrGLLegacyNvprProgramBuilder;
-
-    typedef GrGLNvprProgramBase INHERITED;
-};
-
 #endif
index f8d996b542e0cd8c11f33dd27bebb5fc73f67a4e..c53abd79abe3a3774129c8aff17b75201e556a19 100644 (file)
@@ -5,7 +5,9 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "gl/GrGLPathRendering.h"
+#include "gl/GrGLProgram.h"
 #include "gl/GrGLUniformHandle.h"
 #include "gl/GrGpuGL.h"
 #include "SkMatrix.h"
          SkASSERT(arrayCount <= uni.fArrayCount || \
                   (1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount))
 
-GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, const UniformInfoArray& uniforms)
-    : fGpu(gpu) {
-    int count = uniforms.count();
+GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu,
+                                               GrGLProgram* program,
+                                               const GrGLProgramBuilder& builder)
+    : fGpu(gpu),
+      fProgram(program) {
+    int count = builder.getUniformInfos().count();
     fUniforms.push_back_n(count);
     for (int i = 0; i < count; i++) {
         Uniform& uniform = fUniforms[i];
-        const UniformInfo& builderUniform = uniforms[i];
+        const GrGLProgramBuilder::UniformInfo& builderUniform = builder.getUniformInfos()[i];
         SkASSERT(GrGLShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() ||
                  builderUniform.fVariable.getArrayCount() > 0);
         SkDEBUGCODE(
@@ -33,13 +38,26 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, const UniformInfoAr
             uniform.fVSLocation = builderUniform.fLocation;
         } else {
             uniform.fVSLocation = kUnusedUniform;
-        }
+            }
         if (GrGLProgramBuilder::kFragment_Visibility & builderUniform.fVisibility) {
             uniform.fFSLocation = builderUniform.fLocation;
         } else {
             uniform.fFSLocation = kUnusedUniform;
         }
     }
+
+    count = builder.getSeparableVaryingInfos().count();
+    fVaryings.push_back_n(count);
+    for (int i = 0; i < count; i++) {
+        Varying& varying = fVaryings[i];
+        const GrGLProgramBuilder::SeparableVaryingInfo& builderVarying =
+            builder.getSeparableVaryingInfos()[i];
+        SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
+        SkDEBUGCODE(
+            varying.fType = builderVarying.fVariable.getType();
+        );
+        varying.fLocation = builderVarying.fLocation;
+    }
 }
 
 void GrGLProgramDataManager::setSampler(UniformHandle u, GrGLint texUnit) const {
@@ -258,3 +276,14 @@ void GrGLProgramDataManager::setSkMatrix(UniformHandle u, const SkMatrix& matrix
     };
     this->setMatrix3f(u, mt);
 }
+
+void GrGLProgramDataManager::setProgramPathFragmentInputTransform(VaryingHandle i,
+                                                                  unsigned components,
+                                                                  const SkMatrix& matrix) const {
+    const Varying& fragmentInput = fVaryings[i.toProgramDataIndex()];
+    fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgram->programID(),
+                                                                  fragmentInput.fLocation,
+                                                                  GR_GL_OBJECT_LINEAR,
+                                                                  components,
+                                                                  matrix);
+}
index bbf7d42e89b5d12f0e18c9542487890d7c394b00..8a98a75caea0eff1a62d52cbc214f16497dd62ac 100644 (file)
@@ -56,18 +56,22 @@ public:
         friend class GrGLProgramBuilder; // For accessing toShaderBuilderIndex().
     };
 
-    struct UniformInfo {
-        GrGLShaderVar fVariable;
-        uint32_t      fVisibility;
-        GrGLint       fLocation;
+    class VaryingHandle : public ShaderResourceHandle {
+    public:
+        /** Creates a reference to a varying in separable varyings of a GrGLShaderBuilder.
+         * The ref can be used to set the varying with the corresponding GrGLProgramDataManager.*/
+        static VaryingHandle CreateFromSeparableVaryingIndex(int i) {
+            return VaryingHandle(i);
+        }
+        VaryingHandle() { }
+        bool operator==(const VaryingHandle& other) const { return other.fValue == fValue; }
+    private:
+        VaryingHandle(int value) : ShaderResourceHandle(value) { }
+        int toProgramDataIndex() const { SkASSERT(isValid()); return fValue; }
+        friend class GrGLProgramDataManager; // For accessing toProgramDataIndex().
     };
 
-    // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
-    // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
-    // name strings. Otherwise, we'd have to hand out copies.
-    typedef GrTAllocator<UniformInfo> UniformInfoArray;
-
-    GrGLProgramDataManager(GrGpuGL*, const UniformInfoArray&);
+    GrGLProgramDataManager(GrGpuGL*, GrGLProgram*, const GrGLProgramBuilder&);
 
     /** Functions for uploading uniform values. The varities ending in v can be used to upload to an
      *  array of uniforms. arrayCount must be <= the array count of the uniform.
@@ -91,6 +95,10 @@ public:
     // convenience method for uploading a SkMatrix to a 3x3 matrix uniform
     void setSkMatrix(UniformHandle, const SkMatrix&) const;
 
+    void setProgramPathFragmentInputTransform(VaryingHandle i,
+                                              unsigned components,
+                                              const SkMatrix& matrix) const;
+
 private:
     enum {
         kUnusedUniform = -1,
@@ -104,10 +112,19 @@ private:
             int         fArrayCount;
         );
     };
+    struct Varying {
+        GrGLint     fLocation;
+        SkDEBUGCODE(
+            GrSLType    fType;
+        );
+    };
 
     SkTArray<Uniform, true> fUniforms;
+    SkTArray<Varying, true> fVaryings;
     GrGpuGL* fGpu;
+    GrGLProgram* fProgram;
 
     typedef SkRefCnt INHERITED;
 };
+
 #endif
index ec095271828c763f3df8bdcb640a6b992cdd835d..19a26c9b08c887f69438174a9da8a88684613833 100644 (file)
@@ -5,7 +5,7 @@
  * found in the LICENSE file.
  */
 
-#include "gl/builders/GrGLFragmentShaderBuilder.h"
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrGLProgramDesc.h"
 #include "GrBackendProcessorFactory.h"
 #include "GrProcessor.h"
@@ -178,7 +178,7 @@ bool GrGLProgramDesc::GetGeometryProcessorKey(const GrGeometryStage& stage,
     if (NULL == key) {
         return false;
     }
-    uint32_t attribKey = gen_attrib_key(stage.getProcessor());
+    uint32_t attribKey = gen_attrib_key(stage.getGeometryProcessor());
 
     // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
     // don't fit.
@@ -348,16 +348,15 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
             dstCopyTexture = dstCopy->texture();
         }
         header->fDstReadKey = GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture,
-                                                                       gpu->glCaps());
+                gpu->glCaps());
         SkASSERT(0 != header->fDstReadKey);
     } else {
         header->fDstReadKey = 0;
     }
 
     if (optState.readsFragPosition()) {
-        header->fFragPosKey =
-                GrGLFragmentShaderBuilder::KeyForFragmentPosition(optState.getRenderTarget(),
-                                                                  gpu->glCaps());
+        header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(
+                optState.getRenderTarget(), gpu->glCaps());
     } else {
         header->fFragPosKey = 0;
     }
index faa59f329fc4e6722fcc8dd58ec9df4badfb71e2..97f00f44b8886c165b7ea5fd85df58ccafc4f7d8 100644 (file)
@@ -247,10 +247,11 @@ private:
     // visible to GrGLProcessors. Then make public accessors as necessary and remove friends.
     friend class GrGLProgram;
     friend class GrGLProgramBuilder;
-    friend class GrGLLegacyNvprProgramBuilder;
-    friend class GrGLVertexBuilder;
+    friend class GrGLFullProgramBuilder;
+    friend class GrGLFragmentOnlyProgramBuilder;
+    friend class GrGLVertexShaderBuilder;
     friend class GrGLFragmentShaderBuilder;
-    friend class GrGLGeometryBuilder;
+    friend class GrGLGeometryShaderBuilder;
 };
 
 #endif
diff --git a/src/gpu/gl/GrGLProgramEffects.cpp b/src/gpu/gl/GrGLProgramEffects.cpp
new file mode 100644 (file)
index 0000000..6ab8654
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLProgramEffects.h"
+#include "gl/GrGLProcessor.h"
+#include "gl/GrGLPathRendering.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
+#include "gl/builders/GrGLFragmentOnlyProgramBuilder.h"
+#include "gl/GrGLGeometryProcessor.h"
+#include "gl/GrGpuGL.h"
+
+typedef GrGLProcessor::TransformedCoords TransformedCoords;
+typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
+typedef GrGLProcessor::TextureSampler TextureSampler;
+typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
+
+namespace {
+/**
+ * Retrieves the final matrix that a transform needs to apply to its source coords.
+ */
+SkMatrix get_transform_matrix(const GrProcessorStage& effectStage,
+                              bool useExplicitLocalCoords,
+                              int transformIdx) {
+    const GrCoordTransform& coordTransform = effectStage.getProcessor()->coordTransform(transformIdx);
+    SkMatrix combined;
+
+    if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
+        // If we have explicit local coords then we shouldn't need a coord change.
+        const SkMatrix& ccm =
+                useExplicitLocalCoords ? SkMatrix::I() : effectStage.getCoordChangeMatrix();
+        combined.setConcat(coordTransform.getMatrix(), ccm);
+    } else {
+        combined = coordTransform.getMatrix();
+    }
+    if (coordTransform.reverseY()) {
+        // combined.postScale(1,-1);
+        // combined.postTranslate(0,1);
+        combined.set(SkMatrix::kMSkewY,
+            combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
+        combined.set(SkMatrix::kMScaleY,
+            combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
+        combined.set(SkMatrix::kMTransY,
+            combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
+    }
+    return combined;
+}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+GrGLProgramEffects::~GrGLProgramEffects() {
+    int numEffects = fGLProcessors.count();
+    for (int e = 0; e < numEffects; ++e) {
+        SkDELETE(fGLProcessors[e]);
+    }
+}
+
+void GrGLProgramEffects::initSamplers(const GrGLProgramDataManager& programResourceManager, int* texUnitIdx) {
+    int numEffects = fGLProcessors.count();
+    SkASSERT(numEffects == fSamplers.count());
+    for (int e = 0; e < numEffects; ++e) {
+        SkTArray<Sampler, true>& samplers = fSamplers[e];
+        int numSamplers = samplers.count();
+        for (int s = 0; s < numSamplers; ++s) {
+            SkASSERT(samplers[s].fUniform.isValid());
+            programResourceManager.setSampler(samplers[s].fUniform, *texUnitIdx);
+            samplers[s].fTextureUnit = (*texUnitIdx)++;
+        }
+    }
+}
+
+void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrProcessor& effect, int effectIdx) {
+    const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
+    int numSamplers = samplers.count();
+    SkASSERT(numSamplers == effect.numTextures());
+    for (int s = 0; s < numSamplers; ++s) {
+        SkASSERT(samplers[s].fTextureUnit >= 0);
+        const GrTextureAccess& textureAccess = effect.textureAccess(s);
+        gpu->bindTexture(samplers[s].fTextureUnit,
+                         textureAccess.getParams(),
+                         static_cast<GrGLTexture*>(textureAccess.getTexture()));
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
+                                       GrGpu::DrawType drawType,
+                                       const GrGLProgramDataManager& programDataManager,
+                                       const GrGeometryStage* effectStages) {
+    SkASSERT(1 == fGLProcessors.count());
+    SkASSERT(1 == fTransforms.count());
+    SkASSERT(1 == fSamplers.count());
+    this->setDataInternal(gpu, drawType, programDataManager, *effectStages, 0);
+}
+
+void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
+                                       GrGpu::DrawType drawType,
+                                       const GrGLProgramDataManager& programDataManager,
+                                       const GrFragmentStage* effectStages[]) {
+    int numEffects = fGLProcessors.count();
+    SkASSERT(numEffects == fTransforms.count());
+    SkASSERT(numEffects == fSamplers.count());
+    for (int e = 0; e < numEffects; ++e) {
+        this->setDataInternal(gpu, drawType, programDataManager, *effectStages[e], e);
+    }
+}
+
+void GrGLVertexProgramEffects::setDataInternal(GrGpuGL* gpu,
+                                               GrGpu::DrawType drawType,
+                                               const GrGLProgramDataManager& programDataManager,
+                                               const GrProcessorStage& effectStage,
+                                               int index) {
+    const GrProcessor& effect = *effectStage.getProcessor();
+    fGLProcessors[index]->setData(programDataManager, effect);
+    if (GrGpu::IsPathRenderingDrawType(drawType)) {
+        this->setPathTransformData(gpu, programDataManager, effectStage, index);
+    } else {
+        this->setTransformData(gpu, programDataManager, effectStage, index);
+    }
+    this->bindTextures(gpu, effect, index);
+}
+
+void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
+                                                const GrGLProgramDataManager& pdman,
+                                                const GrProcessorStage& effectStage,
+                                                int effectIdx) {
+    SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
+    int numTransforms = transforms.count();
+    SkASSERT(numTransforms == effectStage.getProcessor()->numTransforms());
+    for (int t = 0; t < numTransforms; ++t) {
+        SkASSERT(transforms[t].fHandle.isValid());
+        const SkMatrix& matrix = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
+        if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
+            pdman.setSkMatrix(transforms[t].fHandle, matrix);
+            transforms[t].fCurrentValue = matrix;
+        }
+    }
+}
+
+void GrGLVertexProgramEffects::setPathTransformData(GrGpuGL* gpu,
+                                                    const GrGLProgramDataManager& pdman,
+                                                    const GrProcessorStage& effectStage,
+                                                    int effectIdx) {
+    SkTArray<PathTransform, true>& transforms = fPathTransforms[effectIdx];
+    int numTransforms = transforms.count();
+    SkASSERT(numTransforms == effectStage.getProcessor()->numTransforms());
+    for (int t = 0; t < numTransforms; ++t) {
+        SkASSERT(transforms[t].fHandle.isValid());
+        const SkMatrix& transform = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
+        if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
+            continue;
+        }
+        transforms[t].fCurrentValue = transform;
+        switch (transforms[t].fType) {
+            case kVec2f_GrSLType:
+                pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 2, transform);
+                break;
+            case kVec3f_GrSLType:
+                pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 3, transform);
+                break;
+            default:
+                SkFAIL("Unexpected matrix type.");
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
+                                           GrGpu::DrawType,
+                                           const GrGLProgramDataManager& pdman,
+                                           const GrFragmentStage* effectStages[]) {
+    int numEffects = fGLProcessors.count();
+    SkASSERT(numEffects == fTransforms.count());
+    SkASSERT(numEffects == fSamplers.count());
+    for (int e = 0; e < numEffects; ++e) {
+        const GrProcessorStage& effectStage = *effectStages[e];
+        const GrProcessor& effect = *effectStage.getProcessor();
+        fGLProcessors[e]->setData(pdman, effect);
+        this->setPathTexGenState(gpu, effectStage, e);
+        this->bindTextures(gpu, effect, e);
+    }
+}
+
+void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
+                                              const GrProcessorStage& effectStage,
+                                              int effectIdx) {
+    int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
+    int numTransforms = effectStage.getProcessor()->numTransforms();
+    for (int t = 0; t < numTransforms; ++t) {
+        const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
+        GrGLPathRendering::PathTexGenComponents components =
+                GrGLPathRendering::kST_PathTexGenComponents;
+        if (effectStage.isPerspectiveCoordTransform(t, false)) {
+            components = GrGLPathRendering::kSTR_PathTexGenComponents;
+        }
+        gpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
+    }
+}
diff --git a/src/gpu/gl/GrGLProgramEffects.h b/src/gpu/gl/GrGLProgramEffects.h
new file mode 100644 (file)
index 0000000..6140cde
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLProgramEffects_DEFINED
+#define GrGLProgramEffects_DEFINED
+
+#include "GrBackendProcessorFactory.h"
+#include "GrGLProgramDataManager.h"
+#include "GrGpu.h"
+#include "GrTexture.h"
+#include "GrTextureAccess.h"
+
+class GrProcessor;
+class GrProcessorStage;
+class GrGLVertexProgramEffectsBuilder;
+class GrGLProgramBuilder;
+class GrGLFullProgramBuilder;
+class GrGLFragmentOnlyProgramBuilder;
+
+/**
+ * This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
+ * and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL
+ * state and shader uniforms.
+ */
+class GrGLProgramEffects : public SkRefCnt {
+public:
+    typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+    typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
+    virtual ~GrGLProgramEffects();
+
+    /**
+     * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next
+     * available unit to *texUnitIdx when it returns.
+     */
+    void initSamplers(const GrGLProgramDataManager&, int* texUnitIdx);
+
+    /**
+     * Calls setData() on each effect, and sets their transformation matrices and texture bindings.
+     */
+    virtual void setData(GrGpuGL*,
+                         GrGpu::DrawType,
+                         const GrGLProgramDataManager&,
+                         const GrGeometryStage* effectStages) {
+        SkFAIL("For geometry processor only");
+    }
+
+    virtual void setData(GrGpuGL*,
+                         GrGpu::DrawType,
+                         const GrGLProgramDataManager&,
+                         const GrFragmentStage* effectStages[]) = 0;
+
+protected:
+    GrGLProgramEffects(int reserveCount)
+        : fGLProcessors(reserveCount)
+        , fSamplers(reserveCount) {
+    }
+
+    /**
+     * Helper for setData(). Binds all the textures for an effect.
+     */
+    void bindTextures(GrGpuGL*, const GrProcessor&, int effectIdx);
+
+    struct Sampler {
+        SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
+        UniformHandle fUniform;
+        int           fTextureUnit;
+    };
+
+    /*
+     * Helpers for shader builders to build up program effects objects alongside shader code
+     */
+    void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
+    SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
+
+    SkTArray<GrGLProcessor*>               fGLProcessors;
+    SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
+
+private:
+    friend class GrGLProgramBuilder;
+    friend class GrGLFullProgramBuilder;
+    friend class GrGLFragmentOnlyShaderBuilder;
+
+    typedef SkRefCnt INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
+ */
+class GrGLVertexProgramEffects : public GrGLProgramEffects {
+public:
+    virtual void setData(GrGpuGL*,
+                         GrGpu::DrawType,
+                         const GrGLProgramDataManager&,
+                         const GrGeometryStage* effectStages) SK_OVERRIDE;
+
+    virtual void setData(GrGpuGL*,
+                         GrGpu::DrawType,
+                         const GrGLProgramDataManager&,
+                         const GrFragmentStage* effectStages[]) SK_OVERRIDE;
+
+private:
+    GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
+        : INHERITED(reserveCount)
+        , fTransforms(reserveCount)
+        , fHasExplicitLocalCoords(explicitLocalCoords) {
+    }
+
+    struct Transform {
+        Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
+        UniformHandle fHandle;
+        SkMatrix      fCurrentValue;
+    };
+
+    struct PathTransform {
+        PathTransform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
+        VaryingHandle fHandle;
+        SkMatrix fCurrentValue;
+        GrSLType fType;
+    };
+
+    /*
+     * These functions are used by the builders to build up program effects along side the shader
+     * code itself
+     */
+    SkSTArray<2, Transform, true>& addTransforms() { return fTransforms.push_back(); }
+    SkTArray<PathTransform, true>& addPathTransforms() { return fPathTransforms.push_back(); }
+
+    /**
+     * Helper for setData(). Sets all the transform matrices for an effect.
+     */
+    void setDataInternal(GrGpuGL* gpu,
+                         GrGpu::DrawType drawType,
+                         const GrGLProgramDataManager& programDataManager,
+                         const GrProcessorStage& effectStage,
+                         int index);
+    void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrProcessorStage&,
+                          int effectIdx);
+    void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&,
+                              const GrProcessorStage&, int effectIdx);
+
+
+    SkTArray<SkSTArray<2, Transform, true> > fTransforms;
+    SkTArray<SkTArray<PathTransform, true> > fPathTransforms;
+    bool                                     fHasExplicitLocalCoords;
+
+    friend class GrGLFullProgramBuilder;
+
+    typedef GrGLProgramEffects INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * This is a GrGLProgramEffects implementation that does coord transforms with
+ * the the  NV_path_rendering PathTexGen functionality.
+ */
+class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
+public:
+    virtual void setData(GrGpuGL*,
+                         GrGpu::DrawType,
+                         const GrGLProgramDataManager&,
+                         const GrFragmentStage* effectStages[]) SK_OVERRIDE;
+
+private:
+    GrGLPathTexGenProgramEffects(int reserveCount)
+        : INHERITED(reserveCount)
+        , fTransforms(reserveCount) {
+    }
+
+    /**
+     * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
+     */
+    void setPathTexGenState(GrGpuGL*, const GrProcessorStage&, int effectIdx);
+
+    struct Transforms {
+        Transforms(int texCoordIndex)
+            : fTexCoordIndex(texCoordIndex) {}
+        int fTexCoordIndex;
+    };
+
+    /*
+     * Helper for fragment only shader builder to build up the program effects alongside the shader
+     */
+    void addTransforms(int coordIndex) {
+        fTransforms.push_back(Transforms(coordIndex));
+    }
+
+    SkTArray<Transforms> fTransforms;
+
+    friend class GrGLFragmentOnlyProgramBuilder;
+
+    typedef GrGLProgramEffects INHERITED;
+};
+
+#endif
index 056f0935eca6a1db4d235827ab076ea391ec8c7d..7ace6788d17a4af0a3fa42060f28ba817d1f7951 100644 (file)
@@ -179,9 +179,8 @@ private:
         ~ProgramCache();
 
         void abandon();
-        GrGLProgram* getProgram(const GrOptDrawState&,
-                                const GrGLProgramDesc&,
-                                DrawType,
+        GrGLProgram* getProgram(const GrOptDrawState& optState,
+                                const GrGLProgramDesc& desc,
                                 const GrGeometryStage* geometryProcessor,
                                 const GrFragmentStage* colorStages[],
                                 const GrFragmentStage* coverageStages[]);
index 891b49a1f87f7c5f3577e49423599f99c66a5741..4529a1c22e151bf0a2f3f82b1ff19b4580300e7d 100644 (file)
@@ -7,7 +7,6 @@
 
 #include "GrGpuGL.h"
 
-#include "builders/GrGLProgramBuilder.h"
 #include "GrProcessor.h"
 #include "GrGLProcessor.h"
 #include "GrGLPathRendering.h"
@@ -93,7 +92,6 @@ int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
 
 GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
                                                const GrGLProgramDesc& desc,
-                                               DrawType type,
                                                const GrGeometryStage* geometryProcessor,
                                                const GrFragmentStage* colorStages[],
                                                const GrFragmentStage* coverageStages[]) {
@@ -131,9 +129,8 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
 #ifdef PROGRAM_CACHE_STATS
         ++fCacheMisses;
 #endif
-        GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, desc, type,
-                                                                 geometryProcessor, colorStages,
-                                                                 coverageStages, fGpu);
+        GrGLProgram* program = GrGLProgram::Create(fGpu, optState, desc, geometryProcessor,
+                                                   colorStages, coverageStages);
         if (NULL == program) {
             return NULL;
         }
@@ -257,7 +254,6 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
 
         fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(),
                                                         desc,
-                                                        type,
                                                         geometryProcessor,
                                                         colorStages.begin(),
                                                         coverageStages.begin()));
diff --git a/src/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.cpp
new file mode 100644 (file)
index 0000000..d5bccd7
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLFragmentOnlyProgramBuilder.h"
+#include "../GrGpuGL.h"
+
+GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu,
+                                                               const GrOptDrawState& optState,
+                                                               const GrGLProgramDesc& desc)
+    : INHERITED(gpu, optState, desc) {
+    SkASSERT(desc.getHeader().fUseFragShaderOnly);
+    SkASSERT(gpu->glCaps().pathRenderingSupport());
+    SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
+    SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
+}
+
+int GrGLFragmentOnlyProgramBuilder::addTexCoordSets(int count) {
+    int firstFreeCoordSet = fTexCoordSetCnt;
+    fTexCoordSetCnt += count;
+    SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt);
+    return firstFreeCoordSet;
+}
+
+void
+GrGLFragmentOnlyProgramBuilder::createAndEmitEffects(const GrGeometryStage* geometryProcessor,
+                                                     const GrFragmentStage* colorStages[],
+                                                     const GrFragmentStage* coverageStages[],
+                                                     GrGLSLExpr4* inputColor,
+                                                     GrGLSLExpr4* inputCoverage) {
+    ///////////////////////////////////////////////////////////////////////////
+    // emit the per-effect code for both color and coverage effects
+
+    EffectKeyProvider colorKeyProvider(&this->desc(), EffectKeyProvider::kColor_EffectType);
+    fColorEffects.reset(this->onCreateAndEmitEffects(colorStages,
+                                                     this->desc().numColorEffects(),
+                                                     colorKeyProvider,
+                                                     inputColor));
+
+    EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCoverage_EffectType);
+    fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages,
+                                                        this->desc().numCoverageEffects(),
+                                                        coverageKeyProvider,
+                                                        inputCoverage));
+}
+
+GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::onCreateAndEmitEffects(
+        const GrFragmentStage* effectStages[], int effectCnt,
+        const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* inOutFSColor) {
+    fProgramEffects.reset(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (effectCnt)));
+    this->INHERITED::createAndEmitEffects(effectStages,
+                                          effectCnt,
+                                          keyProvider,
+                                          inOutFSColor);
+    return fProgramEffects.detach();
+}
+
+void GrGLFragmentOnlyProgramBuilder::emitEffect(const GrProcessorStage& stage,
+                                                const GrProcessorKey& key,
+                                                const char* outColor,
+                                                const char* inColor,
+                                                int stageIndex) {
+    SkASSERT(fProgramEffects.get());
+    const GrProcessor& effect = *stage.getProcessor();
+
+    SkSTArray<2, GrGLProcessor::TransformedCoords> coords(effect.numTransforms());
+    SkSTArray<4, GrGLProcessor::TextureSampler> samplers(effect.numTextures());
+
+    this->setupPathTexGen(stage, &coords);
+    this->emitSamplers(effect, &samplers);
+
+    SkASSERT(fEffectEmitter);
+    GrGLProcessor* glEffect = fEffectEmitter->createGLInstance();
+    fProgramEffects->addEffect(glEffect);
+
+    GrGLFragmentShaderBuilder* fsBuilder = this->getFragmentShaderBuilder();
+    // Enclose custom code in a block to avoid namespace conflicts
+    SkString openBrace;
+    openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
+    fsBuilder->codeAppend(openBrace.c_str());
+
+    fEffectEmitter->emit(key, outColor, inColor, coords, samplers);
+
+    fsBuilder->codeAppend("\t}\n");
+}
+
+void GrGLFragmentOnlyProgramBuilder::setupPathTexGen(
+        const GrProcessorStage& effectStage, GrGLProcessor::TransformedCoordsArray* outCoords) {
+    int numTransforms = effectStage.getProcessor()->numTransforms();
+    int texCoordIndex = this->addTexCoordSets(numTransforms);
+
+    fProgramEffects->addTransforms(texCoordIndex);
+
+    SkString name;
+    for (int t = 0; t < numTransforms; ++t) {
+        GrSLType type =
+                effectStage.isPerspectiveCoordTransform(t, false) ?
+                        kVec3f_GrSLType :
+                        kVec2f_GrSLType;
+
+        name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
+        SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, (name, type));
+    }
+}
diff --git a/src/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.h b/src/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.h
new file mode 100644 (file)
index 0000000..06c15fd
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLFragmentOnlyProgramBuilder_DEFINED
+#define GrGLFragmentOnlyProgramBuilder_DEFINED
+
+#include "GrGLProgramBuilder.h"
+
+class GrGLFragmentOnlyProgramBuilder : public GrGLProgramBuilder {
+public:
+    GrGLFragmentOnlyProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
+
+    int addTexCoordSets(int count);
+
+private:
+    virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
+                                      const GrFragmentStage* colorStages[],
+                                      const GrFragmentStage* coverageStages[],
+                                      GrGLSLExpr4* inputColor,
+                                      GrGLSLExpr4* inputCoverage) SK_OVERRIDE;
+
+    GrGLProgramEffects* onCreateAndEmitEffects(const GrFragmentStage* effectStages[],
+                                               int effectCnt,
+                                               const GrGLProgramDesc::EffectKeyProvider&,
+                                                   GrGLSLExpr4* inOutFSColor);
+
+    virtual void emitEffect(const GrProcessorStage& stage,
+                            const GrProcessorKey& key,
+                            const char* outColor,
+                            const char* inColor,
+                            int stageIndex) SK_OVERRIDE;
+
+    /**
+     * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
+     * effect. The transforms all use adjacent texture units. They either use two or three of the
+     * coordinates at a given texture unit, depending on if they need perspective interpolation.
+     * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
+     * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
+     * effect's emitCode() function.
+     */
+    void setupPathTexGen(const GrProcessorStage&, GrGLProcessor::TransformedCoordsArray*);
+
+    virtual GrGLProgramEffects* getProgramEffects() SK_OVERRIDE { return fProgramEffects.get(); }
+
+    typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
+
+    SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
+
+    typedef GrGLProgramBuilder INHERITED;
+};
+
+#endif
index 488d07b8dbd21f0de7c8d2db4e9bd7ff722668af..4266d9fc43ee1e32a5109636f8deb8cdee25d67c 100644 (file)
 #include "GrGLProgramBuilder.h"
 #include "../GrGpuGL.h"
 
-#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X)
-#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X)
-
+namespace {
+#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
+#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
 // ES2 FS only guarantees mediump and lowp support
 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
-const char* GrGLFragmentShaderBuilder::kDstCopyColorName = "_dstColor";
-static const char* declared_color_output_name() { return "fsColorOut"; }
-static const char* dual_source_output_name() { return "dualSourceOut"; }
-static void append_default_precision_qualifier(GrGLShaderVar::Precision p,
+static const char kDstCopyColorName[] = "_dstColor";
+inline const char* declared_color_output_name() { return "fsColorOut"; }
+inline const char* dual_source_output_name() { return "dualSourceOut"; }
+inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
                                                GrGLStandard standard,
                                                SkString* str) {
     // Desktop GLSL has added precision qualifiers but they don't do anything.
@@ -40,10 +40,10 @@ static void append_default_precision_qualifier(GrGLShaderVar::Precision p,
         }
     }
 }
+}
 
-GrGLFragmentShaderBuilder::DstReadKey
-GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
-                                                                 const GrGLCaps& caps) {
+GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead(
+        const GrTexture* dstCopy, const GrGLCaps& caps) {
     uint32_t key = kYesDstRead_DstReadKeyBit;
     if (caps.fbFetchSupport()) {
         return key;
@@ -60,9 +60,8 @@ GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
     return static_cast<DstReadKey>(key);
 }
 
-GrGLFragmentShaderBuilder::FragPosKey
-GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
-                                                                          const GrGLCaps&) {
+GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentPosition(
+        const GrRenderTarget* dst, const GrGLCaps&) {
     if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
         return kTopLeftFragPosRead_FragPosKey;
     } else {
@@ -76,9 +75,33 @@ GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program
     , fHasCustomColorOutput(false)
     , fHasSecondaryOutput(false)
     , fSetupFragPosition(false)
-    , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey)
-    , fHasReadDstColor(false)
-    , fHasReadFragmentPosition(false) {
+    , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey){
+}
+
+const char* GrGLFragmentShaderBuilder::dstColor() {
+    if (fProgramBuilder->fCodeStage.inStageCode()) {
+        const GrProcessor* effect = fProgramBuilder->fCodeStage.effectStage()->getProcessor();
+        // TODO GPs can't read dst color, and full program builder only returns a pointer to the
+        // base fragment shader builder which does not have this function.  Unfortunately,
+        // the code stage class only has a GrProcessor pointer so this is required for the time
+        // being
+        if (!static_cast<const GrFragmentProcessor*>(effect)->willReadDstColor()) {
+            SkDEBUGFAIL("GrGLProcessor asked for dst color but its generating GrProcessor "
+                        "did not request access.");
+            return "";
+        }
+    }
+
+    GrGpuGL* gpu = fProgramBuilder->gpu();
+    if (gpu->glCaps().fbFetchSupport()) {
+        this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
+                         gpu->glCaps().fbFetchExtensionString());
+        return gpu->glCaps().fbFetchColorName();
+    } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
+        return kDstCopyColorName;
+    } else {
+        return "";
+    }
 }
 
 bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
@@ -117,7 +140,15 @@ SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(
 }
 
 const char* GrGLFragmentShaderBuilder::fragmentPosition() {
-    fHasReadFragmentPosition = true;
+    GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage;
+    if (cs->inStageCode()) {
+        const GrProcessor* effect = cs->effectStage()->getProcessor();
+        if (!effect->willReadFragmentPosition()) {
+            SkDEBUGFAIL("GrGLProcessor asked for frag position but its generating GrProcessor "
+                        "did not request access.");
+            return "";
+        }
+    }
 
     GrGpuGL* gpu = fProgramBuilder->gpu();
     // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
@@ -144,15 +175,16 @@ const char* GrGLFragmentShaderBuilder::fragmentPosition() {
         static const char* kCoordName = "fragCoordYDown";
         if (!fSetupFragPosition) {
             // temporarily change the stage index because we're inserting non-stage code.
-            GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder);
+            GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL);
+
             SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
             const char* rtHeightName;
 
             fProgramBuilder->fUniformHandles.fRTHeightUni =
                     fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
-                                                kFloat_GrSLType,
-                                                "RTHeight",
-                                                &rtHeightName);
+                                         kFloat_GrSLType,
+                                         "RTHeight",
+                                         &rtHeightName);
 
             // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that
             // causes programs to fail to link. Making this function return a vec2() didn't fix the
@@ -166,133 +198,24 @@ const char* GrGLFragmentShaderBuilder::fragmentPosition() {
     }
 }
 
-const char* GrGLFragmentShaderBuilder::dstColor() {
-    fHasReadDstColor = true;
-
-    GrGpuGL* gpu = fProgramBuilder->gpu();
-    if (gpu->glCaps().fbFetchSupport()) {
-        this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
-                         gpu->glCaps().fbFetchExtensionString());
-        return gpu->glCaps().fbFetchColorName();
-    } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
-        return kDstCopyColorName;
-    } else {
-        return "";
-    }
-}
-
-void GrGLFragmentShaderBuilder::emitCodeToReadDstTexture() {
-    bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & fProgramBuilder->header().fDstReadKey);
-    const char* dstCopyTopLeftName;
-    const char* dstCopyCoordScaleName;
-    const char* dstCopySamplerName;
-    uint32_t configMask;
-    if (SkToBool(kUseAlphaConfig_DstReadKeyBit & fProgramBuilder->header().fDstReadKey)) {
-        configMask = kA_GrColorComponentFlag;
-    } else {
-        configMask = kRGBA_GrColorComponentFlags;
-    }
-    fProgramBuilder->fUniformHandles.fDstCopySamplerUni =
-            fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
-                                        kSampler2D_GrSLType,
-                                        "DstCopySampler",
-                                        &dstCopySamplerName);
-    fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni =
-            fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
-                                        kVec2f_GrSLType,
-                                        "DstCopyUpperLeft",
-                                        &dstCopyTopLeftName);
-    fProgramBuilder->fUniformHandles.fDstCopyScaleUni =
-            fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
-                                        kVec2f_GrSLType,
-                                        "DstCopyCoordScale",
-                                        &dstCopyCoordScaleName);
-    const char* fragPos = this->fragmentPosition();
-
-    this->codeAppend("// Read color from copy of the destination.\n");
-    this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
-                      fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
-    if (!topDown) {
-        this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
-    }
-    this->codeAppendf("vec4 %s = ", GrGLFragmentShaderBuilder::kDstCopyColorName);
-    this->appendTextureLookup(dstCopySamplerName,
-                              "_dstTexCoord",
-                              configMask,
-                              "rgba");
-    this->codeAppend(";");
-}
-
-void GrGLFragmentShaderBuilder::enableCustomOutput() {
-    SkASSERT(!fHasCustomColorOutput);
-    fHasCustomColorOutput = true;
-    fOutputs.push_back().set(kVec4f_GrSLType,
-                             GrGLShaderVar::kOut_TypeModifier,
-                             declared_color_output_name());
-}
-
-void GrGLFragmentShaderBuilder::enableSecondaryOutput() {
-    SkASSERT(!fHasSecondaryOutput);
-    fHasSecondaryOutput = true;
-    fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier,
-                             dual_source_output_name());
-}
-
-const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const {
-    return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
-}
-
-const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const {
-    return dual_source_output_name();
-}
-
-void GrGLFragmentShaderBuilder::enableSecondaryOutput(const GrGLSLExpr4& inputColor,
-                                                      const GrGLSLExpr4& inputCoverage) {
-    this->enableSecondaryOutput();
-    const char* secondaryOutputName = this->getSecondaryColorOutputName();
-    GrGLSLExpr4 coeff(1);
-    switch (fProgramBuilder->header().fSecondaryOutputType) {
-        case GrOptDrawState::kCoverage_SecondaryOutputType:
-            break;
-        case GrOptDrawState::kCoverageISA_SecondaryOutputType:
-            // Get (1-A) into coeff
-            coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
-            break;
-        case GrOptDrawState::kCoverageISC_SecondaryOutputType:
-            // Get (1-RGBA) into coeff
-            coeff = GrGLSLExpr4(1) - inputColor;
-            break;
-        default:
-            SkFAIL("Unexpected Secondary Output");
+void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
+               const char* name,
+               const char** fsInName,
+               GrGLShaderVar::Precision fsPrecision) {
+    fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision);
+    if (fsInName) {
+        *fsInName = name;
     }
-    // Get coeff * coverage into modulate and then write that to the dual source output.
-    this->codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
 }
 
-void GrGLFragmentShaderBuilder::combineColorAndCoverage(const GrGLSLExpr4& inputColor,
-                                                        const GrGLSLExpr4& inputCoverage) {
-    GrGLSLExpr4 fragColor = inputColor * inputCoverage;
-    switch (fProgramBuilder->header().fPrimaryOutputType) {
-        case GrOptDrawState::kModulate_PrimaryOutputType:
-            break;
-        case GrOptDrawState::kCombineWithDst_PrimaryOutputType:
-            {
-                // Tack on "+(1-coverage)dst onto the frag color.
-                GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
-                GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor());
-                fragColor = fragColor + dstContribution;
-            }
-            break;
-        default:
-            SkFAIL("Unknown Primary Output");
+void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) {
+    GrGpuGL* gpu = fProgramBuilder->gpu();
+    if (fHasCustomColorOutput) {
+        GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()));
     }
-
-    // On any post 1.10 GLSL supporting GPU, we declare custom output
-    if (k110_GrGLSLGeneration != fProgramBuilder->gpu()->glslGeneration()) {
-        this->enableCustomOutput();
+    if (fHasSecondaryOutput) {
+        GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name()));
     }
-
-    this->codeAppendf("\t%s = %s;\n", this->getPrimaryColorOutputName(), fragColor.c_str());
 }
 
 bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
@@ -304,10 +227,10 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
                                        gpu->glStandard(),
                                        &fragShaderSrc);
     fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc);
-    this->appendDecls(fInputs, &fragShaderSrc);
+    fProgramBuilder->appendDecls(fInputs, &fragShaderSrc);
     // We shouldn't have declared outputs on 1.10
     SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty());
-    this->appendDecls(fOutputs, &fragShaderSrc);
+    fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc);
     fragShaderSrc.append(fFunctions);
     fragShaderSrc.append("void main() {\n");
     fragShaderSrc.append(fCode);
@@ -325,21 +248,121 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
     return true;
 }
 
-void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) {
-    if (fHasCustomColorOutput) {
-        GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name()));
+void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() {
+    const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
+    GrGpuGL* gpu = fProgramBuilder->gpu();
+
+    ///////////////////////////////////////////////////////////////////////////
+    // emit code to read the dst copy texture, if necessary
+    if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSupport()) {
+        bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
+        const char* dstCopyTopLeftName;
+        const char* dstCopyCoordScaleName;
+        const char* dstCopySamplerName;
+        uint32_t configMask;
+        if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
+            configMask = kA_GrColorComponentFlag;
+        } else {
+            configMask = kRGBA_GrColorComponentFlags;
+        }
+        fProgramBuilder->fUniformHandles.fDstCopySamplerUni =
+            fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+                                 kSampler2D_GrSLType,
+                                 "DstCopySampler",
+                                 &dstCopySamplerName);
+        fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni =
+            fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+                                 kVec2f_GrSLType,
+                                 "DstCopyUpperLeft",
+                                 &dstCopyTopLeftName);
+        fProgramBuilder->fUniformHandles.fDstCopyScaleUni =
+            fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+                                 kVec2f_GrSLType,
+                                 "DstCopyCoordScale",
+                                 &dstCopyCoordScaleName);
+        const char* fragPos = fragmentPosition();
+
+        this->codeAppend("// Read color from copy of the destination.\n");
+        this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
+                          fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
+        if (!topDown) {
+            this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
+        }
+        this->codeAppendf("vec4 %s = ", kDstCopyColorName);
+        this->appendTextureLookup(dstCopySamplerName,
+                                  "_dstTexCoord",
+                                  configMask,
+                                  "rgba");
+        this->codeAppend(";");
     }
-    if (fHasSecondaryOutput) {
-        GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_name()));
+
+    if (k110_GrGLSLGeneration != gpu->glslGeneration()) {
+        fOutputs.push_back().set(kVec4f_GrSLType,
+                                 GrGLShaderVar::kOut_TypeModifier,
+                                 declared_color_output_name());
+        fHasCustomColorOutput = true;
     }
 }
 
-void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
-               const char* name,
-               const char** fsInName,
-               GrGLShaderVar::Precision fsPrecision) {
-    fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision);
-    if (fsInName) {
-        *fsInName = name;
+void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage) {
+    const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
+
+    ///////////////////////////////////////////////////////////////////////////
+    // write the secondary color output if necessary
+    if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
+        const char* secondaryOutputName = this->enableSecondaryOutput();
+        GrGLSLExpr4 coeff(1);
+        switch (header.fSecondaryOutputType) {
+            case GrOptDrawState::kCoverage_SecondaryOutputType:
+                break;
+            case GrOptDrawState::kCoverageISA_SecondaryOutputType:
+                // Get (1-A) into coeff
+                coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
+                break;
+            case GrOptDrawState::kCoverageISC_SecondaryOutputType:
+                // Get (1-RGBA) into coeff
+                coeff = GrGLSLExpr4(1) - inputColor;
+                break;
+            default:
+                SkFAIL("Unexpected Secondary Output");
+        }
+        // Get coeff * coverage into modulate and then write that to the dual source output.
+        codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // combine color and coverage as frag color
+
+    // Get "color * coverage" into fragColor
+    GrGLSLExpr4 fragColor = inputColor * inputCoverage;
+    switch (header.fPrimaryOutputType) {
+        case GrOptDrawState::kModulate_PrimaryOutputType:
+            break;
+        case GrOptDrawState::kCombineWithDst_PrimaryOutputType:
+            {
+                // Tack on "+(1-coverage)dst onto the frag color.
+                GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
+                GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor());
+                fragColor = fragColor + dstContribution;
+            }
+            break;
+        default:
+            SkFAIL("Unknown Primary Output");
     }
+    codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str());
 }
+
+const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() {
+    if (!fHasSecondaryOutput) {
+        fOutputs.push_back().set(kVec4f_GrSLType,
+                                 GrGLShaderVar::kOut_TypeModifier,
+                                 dual_source_output_name());
+        fHasSecondaryOutput = true;
+    }
+    return dual_source_output_name();
+}
+
+const char* GrGLFragmentShaderBuilder::getColorOutputName() const {
+    return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
+}
+
index fdf685cc09bcc32c28e2eec296979b170861eaad..38d569e734189f552713d4ba07160ba2672ab897 100644 (file)
@@ -7,16 +7,18 @@
 
 #ifndef GrGLFragmentShaderBuilder_DEFINED
 #define GrGLFragmentShaderBuilder_DEFINED
-
 #include "GrGLShaderBuilder.h"
 
+class GrGLProgramBuilder;
+
 /*
- * This base class encapsulates the functionality which the GP uses to build fragment shaders
+ * This base class encapsulates the functionality which all GrProcessors are allowed to use in their
+ * fragment shader
  */
-class GrGLGPFragmentBuilder : public GrGLShaderBuilder {
+class GrGLProcessorFragmentShaderBuilder : public GrGLShaderBuilder {
 public:
-    GrGLGPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
-    virtual ~GrGLGPFragmentBuilder() {}
+    GrGLProcessorFragmentShaderBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
+    virtual ~GrGLProcessorFragmentShaderBuilder() {}
     /**
      * Use of these features may require a GLSL extension to be enabled. Shaders may not compile
      * if code is added that uses one of these features without calling enableFeature()
@@ -51,23 +53,20 @@ private:
 
 /*
  * Fragment processor's, in addition to all of the above, may need to use dst color so they use
- * this builder to create their shader.  Because this is the only shader builder the FP sees, we
- * just call it FPShaderBuilder
+ * this builder to create their shader
  */
-class GrGLFPFragmentBuilder : public GrGLGPFragmentBuilder {
+class GrGLFragmentProcessorShaderBuilder : public GrGLProcessorFragmentShaderBuilder {
 public:
-    GrGLFPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
-
+    GrGLFragmentProcessorShaderBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
     /** Returns the variable name that holds the color of the destination pixel. This may be NULL if
         no effect advertised that it will read the destination. */
     virtual const char* dstColor() = 0;
 
 private:
-    typedef GrGLGPFragmentBuilder INHERITED;
+    typedef GrGLProcessorFragmentShaderBuilder INHERITED;
 };
 
-// TODO rename to Fragment Builder
-class GrGLFragmentShaderBuilder : public GrGLFPFragmentBuilder {
+class GrGLFragmentShaderBuilder : public GrGLFragmentProcessorShaderBuilder {
 public:
     typedef uint8_t DstReadKey;
     typedef uint8_t FragPosKey;
@@ -84,42 +83,39 @@ public:
 
     GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, const GrGLProgramDesc& desc);
 
-    // true public interface, defined explicitly in the abstract interfaces above
+    virtual const char* dstColor() SK_OVERRIDE;
+
     virtual bool enableFeature(GLSLFeature) SK_OVERRIDE;
+
     virtual SkString ensureFSCoords2D(const GrGLProcessor::TransformedCoordsArray& coords,
                                       int index) SK_OVERRIDE;
-    virtual const char* fragmentPosition() SK_OVERRIDE;
-    virtual const char* dstColor() SK_OVERRIDE;
 
-    // Private public interface, used by GrGLProgramBuilder to build a fragment shader
-    void emitCodeToReadDstTexture();
-    void enableCustomOutput();
-    void enableSecondaryOutput();
-    const char* getPrimaryColorOutputName() const;
-    const char* getSecondaryColorOutputName() const;
-    void enableSecondaryOutput(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
-    void combineColorAndCoverage(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
-    bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
-    void bindFragmentShaderLocations(GrGLuint programID);
+    virtual const char* fragmentPosition() SK_OVERRIDE;
 
+private:
     /*
-     * An internal call for GrGLProgramBuilder to use to add varyings to the vertex shader
+     * An internal call for GrGLFullProgramBuilder to use to add varyings to the vertex shader
      */
     void addVarying(GrSLType type,
                    const char* name,
                    const char** fsInName,
                    GrGLShaderVar::Precision fsPrecision = GrGLShaderVar::kDefault_Precision);
 
-    // As GLProcessors emit code, there are some conditions we need to verify.  We use the below
-    // state to track this.  The reset call is called per processor emitted.
-    bool hasReadDstColor() const { return fHasReadDstColor; }
-    bool hasReadFragmentPosition() const { return fHasReadFragmentPosition; }
-    void reset() {
-        fHasReadDstColor = false;
-        fHasReadFragmentPosition = false;
-    }
+    /*
+     * Private functions used by GrGLProgramBuilder for compilation
+    */
+    void bindProgramLocations(GrGLuint programId);
+    bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
+    void emitCodeBeforeEffects();
+    void emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
+
+    /** Enables using the secondary color output and returns the name of the var in which it is
+        to be stored */
+    const char* enableSecondaryOutput();
+
+    /** Gets the name of the primary color output. */
+    const char* getColorOutputName() const;
 
-private:
     /**
      * Features that should only be enabled by GrGLFragmentShaderBuilder itself.
      */
@@ -136,29 +132,21 @@ private:
         kTopLeftOrigin_DstReadKeyBit    = 0x4, // Set if dst-copy origin is top-left.
     };
 
-    // Interpretation of FragPosKey when generating code
     enum {
         kNoFragPosRead_FragPosKey           = 0,  // The fragment positition will not be needed.
         kTopLeftFragPosRead_FragPosKey      = 0x1,// Read frag pos relative to top-left.
         kBottomLeftFragPosRead_FragPosKey   = 0x2,// Read frag pos relative to bottom-left.
     };
 
-    static const char* kDstCopyColorName;
-
     bool fHasCustomColorOutput;
     bool fHasSecondaryOutput;
     bool fSetupFragPosition;
     bool fTopLeftFragPosRead;
 
-    // some state to verify shaders and effects are consistent, this is reset between effects by
-    // the program creator
-    bool fHasReadDstColor;
-    bool fHasReadFragmentPosition;
-
-    friend class GrGLNvprProgramBuilder;
     friend class GrGLProgramBuilder;
+    friend class GrGLFullProgramBuilder;
 
-    typedef GrGLFPFragmentBuilder INHERITED;
+    typedef GrGLFragmentProcessorShaderBuilder INHERITED;
 };
 
 #endif
diff --git a/src/gpu/gl/builders/GrGLFullProgramBuilder.cpp b/src/gpu/gl/builders/GrGLFullProgramBuilder.cpp
new file mode 100644 (file)
index 0000000..d309b27
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLFullProgramBuilder.h"
+#include "../GrGLGeometryProcessor.h"
+#include "../GrGpuGL.h"
+
+GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState,
+                                               const GrGLProgramDesc& desc)
+    : INHERITED(gpu, optState, desc)
+    , fGLGeometryProcessorEmitter(this)
+    , fGS(this)
+    , fVS(this) {
+}
+
+void
+GrGLFullProgramBuilder::createAndEmitEffects(const GrGeometryStage* geometryProcessor,
+                                             const GrFragmentStage* colorStages[],
+                                             const GrFragmentStage* coverageStages[],
+                                             GrGLSLExpr4* inputColor,
+                                             GrGLSLExpr4* inputCoverage) {
+    fVS.emitCodeBeforeEffects(inputColor, inputCoverage);
+
+    ///////////////////////////////////////////////////////////////////////////
+    // emit the per-effect code for both color and coverage effects
+
+    EffectKeyProvider colorKeyProvider(&this->desc(), EffectKeyProvider::kColor_EffectType);
+    fColorEffects.reset(this->onCreateAndEmitEffects(colorStages,
+                                                     this->desc().numColorEffects(),
+                                                     colorKeyProvider,
+                                                     inputColor));
+
+    if (geometryProcessor) {
+        const GrGeometryProcessor& gp = *geometryProcessor->getGeometryProcessor();
+        fGLGeometryProcessorEmitter.set(&gp);
+        fEffectEmitter = &fGLGeometryProcessorEmitter;
+        fVS.emitAttributes(gp);
+        GrGLSLExpr4 gpInputCoverage = *inputCoverage;
+        GrGLSLExpr4 gpOutputCoverage;
+        EffectKeyProvider gpKeyProvider(&this->desc(),
+                EffectKeyProvider::kGeometryProcessor_EffectType);
+        bool useLocalCoords = this->getVertexShaderBuilder()->hasExplicitLocalCoords();
+        fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects, (1, useLocalCoords)));
+        this->INHERITED::emitEffect(*geometryProcessor, 0, gpKeyProvider, &gpInputCoverage,
+                                    &gpOutputCoverage);
+        fGeometryProcessor.reset(fProgramEffects.detach());
+        *inputCoverage = gpOutputCoverage;
+    }
+
+    EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCoverage_EffectType);
+    fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages,
+                                                        this->desc().numCoverageEffects(),
+                                                        coverageKeyProvider,
+                                                        inputCoverage));
+
+     fVS.emitCodeAfterEffects();
+}
+
+void GrGLFullProgramBuilder::addVarying(GrSLType type,
+                                        const char* name,
+                                        const char** vsOutName,
+                                        const char** fsInName,
+                                        GrGLShaderVar::Precision fsPrecision) {
+    fVS.addVarying(type, name, vsOutName);
+
+    SkString* fsInputName = fVS.fOutputs.back().accessName();
+
+#if GR_GL_EXPERIMENTAL_GS
+    if (desc().getHeader().fExperimentalGS) {
+       // TODO let the caller use these names
+       fGS.addVarying(type, fsInputName->c_str(), NULL);
+       fsInputName = fGS.fOutputs.back().accessName();
+    }
+#endif
+    fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
+}
+
+GrGLFullProgramBuilder::VaryingHandle
+GrGLFullProgramBuilder::addSeparableVarying(GrSLType type,
+                                            const char* name,
+                                            const char** vsOutName,
+                                            const char** fsInName) {
+    addVarying(type, name, vsOutName, fsInName);
+    SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
+    varying.fVariable = fFS.fInputs.back();
+    return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1);
+}
+
+GrGLProgramEffects* GrGLFullProgramBuilder::onCreateAndEmitEffects(
+        const GrFragmentStage* effectStages[],
+        int effectCnt,
+        const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+        GrGLSLExpr4* inOutFSColor) {
+    fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects,
+                                 (effectCnt,
+                                  this->getVertexShaderBuilder()->hasExplicitLocalCoords())));
+    this->INHERITED::createAndEmitEffects(effectStages,
+                                          effectCnt,
+                                          keyProvider,
+                                          inOutFSColor);
+    return fProgramEffects.detach();
+}
+
+void GrGLFullProgramBuilder::emitEffect(const GrProcessorStage& stage,
+                                        const GrProcessorKey& key,
+                                        const char* outColor,
+                                        const char* inColor,
+                                        int stageIndex) {
+    SkASSERT(fProgramEffects.get());
+    const GrProcessor& effect = *stage.getProcessor();
+    SkSTArray<2, GrGLProcessor::TransformedCoords> coords(effect.numTransforms());
+    SkSTArray<4, GrGLProcessor::TextureSampler> samplers(effect.numTextures());
+
+    this->emitTransforms(stage, &coords);
+    this->emitSamplers(effect, &samplers);
+
+    SkASSERT(fEffectEmitter);
+    GrGLProcessor* glEffect = fEffectEmitter->createGLInstance();
+    fProgramEffects->addEffect(glEffect);
+
+    // Enclose custom code in a block to avoid namespace conflicts
+    SkString openBrace;
+    openBrace.printf("{ // Stage %d: %s\n", stageIndex, glEffect->name());
+    fFS.codeAppend(openBrace.c_str());
+    fVS.codeAppend(openBrace.c_str());
+
+    fEffectEmitter->emit(key, outColor, inColor, coords, samplers);
+
+    fVS.codeAppend("\t}\n");
+    fFS.codeAppend("\t}\n");
+}
+
+void GrGLFullProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
+                                            GrGLProcessor::TransformedCoordsArray* outCoords) {
+    SkTArray<GrGLVertexProgramEffects::Transform, true>& transforms =
+            fProgramEffects->addTransforms();
+    const GrProcessor* effect = effectStage.getProcessor();
+    int numTransforms = effect->numTransforms();
+    transforms.push_back_n(numTransforms);
+
+    SkTArray<GrGLVertexProgramEffects::PathTransform, true>* pathTransforms = NULL;
+    const GrGLCaps* glCaps = this->ctxInfo().caps();
+    if (glCaps->pathRenderingSupport() &&
+        this->gpu()->glPathRendering()->texturingMode() ==
+           GrGLPathRendering::SeparableShaders_TexturingMode) {
+        pathTransforms = &fProgramEffects->addPathTransforms();
+        pathTransforms->push_back_n(numTransforms);
+    }
+
+    for (int t = 0; t < numTransforms; t++) {
+        const char* uniName = "StageMatrix";
+        GrSLType varyingType =
+                effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
+                        kVec3f_GrSLType :
+                        kVec2f_GrSLType;
+
+        SkString suffixedUniName;
+        if (0 != t) {
+            suffixedUniName.append(uniName);
+            suffixedUniName.appendf("_%i", t);
+            uniName = suffixedUniName.c_str();
+        }
+        transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+                                                 kMat33f_GrSLType,
+                                                 uniName,
+                                                 &uniName);
+
+        const char* varyingName = "MatrixCoord";
+        SkString suffixedVaryingName;
+        if (0 != t) {
+            suffixedVaryingName.append(varyingName);
+            suffixedVaryingName.appendf("_%i", t);
+            varyingName = suffixedVaryingName.c_str();
+        }
+        const char* vsVaryingName;
+        const char* fsVaryingName;
+        if (pathTransforms) {
+            (*pathTransforms)[t].fHandle =
+                this->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
+            (*pathTransforms)[t].fType = varyingType;
+        } else {
+            this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
+        }
+
+        const GrGLShaderVar& coords =
+                kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
+                                          fVS.positionAttribute() :
+                                          fVS.localCoordsAttribute();
+        // varying = matrix * coords (logically)
+        SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
+        if (kVec2f_GrSLType == varyingType) {
+            fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
+                            vsVaryingName, uniName, coords.c_str());
+        } else {
+            fVS.codeAppendf("%s = %s * vec3(%s, 1);",
+                            vsVaryingName, uniName, coords.c_str());
+        }
+        SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
+                               (SkString(fsVaryingName), varyingType));
+    }
+}
+
+bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
+                                                     SkTDArray<GrGLuint>* shaderIds) const {
+    return INHERITED::compileAndAttachShaders(programId, shaderIds)
+         && fVS.compileAndAttachShaders(programId, shaderIds)
+#if GR_GL_EXPERIMENTAL_GS
+         && (!desc().getHeader().fExperimentalGS
+                 || fGS.compileAndAttachShaders(programId, shaderIds))
+#endif
+         ;
+}
+
+void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) {
+    fVS.bindProgramLocations(programId);
+    INHERITED::bindProgramLocations(programId);
+}
diff --git a/src/gpu/gl/builders/GrGLFullProgramBuilder.h b/src/gpu/gl/builders/GrGLFullProgramBuilder.h
new file mode 100644 (file)
index 0000000..0f38341
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLFullProgramBuilder_DEFINED
+#define GrGLFullProgramBuilder_DEFINED
+
+#include "GrGLProgramBuilder.h"
+#include "../GrGLGeometryProcessor.h"
+
+class GrGLVertexProgramEffects;
+
+class GrGLFullProgramBuilder : public GrGLProgramBuilder {
+public:
+    GrGLFullProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
+
+   /** Add a varying variable to the current program to pass values between vertex and fragment
+        shaders. If the last two parameters are non-NULL, they are filled in with the name
+        generated. */
+    void addVarying(GrSLType type,
+                    const char* name,
+                    const char** vsOutName = NULL,
+                    const char** fsInName = NULL,
+                    GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
+
+    /** Add a separable varying input variable to the current program.
+     * A separable varying (fragment shader input) is a varying that can be used also when vertex
+     * shaders are not used. With a vertex shader, the operation is same as with other
+     * varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
+     * populate the variable. The APIs can refer to the variable through the returned handle.
+     */
+    VaryingHandle addSeparableVarying(GrSLType type,
+                                      const char* name,
+                                      const char** vsOutName,
+                                      const char** fsInName);
+
+    GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
+
+    /*
+     * This non-virtual call will hide the parent call to prevent GPs from accessing fragment shader
+     * functionality they shouldn't be using
+     */
+    GrGLProcessorFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
+
+private:
+    virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
+                                      const GrFragmentStage* colorStages[],
+                                      const GrFragmentStage* coverageStages[],
+                                      GrGLSLExpr4* inputColor,
+                                      GrGLSLExpr4* inputCoverage) SK_OVERRIDE;
+
+    GrGLProgramEffects* onCreateAndEmitEffects(const GrFragmentStage* effectStages[],
+                                               int effectCnt,
+                                               const GrGLProgramDesc::EffectKeyProvider&,
+                                               GrGLSLExpr4* inOutFSColor);
+
+    class GrGLGeometryProcessorEmitter : public GrGLProgramBuilder::GrGLProcessorEmitterInterface {
+        public:
+            GrGLGeometryProcessorEmitter(GrGLFullProgramBuilder* builder)
+                : fBuilder(builder)
+                , fGeometryProcessor(NULL)
+                , fGLGeometryProcessor(NULL) {}
+            virtual ~GrGLGeometryProcessorEmitter() {}
+            void set(const GrGeometryProcessor* gp) {
+                SkASSERT(NULL == fGeometryProcessor);
+                fGeometryProcessor = gp;
+            }
+            virtual GrGLProcessor* createGLInstance() {
+                SkASSERT(fGeometryProcessor);
+                SkASSERT(NULL == fGLGeometryProcessor);
+                fGLGeometryProcessor =
+                        fGeometryProcessor->getFactory().createGLInstance(*fGeometryProcessor);
+                return fGLGeometryProcessor;
+            }
+            virtual void emit(const GrProcessorKey& key,
+                              const char* outColor,
+                              const char* inColor,
+                              const GrGLProcessor::TransformedCoordsArray& coords,
+                              const GrGLProcessor::TextureSamplerArray& samplers) {
+                SkASSERT(fGeometryProcessor);
+                SkASSERT(fGLGeometryProcessor);
+                fGLGeometryProcessor->emitCode(fBuilder, *fGeometryProcessor, key, outColor,
+                                               inColor, coords, samplers);
+                // this will not leak because it has already been used by createGLInstance
+                fGLGeometryProcessor = NULL;
+                fGeometryProcessor = NULL;
+            }
+        private:
+            GrGLFullProgramBuilder*     fBuilder;
+            const GrGeometryProcessor*  fGeometryProcessor;
+            GrGLGeometryProcessor*      fGLGeometryProcessor;
+        };
+
+    virtual void emitEffect(const GrProcessorStage& stage,
+                            const GrProcessorKey& key,
+                            const char* outColor,
+                            const char* inColor,
+                            int stageIndex) SK_OVERRIDE;
+
+    /**
+     * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
+     * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
+     * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
+     * of the varyings in the VS and FS as well their types are appended to the
+     * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
+     */
+    void emitTransforms(const GrProcessorStage& effectStage,
+                        GrGLProcessor::TransformedCoordsArray* outCoords);
+
+    virtual bool compileAndAttachShaders(GrGLuint programId,
+                                         SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
+
+    virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE;
+
+    virtual GrGLProgramEffects* getProgramEffects() SK_OVERRIDE { return fProgramEffects.get(); }
+
+    typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
+
+    GrGLGeometryProcessorEmitter fGLGeometryProcessorEmitter;
+    GrGLGeometryShaderBuilder fGS;
+    GrGLVertexShaderBuilder   fVS;
+    SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
+
+    typedef GrGLProgramBuilder INHERITED;
+};
+
+#endif
index 8a3b1f4a6eb7df27dd8826509c637e4601afb565..117497b9ee9f3ebd6cc63b9bb37dd256cbe888bb 100644 (file)
 #include "GrGLProgramBuilder.h"
 #include "../GrGpuGL.h"
 
-GrGLGeometryBuilder::GrGLGeometryBuilder(GrGLProgramBuilder* program)
+GrGLGeometryShaderBuilder::GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program)
     : INHERITED(program) {
 
 }
 
-void GrGLGeometryBuilder::addVarying(GrSLType type,
+void GrGLGeometryShaderBuilder::addVarying(GrSLType type,
                const char* name,
                const char** gsOutName) {
     // if we have a GS take each varying in as an array
@@ -35,15 +35,15 @@ void GrGLGeometryBuilder::addVarying(GrSLType type,
 }
 
 
-bool GrGLGeometryBuilder::compileAndAttachShaders(GrGLuint programId,
+bool GrGLGeometryShaderBuilder::compileAndAttachShaders(GrGLuint programId,
         SkTDArray<GrGLuint>* shaderIds) const {
     const GrGLContext& glCtx = fProgramBuilder->gpu()->glContext();
     SkASSERT(fProgramBuilder->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration);
     SkString geomShaderSrc(GrGetGLSLVersionDecl(fProgramBuilder->ctxInfo()));
     geomShaderSrc.append("layout(triangles) in;\n"
                          "layout(triangle_strip, max_vertices = 6) out;\n");
-    this->appendDecls(fInputs, &geomShaderSrc);
-    this->appendDecls(fOutputs, &geomShaderSrc);
+    fProgramBuilder->appendDecls(fInputs, &geomShaderSrc);
+    fProgramBuilder->appendDecls(fOutputs, &geomShaderSrc);
     geomShaderSrc.append("void main() {\n");
     geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n"
                          "\t\tgl_Position = gl_in[i].gl_Position;\n");
index aa27f23f03f6d402900cf30736a8f171dc4771fc..833d31774f82f7f0a69d0921a4a98b95d9181b66 100644 (file)
 
 #include "GrGLShaderBuilder.h"
 
-class GrGLGeometryBuilder : public GrGLShaderBuilder {
+class GrGLProgramBuilder;
+
+class GrGLGeometryShaderBuilder : public GrGLFullShaderBuilder {
 public:
-    GrGLGeometryBuilder(GrGLProgramBuilder* program);
+    GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program);
+private:
     /*
      * an internal call for GrGLFullProgramBuilder to add varyings
      */
@@ -22,7 +25,8 @@ public:
 
     bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
 
-    typedef GrGLShaderBuilder INHERITED;
+    friend class GrGLFullProgramBuilder;
+    typedef GrGLFullShaderBuilder INHERITED;
 };
 
 #endif
diff --git a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
deleted file mode 100644 (file)
index acb4af1..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrGLLegacyNvprProgramBuilder.h"
-#include "../GrGpuGL.h"
-
-GrGLLegacyNvprProgramBuilder::GrGLLegacyNvprProgramBuilder(GrGpuGL* gpu,
-                                                           const GrOptDrawState& optState,
-                                                           const GrGLProgramDesc& desc)
-    : INHERITED(gpu, optState, desc)
-    , fTexCoordSetCnt(0) {
-    SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
-    SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
-}
-
-int GrGLLegacyNvprProgramBuilder::addTexCoordSets(int count) {
-    int firstFreeCoordSet = fTexCoordSetCnt;
-    fTexCoordSetCnt += count;
-    SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt);
-    return firstFreeCoordSet;
-}
-
-void GrGLLegacyNvprProgramBuilder::emitTransforms(const GrProcessorStage& processorStage,
-                                            GrGLProcessor::TransformedCoordsArray* outCoords,
-                                            GrGLInstalledProcessors* installedProcessors) {
-    int numTransforms = processorStage.getProcessor()->numTransforms();
-    int texCoordIndex = this->addTexCoordSets(numTransforms);
-
-    SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
-            installedProcessors->addTransforms();
-
-    // Use the first uniform location as the texcoord index.  This may seem a bit hacky but it
-    // allows us to use one program effects object for all of our programs which really simplifies
-    // the code overall
-    transforms.push_back_n(1);
-    transforms[0].fHandle = GrGLInstalledProcessors::ShaderVarHandle(texCoordIndex);
-
-    SkString name;
-    for (int t = 0; t < numTransforms; ++t) {
-        GrSLType type = processorStage.isPerspectiveCoordTransform(t, false) ? kVec3f_GrSLType :
-                                                                               kVec2f_GrSLType;
-
-        name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
-        SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, (name, type));
-    }
-}
-
-GrGLProgram* GrGLLegacyNvprProgramBuilder::createProgram(GrGLuint programID) {
-    return SkNEW_ARGS(GrGLLegacyNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
-                                        fColorEffects, fCoverageEffects,  fTexCoordSetCnt));
-}
diff --git a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h
deleted file mode 100644 (file)
index 496fbd8..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrGLLegacyNvprProgramBuilder_DEFINED
-#define GrGLLegacyNvprProgramBuilder_DEFINED
-
-#include "GrGLProgramBuilder.h"
-
-class GrGLLegacyNvprProgramBuilder : public GrGLProgramBuilder {
-public:
-    GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
-
-    virtual GrGLProgram* createProgram(GrGLuint programID);
-
-private:
-    int addTexCoordSets(int count);
-    void emitTransforms(const GrProcessorStage&,
-                        GrGLProcessor::TransformedCoordsArray* outCoords,
-                        GrGLInstalledProcessors*);
-
-    int fTexCoordSetCnt;
-
-    typedef GrGLProgramBuilder INHERITED;
-};
-
-#endif
diff --git a/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp b/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
deleted file mode 100644 (file)
index e5eae9d..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrGLNvprProgramBuilder.h"
-#include "../GrGpuGL.h"
-
-#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
-#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
-
-GrGLNvprProgramBuilder::GrGLNvprProgramBuilder(GrGpuGL* gpu,
-                                               const GrOptDrawState& optState,
-                                               const GrGLProgramDesc& desc)
-        : INHERITED(gpu, optState, desc)
-        , fSeparableVaryingInfos(kVarsPerBlock) {
-}
-
-void GrGLNvprProgramBuilder::emitTransforms(const GrProcessorStage& processorStage,
-                                            GrGLProcessor::TransformedCoordsArray* outCoords,
-                                            GrGLInstalledProcessors* installedProcessors) {
-    const GrProcessor* effect = processorStage.getProcessor();
-    int numTransforms = effect->numTransforms();
-
-    SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
-            installedProcessors->addTransforms();
-    transforms.push_back_n(numTransforms);
-
-    for (int t = 0; t < numTransforms; t++) {
-        GrSLType varyingType =
-                processorStage.isPerspectiveCoordTransform(t, false) ?
-                        kVec3f_GrSLType :
-                        kVec2f_GrSLType;
-
-        const char* varyingName = "MatrixCoord";
-        SkString suffixedVaryingName;
-        if (0 != t) {
-            suffixedVaryingName.append(varyingName);
-            suffixedVaryingName.appendf("_%i", t);
-            varyingName = suffixedVaryingName.c_str();
-        }
-        const char* vsVaryingName;
-        const char* fsVaryingName;
-        transforms[t].fHandle = this->addSeparableVarying(varyingType, varyingName,
-                                                          &vsVaryingName, &fsVaryingName);
-        transforms[t].fType = varyingType;
-
-        SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
-                               (SkString(fsVaryingName), varyingType));
-    }
-}
-
-GrGLInstalledProcessors::ShaderVarHandle
-GrGLNvprProgramBuilder::addSeparableVarying(GrSLType type,
-                                              const char* name,
-                                              const char** vsOutName,
-                                              const char** fsInName) {
-    addVarying(type, name, vsOutName, fsInName);
-    SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
-    varying.fVariable = fFS.fInputs.back();
-    return GrGLInstalledProcessors::ShaderVarHandle(fSeparableVaryingInfos.count() - 1);
-}
-
-void GrGLNvprProgramBuilder::resolveSeparableVaryings(GrGLuint programId) {
-    int count = fSeparableVaryingInfos.count();
-    for (int i = 0; i < count; ++i) {
-        GrGLint location;
-        GL_CALL_RET(location,
-                    GetProgramResourceLocation(programId,
-                                               GR_GL_FRAGMENT_INPUT,
-                                               fSeparableVaryingInfos[i].fVariable.c_str()));
-        fSeparableVaryingInfos[i].fLocation = location;
-    }
-}
-
-GrGLProgram* GrGLNvprProgramBuilder::createProgram(GrGLuint programID) {
-    // this is just for nvpr es, which has separable varyings that are plugged in after
-    // building
-    this->resolveSeparableVaryings(programID);
-    return SkNEW_ARGS(GrGLNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
-                                        fColorEffects, fCoverageEffects, fSeparableVaryingInfos));
-}
diff --git a/src/gpu/gl/builders/GrGLNvprProgramBuilder.h b/src/gpu/gl/builders/GrGLNvprProgramBuilder.h
deleted file mode 100644 (file)
index cb13375..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrGLNvprProgramBuilder_DEFINED
-#define GrGLNvprProgramBuilder_DEFINED
-
-#include "GrGLProgramBuilder.h"
-
-class GrGLNvprProgramBuilder : public GrGLProgramBuilder {
-public:
-    GrGLNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
-
-    /*
-     * The separable varying info must be passed to GrGLProgram so this must
-     * be part of the public interface
-     */
-    struct SeparableVaryingInfo {
-        GrGLShaderVar fVariable;
-        GrGLint       fLocation;
-    };
-
-    typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
-
-    virtual GrGLProgram* createProgram(GrGLuint programID);
-
-private:
-    virtual void emitTransforms(const GrProcessorStage&,
-                                GrGLProcessor::TransformedCoordsArray* outCoords,
-                                GrGLInstalledProcessors*) SK_OVERRIDE;
-
-    typedef GrGLInstalledProcessors::ShaderVarHandle ShaderVarHandle;
-
-    /**
-     * Add a separable varying input variable to the current program.
-     * A separable varying (fragment shader input) is a varying that can be used also when vertex
-     * shaders are not used. With a vertex shader, the operation is same as with other
-     * varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
-     * populate the variable. The APIs can refer to the variable through the returned handle.
-     */
-    ShaderVarHandle addSeparableVarying(GrSLType type,
-                                      const char* name,
-                                      const char** vsOutName,
-                                      const char** fsInName);
-
-    void resolveSeparableVaryings(GrGLuint programId);
-
-    SeparableVaryingInfoArray fSeparableVaryingInfos;
-
-    typedef GrGLProgramBuilder INHERITED;
-};
-
-#endif
index 113463b978f83a0941e8d6cecfa1146ab68d54a6..de08ec4ad06502b45a9ffb2a5794c4e0a745c839 100644 (file)
  * found in the LICENSE file.
  */
 
-#include "GrGLProgramBuilder.h"
-#include "gl/GrGLGeometryProcessor.h"
 #include "gl/GrGLProgram.h"
 #include "gl/GrGLSLPrettyPrint.h"
 #include "gl/GrGLUniformHandle.h"
-#include "../GrGpuGL.h"
 #include "GrCoordTransform.h"
-#include "GrGLLegacyNvprProgramBuilder.h"
-#include "GrGLNvprProgramBuilder.h"
+#include "../GrGpuGL.h"
+#include "GrGLFragmentShaderBuilder.h"
 #include "GrGLProgramBuilder.h"
 #include "GrTexture.h"
+#include "GrGLVertexShaderBuilder.h"
 #include "SkRTConf.h"
 #include "SkTraceEvent.h"
 
+namespace {
 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
 
+// number of each input/output type in a single allocation block
+static const int kVarsPerBlock = 8;
+
 // ES2 FS only guarantees mediump and lowp support
 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
+}
 
-//////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-const int GrGLProgramBuilder::kVarsPerBlock = 8;
-
-GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
-                                               const GrGLProgramDesc& desc,
-                                               GrGpu::DrawType drawType,
-                                               const GrGeometryStage* geometryProcessor,
-                                               const GrFragmentStage* colorStages[],
-                                               const GrFragmentStage* coverageStages[],
-                                               GrGpuGL* gpu) {
-    // create a builder.  This will be handed off to effects so they can use it to add
-    // uniforms, varyings, textures, etc
-    SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc,
-                                                                   optState,
-                                                                   drawType,
-                                                                   SkToBool(geometryProcessor),
-                                                                   gpu));
-
-    GrGLProgramBuilder* pb = builder.get();
-    const GrGLProgramDesc::KeyHeader& header = pb->header();
-
-    // emit code to read the dst copy texture, if necessary
-    if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey
-            && !gpu->glCaps().fbFetchSupport()) {
-        pb->fFS.emitCodeToReadDstTexture();
-    }
+bool GrGLProgramBuilder::genProgram(const GrGeometryStage* geometryProcessor,
+                                    const GrFragmentStage* colorStages[],
+                                    const GrFragmentStage* coverageStages[]) {
+    const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
+
+    fFS.emitCodeBeforeEffects();
 
+    ///////////////////////////////////////////////////////////////////////////
     // get the initial color and coverage to feed into the first effect in each effect chain
-    GrGLSLExpr4 inputColor, inputCoverage;
-    pb->setupUniformColorAndCoverageIfNeeded(&inputColor,  &inputCoverage);
-
-    // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES), then we may have
-    // to setup a few more things like builtin vertex attributes
-    bool hasVertexShader = !header.fUseFragShaderOnly;
-    if (hasVertexShader) {
-        pb->fVS.setupLocalCoords();
-        pb->fVS.transformGLToSkiaCoords();
-        if (header.fEmitsPointSize) {
-            pb->fVS.codeAppend("gl_PointSize = 1.0;");
-        }
-        if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
-            pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor);
-        }
-        if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
-            pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage);
-        }
-    }
 
-    pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages, &inputColor,
-                                &inputCoverage);
+    GrGLSLExpr4 inputColor;
+    GrGLSLExpr4 inputCoverage;
 
-    if (hasVertexShader) {
-        pb->fVS.transformSkiaToGLCoords();
+    if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
+        const char* name;
+        fUniformHandles.fColorUni =
+            this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+                             kVec4f_GrSLType,
+                             "Color",
+                             &name);
+        inputColor = GrGLSLExpr4(name);
+    } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
+        inputColor = GrGLSLExpr4(1);
     }
 
-    // write the secondary color output if necessary
-    if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
-        pb->fFS.enableSecondaryOutput(inputColor, inputCoverage);
+    if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
+        const char* name;
+        fUniformHandles.fCoverageUni =
+            this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+                             kVec4f_GrSLType,
+                             "Coverage",
+                             &name);
+        inputCoverage = GrGLSLExpr4(name);
+    } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
+        inputCoverage = GrGLSLExpr4(1);
     }
 
-    pb->fFS.combineColorAndCoverage(inputColor, inputCoverage);
+    // Subclasses drive effect emitting
+    this->createAndEmitEffects(geometryProcessor, colorStages, coverageStages, &inputColor,
+                               &inputCoverage);
 
-    return pb->finalize();
-}
+    fFS.emitCodeAfterEffects(inputColor, inputCoverage);
 
-GrGLProgramBuilder*
-GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc,
-                                         const GrOptDrawState& optState,
-                                         GrGpu::DrawType drawType,
-                                         bool hasGeometryProcessor,
-                                         GrGpuGL* gpu) {
-    if (desc.getHeader().fUseFragShaderOnly) {
-        SkASSERT(gpu->glCaps().pathRenderingSupport());
-        SkASSERT(gpu->glPathRendering()->texturingMode() ==
-                 GrGLPathRendering::FixedFunction_TexturingMode);
-        SkASSERT(!hasGeometryProcessor);
-        return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc));
-    } else if (GrGpu::IsPathRenderingDrawType(drawType)) {
-        SkASSERT(gpu->glCaps().pathRenderingSupport());
-        SkASSERT(gpu->glPathRendering()->texturingMode() ==
-                 GrGLPathRendering::SeparableShaders_TexturingMode);
-        SkASSERT(!hasGeometryProcessor);
-        return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc));
-    } else {
-        return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc));
+    if (!this->finish()) {
+        return false;
     }
+
+    return true;
 }
 
-/////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
 
 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState,
                                        const GrGLProgramDesc& desc)
-    : fVS(this)
-    , fGS(this)
+    : fEffectEmitter(NULL)
+    , fFragOnly(SkToBool(desc.getHeader().fUseFragShaderOnly))
+    , fTexCoordSetCnt(0)
+    , fProgramID(0)
     , fFS(this, desc)
-    , fOutOfStage(true)
-    , fStageIndex(-1)
+    , fSeparableVaryingInfos(kVarsPerBlock)
+    , fGrProcessorEmitter(this)
     , fOptState(optState)
     , fDesc(desc)
     , fGpu(gpu)
     , fUniforms(kVarsPerBlock) {
 }
 
-void GrGLProgramBuilder::addVarying(GrSLType type,
-                                    const char* name,
-                                    const char** vsOutName,
-                                    const char** fsInName,
-                                    GrGLShaderVar::Precision fsPrecision) {
-    SkString* fsInputName = fVS.addVarying(type, name, vsOutName);
-    fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
-}
-
 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
     if ('\0' == prefix) {
         *out = name;
     } else {
         out->printf("%c%s", prefix, name);
     }
-    if (!fOutOfStage) {
+    if (fCodeStage.inStageCode()) {
         if (out->endsWith('_')) {
             // Names containing "__" are reserved.
             out->append("x");
         }
-        out->appendf("_Stage%d", fStageIndex);
+        out->appendf("_Stage%d", fCodeStage.stageIndex());
     }
 }
 
@@ -184,6 +143,13 @@ GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32
     return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
 }
 
+void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const {
+    for (int i = 0; i < vars.count(); ++i) {
+        vars[i].appendDecl(this->ctxInfo(), out);
+        out->append(";\n");
+    }
+}
+
 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
                                             SkString* out) const {
     for (int i = 0; i < fUniforms.count(); ++i) {
@@ -194,127 +160,20 @@ void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
     }
 }
 
-const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
-    return fGpu->ctxInfo();
-}
-
-void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor,
-                                                              GrGLSLExpr4* inputCoverage) {
-    const GrGLProgramDesc::KeyHeader& header = this->header();
-    if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
-        const char* name;
-        fUniformHandles.fColorUni =
-            this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
-                             kVec4f_GrSLType,
-                             "Color",
-                             &name);
-        *inputColor = GrGLSLExpr4(name);
-    } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
-        *inputColor = GrGLSLExpr4(1);
-    }
-    if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
-        const char* name;
-        fUniformHandles.fCoverageUni =
-            this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
-                             kVec4f_GrSLType,
-                             "Coverage",
-                             &name);
-        *inputCoverage = GrGLSLExpr4(name);
-    } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
-        *inputCoverage = GrGLSLExpr4(1);
-    }
-}
-
-void GrGLProgramBuilder::createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
-                                                 const GrFragmentStage* colorStages[],
-                                                 const GrFragmentStage* coverageStages[],
-                                                 GrGLSLExpr4* inputColor,
-                                                 GrGLSLExpr4* inputCoverage) {
-    bool useLocalCoords = fVS.hasExplicitLocalCoords();
-
-    EffectKeyProvider colorKeyProvider(&fDesc, EffectKeyProvider::kColor_EffectType);
-    int numColorEffects = fDesc.numColorEffects();
-    GrGLInstalledProcessors* ip = SkNEW_ARGS(GrGLInstalledProcessors, (numColorEffects,
-                                                                       useLocalCoords));
-    this->createAndEmitProcessors<GrFragmentStage>(colorStages, numColorEffects, colorKeyProvider,
-                                                   inputColor, ip);
-    fColorEffects.reset(ip);
-
-    if (geometryProcessor) {
-        fVS.emitAttributes(*geometryProcessor->getProcessor());
-        EffectKeyProvider gpKeyProvider(&fDesc, EffectKeyProvider::kGeometryProcessor_EffectType);
-        ip = SkNEW_ARGS(GrGLInstalledProcessors, (1, useLocalCoords));
-        this->createAndEmitProcessors<GrGeometryStage>(&geometryProcessor, 1, gpKeyProvider,
-                                                       inputCoverage, ip);
-        fGeometryProcessor.reset(ip);
-    }
-
-    EffectKeyProvider coverageKeyProvider(&fDesc, EffectKeyProvider::kCoverage_EffectType);
-    int numCoverageEffects = fDesc.numCoverageEffects();
-    ip = SkNEW_ARGS(GrGLInstalledProcessors, (numCoverageEffects, useLocalCoords));
-    this->createAndEmitProcessors<GrFragmentStage>(coverageStages, numCoverageEffects,
-                                                   coverageKeyProvider, inputCoverage, ip);
-    fCoverageEffects.reset(ip);
-}
-
-template <class ProcessorStage>
-void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processStages[],
-                                                 int effectCnt,
-                                                 const EffectKeyProvider& keyProvider,
-                                                 GrGLSLExpr4* fsInOutColor,
-                                                 GrGLInstalledProcessors* installedProcessors) {
+void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStages[],
+                                              int effectCnt,
+                                              const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+                                              GrGLSLExpr4* fsInOutColor) {
     bool effectEmitted = false;
 
     GrGLSLExpr4 inColor = *fsInOutColor;
     GrGLSLExpr4 outColor;
 
     for (int e = 0; e < effectCnt; ++e) {
-        // Program builders have a bit of state we need to clear with each effect
-        this->reset();
-        const ProcessorStage& stage = *processStages[e];
-        SkASSERT(stage.getProcessor());
-
-        if (inColor.isZeros()) {
-            SkString inColorName;
-
-            // Effects have no way to communicate zeros, they treat an empty string as ones.
-            this->nameVariable(&inColorName, '\0', "input");
-            fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str());
-            inColor = inColorName;
-        }
-
-        // create var to hold stage result
-        SkString outColorName;
-        this->nameVariable(&outColorName, '\0', "output");
-        fFS.codeAppendf("vec4 %s;", outColorName.c_str());
-        outColor = outColorName;
-
-        SkASSERT(installedProcessors);
-        const typename ProcessorStage::Processor& processor = *stage.getProcessor();
-        SkSTArray<2, GrGLProcessor::TransformedCoords> coords(processor.numTransforms());
-        SkSTArray<4, GrGLProcessor::TextureSampler> samplers(processor.numTextures());
-
-        this->emitTransforms(stage, &coords, installedProcessors);
-        this->emitSamplers(processor, &samplers, installedProcessors);
-
-        typename ProcessorStage::GLProcessor* glEffect =
-                processor.getFactory().createGLInstance(processor);
-        installedProcessors->addEffect(glEffect);
-
-        // Enclose custom code in a block to avoid namespace conflicts
-        SkString openBrace;
-        openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glEffect->name());
-        fFS.codeAppend(openBrace.c_str());
-
-        glEffect->emitCode(this, processor, keyProvider.get(e), outColor.c_str(), inColor.c_str(),
-                           coords, samplers);
-
-        // We have to check that effects and the code they emit are consistent, ie if an effect
-        // asks for dst color, then the emit code needs to follow suit
-        verify(processor);
-        fFS.codeAppend("}");
-
-        inColor = outColor;
+        fGrProcessorEmitter.set(effectStages[e]->getFragmentProcessor());
+        fEffectEmitter = &fGrProcessorEmitter;
+        // calls into the subclass to emit the actual effect into the program effect object
+        this->emitEffect(*effectStages[e], e, keyProvider, &inColor, &outColor);
         effectEmitted = true;
     }
 
@@ -323,77 +182,40 @@ void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processSt
     }
 }
 
-void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
-    SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
-}
+void GrGLProgramBuilder::emitEffect(const GrProcessorStage& effectStage,
+                                    int effectIndex,
+                                    const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+                                    GrGLSLExpr4* inColor,
+                                    GrGLSLExpr4* outColor) {
+    SkASSERT(effectStage.getProcessor());
+    CodeStage::AutoStageRestore csar(&fCodeStage, &effectStage);
+
+    if (inColor->isZeros()) {
+        SkString inColorName;
+
+        // Effects have no way to communicate zeros, they treat an empty string as ones.
+        this->nameVariable(&inColorName, '\0', "input");
+        fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor->c_str());
+        *inColor = inColorName;
+    }
 
-void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
-    SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
-    SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
-}
+    // create var to hold stage result
+    SkString outColorName;
+    this->nameVariable(&outColorName, '\0', "output");
+    fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
+    *outColor = outColorName;
 
-void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
-                                        GrGLProcessor::TransformedCoordsArray* outCoords,
-                                        GrGLInstalledProcessors* installedProcessors) {
-    SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
-            installedProcessors->addTransforms();
-    const GrProcessor* effect = effectStage.getProcessor();
-    int numTransforms = effect->numTransforms();
-    transforms.push_back_n(numTransforms);
-
-    for (int t = 0; t < numTransforms; t++) {
-        const char* uniName = "StageMatrix";
-        GrSLType varyingType =
-                effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
-                        kVec3f_GrSLType :
-                        kVec2f_GrSLType;
-
-        SkString suffixedUniName;
-        if (0 != t) {
-            suffixedUniName.append(uniName);
-            suffixedUniName.appendf("_%i", t);
-            uniName = suffixedUniName.c_str();
-        }
-        transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
-                                                 kMat33f_GrSLType,
-                                                 uniName,
-                                                 &uniName).toShaderBuilderIndex();
-
-        const char* varyingName = "MatrixCoord";
-        SkString suffixedVaryingName;
-        if (0 != t) {
-            suffixedVaryingName.append(varyingName);
-            suffixedVaryingName.appendf("_%i", t);
-            varyingName = suffixedVaryingName.c_str();
-        }
-        const char* vsVaryingName;
-        const char* fsVaryingName;
-        this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
-
-        const GrGLShaderVar& coords =
-                kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
-                                          fVS.positionAttribute() :
-                                          fVS.localCoordsAttribute();
-
-        // varying = matrix * coords (logically)
-        SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
-        if (kVec2f_GrSLType == varyingType) {
-            fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
-                            vsVaryingName, uniName, coords.c_str());
-        } else {
-            fVS.codeAppendf("%s = %s * vec3(%s, 1);",
-                            vsVaryingName, uniName, coords.c_str());
-        }
-        SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
-                               (SkString(fsVaryingName), varyingType));
-    }
+    this->emitEffect(effectStage, keyProvider.get(effectIndex), outColor->c_str(),
+                     inColor->isOnes() ? NULL : inColor->c_str(), fCodeStage.stageIndex());
+
+    *inColor = *outColor;
 }
 
-void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
-                                      GrGLProcessor::TextureSamplerArray* outSamplers,
-                                      GrGLInstalledProcessors* installedProcessors) {
-    SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = installedProcessors->addSamplers();
-    int numTextures = processor.numTextures();
+void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect,
+                                      GrGLProcessor::TextureSamplerArray* outSamplers) {
+    SkTArray<GrGLProgramEffects::Sampler, true>& samplers =
+            this->getProgramEffects()->addSamplers();
+    int numTextures = effect.numTextures();
     samplers.push_back_n(numTextures);
     SkString name;
     for (int t = 0; t < numTextures; ++t) {
@@ -402,37 +224,27 @@ void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
                                                 kSampler2D_GrSLType,
                                                 name.c_str());
         SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
-                               (samplers[t].fUniform, processor.textureAccess(t)));
+                               (samplers[t].fUniform, effect.textureAccess(t)));
     }
 }
 
-GrGLProgram* GrGLProgramBuilder::finalize() {
-    // verify we can get a program id
-    GrGLuint programID;
-    GL_CALL_RET(programID, CreateProgram());
-    if (0 == programID) {
-        return NULL;
+bool GrGLProgramBuilder::finish() {
+    SkASSERT(0 == fProgramID);
+    GL_CALL_RET(fProgramID, CreateProgram());
+    if (!fProgramID) {
+        return false;
     }
 
-    // compile shaders and bind attributes / uniforms
     SkTDArray<GrGLuint> shadersToDelete;
-    if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
-        this->cleanupProgram(programID, shadersToDelete);
-        return NULL;
-    }
-    if (!this->header().fUseFragShaderOnly) {
-        if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
-            this->cleanupProgram(programID, shadersToDelete);
-            return NULL;
-        }
-        fVS.bindVertexAttributes(programID);
-    }
-    bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
-    if (usingBindUniform) {
-        this->bindUniformLocations(programID);
+
+    if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) {
+        GL_CALL(DeleteProgram(fProgramID));
+        return false;
     }
-    fFS.bindFragmentShaderLocations(programID);
-    GL_CALL(LinkProgram(programID));
+
+    this->bindProgramLocations(fProgramID);
+
+    GL_CALL(LinkProgram(fProgramID));
 
     // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
     bool checkLinked = !fGpu->ctxInfo().isChromium();
@@ -440,78 +252,80 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
     checkLinked = true;
 #endif
     if (checkLinked) {
-        checkLinkStatus(programID);
+        GrGLint linked = GR_GL_INIT_ZERO;
+        GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
+        if (!linked) {
+            GrGLint infoLen = GR_GL_INIT_ZERO;
+            GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
+            SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
+            if (infoLen > 0) {
+                // retrieve length even though we don't need it to workaround
+                // bug in chrome cmd buffer param validation.
+                GrGLsizei length = GR_GL_INIT_ZERO;
+                GL_CALL(GetProgramInfoLog(fProgramID,
+                                          infoLen+1,
+                                          &length,
+                                          (char*)log.get()));
+                GrPrintf((char*)log.get());
+            }
+            SkDEBUGFAIL("Error linking program");
+            GL_CALL(DeleteProgram(fProgramID));
+            fProgramID = 0;
+            return false;
+        }
     }
-    if (!usingBindUniform) {
-        this->resolveUniformLocations(programID);
+
+    this->resolveProgramLocations(fProgramID);
+
+    for (int i = 0; i < shadersToDelete.count(); ++i) {
+      GL_CALL(DeleteShader(shadersToDelete[i]));
     }
 
-    this->cleanupShaders(shadersToDelete);
+    return true;
+}
 
-    return this->createProgram(programID);
+bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId,
+                                                 SkTDArray<GrGLuint>* shaderIds) const {
+    return fFS.compileAndAttachShaders(programId, shaderIds);
 }
 
-void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
-    int count = fUniforms.count();
-    for (int i = 0; i < count; ++i) {
-        GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
-        fUniforms[i].fLocation = i;
+void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) {
+    fFS.bindProgramLocations(programId);
+
+    // skbug.com/2056
+    bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
+    if (usingBindUniform) {
+        int count = fUniforms.count();
+        for (int i = 0; i < count; ++i) {
+            GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str()));
+            fUniforms[i].fLocation = i;
+        }
     }
 }
 
-bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
-    GrGLint linked = GR_GL_INIT_ZERO;
-    GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
-    if (!linked) {
-        GrGLint infoLen = GR_GL_INIT_ZERO;
-        GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
-        SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
-        if (infoLen > 0) {
-            // retrieve length even though we don't need it to workaround
-            // bug in chrome cmd buffer param validation.
-            GrGLsizei length = GR_GL_INIT_ZERO;
-            GL_CALL(GetProgramInfoLog(programID,
-                                      infoLen+1,
-                                      &length,
-                                      (char*)log.get()));
-            GrPrintf((char*)log.get());
+void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) {
+    bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
+    if (!usingBindUniform) {
+        int count = fUniforms.count();
+        for (int i = 0; i < count; ++i) {
+            GrGLint location;
+            GL_CALL_RET(location,
+                        GetUniformLocation(programId, fUniforms[i].fVariable.c_str()));
+            fUniforms[i].fLocation = location;
         }
-        SkDEBUGFAIL("Error linking program");
-        GL_CALL(DeleteProgram(programID));
-        programID = 0;
     }
-    return SkToBool(linked);
-}
 
-void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
-    int count = fUniforms.count();
+    int count = fSeparableVaryingInfos.count();
     for (int i = 0; i < count; ++i) {
         GrGLint location;
-        GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
-        fUniforms[i].fLocation = location;
-    }
-}
-
-void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
-    GL_CALL(DeleteProgram(programID));
-    cleanupShaders(shaderIDs);
-}
-void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
-    for (int i = 0; i < shaderIDs.count(); ++i) {
-      GL_CALL(DeleteShader(shaderIDs[i]));
+        GL_CALL_RET(location,
+                    GetProgramResourceLocation(programId,
+                                               GR_GL_FRAGMENT_INPUT,
+                                               fSeparableVaryingInfos[i].fVariable.c_str()));
+        fSeparableVaryingInfos[i].fLocation = location;
     }
 }
 
-GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
-    return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
-                                    fGeometryProcessor, fColorEffects, fCoverageEffects));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-GrGLInstalledProcessors::~GrGLInstalledProcessors() {
-    int numEffects = fGLProcessors.count();
-    for (int e = 0; e < numEffects; ++e) {
-        SkDELETE(fGLProcessors[e]);
-    }
+const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
+    return fGpu->ctxInfo();
 }
index c51dcbba9f3923ac273a7f9c14a019b6bf1484da..7fa8ba266c56ad079c85a60a347ee447a4784e2e 100644 (file)
@@ -8,25 +8,31 @@
 #ifndef GrGLProgramBuilder_DEFINED
 #define GrGLProgramBuilder_DEFINED
 
+#include "GrAllocator.h"
+#include "GrBackendProcessorFactory.h"
+#include "GrColor.h"
+#include "GrProcessor.h"
 #include "GrGLFragmentShaderBuilder.h"
 #include "GrGLGeometryShaderBuilder.h"
 #include "GrGLVertexShaderBuilder.h"
-#include "../GrGLProgramDataManager.h"
-#include "../GrGLUniformHandle.h"
+#include "SkTypes.h"
+#include "gl/GrGLProcessor.h"
+#include "gl/GrGLProgramDesc.h"
+#include "gl/GrGLProgramEffects.h"
+#include "gl/GrGLSL.h"
+#include "gl/GrGLProgramDataManager.h"
 
-class GrGLInstalledProcessors;
+#include <stdarg.h>
 
-/*
- * This is the base class for a series of interfaces.  This base class *MUST* remain abstract with
- * NO data members because it is used in multiple interface inheritance.
- * Heirarchy:
- *                      GrGLUniformBuilder
- *                     /                  \
- *                GrGLFPBuilder       GrGLGPBuilder
- *                     \                  /
- *                     GrGLProgramBuilder(internal use only)
- */
-class GrGLUniformBuilder {
+class GrGLContextInfo;
+class GrProcessorStage;
+class GrGLProgramDesc;
+
+/**
+  Contains all the incremental state of a shader as it is being built,as well as helpers to
+  manipulate that state.
+*/
+class GrGLProgramBuilder {
 public:
     enum ShaderVisibility {
         kVertex_Visibility   = 0x1,
@@ -34,80 +40,44 @@ public:
         kFragment_Visibility = 0x4,
     };
 
-    virtual ~GrGLUniformBuilder() {}
-
     typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+    typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
 
-    /** Add a uniform variable to the current program, that has visibility in one or more shaders.
-        visibility is a bitfield of ShaderVisibility values indicating from which shaders the
-        uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
-        supported at this time. The actual uniform name will be mangled. If outName is not NULL then
-        it will refer to the final uniform name after return. Use the addUniformArray variant to add
-        an array of uniforms. */
-    virtual UniformHandle addUniform(uint32_t visibility,
-                                     GrSLType type,
-                                     const char* name,
-                                     const char** outName = NULL) = 0;
-    virtual UniformHandle addUniformArray(uint32_t visibility,
-                                          GrSLType type,
-                                          const char* name,
-                                          int arrayCount,
-                                          const char** outName = NULL) = 0;
-
-    virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
-
-    /**
-     * Shortcut for getUniformVariable(u).c_str()
-     */
-    virtual const char* getUniformCStr(UniformHandle u) const = 0;
-
-    virtual const GrGLContextInfo& ctxInfo() const = 0;
-
-    virtual GrGpuGL* gpu() const = 0;
+    // Handles for program uniforms (other than per-effect uniforms)
+    struct BuiltinUniformHandles {
+        UniformHandle       fViewMatrixUni;
+        UniformHandle       fRTAdjustmentUni;
+        UniformHandle       fColorUni;
+        UniformHandle       fCoverageUni;
 
-    /*
-     * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
-     */
-};
+        // We use the render target height to provide a y-down frag coord when specifying
+        // origin_upper_left is not supported.
+        UniformHandle       fRTHeightUni;
 
-/* a specialization of the above for GPs.  Lets the user add uniforms, varyings, and VS / FS code */
-class GrGLGPBuilder : public virtual GrGLUniformBuilder {
-public:
-    virtual void addVarying(GrSLType type,
-                            const char* name,
-                            const char** vsOutName = NULL,
-                            const char** fsInName = NULL,
-                            GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
+        // Uniforms for computing texture coords to do the dst-copy lookup
+        UniformHandle       fDstCopyTopLeftUni;
+        UniformHandle       fDstCopyScaleUni;
+        UniformHandle       fDstCopySamplerUni;
+    };
 
-    // TODO rename getFragmentBuilder
-    virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
-    virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
+    struct UniformInfo {
+        GrGLShaderVar fVariable;
+        uint32_t      fVisibility;
+        GrGLint       fLocation;
+    };
 
-    /*
-     * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
-     */
-};
+    // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
+    // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
+    // name strings. Otherwise, we'd have to hand out copies.
+    typedef GrTAllocator<UniformInfo> UniformInfoArray;
 
-/* a specializations for FPs. Lets the user add uniforms and FS code */
-class GrGLFPBuilder : public virtual GrGLUniformBuilder {
-public:
-    virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
+    struct SeparableVaryingInfo {
+        GrGLShaderVar fVariable;
+        GrGLint       fLocation;
+    };
 
-    /*
-     * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
-     */
-};
+    typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
 
-/*
- * Please note - no diamond problems because of virtual inheritance.  Also, both base classes
- * are pure virtual with no data members.  This is the base class for program building.
- * Subclasses are nearly identical but each has their own way of emitting transforms.  State for
- * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
- * respective builders
-*/
-class GrGLProgramBuilder : public GrGLGPBuilder,
-                           public GrGLFPBuilder {
-public:
     /** Generates a shader program.
      *
      * The program implements what is specified in the stages given as input.
@@ -115,226 +85,252 @@ public:
      * to be used.
      * @return true if generation was successful.
      */
-    static GrGLProgram* CreateProgram(const GrOptDrawState&,
-                                      const GrGLProgramDesc&,
-                                      GrGpu::DrawType,
-                                      const GrGeometryStage* inGeometryProcessor,
-                                      const GrFragmentStage* inColorStages[],
-                                      const GrFragmentStage* inCoverageStages[],
-                                      GrGpuGL* gpu);
-
-    virtual UniformHandle addUniform(uint32_t visibility,
-                                     GrSLType type,
-                                     const char* name,
-                                     const char** outName = NULL) SK_OVERRIDE {
+
+    bool genProgram(const GrGeometryStage* inGeometryProcessor,
+                    const GrFragmentStage* inColorStages[],
+                    const GrFragmentStage* inCoverageStages[]);
+
+    GrGLProgramEffects* getGeometryProcessor() const {
+        SkASSERT(fProgramID); return fGeometryProcessor.get();
+    }
+    GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
+    GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
+    const BuiltinUniformHandles& getBuiltinUniformHandles() const {
+        SkASSERT(fProgramID);
+        return fUniformHandles;
+    }
+    GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
+    bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
+    int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
+    const UniformInfoArray& getUniformInfos() const { return fUniforms; }
+    const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
+        return fSeparableVaryingInfos;
+    }
+
+    virtual ~GrGLProgramBuilder() {}
+
+    /** Add a uniform variable to the current program, that has visibility in one or more shaders.
+        visibility is a bitfield of ShaderVisibility values indicating from which shaders the
+        uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
+        supported at this time. The actual uniform name will be mangled. If outName is not NULL then
+        it will refer to the final uniform name after return. Use the addUniformArray variant to add
+        an array of uniforms. */
+    GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
+                                                     GrSLType type,
+                                                     const char* name,
+                                                     const char** outName = NULL) {
         return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
     }
-    virtual UniformHandle addUniformArray(uint32_t visibility,
-                                          GrSLType type,
-                                          const char* name,
-                                          int arrayCount,
-                                          const char** outName = NULL) SK_OVERRIDE;
+    GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
+                                                          GrSLType type,
+                                                          const char* name,
+                                                          int arrayCount,
+                                                          const char** outName = NULL);
 
-    virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
+    const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
         return fUniforms[u.toShaderBuilderIndex()].fVariable;
     }
 
-    virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
+    /**
+     * Shortcut for getUniformVariable(u).c_str()
+     */
+    const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
         return this->getUniformVariable(u).c_str();
     }
 
-    virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
+    const GrGLContextInfo& ctxInfo() const;
 
-    virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
-
-    virtual GrGLFragmentShaderBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
-    virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
-
-    virtual void addVarying(GrSLType type,
-                            const char* name,
-                            const char** vsOutName = NULL,
-                            const char** fsInName = NULL,
-                            GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
-
-    // Handles for program uniforms (other than per-effect uniforms)
-    struct BuiltinUniformHandles {
-        UniformHandle       fViewMatrixUni;
-        UniformHandle       fRTAdjustmentUni;
-        UniformHandle       fColorUni;
-        UniformHandle       fCoverageUni;
-
-        // We use the render target height to provide a y-down frag coord when specifying
-        // origin_upper_left is not supported.
-        UniformHandle       fRTHeightUni;
-
-        // Uniforms for computing texture coords to do the dst-copy lookup
-        UniformHandle       fDstCopyTopLeftUni;
-        UniformHandle       fDstCopyScaleUni;
-        UniformHandle       fDstCopySamplerUni;
-    };
+    GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
+    GrGpuGL* gpu() const { return fGpu; }
 
 protected:
-    static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&,
-                                                    const GrOptDrawState&,
-                                                    GrGpu::DrawType,
-                                                    bool hasGeometryProcessor,
-                                                    GrGpuGL*);
-
+    typedef GrTAllocator<GrGLShaderVar> VarArray;
     GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
 
     const GrOptDrawState& optState() const { return fOptState; }
     const GrGLProgramDesc& desc() const { return fDesc; }
-    const GrGLProgramDesc::KeyHeader& header() const { return fDesc.getHeader(); }
+
+    // Helper for emitEffects().
+    void createAndEmitEffects(const GrFragmentStage* effectStages[],
+                              int effectCnt,
+                              const GrGLProgramDesc::EffectKeyProvider&,
+                              GrGLSLExpr4* inOutFSColor);
+
+    /*
+     * A helper function called to emit the geometry processor as well as individual coverage
+     * and color stages.  this will call into subclasses emit effect
+     */
+    void emitEffect(const GrProcessorStage& effectStage,
+                    int effectIndex,
+                    const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+                    GrGLSLExpr4* inColor,
+                    GrGLSLExpr4* outColor);
+
+    /**
+     * Helper for emitEffect() in subclasses. Emits uniforms for an effect's texture accesses and
+     * appends the necessary data to the TextureSamplerArray* object so effects can add texture
+     * lookups to their code. This method is only meant to be called during the construction phase.
+     */
+    void emitSamplers(const GrProcessor& effect,
+                      GrGLProcessor::TextureSamplerArray* outSamplers);
 
     // Generates a name for a variable. The generated string will be name prefixed by the prefix
     // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
     // generating stage code.
     void nameVariable(SkString* out, char prefix, const char* name);
-    void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
-    void createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
-                                 const GrFragmentStage* colorStages[],
-                                 const GrFragmentStage* coverageStages[],
-                                 GrGLSLExpr4* inputColor,
-                                 GrGLSLExpr4* inputCoverage);
-    template <class ProcessorStage>
-    void createAndEmitProcessors(const ProcessorStage*[],
-                                 int effectCnt,
-                                 const GrGLProgramDesc::EffectKeyProvider&,
-                                 GrGLSLExpr4* fsInOutColor,
-                                 GrGLInstalledProcessors*);
-    void verify(const GrGeometryProcessor&);
-    void verify(const GrFragmentProcessor&);
-    void emitSamplers(const GrProcessor&,
-                      GrGLProcessor::TextureSamplerArray* outSamplers,
-                      GrGLInstalledProcessors*);
-
-    // each specific program builder has a distinct transform and must override this function
-    virtual void emitTransforms(const GrProcessorStage&,
-                                GrGLProcessor::TransformedCoordsArray* outCoords,
-                                GrGLInstalledProcessors*);
-    GrGLProgram* finalize();
-    void bindUniformLocations(GrGLuint programID);
-    bool checkLinkStatus(GrGLuint programID);
-    void resolveUniformLocations(GrGLuint programID);
-
-    void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
-    void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
-
-    // Subclasses create different programs
-    virtual GrGLProgram* createProgram(GrGLuint programID);
 
-    void appendUniformDecls(ShaderVisibility, SkString*) const;
+    virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
 
-    // reset is called by program creator between each processor's emit code.  It increments the
-    // stage offset for variable name mangling, and also ensures verfication variables in the
-    // fragment shader are cleared.
-    void reset() {
-        this->enterStage();
-        this->addStage();
-        fFS.reset();
-    }
-    void addStage() { fStageIndex++; }
+    virtual void bindProgramLocations(GrGLuint programId);
+    void resolveProgramLocations(GrGLuint programId);
 
-    // This simple class exits the stage and then restores the stage when it goes out of scope
-    class AutoStageRestore {
-    public:
-        AutoStageRestore(GrGLProgramBuilder* pb)
-            : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
-        ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
-    private:
-        GrGLProgramBuilder* fPB;
-        bool fOutOfStage;
-    };
-    void exitStage() { fOutOfStage = true; }
-    void enterStage() { fOutOfStage = false; }
-    int stageIndex() const { return fStageIndex; }
-
-    typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
-    typedef GrGLProgramDataManager::UniformInfo UniformInfo;
-    typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
-
-    // number of each input/output type in a single allocation block, used by many builders
-    static const int kVarsPerBlock;
-
-    BuiltinUniformHandles fUniformHandles;
-    GrGLVertexBuilder fVS;
-    GrGLGeometryBuilder fGS;
-    GrGLFragmentShaderBuilder fFS;
-    bool fOutOfStage;
-    int fStageIndex;
-
-    SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
-    SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
-    SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
+    void appendDecls(const VarArray&, SkString*) const;
+    void appendUniformDecls(ShaderVisibility, SkString*) const;
 
-    const GrOptDrawState& fOptState;
-    const GrGLProgramDesc& fDesc;
-    GrGpuGL* fGpu;
-    UniformInfoArray fUniforms;
+    class CodeStage : SkNoncopyable {
+    public:
+        CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
 
-    friend class GrGLShaderBuilder;
-    friend class GrGLVertexBuilder;
-    friend class GrGLFragmentShaderBuilder;
-    friend class GrGLGeometryBuilder;
-};
+        bool inStageCode() const {
+            this->validate();
+            return SkToBool(fEffectStage);
+        }
 
-/**
- * This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
- * and textures). It is built by GrGLProgramBuilder, then used to manage the necessary GL
- * state and shader uniforms in GLPrograms.  Its just Plain old data, and as such is entirely public
- *
- * TODO We really don't need this class to have an array of processors.  It makes sense for it
- * to just have one, also break out the transforms
- */
-class GrGLInstalledProcessors : public SkRefCnt {
-public:
-    GrGLInstalledProcessors(int reserveCount, bool hasExplicitLocalCoords = false)
-        : fGLProcessors(reserveCount)
-        , fSamplers(reserveCount)
-        , fTransforms(reserveCount)
-        , fHasExplicitLocalCoords(hasExplicitLocalCoords) {
-    }
+        const GrProcessorStage* effectStage() const {
+            this->validate();
+            return fEffectStage;
+        }
 
-    virtual ~GrGLInstalledProcessors();
+        int stageIndex() const {
+            this->validate();
+            return fCurrentIndex;
+        }
 
-    typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+        class AutoStageRestore : SkNoncopyable {
+        public:
+            AutoStageRestore(CodeStage* codeStage, const GrProcessorStage* newStage) {
+                SkASSERT(codeStage);
+                fSavedIndex = codeStage->fCurrentIndex;
+                fSavedEffectStage = codeStage->fEffectStage;
+
+                if (NULL == newStage) {
+                    codeStage->fCurrentIndex = -1;
+                } else {
+                    codeStage->fCurrentIndex = codeStage->fNextIndex++;
+                }
+                codeStage->fEffectStage = newStage;
+
+                fCodeStage = codeStage;
+            }
+            ~AutoStageRestore() {
+                fCodeStage->fCurrentIndex = fSavedIndex;
+                fCodeStage->fEffectStage = fSavedEffectStage;
+            }
+        private:
+            CodeStage*              fCodeStage;
+            int                     fSavedIndex;
+            const GrProcessorStage*    fSavedEffectStage;
+        };
+    private:
+        void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
+        int                     fNextIndex;
+        int                     fCurrentIndex;
+        const GrProcessorStage*    fEffectStage;
+    };
 
-    struct Sampler {
-        SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
-        UniformHandle  fUniform;
-        int            fTextureUnit;
+    class GrGLProcessorEmitterInterface {
+     public:
+        virtual ~GrGLProcessorEmitterInterface() {}
+        virtual GrGLProcessor* createGLInstance() = 0;
+        virtual void emit(const GrProcessorKey& key,
+                          const char* outColor,
+                          const char* inColor,
+                          const GrGLProcessor::TransformedCoordsArray& coords,
+                          const GrGLProcessor::TextureSamplerArray& samplers) = 0;
     };
 
-    class ShaderVarHandle {
+    class GrGLFragmentProcessorEmitter  : public GrGLProcessorEmitterInterface {
     public:
-        bool isValid() const { return fHandle > -1; }
-        ShaderVarHandle() : fHandle(-1) {}
-        ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
-        int handle() const { SkASSERT(this->isValid()); return fHandle; }
-        UniformHandle convertToUniformHandle() {
-            SkASSERT(this->isValid());
-            return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
+        GrGLFragmentProcessorEmitter(GrGLProgramBuilder* builder)
+            : fBuilder(builder)
+            , fFragmentProcessor(NULL)
+            , fGLFragmentProcessor(NULL) {}
+        virtual ~GrGLFragmentProcessorEmitter() {}
+        void set(const GrFragmentProcessor* fp) {
+            SkASSERT(NULL == fFragmentProcessor);
+            fFragmentProcessor = fp;
+        }
+        virtual GrGLProcessor* createGLInstance() {
+            SkASSERT(fFragmentProcessor);
+            SkASSERT(NULL == fGLFragmentProcessor);
+            fGLFragmentProcessor =
+                    fFragmentProcessor->getFactory().createGLInstance(*fFragmentProcessor);
+            return fGLFragmentProcessor;
+        }
+        virtual void emit(const GrProcessorKey& key,
+                          const char* outColor,
+                          const char* inColor,
+                          const GrGLProcessor::TransformedCoordsArray& coords,
+                          const GrGLProcessor::TextureSamplerArray& samplers) {
+            SkASSERT(fFragmentProcessor);
+            SkASSERT(fGLFragmentProcessor);
+            fGLFragmentProcessor->emitCode(fBuilder, *fFragmentProcessor, key, outColor, inColor,
+                                           coords, samplers);
+            // this will not leak because it hasa already been used by createGLInstance
+            fGLFragmentProcessor = NULL;
+            fFragmentProcessor = NULL;
         }
-
     private:
-        int fHandle;
+        GrGLProgramBuilder*         fBuilder;
+        const GrFragmentProcessor*  fFragmentProcessor;
+        GrGLFragmentProcessor*      fGLFragmentProcessor;
     };
 
-    struct Transform {
-        Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
-        ShaderVarHandle fHandle;
-        SkMatrix       fCurrentValue;
-        GrSLType       fType;
-    };
+    GrGLProcessorEmitterInterface*   fEffectEmitter;
+    CodeStage                        fCodeStage;
+    SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
+    SkAutoTUnref<GrGLProgramEffects> fColorEffects;
+    SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
+    BuiltinUniformHandles            fUniformHandles;
+    bool                             fFragOnly;
+    int                              fTexCoordSetCnt;
+    GrGLuint                         fProgramID;
+    GrGLFragmentShaderBuilder        fFS;
+    SeparableVaryingInfoArray        fSeparableVaryingInfos;
+
+private:
+    virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
+                                      const GrFragmentStage* colorStages[],
+                                      const GrFragmentStage* coverageStages[],
+                                      GrGLSLExpr4* inputColor,
+                                      GrGLSLExpr4* inputCoverage) = 0;
+    /*
+     * Subclasses override emitEffect below to emit data and code for a specific single effect
+     */
+    virtual void emitEffect(const GrProcessorStage&,
+                            const GrProcessorKey&,
+                            const char* outColor,
+                            const char* inColor,
+                            int stageIndex) = 0;
+
+    /*
+     * Because we have fragment only builders, and those builders need to implement a subclass
+     * of program effects, we have to have base classes overload the program effects here
+     */
+    virtual GrGLProgramEffects* getProgramEffects() = 0;
+
+    /**
+     * Compiles all the shaders, links them into a program, and writes the program id to the output
+     * struct.
+     **/
+    bool finish();
 
-    void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
-    SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
-    SkTArray<Transform, true>& addTransforms() { return fTransforms.push_back(); }
+    GrGLFragmentProcessorEmitter            fGrProcessorEmitter;
 
-    SkTArray<GrGLProcessor*>                 fGLProcessors;
-    SkTArray<SkSTArray<4, Sampler, true> >   fSamplers;
-    SkTArray<SkSTArray<2, Transform, true> > fTransforms;
-    bool                                     fHasExplicitLocalCoords;
+    const GrOptDrawState&                   fOptState;
+    const GrGLProgramDesc&                  fDesc;
+    GrGpuGL*                                fGpu;
+    UniformInfoArray                        fUniforms;
 
     friend class GrGLShaderBuilder;
     friend class GrGLVertexShaderBuilder;
index 36d124f3873ec3a79c1bb2ba462339a9a35a92c8..33474e60d4366e029e4db798248fa42f355c4713 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #include "GrGLShaderBuilder.h"
-#include "GrGLProgramBuilder.h"
+#include "GrGLFullProgramBuilder.h"
 #include "GrGLProgramBuilder.h"
 #include "../GrGpuGL.h"
 #include "../GrGLShaderVar.h"
@@ -53,12 +53,13 @@ void append_texture_lookup(SkString* out,
         out->appendf(".%s", swizzle);
     }
 }
+static const int kVarsPerBlock = 8;
 }
 
 GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program)
     : fProgramBuilder(program)
-    , fInputs(GrGLProgramBuilder::kVarsPerBlock)
-    , fOutputs(GrGLProgramBuilder::kVarsPerBlock)
+    , fInputs(kVarsPerBlock)
+    , fOutputs(kVarsPerBlock)
     , fFeaturesAddedMask(0) {
 }
 
@@ -142,13 +143,6 @@ void GrGLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionNam
     }
 }
 
-void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
-    for (int i = 0; i < vars.count(); ++i) {
-        vars[i].appendDecl(fProgramBuilder->ctxInfo(), out);
-        out->append(";\n");
-    }
-}
-
 void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
                                             const char* coordName,
                                             uint32_t configComponentMask,
@@ -161,3 +155,8 @@ void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
                           swizzle,
                           kVec2f_GrSLType);
 }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGLFullProgramBuilder* program)
+    : INHERITED(program)
+    , fFullProgramBuilder(program) {}
index cf7ae9b53d21f081b6452b312b7d546625c80c71..e99fcce7478d4058164af1a44954f3ac1a32e559 100644 (file)
@@ -9,12 +9,21 @@
 #define GrGLShaderBuilder_DEFINED
 
 #include "gl/GrGLProgramDesc.h"
+#include "gl/GrGLProgramEffects.h"
+#include "gl/GrGLSL.h"
 #include "gl/GrGLProgramDataManager.h"
+#include "GrBackendProcessorFactory.h"
+#include "GrColor.h"
+#include "GrProcessor.h"
+#include "SkTypes.h"
 
 #include <stdarg.h>
 
 class GrGLContextInfo;
+class GrProcessorStage;
+class GrGLProgramDesc;
 class GrGLProgramBuilder;
+class GrGLFullProgramBuilder;
 
 /**
   base class for all shaders builders
@@ -23,7 +32,6 @@ class GrGLShaderBuilder {
 public:
     typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
     typedef GrGLProcessor::TextureSampler TextureSampler;
-
     GrGLShaderBuilder(GrGLProgramBuilder* program);
 
     void addInput(GrGLShaderVar i) { fInputs.push_back(i); }
@@ -104,7 +112,7 @@ public:
     GrGLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
 
     /**
-     * Helper for begining and ending a block in the shader code.
+     * Helper for begining and ending a block in the fragment code.
      */
     class ShaderBlock {
     public:
@@ -119,10 +127,7 @@ public:
     private:
         GrGLShaderBuilder* fBuilder;
     };
-
 protected:
-    typedef GrTAllocator<GrGLShaderVar> VarArray;
-    void appendDecls(const VarArray& vars, SkString* out) const;
 
     /*
      * this super low level function is just for use internally to builders
@@ -137,6 +142,8 @@ protected:
      */
     void addFeature(uint32_t featureBit, const char* extensionName);
 
+    typedef GrTAllocator<GrGLShaderVar> VarArray;
+
     GrGLProgramBuilder* fProgramBuilder;
 
     SkString fCode;
@@ -147,4 +154,21 @@ protected:
     VarArray fOutputs;
     uint32_t fFeaturesAddedMask;
 };
+
+
+/*
+ * Full Shader builder is the base class for shaders which are only accessible through full program
+ * builder, ie vertex, geometry, and later TCU / TES.  Using this base class, they can access the
+ * full program builder functionality through the full program pointer
+ */
+class GrGLFullShaderBuilder : public GrGLShaderBuilder {
+public:
+    GrGLFullShaderBuilder(GrGLFullProgramBuilder* program);
+
+    GrGLFullProgramBuilder* fullProgramBuilder() { return fFullProgramBuilder; }
+protected:
+    GrGLFullProgramBuilder* fFullProgramBuilder;
+private:
+    typedef GrGLShaderBuilder INHERITED;
+};
 #endif
index 76026b7a25005509701e91a874837d72555fe81f..55ce7d14587b5d9045440fa51e54f7c0b5868aa1 100644 (file)
@@ -6,76 +6,38 @@
  */
 
 #include "GrGLVertexShaderBuilder.h"
-#include "GrGLProgramBuilder.h"
+#include "GrGLFullProgramBuilder.h"
 #include "GrGLShaderStringBuilder.h"
 #include "../GrGpuGL.h"
+#include "../../GrOptDrawState.h"
 
-#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X)
-#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X)
+#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
+#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
 
-static const char* color_attribute_name() { return "inColor"; }
-static const char* coverage_attribute_name() { return "inCoverage"; }
+namespace {
+inline const char* color_attribute_name() { return "inColor"; }
+inline const char* coverage_attribute_name() { return "inCoverage"; }
+}
 
-GrGLVertexBuilder::GrGLVertexBuilder(GrGLProgramBuilder* program)
+GrGLVertexShaderBuilder::GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program)
     : INHERITED(program)
     , fPositionVar(NULL)
-    , fLocalCoordsVar(NULL)
-    , fEffectAttribOffset(0) {
-}
-
-SkString* GrGLVertexBuilder::addVarying(GrSLType type, const char* name,
-                                              const char** vsOutName) {
-    fOutputs.push_back();
-    fOutputs.back().setType(type);
-    fOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
-    fProgramBuilder->nameVariable(fOutputs.back().accessName(), 'v', name);
-
-    if (vsOutName) {
-        *vsOutName = fOutputs.back().getName().c_str();
-    }
-    return fOutputs.back().accessName();
+    , fLocalCoordsVar(NULL) {
 }
-
-void GrGLVertexBuilder::setupLocalCoords() {
-    fPositionVar = &fInputs.push_back();
-    fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition");
-    if (-1 != fProgramBuilder->header().fLocalCoordAttributeIndex) {
-        fLocalCoordsVar = &fInputs.push_back();
-        fLocalCoordsVar->set(kVec2f_GrSLType,
-                             GrGLShaderVar::kAttribute_TypeModifier,
-                             "inLocalCoords");
-    } else {
-        fLocalCoordsVar = fPositionVar;
+bool GrGLVertexShaderBuilder::addAttribute(const GrShaderVar& var) {
+    SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier());
+    for (int i = 0; i < fInputs.count(); ++i) {
+        const GrGLShaderVar& attr = fInputs[i];
+        // if attribute already added, don't add it again
+        if (attr.getName().equals(var.getName())) {
+            return false;
+        }
     }
-    fEffectAttribOffset = fInputs.count();
-}
-
-void GrGLVertexBuilder::transformGLToSkiaCoords() {
-    const char* viewMName;
-    fProgramBuilder->fUniformHandles.fViewMatrixUni =
-            fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
-                                        kMat33f_GrSLType,
-                                        "ViewM",
-                                        &viewMName);
-
-    // Transform the position into Skia's device coords.
-    this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);", viewMName, fPositionVar->c_str());
-}
-
-void GrGLVertexBuilder::setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out) {
-    SkString name(inName);
-    const char *vsName, *fsName;
-    fProgramBuilder->addVarying(kVec4f_GrSLType, name.c_str(), &vsName, &fsName);
-    name.prepend("in");
-    this->addAttribute(GrShaderVar(name.c_str(),
-                                   kVec4f_GrSLType,
-                                   GrShaderVar::kAttribute_TypeModifier));
-    this->codeAppendf("%s = %s;", vsName, name.c_str());
-    *out = fsName;
-    fEffectAttribOffset++;
+    fInputs.push_back(var);
+    return true;
 }
 
-void GrGLVertexBuilder::emitAttributes(const GrGeometryProcessor& gp) {
+void GrGLVertexShaderBuilder::emitAttributes(const GrGeometryProcessor& gp) {
     const GrGeometryProcessor::VertexAttribArray& vars = gp.getVertexAttribs();
     int numAttributes = vars.count();
     for (int a = 0; a < numAttributes; ++a) {
@@ -83,38 +45,39 @@ void GrGLVertexBuilder::emitAttributes(const GrGeometryProcessor& gp) {
     }
 }
 
-void GrGLVertexBuilder::transformSkiaToGLCoords() {
-    const char* rtAdjustName;
-    fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
-            fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
-                                        kVec4f_GrSLType,
-                                        "rtAdjustment",
-                                        &rtAdjustName);
+void GrGLVertexShaderBuilder::addVarying(GrSLType type, const char* name, const char** vsOutName) {
+    fOutputs.push_back();
+    fOutputs.back().setType(type);
+    fOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
+    fProgramBuilder->nameVariable(fOutputs.back().accessName(), 'v', name);
 
-    // Transform from Skia's device coords to GL's normalized device coords.
-    this->codeAppendf("gl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);",
-                    rtAdjustName, rtAdjustName);
+    if (vsOutName) {
+        *vsOutName = fOutputs.back().getName().c_str();
+    }
 }
 
-void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) {
+
+void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) {
+    const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
+    GrGpuGL* gpu = fProgramBuilder->gpu();
+
     // Bind the attrib locations to same values for all shaders
-    const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->header();
     SkASSERT(-1 != header.fPositionAttributeIndex);
-    GL_CALL(BindAttribLocation(programID,
+    GL_CALL(BindAttribLocation(programId,
                                header.fPositionAttributeIndex,
                                fPositionVar->c_str()));
     if (-1 != header.fLocalCoordAttributeIndex) {
-        GL_CALL(BindAttribLocation(programID,
+        GL_CALL(BindAttribLocation(programId,
                                    header.fLocalCoordAttributeIndex,
                                    fLocalCoordsVar->c_str()));
     }
     if (-1 != header.fColorAttributeIndex) {
-        GL_CALL(BindAttribLocation(programID,
+        GL_CALL(BindAttribLocation(programId,
                                    header.fColorAttributeIndex,
                                    color_attribute_name()));
     }
     if (-1 != header.fCoverageAttributeIndex) {
-        GL_CALL(BindAttribLocation(programID,
+        GL_CALL(BindAttribLocation(programId,
                                    header.fCoverageAttributeIndex,
                                    coverage_attribute_name()));
     }
@@ -123,7 +86,6 @@ void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) {
     const GrVertexAttrib* vaPtr = optState.getVertexAttribs();
     const int vaCount = optState.getVertexAttribCount();
 
-    // We start binding attributes after builtins
     int i = fEffectAttribOffset;
     for (int index = 0; index < vaCount; index++) {
         if (kGeometryProcessor_GrVertexAttribBinding != vaPtr[index].fBinding) {
@@ -135,22 +97,22 @@ void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) {
                  index != header.fCoverageAttributeIndex);
         // We should never find another effect attribute if we have bound everything
         SkASSERT(i < fInputs.count());
-        GL_CALL(BindAttribLocation(programID, index, fInputs[i].c_str()));
+        GL_CALL(BindAttribLocation(programId, index, fInputs[i].c_str()));
         i++;
     }
     // Make sure we bound everything
     SkASSERT(fInputs.count() == i);
 }
 
-bool GrGLVertexBuilder::compileAndAttachShaders(GrGLuint programId,
+bool GrGLVertexShaderBuilder::compileAndAttachShaders(GrGLuint programId,
         SkTDArray<GrGLuint>* shaderIds) const {
     GrGpuGL* gpu = fProgramBuilder->gpu();
     const GrGLContext& glCtx = gpu->glContext();
     const GrGLContextInfo& ctxInfo = gpu->ctxInfo();
     SkString vertShaderSrc(GrGetGLSLVersionDecl(ctxInfo));
     fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &vertShaderSrc);
-    this->appendDecls(fInputs, &vertShaderSrc);
-    this->appendDecls(fOutputs, &vertShaderSrc);
+    fProgramBuilder->appendDecls(fInputs, &vertShaderSrc);
+    fProgramBuilder->appendDecls(fOutputs, &vertShaderSrc);
     vertShaderSrc.append("void main() {");
     vertShaderSrc.append(fCode);
     vertShaderSrc.append("}\n");
@@ -164,15 +126,72 @@ bool GrGLVertexBuilder::compileAndAttachShaders(GrGLuint programId,
     return true;
 }
 
-bool GrGLVertexBuilder::addAttribute(const GrShaderVar& var) {
-    SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier());
-    for (int i = 0; i < fInputs.count(); ++i) {
-        const GrGLShaderVar& attr = fInputs[i];
-        // if attribute already added, don't add it again
-        if (attr.getName().equals(var.getName())) {
-            return false;
-        }
+void GrGLVertexShaderBuilder::emitCodeAfterEffects() {
+    const char* rtAdjustName;
+    fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
+        fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+                             kVec4f_GrSLType,
+                             "rtAdjustment",
+                             &rtAdjustName);
+
+    // Transform from Skia's device coords to GL's normalized device coords.
+    this->codeAppendf(
+        "gl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);",
+        rtAdjustName, rtAdjustName);
+}
+
+void GrGLVertexShaderBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
+    const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
+
+    fPositionVar = &fInputs.push_back();
+    fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition");
+    if (-1 != header.fLocalCoordAttributeIndex) {
+        fLocalCoordsVar = &fInputs.push_back();
+        fLocalCoordsVar->set(kVec2f_GrSLType,
+                             GrGLShaderVar::kAttribute_TypeModifier,
+                             "inLocalCoords");
+    } else {
+        fLocalCoordsVar = fPositionVar;
     }
-    fInputs.push_back(var);
-    return true;
+
+    const char* viewMName;
+    fProgramBuilder->fUniformHandles.fViewMatrixUni =
+            fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+                                 kMat33f_GrSLType,
+                                 "ViewM",
+                                 &viewMName);
+
+    // Transform the position into Skia's device coords.
+    this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);",
+                      viewMName, fPositionVar->c_str());
+
+    // we output point size in the GS if present
+    if (header.fEmitsPointSize
+#if GR_GL_EXPERIMENTAL_GS
+        && !header.fExperimentalGS
+#endif
+        ) {
+        this->codeAppend("gl_PointSize = 1.0;");
+    }
+
+    if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
+        this->addAttribute(GrShaderVar(color_attribute_name(),
+                                       kVec4f_GrSLType,
+                                       GrShaderVar::kAttribute_TypeModifier));
+        const char *vsName, *fsName;
+        fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
+        this->codeAppendf("%s = %s;", vsName, color_attribute_name());
+        *color = fsName;
+    }
+
+    if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
+        this->addAttribute(GrShaderVar(coverage_attribute_name(),
+                                       kVec4f_GrSLType,
+                                       GrShaderVar::kAttribute_TypeModifier));
+        const char *vsName, *fsName;
+        fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
+        this->codeAppendf("%s = %s;", vsName, coverage_attribute_name());
+        *coverage = fsName;
+    }
+    fEffectAttribOffset = fInputs.count();
 }
index 0b85b84dfb6994642fff5152cbe42c3ce68b9c12..c93b3be6682c5252025a27233deb9ad3ea78f71b 100644 (file)
@@ -7,22 +7,26 @@
 
 #ifndef GrGLVertexShader_DEFINED
 #define GrGLVertexShader_DEFINED
-
 #include "GrGLShaderBuilder.h"
 
 class GrGLProgramBuilder;
 
-// TODO we only actually ever need to return a GrGLShaderBuilder for this guy, none of the below
-// functions need to be part of VertexShaderBuilder's public interface
-class GrGLVertexBuilder : public GrGLShaderBuilder {
+class GrGLVertexShaderBuilder : public GrGLFullShaderBuilder {
 public:
-    GrGLVertexBuilder(GrGLProgramBuilder* program);
+    GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program);
+
+    /*
+     * this call is only for GrGLProgramEffects' internal use
+     */
+    void emitAttributes(const GrGeometryProcessor& gp);
 
     /**
      * Are explicit local coordinates provided as input to the vertex shader.
      */
     bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
 
+    const SkString* getEffectAttributeName(int attributeIndex) const;
+
     /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
         as positionAttribute() or it may not be. It depends upon whether the rendering code
         specified explicit local coords or not in the GrDrawState. */
@@ -33,25 +37,28 @@ public:
       */
     const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
 
+private:
     /*
-     * Internal call for GrGLProgramBuilder.addVarying
+     * Add attribute will push a new attribute onto the end.  It will also assert if there is
+     * a duplicate attribute
      */
-    SkString* addVarying(GrSLType type, const char* name, const char** vsOutName);
+    bool addAttribute(const GrShaderVar& var);
+
+    /*
+     * Internal call for GrGLFullProgramBuilder.addVarying
+     */
+    void addVarying(GrSLType type,
+                   const char* name,
+                   const char** vsOutName);
 
     /*
      * private helpers for compilation by GrGLProgramBuilder
      */
-    void setupLocalCoords();
-    void transformGLToSkiaCoords();
-    void setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out);
-    void emitAttributes(const GrGeometryProcessor& gp);
-    void transformSkiaToGLCoords();
-    void bindVertexAttributes(GrGLuint programID);
+    void bindProgramLocations(GrGLuint programId);
     bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
+    void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage);
+    void emitCodeAfterEffects();
 
-private:
-    // an internal call which checks for uniquness of a var before adding it to the list of inputs
-    bool addAttribute(const GrShaderVar& var);
     struct AttributePair {
         void set(int index, const SkString& name) {
             fIndex = index; fName = name;
@@ -64,7 +71,9 @@ private:
     GrGLShaderVar*                      fLocalCoordsVar;
     int                                 fEffectAttribOffset;
 
-    typedef GrGLShaderBuilder INHERITED;
+    friend class GrGLFullProgramBuilder;
+
+    typedef GrGLFullShaderBuilder INHERITED;
 };
 
 #endif
index c31aa1e0da6b909a3d884f8d9e0ffcea7dfdd0a3..d8ce3fdc9ff4d312b7ef5292692f10ddca199ce3 100644 (file)
@@ -16,7 +16,6 @@
 #include "GrContextFactory.h"
 #include "GrOptDrawState.h"
 #include "effects/GrConfigConversionEffect.h"
-#include "gl/builders/GrGLProgramBuilder.h"
 #include "gl/GrGLPathRendering.h"
 #include "gl/GrGpuGL.h"
 #include "SkChecksum.h"
@@ -25,7 +24,7 @@
 
 static void get_stage_stats(const GrFragmentStage stage, bool* readsDst,
                             bool* readsFragPosition, bool* requiresVertexShader) {
-    if (stage.getProcessor()->willReadDstColor()) {
+    if (stage.getFragmentProcessor()->willReadDstColor()) {
         *readsDst = true;
     }
     if (stage.getProcessor()->willReadFragmentPosition()) {
@@ -336,14 +335,12 @@ bool GrGpuGL::programUnitTest(int maxStages) {
         SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawState(),
                                                                      *this->caps(),
                                                                      drawType));
-        SkAutoTUnref<GrGLProgram> program(
-                        GrGLProgramBuilder::CreateProgram(*optState,
-                                                          pdesc,
-                                                          drawType,
-                                                          geometryProcessor,
-                                                          stages,
-                                                          stages + numColorStages,
-                                                          this));
+        SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
+                                                              *optState.get(),
+                                                              pdesc,
+                                                              geometryProcessor.get(),
+                                                              stages,
+                                                              stages + numColorStages));
         for (int s = 0; s < numStages; ++s) {
             SkDELETE(stages[s]);
         }