Make GrGLShaderBuilder produce the shader strings
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 11 Jul 2012 18:11:27 +0000 (18:11 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 11 Jul 2012 18:11:27 +0000 (18:11 +0000)
Review URL: http://codereview.appspot.com/6356089/

git-svn-id: http://skia.googlecode.com/svn/trunk@4544 2bbb7eff-a529-9590-31e7-b0007b416f81

src/gpu/gl/GrGLProgram.cpp
src/gpu/gl/GrGLProgram.h
src/gpu/gl/GrGLShaderBuilder.cpp
src/gpu/gl/GrGLShaderBuilder.h

index d673aca..5545560 100644 (file)
@@ -460,17 +460,123 @@ GrGLProgram::CachedData::~CachedData() {
     }
 }
 
+namespace {
+#define GL_CALL(X) GR_GL_CALL(gl.interface(), X)
+#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gl.interface(), R, X)
+
+// prints a shader using params similar to glShaderSource
+void print_shader(GrGLint stringCnt,
+                  const GrGLchar** strings,
+                  GrGLint* stringLengths) {
+    for (int i = 0; i < stringCnt; ++i) {
+        if (NULL == stringLengths || stringLengths[i] < 0) {
+            GrPrintf(strings[i]);
+        } else {
+            GrPrintf("%.*s", stringLengths[i], strings[i]);
+        }
+    }
+}
+
+// Compiles a GL shader, returns shader ID or 0 if failed params have same meaning as glShaderSource
+GrGLuint compile_shader(const GrGLContextInfo& gl,
+                        GrGLenum type,
+                        int stringCnt,
+                        const char** strings,
+                        int* stringLengths) {
+    SK_TRACE_EVENT1("GrGLProgram::CompileShader",
+                    "stringCount", SkStringPrintf("%i", stringCnt).c_str());
+
+    GrGLuint shader;
+    GL_CALL_RET(shader, CreateShader(type));
+    if (0 == shader) {
+        return 0;
+    }
+
+    GrGLint compiled = GR_GL_INIT_ZERO;
+    GL_CALL(ShaderSource(shader, stringCnt, strings, stringLengths));
+    GL_CALL(CompileShader(shader));
+    GL_CALL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
+
+    if (!compiled) {
+        GrGLint infoLen = GR_GL_INIT_ZERO;
+        GL_CALL(GetShaderiv(shader, 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(GetShaderInfoLog(shader, infoLen+1, 
+                                         &length, (char*)log.get()));
+            print_shader(stringCnt, strings, stringLengths);
+            GrPrintf("\n%s", log.get());
+        }
+        GrAssert(!"Shader compilation failed!");
+        GL_CALL(DeleteShader(shader));
+        return 0;
+    }
+    return shader;
+}
+
+// helper version of above for when shader is already flattened into a single SkString
+GrGLuint compile_shader(const GrGLContextInfo& gl, GrGLenum type, const SkString& shader) {
+    const GrGLchar* str = shader.c_str();
+    int length = shader.size();
+    return compile_shader(gl, type, 1, &str, &length);
+}
+
+// compiles all the shaders from builder and stores the shader IDs in programData.
+bool compile_shaders(const GrGLContextInfo& gl,
+                     const GrGLShaderBuilder& builder,
+                     GrGLProgram::CachedData* programData) {
+
+    SkString shader;
+
+    builder.getShader(GrGLShaderBuilder::kVertex_ShaderType, &shader);
+#if PRINT_SHADERS
+    GrPrintf(shader.c_str());
+    GrPrintf("\n");
+#endif
+    if (!(programData->fVShaderID = compile_shader(gl, GR_GL_VERTEX_SHADER, shader))) {
+        return false;
+    }
+
+    if (builder.fUsesGS) {
+        builder.getShader(GrGLShaderBuilder::kGeometry_ShaderType, &shader);
+#if PRINT_SHADERS
+        GrPrintf(shader.c_str());
+        GrPrintf("\n");
+#endif
+        if (!(programData->fVShaderID = compile_shader(gl, GR_GL_GEOMETRY_SHADER, shader))) {
+            return false;
+        }
+    } else {
+        programData->fGShaderID = 0;
+    }
+
+    builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader);
+#if PRINT_SHADERS
+    GrPrintf(shader.c_str());
+    GrPrintf("\n");
+#endif
+    if (!(programData->fFShaderID = compile_shader(gl, GR_GL_FRAGMENT_SHADER, shader))) {
+        return false;
+    }
+
+    return true;
+}
+
+}
 
 bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
                              GrCustomStage** customStages,
                              GrGLProgram::CachedData* programData) const {
-    GrGLShaderBuilder segments;
+    GrGLShaderBuilder builder(gl);
     const uint32_t& layout = fProgramDesc.fVertexLayout;
 
     programData->fUniLocations.reset();
 
 #if GR_GL_EXPERIMENTAL_GS
-    segments.fUsesGS = fProgramDesc.fExperimentalGS;
+    builder.fUsesGS = fProgramDesc.fExperimentalGS;
 #endif
 
     SkXfermode::Coeff colorCoeff, uniformCoeff;
@@ -518,50 +624,50 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
     // the dual source output has no canonical var name, have to
     // declare an output, which is incompatible with gl_FragColor/gl_FragData.
     bool dualSourceOutputWritten = false;
-    segments.fHeader.append(GrGetGLSLVersionDecl(gl.binding(),
-                                                 gl.glslGeneration()));
+    builder.fHeader.append(GrGetGLSLVersionDecl(gl.binding(),
+                                                gl.glslGeneration()));
 
     GrGLShaderVar colorOutput;
     bool isColorDeclared = GrGLSLSetupFSColorOuput(gl.glslGeneration(),
                                                    declared_color_output_name(),
                                                    &colorOutput);
     if (isColorDeclared) {
-        segments.fFSOutputs.push_back(colorOutput);
+        builder.fFSOutputs.push_back(colorOutput);
     }
 
-    segments.addUniform(GrGLShaderBuilder::kVertex_ShaderType,
-                        kMat33f_GrSLType, VIEW_MATRIX_NAME);
+    builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType,
+                       kMat33f_GrSLType, VIEW_MATRIX_NAME);
     programData->fUniLocations.fViewMatrixUni = kUseUniform;
 
