Hooks up the GrCustomStage/GrGLProgramStageFactory/GrGLProgramStage
classes from r3726 so they can be used. Does not implement any actual
effect stages.

Has one large known bug: if custom stages are provided, GrSamplerState
comparisons will break; this should preserve correct drawing, but decrease
performance - among other things, we'll break draw batching. To fix this
we'll need a RTTI system for GrCustomState objects, and we'll need to change
the GrSamplerState comparison from a memcmp to something that also does a
deep type-sensitive compare of any GrCustomState objects present.

http://codereview.appspot.com/6074043/



git-svn-id: http://skia.googlecode.com/svn/trunk@3742 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGpuGLShaders.cpp b/src/gpu/gl/GrGpuGLShaders.cpp
index 9627107..1fcfbbe 100644
--- a/src/gpu/gl/GrGpuGLShaders.cpp
+++ b/src/gpu/gl/GrGpuGLShaders.cpp
@@ -8,7 +8,9 @@
 
 
 #include "../GrBinHashKey.h"
+#include "GrCustomStage.h"
 #include "GrGLProgram.h"
+#include "GrGLProgramStage.h"
 #include "GrGLSL.h"
 #include "GrGpuGLShaders.h"
 #include "../GrGpuVertex.h"
@@ -82,13 +84,14 @@
         }
     }
 
-    GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc) {
+    GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc,
+                                            GrCustomStage** stages) {
         Entry newEntry;
         newEntry.fKey.setKeyData(desc.keyData());
         
         Entry* entry = fHashCache.find(newEntry.fKey);
         if (NULL == entry) {
-            if (!desc.genProgram(fGL, &newEntry.fProgramData)) {
+            if (!desc.genProgram(fGL, stages, &newEntry.fProgramData)) {
                 return NULL;
             }
             if (fCount < kMaxEntries) {
@@ -242,6 +245,8 @@
             pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
         }
 
+        GrCustomStage* customStages[GrDrawState::kNumStages];
+
         for (int s = 0; s < GrDrawState::kNumStages; ++s) {
             // enable the stage?
             if (random_bool(&random)) {
@@ -288,9 +293,13 @@
                     stage.fInConfigFlags &= ~kMulByAlphaMask;
                     break;
             }
+
+            stage.fCustomStageKey = 0;
+            customStages[s] = NULL;
         }
         CachedData cachedData;
-        if (!program.genProgram(this->glContextInfo(), &cachedData)) {
+        if (!program.genProgram(this->glContextInfo(), customStages,
+                                &cachedData)) {
             return false;
         }
         DeleteProgram(this->glInterface(), &cachedData);
@@ -772,8 +781,10 @@
         return false;
     }
 
-    this->buildProgram(type, blendOpts, dstCoeff);
-    fProgramData = fProgramCache->getProgramData(fCurrentProgram);
+    GrCustomStage* customStages [GrDrawState::kNumStages];
+    this->buildProgram(type, blendOpts, dstCoeff, customStages);
+    fProgramData = fProgramCache->getProgramData(fCurrentProgram,
+                                                 customStages);
     if (NULL == fProgramData) {
         GrAssert(!"Failed to create program!");
         return false;
@@ -814,6 +825,13 @@
             this->flushTexelSize(s);
 
             this->flushTextureDomain(s);
+
+            if (NULL != fProgramData->fCustomStage[s]) {
+                const GrSamplerState& sampler =
+                    this->getDrawState().getSampler(s);
+                fProgramData->fCustomStage[s]->setData(
+                    this->glInterface(), sampler.getCustomStage());
+            }
         }
     }
     this->flushEdgeAAData();
@@ -962,9 +980,29 @@
     fHWGeometryState.fArrayPtrsDirty = false;
 }
 
+namespace {
+
+void setup_custom_stage(GrGLProgram::ProgramDesc::StageDesc* stage,
+                        const GrSamplerState& sampler,
+                        GrCustomStage** customStages,
+                        GrGLProgram* program, int index) {
+    GrCustomStage* customStage = sampler.getCustomStage();
+    if (customStage) {
+        GrGLProgramStageFactory* factory = customStage->getGLFactory();
+        stage->fCustomStageKey = factory->stageKey(customStage);
+        customStages[index] = customStage;
+    } else {
+        stage->fCustomStageKey = 0;
+        customStages[index] = NULL;
+    }
+}
+
+}
+
 void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
                                   BlendOptFlags blendOpts,
-                                  GrBlendCoeff dstCoeff) {
+                                  GrBlendCoeff dstCoeff,
+                                  GrCustomStage** customStages) {
     ProgramDesc& desc = fCurrentProgram.fProgramDesc;
     const GrDrawState& drawState = this->getDrawState();
 
@@ -1170,12 +1208,18 @@
             } else {
                 stage.fKernelWidth = 0;
             }
+
+            setup_custom_stage(&stage, sampler, customStages,
+                               &fCurrentProgram, s);
+
         } else {
             stage.fOptFlags         = 0;
             stage.fCoordMapping     = (StageDesc::CoordMapping) 0;
             stage.fInConfigFlags    = 0;
             stage.fFetchMode        = (StageDesc::FetchMode) 0;
             stage.fKernelWidth      = 0;
+            stage.fCustomStageKey   = 0;
+            customStages[s] = NULL;
         }
     }