aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-11 18:11:27 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-11 18:11:27 +0000
commitad5e937c110efaf9630159d2859fabc4f38f7ab2 (patch)
tree05ba23780c968f71e15a51b4108ae843031bcdc4 /src
parentfa4a6e964691ff9a88bc047418abe2d4324dfcae (diff)
Make GrGLShaderBuilder produce the shader strings
Review URL: http://codereview.appspot.com/6356089/ git-svn-id: http://skia.googlecode.com/svn/trunk@4544 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/gpu/gl/GrGLProgram.cpp425
-rw-r--r--src/gpu/gl/GrGLProgram.h14
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp49
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.h12
4 files changed, 228 insertions, 272 deletions
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index d673acab48..55455604a0 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -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");
}
}
-
-
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index bfc0d2e812..0be08b3b39 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -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],
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 220aed7a41..d24f2f89f6 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -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;
+ }
+
+ }
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index bf308f3fbe..5884a90f85 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -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