-    segments.fVSAttrs.push_back().set(kVec2f_GrSLType,
-        GrGLShaderVar::kAttribute_TypeModifier, POS_ATTR_NAME);
+    builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
+                                     GrGLShaderVar::kAttribute_TypeModifier,
+                                     POS_ATTR_NAME);
 
-    segments.fVSCode.append(
-        "void main() {\n"
-            "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3("POS_ATTR_NAME", 1);\n"
-            "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n");
+    builder.fVSCode.append("void main() {\n"
+                              "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3("POS_ATTR_NAME", 1);\n"
+                              "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n");
 
     // incoming color to current stage being processed.
     SkString inColor;
 
     if (needComputedColor) {
         genInputColor((ProgramDesc::ColorInput) fProgramDesc.fColorInput,
-                      programData, &segments, &inColor);
+                      programData, &builder, &inColor);
     }
 
     // we output point size in the GS if present
-    if (fProgramDesc.fEmitsPointSize && !segments.fUsesGS){
-        segments.fVSCode.append("\tgl_PointSize = 1.0;\n");
+    if (fProgramDesc.fEmitsPointSize && !builder.fUsesGS){
+        builder.fVSCode.append("\tgl_PointSize = 1.0;\n");
     }
 
-    segments.fFSCode.append("void main() {\n");
+    builder.fFSCode.append("void main() {\n");
 
     // add texture coordinates that are used to the list of vertex attr decls
     SkString texCoordAttrs[GrDrawState::kMaxTexCoords];
     for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
         if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) {
             tex_attr_name(t, texCoordAttrs + t);
-            segments.fVSAttrs.push_back().set(kVec2f_GrSLType,
+            builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
                 GrGLShaderVar::kAttribute_TypeModifier,
                 texCoordAttrs[t].c_str());
         }
@@ -588,7 +694,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
                 // create var to hold stage result
                 outColor = "color";
                 outColor.appendS32(s);
-                segments.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str());
+                builder.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str());
 
                 const char* inCoords;
                 // figure out what our input coords are
@@ -613,7 +719,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
                                    inColor.size() ? inColor.c_str() : NULL,
                                    outColor.c_str(),
                                    inCoords,
-                                   &segments,
+                                   &builder,
                                    &programData->fUniLocations.fStages[s],
                                    programData->fCustomStage[s]);
                 inColor = outColor;
@@ -635,35 +741,35 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
         }
     }
     if (needColorFilterUniform) {
-        segments.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
-                            kVec4f_GrSLType, COL_FILTER_UNI_NAME);
+        builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                           kVec4f_GrSLType, COL_FILTER_UNI_NAME);
         programData->fUniLocations.fColorFilterUni = kUseUniform;
     }
     bool wroteFragColorZero = false;
     if (SkXfermode::kZero_Coeff == uniformCoeff &&
         SkXfermode::kZero_Coeff == colorCoeff &&
         !applyColorMatrix) {
-        segments.fFSCode.appendf("\t%s = %s;\n",
-                                 colorOutput.getName().c_str(),
-                                 all_zeros_vec(4));
+        builder.fFSCode.appendf("\t%s = %s;\n",
+                                colorOutput.getName().c_str(),
+                                all_zeros_vec(4));
         wroteFragColorZero = true;
     } else if (SkXfermode::kDst_Mode != fProgramDesc.fColorFilterXfermode) {
-        segments.fFSCode.append("\tvec4 filteredColor;\n");
+        builder.fFSCode.append("\tvec4 filteredColor;\n");
         const char* color = adjustInColor(inColor);
-        addColorFilter(&segments.fFSCode, "filteredColor", uniformCoeff,
+        addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff,
                        colorCoeff, color);
         inColor = "filteredColor";
     }
     if (applyColorMatrix) {
-        segments.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
-                            kMat44f_GrSLType, COL_MATRIX_UNI_NAME);
-        segments.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
-                            kVec4f_GrSLType, COL_MATRIX_VEC_UNI_NAME);
+        builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                           kMat44f_GrSLType, COL_MATRIX_UNI_NAME);
+        builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                           kVec4f_GrSLType, COL_MATRIX_VEC_UNI_NAME);
         programData->fUniLocations.fColorMatrixUni = kUseUniform;
         programData->fUniLocations.fColorMatrixVecUni = kUseUniform;
-        segments.fFSCode.append("\tvec4 matrixedColor;\n");
+        builder.fFSCode.append("\tvec4 matrixedColor;\n");
         const char* color = adjustInColor(inColor);
-        addColorMatrix(&segments.fFSCode, "matrixedColor", color);
+        addColorMatrix(&builder.fFSCode, "matrixedColor", color);
         inColor = "matrixedColor";
     }
 
@@ -679,21 +785,17 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
         ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
 
         if (!coverageIsZero) {
-            this->genEdgeCoverage(gl,
-                                  layout,
-                                  programData,
-                                  &inCoverage,
-                                  &segments);
+            this->genEdgeCoverage(gl, layout, programData, &inCoverage, &builder);
 
             switch (fProgramDesc.fCoverageInput) {
                 case ProgramDesc::kSolidWhite_ColorInput:
                     // empty string implies solid white
                     break;
                 case ProgramDesc::kAttribute_ColorInput:
-                    genAttributeCoverage(&segments, &inCoverage);
+                    genAttributeCoverage(&builder, &inCoverage);
                     break;
                 case ProgramDesc::kUniform_ColorInput:
-                    genUniformCoverage(&segments, programData, &inCoverage);
+                    genUniformCoverage(&builder, programData, &inCoverage);
                     break;
                 default:
                     GrCrash("Unexpected input coverage.");
@@ -706,8 +808,8 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
                     // create var to hold stage output
                     outCoverage = "coverage";
                     outCoverage.appendS32(s);
-                    segments.fFSCode.appendf("\tvec4 %s;\n",
-                                             outCoverage.c_str());
+                    builder.fFSCode.appendf("\tvec4 %s;\n",
+                                            outCoverage.c_str());
 
                     const char* inCoords;
                     // figure out what our input coords are
@@ -733,7 +835,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
                         inCoverage.size() ? inCoverage.c_str() : NULL,
                         outCoverage.c_str(),
                         inCoords,
-                        &segments,
+                        &builder,
                         &programData->fUniLocations.fStages[s],
                         programData->fCustomStage[s]);
                     inCoverage = outCoverage;
@@ -741,9 +843,9 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
             }
         }
         if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
-            segments.fFSOutputs.push_back().set(kVec4f_GrSLType,
-                GrGLShaderVar::kOut_TypeModifier,
-                dual_source_output_name());
+            builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
+                                               GrGLShaderVar::kOut_TypeModifier,
+                                               dual_source_output_name());
             bool outputIsZero = coverageIsZero;
             SkString coeff;
             if (!outputIsZero &&
@@ -761,14 +863,14 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
                 }
             }
             if (outputIsZero) {
-                segments.fFSCode.appendf("\t%s = %s;\n",
-                                         dual_source_output_name(),
+                builder.fFSCode.appendf("\t%s = %s;\n",
+                                        dual_source_output_name(),
                                          all_zeros_vec(4));
             } else {
                 modulate_helper(dual_source_output_name(),
                                 coeff.c_str(),
                                 inCoverage.c_str(),
-                                &segments.fFSCode);
+                                &builder.fFSCode);
             }
             dualSourceOutputWritten = true;
         }
@@ -779,47 +881,47 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
 
     if (!wroteFragColorZero) {
         if (coverageIsZero) {
-            segments.fFSCode.appendf("\t%s = %s;\n",
-                                     colorOutput.getName().c_str(),
-                                     all_zeros_vec(4));
+            builder.fFSCode.appendf("\t%s = %s;\n",
+                                    colorOutput.getName().c_str(),
+                                    all_zeros_vec(4));
         } else {
             modulate_helper(colorOutput.getName().c_str(),
                             inColor.c_str(),
                             inCoverage.c_str(),
-                            &segments.fFSCode);
+                            &builder.fFSCode);
         }
         if (ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig ==
             fProgramDesc.fOutputConfig) {
-            segments.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
-                                        colorOutput.getName().c_str(),
-                                        colorOutput.getName().c_str(),
-                                        colorOutput.getName().c_str(),
-                                        colorOutput.getName().c_str(),
-                                        colorOutput.getName().c_str());
+            builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
+                                    colorOutput.getName().c_str(),
+                                    colorOutput.getName().c_str(),
+                                    colorOutput.getName().c_str(),
+                                    colorOutput.getName().c_str(),
+                                    colorOutput.getName().c_str());
         } else if (ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig ==
                    fProgramDesc.fOutputConfig) {
-            segments.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
-                                        colorOutput.getName().c_str(),
-                                        colorOutput.getName().c_str(),
-                                        colorOutput.getName().c_str(),
-                                        colorOutput.getName().c_str(),
-                                        colorOutput.getName().c_str());
+            builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
+                                    colorOutput.getName().c_str(),
+                                    colorOutput.getName().c_str(),
+                                    colorOutput.getName().c_str(),
+                                    colorOutput.getName().c_str(),
+                                    colorOutput.getName().c_str());
         }
     }
 
-    segments.fVSCode.append("}\n");
-    segments.fFSCode.append("}\n");
+    builder.fVSCode.append("}\n");
+    builder.fFSCode.append("}\n");
 
     ///////////////////////////////////////////////////////////////////////////
     // insert GS
 #if GR_DEBUG
-    this->genGeometryShader(gl, &segments);
+    this->genGeometryShader(gl, &builder);
 #endif
 
     ///////////////////////////////////////////////////////////////////////////
     // compile and setup attribs and unis
 
-    if (!CompileShaders(gl, segments, programData)) {
+    if (!compile_shaders(gl, builder, programData)) {
         return false;
     }
 
@@ -835,188 +937,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
     return true;
 }
 
-namespace {
-
-inline void expand_decls(const VarArray& vars,
-                         const GrGLContextInfo& gl,
-                         SkString* string) {
-    const int count = vars.count();
-    for (int i = 0; i < count; ++i) {
-        vars[i].appendDecl(gl, string);
-    }
-}
-
-inline void print_shader(int stringCnt,
-                         const char** strings,
-                         int* stringLengths) {
-    for (int i = 0; i < stringCnt; ++i) {
-        if (NULL == stringLengths || stringLengths[i] < 0) {
-            GrPrintf(strings[i]);
-        } else {
-            GrPrintf("%.*s", stringLengths[i], strings[i]);
-        }
-    }
-}
-
-typedef SkTArray<const char*, true>         StrArray;
-#define PREALLOC_STR_ARRAY(N) SkSTArray<(N), const char*, true>
-
-typedef SkTArray<int, true>                 LengthArray;
-#define PREALLOC_LENGTH_ARRAY(N) SkSTArray<(N), int, true>
-
-// these shouldn't relocate
-typedef GrTAllocator<SkString>              TempArray;
-#define PREALLOC_TEMP_ARRAY(N) GrSTAllocator<(N), SkString>
-
-inline void append_string(const SkString& str,
-                          StrArray* strings,
-                          LengthArray* lengths) {
-    int length = (int) str.size();
-    if (length) {
-        strings->push_back(str.c_str());
-        lengths->push_back(length);
-    }
-    GrAssert(strings->count() == lengths->count());
-}
-
-inline void append_decls(const VarArray& vars,
-                         const GrGLContextInfo& gl,
-                         StrArray* strings,
-                         LengthArray* lengths,
-                         TempArray* temp) {
-    expand_decls(vars, gl, &temp->push_back());
-    append_string(temp->back(), strings, lengths);
-}
-
-}
-
-bool GrGLProgram::CompileShaders(const GrGLContextInfo& gl,
-                                 const GrGLShaderBuilder& segments,
-                                 CachedData* programData) {
-    enum { kPreAllocStringCnt = 8 };
-
-    PREALLOC_STR_ARRAY(kPreAllocStringCnt)    strs;
-    PREALLOC_LENGTH_ARRAY(kPreAllocStringCnt) lengths;
-    PREALLOC_TEMP_ARRAY(kPreAllocStringCnt)   temps;
-
-    SkString unis;
-    SkString inputs;
-    SkString outputs;
-
-    append_string(segments.fHeader, &strs, &lengths);
-    append_decls(segments.fVSUnis, gl, &strs, &lengths, &temps);
-    append_decls(segments.fVSAttrs, gl, &strs, &lengths, &temps);
-    append_decls(segments.fVSOutputs, gl, &strs, &lengths, &temps);
-    append_string(segments.fVSCode, &strs, &lengths);
-
-#if PRINT_SHADERS
-    print_shader(strs.count(), &strs[0], &lengths[0]);
-    GrPrintf("\n");
-#endif
-
-    programData->fVShaderID =
-        CompileShader(gl, GR_GL_VERTEX_SHADER, strs.count(),
-                      &strs[0], &lengths[0]);
-
-    if (!programData->fVShaderID) {
-        return false;
-    }
-    if (segments.fUsesGS) {
-        strs.reset();
-        lengths.reset();
-        temps.reset();
-        append_string(segments.fHeader, &strs, &lengths);
-        append_string(segments.fGSHeader, &strs, &lengths);
-        append_decls(segments.fGSInputs, gl, &strs, &lengths, &temps);
-        append_decls(segments.fGSOutputs, gl, &strs, &lengths, &temps);
-        append_string(segments.fGSCode, &strs, &lengths);
-#if PRINT_SHADERS
-        print_shader(strs.count(), &strs[0], &lengths[0]);
-        GrPrintf("\n");
-#endif
-        programData->fGShaderID =
-            CompileShader(gl, GR_GL_GEOMETRY_SHADER, strs.count(),
-                          &strs[0], &lengths[0]);
-    } else {
-        programData->fGShaderID = 0;
-    }
-
-    strs.reset();
-    lengths.reset();
-    temps.reset();
-
-    append_string(segments.fHeader, &strs, &lengths);
-    SkString precisionStr(GrGetGLSLShaderPrecisionDecl(gl.binding()));
-    append_string(precisionStr, &strs, &lengths);
-    append_decls(segments.fFSUnis, gl, &strs, &lengths, &temps);
-    append_decls(segments.fFSInputs, gl, &strs, &lengths, &temps);
-    // We shouldn't have declared outputs on 1.10
-    GrAssert(k110_GrGLSLGeneration != gl.glslGeneration() ||
-             segments.fFSOutputs.empty());
-    append_decls(segments.fFSOutputs, gl, &strs, &lengths, &temps);
-    append_string(segments.fFSFunctions, &strs, &lengths);
-    append_string(segments.fFSCode, &strs, &lengths);
-
-#if PRINT_SHADERS
-    print_shader(strs.count(), &strs[0], &lengths[0]);
-    GrPrintf("\n");
-#endif
-
-    programData->fFShaderID =
-        CompileShader(gl, GR_GL_FRAGMENT_SHADER, strs.count(),
-                      &strs[0], &lengths[0]);
-
-    if (!programData->fFShaderID) {
-        return false;
-    }
-
-    return true;
-}
-
-#define GL_CALL(X) GR_GL_CALL(gl.interface(), X)
-#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gl.interface(), R, X)
-
-GrGLuint GrGLProgram::CompileShader(const GrGLContextInfo& gl,
-                                    GrGLenum type,
-                                    int stringCnt,
-                                    const char** strings,
-                                    int* stringLengths) {
-    SK_TRACE_EVENT1("GrGLProgram::CompileShader",
-                    "stringCount", SkStringPrintf("%i", stringCnt).c_str());
-
-    GrGLuint shader;
-    GL_CALL_RET(shader, CreateShader(type));
-    if (0 == shader) {
-        return 0;
-    }
-
-    GrGLint compiled = GR_GL_INIT_ZERO;
-    GL_CALL(ShaderSource(shader, stringCnt, strings, stringLengths));
-    GL_CALL(CompileShader(shader));
-    GL_CALL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
-
-    if (!compiled) {
-        GrGLint infoLen = GR_GL_INIT_ZERO;
-        GL_CALL(GetShaderiv(shader, 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(GetShaderInfoLog(shader, infoLen+1, 
-                                         &length, (char*)log.get()));
-            print_shader(stringCnt, strings, stringLengths);
-            GrPrintf("\n%s", log.get());
-        }
-        GrAssert(!"Shader compilation failed!");
-        GL_CALL(DeleteShader(shader));
-        return 0;
-    }
-    return shader;
-}
-
-bool GrGLProgram::bindOutputsAttribsAndLinkProgram(
-                                        const GrGLContextInfo& gl,
+bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl,
                                         SkString texCoordAttrNames[],
                                         bool bindColorOut,
                                         bool bindDualSrcOut,
@@ -1322,5 +1243,3 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
         segments->fFSCode.appendf("\t}\n");
     }
 }
-
-
index bfc0d2e..0be08b3 100644 (file)
@@ -357,19 +357,7 @@ private:
                          SkString* coverageVar,
                          GrGLShaderBuilder* segments) const;
 
-    static bool CompileShaders(const GrGLContextInfo& gl,
-                               const GrGLShaderBuilder& segments, 
-                               CachedData* programData);
-
-    // Compiles a GL shader, returns shader ID or 0 if failed
-    // params have same meaning as glShaderSource
-    static GrGLuint CompileShader(const GrGLContextInfo& gl,
-                                  GrGLenum type, int stringCnt,
-                                  const char** strings,
-                                  int* stringLengths);
-
-    // Creates a GL program ID, binds shader attributes to GL vertex attrs, and
-    // links the program
+    // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
     bool bindOutputsAttribsAndLinkProgram(
                 const GrGLContextInfo& gl,
                 SkString texCoordAttrNames[GrDrawState::kMaxTexCoords],
index 220aed7..d24f2f8 100644 (file)
@@ -19,7 +19,7 @@ static const int kMaxFSOutputs = 2;
 // varying by stage, if we use 1D textures for gradients!
 //const int GrGLShaderBuilder::fCoordDims = 2;
 
-GrGLShaderBuilder::GrGLShaderBuilder()
+GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctx)
     : fVSUnis(kVarsPerBlock)
     , fVSAttrs(kVarsPerBlock)
     , fVSOutputs(kVarsPerBlock)
@@ -30,7 +30,8 @@ GrGLShaderBuilder::GrGLShaderBuilder()
     , fFSOutputs(kMaxFSOutputs)
     , fUsesGS(false)
     , fVaryingDims(0)
-    , fComplexCoord(false) {
+    , fComplexCoord(false)
+    , fContext(ctx) {
 
 }
 
@@ -196,3 +197,47 @@ void GrGLShaderBuilder::addVarying(GrSLType type,
     this->addVarying(type, nameWithStage.c_str(), vsOutName, fsInName);
 }
 
+namespace {
+void append_decls(const GrGLShaderBuilder::VarArray& vars,
+                  const GrGLContextInfo& ctx,
+                  SkString* string) {
+    for (int i = 0; i < vars.count(); ++i) {
+        vars[i].appendDecl(ctx, string);
+    }
+}
+}
+
+void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
+    switch (type) {
+        case kVertex_ShaderType:
+            *shaderStr = fHeader;
+            append_decls(fVSUnis, fContext, shaderStr);
+            append_decls(fVSAttrs, fContext, shaderStr);
+            append_decls(fVSOutputs, fContext, shaderStr);
+            shaderStr->append(fVSCode);
+            break;
+        case kGeometry_ShaderType:
+            if (fUsesGS) {
+                *shaderStr = fHeader;
+                shaderStr->append(fGSHeader);
+                append_decls(fGSInputs, fContext, shaderStr);
+                append_decls(fGSOutputs, fContext, shaderStr);
+                shaderStr->append(fGSCode);
+            } else {
+                shaderStr->reset();
+            }
+            break;
+        case kFragment_ShaderType:
+            *shaderStr = fHeader;
+            shaderStr->append(GrGetGLSLShaderPrecisionDecl(fContext.binding()));
+            append_decls(fFSUnis, fContext, shaderStr);
+            append_decls(fFSInputs, fContext, shaderStr);
+            // We shouldn't have declared outputs on 1.10
+            GrAssert(k110_GrGLSLGeneration != fContext.glslGeneration() || fFSOutputs.empty());
+            append_decls(fFSOutputs, fContext, shaderStr);
+            shaderStr->append(fFSFunctions);
+            shaderStr->append(fFSCode);
+            break;
+    }
+
+ }
index bf308f3..5884a90 100644 (file)
@@ -12,8 +12,7 @@
 #include "gl/GrGLShaderVar.h"
 #include "gl/GrGLSL.h"
 
-typedef GrTAllocator<GrGLShaderVar> VarArray;
-
+class GrGLContextInfo;
 /**
   Contains all the incremental state of a shader as it is being built,as well as helpers to
   manipulate that state.
@@ -23,6 +22,7 @@ typedef GrTAllocator<GrGLShaderVar> VarArray;
 class GrGLShaderBuilder {
 
 public:
+    typedef GrTAllocator<GrGLShaderVar> VarArray;
 
     enum ShaderType {
         kVertex_ShaderType   = 0x1,
@@ -30,7 +30,7 @@ public:
         kFragment_ShaderType = 0x4,
     };
 
-    GrGLShaderBuilder();
+    GrGLShaderBuilder(const GrGLContextInfo&);
 
     void computeSwizzle(uint32_t configFlags);
     void computeModulate(const char* fsInColor);
@@ -56,7 +56,6 @@ public:
     void emitDefaultFetch(const char* outColor,
                           const char* samplerName);
 
-
     /** Add a uniform variable to the current program, that has visibilty in one or more shaders.
         If stageNum is specified, it is appended to the name to guarantee uniqueness; if count is
         specified, the uniform is an array. visibility is a bitfield of ShaderType values indicating
@@ -86,6 +85,9 @@ public:
                     const char** vsOutName = NULL,
                     const char** fsInName = NULL);
 
+    /** Called after building is complete to get the final shader string. */
+    void getShader(ShaderType, SkString*) const;
+
     // TODO: Everything below here private.
 
     SkString    fHeader; // VS+FS, GLSL version, etc
@@ -122,6 +124,8 @@ public:
 
     //@}
 
+private:
+    const GrGLContextInfo& fContext;
 };
 
 #endif