diff options
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrAAConvexPathRenderer.cpp | 9 | ||||
-rw-r--r-- | src/gpu/GrAARectRenderer.cpp | 28 | ||||
-rw-r--r-- | src/gpu/GrOvalRenderer.cpp | 24 | ||||
-rw-r--r-- | src/gpu/effects/GrBezierEffect.cpp | 31 | ||||
-rw-r--r-- | src/gpu/effects/GrSimpleTextureEffect.cpp | 8 | ||||
-rw-r--r-- | src/gpu/gl/GrGLEffectMatrix.cpp | 25 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 176 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.cpp | 253 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.h | 191 |
10 files changed, 430 insertions, 318 deletions
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index 750ffefbf9..59529c5f8b 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -517,14 +517,17 @@ public: const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) SK_OVERRIDE { + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + const char *vsName, *fsName; const SkString* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); SkAssertResult(builder->enableFeature( GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); - builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName); + vertexBuilder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName); // keep the derivative instructions outside the conditional builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); @@ -546,7 +549,7 @@ public: GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); } static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index 2e86fb7048..9d436c3933 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -50,14 +50,17 @@ public: const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) SK_OVERRIDE { + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + // setup the varying for the Axis aligned rect effect // xy -> interpolated offset // zw -> w/2+0.5, h/2+0.5 const char *vsRectName, *fsRectName; - builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName); + vertexBuilder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsRectName, attr0Name->c_str()); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsRectName, attr0Name->c_str()); // TODO: compute all these offsets, spans, and scales in the VS builder->fsCodeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName); @@ -167,22 +170,25 @@ public: const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) SK_OVERRIDE { + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + // setup the varying for the center point and the unit vector // that points down the height of the rect const char *vsRectEdgeName, *fsRectEdgeName; - builder->addVarying(kVec4f_GrSLType, "RectEdge", - &vsRectEdgeName, &fsRectEdgeName); + vertexBuilder->addVarying(kVec4f_GrSLType, "RectEdge", + &vsRectEdgeName, &fsRectEdgeName); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsRectEdgeName, attr0Name->c_str()); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsRectEdgeName, attr0Name->c_str()); // setup the varying for width/2+.5 and height/2+.5 const char *vsWidthHeightName, *fsWidthHeightName; - builder->addVarying(kVec2f_GrSLType, "WidthHeight", - &vsWidthHeightName, &fsWidthHeightName); + vertexBuilder->addVarying(kVec2f_GrSLType, "WidthHeight", + &vsWidthHeightName, &fsWidthHeightName); const SkString* attr1Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); - builder->vsCodeAppendf("\t%s = %s;\n", vsWidthHeightName, attr1Name->c_str()); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsWidthHeightName, attr1Name->c_str()); // TODO: compute all these offsets, spans, and scales in the VS builder->fsCodeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName); diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index 5ec7504577..de7f4a36ef 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -91,13 +91,16 @@ public: const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) SK_OVERRIDE { + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleEdgeEffect>(); const char *vsName, *fsName; - builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName); + vertexBuilder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName); const SkString* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); builder->fsCodeAppendf("\tfloat d = length(%s.xy);\n", fsName); builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName); @@ -202,20 +205,23 @@ public: const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) SK_OVERRIDE { + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<EllipseEdgeEffect>(); const char *vsOffsetName, *fsOffsetName; const char *vsRadiiName, *fsRadiiName; - builder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName, &fsOffsetName); + vertexBuilder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName, &fsOffsetName); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_str()); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_str()); - builder->addVarying(kVec4f_GrSLType, "EllipseRadii", &vsRadiiName, &fsRadiiName); + vertexBuilder->addVarying(kVec4f_GrSLType, "EllipseRadii", &vsRadiiName, &fsRadiiName); const SkString* attr1Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); - builder->vsCodeAppendf("\t%s = %s;\n", vsRadiiName, attr1Name->c_str()); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsRadiiName, attr1Name->c_str()); // for outer curve builder->fsCodeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffsetName, fsRadiiName); diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp index c5c903b204..0d57b107ac 100644 --- a/src/gpu/effects/GrBezierEffect.cpp +++ b/src/gpu/effects/GrBezierEffect.cpp @@ -45,13 +45,16 @@ void GrGLConicEffect::emitCode(GrGLShaderBuilder* builder, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + const char *vsName, *fsName; - builder->addVarying(kVec4f_GrSLType, "ConicCoeffs", - &vsName, &fsName); + vertexBuilder->addVarying(kVec4f_GrSLType, "ConicCoeffs", + &vsName, &fsName); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); builder->fsCodeAppend("\t\tfloat edgeAlpha;\n"); @@ -185,13 +188,16 @@ void GrGLQuadEffect::emitCode(GrGLShaderBuilder* builder, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + const char *vsName, *fsName; const SkString* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); - builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName); + vertexBuilder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName); switch (fEdgeType) { case kHairAA_GrBezierEdgeType: { @@ -238,7 +244,7 @@ void GrGLQuadEffect::emitCode(GrGLShaderBuilder* builder, GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); } GrGLEffect::EffectKey GrGLQuadEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { @@ -314,13 +320,16 @@ void GrGLCubicEffect::emitCode(GrGLShaderBuilder* builder, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + const char *vsName, *fsName; - builder->addVarying(kVec4f_GrSLType, "CubicCoeffs", - &vsName, &fsName); + vertexBuilder->addVarying(kVec4f_GrSLType, "CubicCoeffs", + &vsName, &fsName); const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); builder->fsCodeAppend("\t\tfloat edgeAlpha;\n"); diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp index 7a1692b325..ccf761ab94 100644 --- a/src/gpu/effects/GrSimpleTextureEffect.cpp +++ b/src/gpu/effects/GrSimpleTextureEffect.cpp @@ -39,11 +39,13 @@ public: fsCoordSLType = kVec2f_GrSLType; const char* vsVaryingName; const char* fsVaryingNamePtr; - builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsVaryingNamePtr); + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + vertexBuilder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsVaryingNamePtr); fsCoordName = fsVaryingNamePtr; const char* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str(); - builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, attrName); + vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str(); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, attrName); } else { fsCoordSLType = fEffectMatrix.get()->emitCode(builder, key, &fsCoordName); } diff --git a/src/gpu/gl/GrGLEffectMatrix.cpp b/src/gpu/gl/GrGLEffectMatrix.cpp index 19f99c0673..7530b5911a 100644 --- a/src/gpu/gl/GrGLEffectMatrix.cpp +++ b/src/gpu/gl/GrGLEffectMatrix.cpp @@ -48,6 +48,9 @@ GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder, SkString* fsCoordName, SkString* vsCoordName, const char* suffix) { + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + GrSLType varyingType = kVoid_GrSLType; const char* uniName; key &= kKeyMask; @@ -96,17 +99,17 @@ GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder, } const char* vsVaryingName; const char* fsVaryingName; - builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); + vertexBuilder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); const GrGLShaderVar* coords; switch (fCoordsType) { case GrEffect::kLocal_CoordsType: SkASSERT(!(kPositionCoords_Flag & key)); - coords = &builder->localCoordsAttribute(); + coords = &vertexBuilder->localCoordsAttribute(); break; case GrEffect::kPosition_CoordsType: - SkASSERT((kPositionCoords_Flag & key) || !builder->hasExplicitLocalCoords()); - coords = &builder->positionAttribute(); + SkASSERT((kPositionCoords_Flag & key) || !vertexBuilder->hasExplicitLocalCoords()); + coords = &vertexBuilder->positionAttribute(); break; default: coords = NULL; // prevents warning @@ -116,21 +119,21 @@ GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder, switch (fUniType) { case kVoid_GrSLType: SkASSERT(kVec2f_GrSLType == varyingType); - builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords->c_str()); + vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords->c_str()); break; case kVec2f_GrSLType: SkASSERT(kVec2f_GrSLType == varyingType); - builder->vsCodeAppendf("\t%s = %s + %s;\n", - vsVaryingName, uniName, coords->c_str()); + vertexBuilder->vsCodeAppendf("\t%s = %s + %s;\n", + vsVaryingName, uniName, coords->c_str()); break; case kMat33f_GrSLType: { SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); if (kVec2f_GrSLType == varyingType) { - builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n", - vsVaryingName, uniName, coords->c_str()); + vertexBuilder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n", + vsVaryingName, uniName, coords->c_str()); } else { - builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n", - vsVaryingName, uniName, coords->c_str()); + vertexBuilder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n", + vsVaryingName, uniName, coords->c_str()); } break; } diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index a1c4fd5d76..540ebcaeb3 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -222,10 +222,12 @@ void add_color_filter(GrGLShaderBuilder* builder, GrSLConstantVec GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) { switch (fDesc.getHeader().fColorInput) { case GrGLProgramDesc::kAttribute_ColorInput: { - builder->addAttribute(kVec4f_GrSLType, COL_ATTR_NAME); + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + vertexBuilder->addAttribute(kVec4f_GrSLType, COL_ATTR_NAME); const char *vsName, *fsName; - builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); - builder->vsCodeAppendf("\t%s = " COL_ATTR_NAME ";\n", vsName); + vertexBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); + vertexBuilder->vsCodeAppendf("\t%s = " COL_ATTR_NAME ";\n", vsName); *inColor = fsName; return kNone_GrSLConstantVec; } @@ -251,10 +253,12 @@ GrSLConstantVec GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* GrSLConstantVec GrGLProgram::genInputCoverage(GrGLShaderBuilder* builder, SkString* inCoverage) { switch (fDesc.getHeader().fCoverageInput) { case GrGLProgramDesc::kAttribute_ColorInput: { - builder->addAttribute(kVec4f_GrSLType, COV_ATTR_NAME); + GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); + SkASSERT(NULL != vertexBuilder); + vertexBuilder->addAttribute(kVec4f_GrSLType, COV_ATTR_NAME); const char *vsName, *fsName; - builder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); - builder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName); + vertexBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); + vertexBuilder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName); *inCoverage = fsName; return kNone_GrSLConstantVec; } @@ -278,28 +282,28 @@ GrSLConstantVec GrGLProgram::genInputCoverage(GrGLShaderBuilder* builder, SkStri } } -void GrGLProgram::genGeometryShader(GrGLShaderBuilder* builder) const { +void GrGLProgram::genGeometryShader(GrGLShaderBuilder::VertexBuilder* vertexBuilder) const { #if GR_GL_EXPERIMENTAL_GS // TODO: The builder should add all this glue code. if (fDesc.getHeader().fExperimentalGS) { SkASSERT(fContext.info().glslGeneration() >= k150_GrGLSLGeneration); - builder->fGSHeader.append("layout(triangles) in;\n" - "layout(triangle_strip, max_vertices = 6) out;\n"); - builder->gsCodeAppend("\tfor (int i = 0; i < 3; ++i) {\n" - "\t\tgl_Position = gl_in[i].gl_Position;\n"); + vertexBuilder->fGSHeader.append("layout(triangles) in;\n" + "layout(triangle_strip, max_vertices = 6) out;\n"); + vertexBuilder->gsCodeAppend("\tfor (int i = 0; i < 3; ++i) {\n" + "\t\tgl_Position = gl_in[i].gl_Position;\n"); if (fDesc.getHeader().fEmitsPointSize) { - builder->gsCodeAppend("\t\tgl_PointSize = 1.0;\n"); + vertexBuilder->gsCodeAppend("\t\tgl_PointSize = 1.0;\n"); } - SkASSERT(builder->fGSInputs.count() == builder->fGSOutputs.count()); - int count = builder->fGSInputs.count(); + SkASSERT(vertexBuilder->fGSInputs.count() == vertexBuilder->fGSOutputs.count()); + int count = vertexBuilder->fGSInputs.count(); for (int i = 0; i < count; ++i) { - builder->gsCodeAppendf("\t\t%s = %s[i];\n", - builder->fGSOutputs[i].getName().c_str(), - builder->fGSInputs[i].getName().c_str()); + vertexBuilder->gsCodeAppendf("\t\t%s = %s[i];\n", + vertexBuilder->fGSOutputs[i].getName().c_str(), + vertexBuilder->fGSInputs[i].getName().c_str()); } - builder->gsCodeAppend("\t\tEmitVertex();\n" - "\t}\n" - "\tEndPrimitive();\n"); + vertexBuilder->gsCodeAppend("\t\tEmitVertex();\n" + "\t}\n" + "\tEndPrimitive();\n"); } #endif } @@ -397,31 +401,34 @@ void expand_known_value4f(SkString* string, GrSLConstantVec vec) { // compiles all the shaders from builder and stores the shader IDs bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) { - SkString shader; - - builder.vsGetShader(&shader); - if (c_PrintShaders) { - GrPrintf(shader.c_str()); - GrPrintf("\n"); - } + SkASSERT(!fVShaderID); + SkASSERT(!fGShaderID); + SkASSERT(!fFShaderID); - if (!(fVShaderID = compile_shader(fContext, GR_GL_VERTEX_SHADER, shader))) { - return false; - } - - fGShaderID = 0; -#if GR_GL_EXPERIMENTAL_GS - if (fDesc.getHeader().fExperimentalGS) { - builder.gsGetShader(&shader); + SkString shader; + if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) { + vertexBuilder->vsGetShader(&shader); if (c_PrintShaders) { GrPrintf(shader.c_str()); GrPrintf("\n"); } - if (!(fGShaderID = compile_shader(fContext, GR_GL_GEOMETRY_SHADER, shader))) { + if (!(fVShaderID = compile_shader(fContext, GR_GL_VERTEX_SHADER, shader))) { return false; } - } + +#if GR_GL_EXPERIMENTAL_GS + if (fDesc.getHeader().fExperimentalGS) { + vertexBuilder->gsGetShader(&shader); + if (c_PrintShaders) { + GrPrintf(shader.c_str()); + GrPrintf("\n"); + } + if (!(fGShaderID = compile_shader(fContext, GR_GL_GEOMETRY_SHADER, shader))) { + return false; + } + } #endif + } builder.fsGetShader(&shader); if (c_PrintShaders) { @@ -441,7 +448,28 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[], const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); - GrGLShaderBuilder builder(fContext.info(), fUniformManager, fDesc); + bool needsVertexShader = true; + + GrGLShaderBuilder builder(fContext.info(), fUniformManager, fDesc, needsVertexShader); + + if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) { + const char* viewMName; + fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_Visibility, + kMat33f_GrSLType, "ViewM", &viewMName); + + vertexBuilder->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n" + "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", + viewMName, vertexBuilder->positionAttribute().c_str()); + + // we output point size in the GS if present + if (header.fEmitsPointSize +#if GR_GL_EXPERIMENTAL_GS + && !header.fExperimentalGS +#endif + ) { + vertexBuilder->vsCodeAppend("\tgl_PointSize = 1.0;\n"); + } + } // the dual source output has no canonical var name, have to // declare an output, which is incompatible with gl_FragColor/gl_FragData. @@ -452,31 +480,13 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[], declared_color_output_name(), &colorOutput); if (isColorDeclared) { - builder.fFSOutputs.push_back(colorOutput); + builder.fsOutputAppend(colorOutput); } - const char* viewMName; - fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_Visibility, - kMat33f_GrSLType, "ViewM", &viewMName); - - - builder.vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n" - "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", - viewMName, builder.positionAttribute().getName().c_str()); - // incoming color to current stage being processed. SkString inColor; GrSLConstantVec knownColorValue = this->genInputColor(&builder, &inColor); - // we output point size in the GS if present - if (header.fEmitsPointSize -#if GR_GL_EXPERIMENTAL_GS - && !header.fExperimentalGS -#endif - ) { - builder.vsCodeAppend("\tgl_PointSize = 1.0;\n"); - } - // Get the coeffs for the Mode-based color filter, determine if color is needed. SkXfermode::Coeff colorCoeff; SkXfermode::Coeff filterColorCoeff; @@ -567,9 +577,9 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[], GrGLProgramDesc::CoverageOutput coverageOutput = static_cast<GrGLProgramDesc::CoverageOutput>(header.fCoverageOutput); if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(coverageOutput)) { - builder.fFSOutputs.push_back().set(kVec4f_GrSLType, - GrGLShaderVar::kOut_TypeModifier, - dual_source_output_name()); + builder.fsOutputAppend().set(kVec4f_GrSLType, + GrGLShaderVar::kOut_TypeModifier, + dual_source_output_name()); // default coeff to ones for kCoverage_DualSrcOutput SkString coeff; GrSLConstantVec knownCoeffValue = kOnes_GrSLConstantVec; @@ -651,7 +661,9 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[], /////////////////////////////////////////////////////////////////////////// // insert GS #ifdef SK_DEBUG - this->genGeometryShader(&builder); + if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) { + this->genGeometryShader(vertexBuilder); + } #endif /////////////////////////////////////////////////////////////////////////// @@ -686,7 +698,9 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil return false; } - GL_CALL(AttachShader(fProgramID, fVShaderID)); + if (fVShaderID) { + GL_CALL(AttachShader(fProgramID, fVShaderID)); + } if (fGShaderID) { GL_CALL(AttachShader(fProgramID, fGShaderID)); } @@ -702,26 +716,28 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); // Bind the attrib locations to same values for all shaders - GL_CALL(BindAttribLocation(fProgramID, - header.fPositionAttributeIndex, - builder.positionAttribute().c_str())); - if (-1 != header.fLocalCoordAttributeIndex) { + if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) { GL_CALL(BindAttribLocation(fProgramID, - header.fLocalCoordAttributeIndex, - builder.localCoordsAttribute().c_str())); - } - if (-1 != header.fColorAttributeIndex) { - GL_CALL(BindAttribLocation(fProgramID, header.fColorAttributeIndex, COL_ATTR_NAME)); - } - if (-1 != header.fCoverageAttributeIndex) { - GL_CALL(BindAttribLocation(fProgramID, header.fCoverageAttributeIndex, COV_ATTR_NAME)); - } + header.fPositionAttributeIndex, + vertexBuilder->positionAttribute().c_str())); + if (-1 != header.fLocalCoordAttributeIndex) { + GL_CALL(BindAttribLocation(fProgramID, + header.fLocalCoordAttributeIndex, + vertexBuilder->localCoordsAttribute().c_str())); + } + if (-1 != header.fColorAttributeIndex) { + GL_CALL(BindAttribLocation(fProgramID, header.fColorAttributeIndex, COL_ATTR_NAME)); + } + if (-1 != header.fCoverageAttributeIndex) { + GL_CALL(BindAttribLocation(fProgramID, header.fCoverageAttributeIndex, COV_ATTR_NAME)); + } - const GrGLShaderBuilder::AttributePair* attribEnd = builder.getEffectAttributes().end(); - for (const GrGLShaderBuilder::AttributePair* attrib = builder.getEffectAttributes().begin(); - attrib != attribEnd; - ++attrib) { - GL_CALL(BindAttribLocation(fProgramID, attrib->fIndex, attrib->fName.c_str())); + const GrGLShaderBuilder::VertexBuilder::AttributePair* attribEnd = vertexBuilder->getEffectAttributes().end(); + for (const GrGLShaderBuilder::VertexBuilder::AttributePair* attrib = vertexBuilder->getEffectAttributes().begin(); + attrib != attribEnd; + ++attrib) { + GL_CALL(BindAttribLocation(fProgramID, attrib->fIndex, attrib->fName.c_str())); + } } GL_CALL(LinkProgram(fProgramID)); diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 279890f5d4..e39e9bf076 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -12,6 +12,7 @@ #include "GrDrawState.h" #include "GrGLContext.h" #include "GrGLProgramDesc.h" +#include "GrGLShaderBuilder.h" #include "GrGLSL.h" #include "GrGLTexture.h" #include "GrGLUniformManager.h" @@ -162,7 +163,7 @@ private: GrSLConstantVec genInputCoverage(GrGLShaderBuilder* builder, SkString* inCoverage); - void genGeometryShader(GrGLShaderBuilder* segments) const; + void genGeometryShader(GrGLShaderBuilder::VertexBuilder* vertexBuilder) const; // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder, diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp index 2554142583..e62bfdebe8 100644 --- a/src/gpu/gl/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/GrGLShaderBuilder.cpp @@ -93,37 +93,23 @@ static const char kDstCopyColorName[] = "_dstColor"; GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, GrGLUniformManager& uniformManager, - const GrGLProgramDesc& desc) + const GrGLProgramDesc& desc, + bool needsVertexShader) : fUniforms(kVarsPerBlock) - , fVSAttrs(kVarsPerBlock) - , fVSOutputs(kVarsPerBlock) - , fGSInputs(kVarsPerBlock) - , fGSOutputs(kVarsPerBlock) - , fFSInputs(kVarsPerBlock) - , fFSOutputs(kMaxFSOutputs) , fCtxInfo(ctxInfo) , fUniformManager(uniformManager) , fFSFeaturesAddedMask(0) -#if GR_GL_EXPERIMENTAL_GS - , fUsesGS(SkToBool(desc.getHeader().fExperimentalGS)) -#else - , fUsesGS(false) -#endif + , fFSInputs(kVarsPerBlock) + , fFSOutputs(kMaxFSOutputs) , fSetupFragPosition(false) , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) { const GrGLProgramDesc::KeyHeader& header = desc.getHeader(); - fPositionVar = &fVSAttrs.push_back(); - fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); - if (-1 != header.fLocalCoordAttributeIndex) { - fLocalCoordsVar = &fVSAttrs.push_back(); - fLocalCoordsVar->set(kVec2f_GrSLType, - GrGLShaderVar::kAttribute_TypeModifier, - "aLocalCoords"); - } else { - fLocalCoordsVar = fPositionVar; + if (needsVertexShader) { + fVertexBuilder.reset(SkNEW_ARGS(VertexBuilder, (this, desc))); } + // Emit code to read the dst copy textue if necessary. if (kNoDstRead_DstReadKey != header.fDstReadKey && GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) { @@ -375,61 +361,6 @@ GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t vi return h; } -bool GrGLShaderBuilder::addAttribute(GrSLType type, - const char* name) { - for (int i = 0; i < fVSAttrs.count(); ++i) { - const GrGLShaderVar& attr = fVSAttrs[i]; - // if attribute already added, don't add it again - if (attr.getName().equals(name)) { - SkASSERT(attr.getType() == type); - return false; - } - } - fVSAttrs.push_back().set(type, - GrGLShaderVar::kAttribute_TypeModifier, - name); - return true; -} - -void GrGLShaderBuilder::addVarying(GrSLType type, - const char* name, - const char** vsOutName, - const char** fsInName) { - fVSOutputs.push_back(); - fVSOutputs.back().setType(type); - fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); - this->nameVariable(fVSOutputs.back().accessName(), 'v', name); - - if (vsOutName) { - *vsOutName = fVSOutputs.back().getName().c_str(); - } - // input to FS comes either from VS or GS - const SkString* fsName; - if (fUsesGS) { - // if we have a GS take each varying in as an array - // and output as non-array. - fGSInputs.push_back(); - fGSInputs.back().setType(type); - fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier); - fGSInputs.back().setUnsizedArray(); - *fGSInputs.back().accessName() = fVSOutputs.back().getName(); - fGSOutputs.push_back(); - fGSOutputs.back().setType(type); - fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); - this->nameVariable(fGSOutputs.back().accessName(), 'g', name); - fsName = fGSOutputs.back().accessName(); - } else { - fsName = fVSOutputs.back().accessName(); - } - fFSInputs.push_back(); - fFSInputs.back().setType(type); - fFSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier); - fFSInputs.back().setName(*fsName); - if (fsInName) { - *fsInName = fsName->c_str(); - } -} - const char* GrGLShaderBuilder::fragmentPosition() { if (fCodeStage.inStageCode()) { const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); @@ -547,31 +478,6 @@ void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility, } } -void GrGLShaderBuilder::vsGetShader(SkString* shaderStr) const { - *shaderStr = GrGetGLSLVersionDecl(fCtxInfo); - this->appendUniformDecls(kVertex_Visibility, shaderStr); - this->appendDecls(fVSAttrs, shaderStr); - this->appendDecls(fVSOutputs, shaderStr); - shaderStr->append("void main() {\n"); - shaderStr->append(fVSCode); - shaderStr->append("}\n"); -} - -void GrGLShaderBuilder::gsGetShader(SkString* shaderStr) const { - if (!fUsesGS) { - shaderStr->reset(); - return; - } - - *shaderStr = GrGetGLSLVersionDecl(fCtxInfo); - shaderStr->append(fGSHeader); - this->appendDecls(fGSInputs, shaderStr); - this->appendDecls(fGSOutputs, shaderStr); - shaderStr->append("void main() {\n"); - shaderStr->append(fGSCode); - shaderStr->append("}\n"); -} - void GrGLShaderBuilder::fsGetShader(SkString* shaderStr) const { *shaderStr = GrGetGLSLVersionDecl(fCtxInfo); shaderStr->append(fFSExtensions); @@ -620,18 +526,20 @@ void GrGLShaderBuilder::emitEffects( textureSamplers[t].init(this, &effect->textureAccess(t), t); effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform); } - GrDrawEffect drawEffect(stage, this->hasExplicitLocalCoords()); + GrDrawEffect drawEffect(stage, fVertexBuilder.get() + && fVertexBuilder->hasExplicitLocalCoords()); int numAttributes = stage.getVertexAttribIndexCount(); const int* attributeIndices = stage.getVertexAttribIndices(); SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames; for (int a = 0; a < numAttributes; ++a) { // TODO: Make addAttribute mangle the name. + SkASSERT(fVertexBuilder.get()); SkString attributeName("aAttr"); attributeName.appendS32(attributeIndices[a]); - if (this->addAttribute(effect->vertexAttribType(a), attributeName.c_str())) { - fEffectAttributes.push_back().set(attributeIndices[a], attributeName); - } + fVertexBuilder->addEffectAttribute(attributeIndices[a], + effect->vertexAttribType(a), + attributeName); } glEffects[e] = effect->getFactory().createGLInstance(drawEffect); @@ -649,8 +557,10 @@ void GrGLShaderBuilder::emitEffects( // Enclose custom code in a block to avoid namespace conflicts SkString openBrace; openBrace.printf("\t{ // Stage %d: %s\n", fCodeStage.stageIndex(), glEffects[e]->name()); - this->fVSCode.append(openBrace); - this->fFSCode.append(openBrace); + if (fVertexBuilder.get()) { + fVertexBuilder->vsCodeAppend(openBrace.c_str()); + } + this->fsCodeAppend(openBrace.c_str()); glEffects[e]->emitCode(this, drawEffect, @@ -658,8 +568,11 @@ void GrGLShaderBuilder::emitEffects( outColor.c_str(), inColor.isEmpty() ? NULL : inColor.c_str(), textureSamplers); - this->fVSCode.append("\t}\n"); - this->fFSCode.append("\t}\n"); + + if (fVertexBuilder.get()) { + fVertexBuilder->vsCodeAppend("\t}\n"); + } + this->fsCodeAppend("\t}\n"); inColor = outColor; *fsInOutColorKnownValue = kNone_GrSLConstantVec; @@ -671,7 +584,127 @@ void GrGLShaderBuilder::emitEffects( } } -const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const { +//////////////////////////////////////////////////////////////////////////// + +GrGLShaderBuilder::VertexBuilder::VertexBuilder(GrGLShaderBuilder* parent, + const GrGLProgramDesc& desc) + : fVSAttrs(kVarsPerBlock) + , fVSOutputs(kVarsPerBlock) + , fGSInputs(kVarsPerBlock) + , fGSOutputs(kVarsPerBlock) + , fParent(parent) +#if GR_GL_EXPERIMENTAL_GS + , fUsesGS(SkToBool(desc.getHeader().fExperimentalGS)) +#else + , fUsesGS(false) +#endif +{ + const GrGLProgramDesc::KeyHeader& header = desc.getHeader(); + + fPositionVar = &fVSAttrs.push_back(); + fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); + if (-1 != header.fLocalCoordAttributeIndex) { + fLocalCoordsVar = &fVSAttrs.push_back(); + fLocalCoordsVar->set(kVec2f_GrSLType, + GrGLShaderVar::kAttribute_TypeModifier, + "aLocalCoords"); + } else { + fLocalCoordsVar = fPositionVar; + } +} + +bool GrGLShaderBuilder::VertexBuilder::addAttribute(GrSLType type, + const char* name) { + for (int i = 0; i < fVSAttrs.count(); ++i) { + const GrGLShaderVar& attr = fVSAttrs[i]; + // if attribute already added, don't add it again + if (attr.getName().equals(name)) { + SkASSERT(attr.getType() == type); + return false; + } + } + fVSAttrs.push_back().set(type, + GrGLShaderVar::kAttribute_TypeModifier, + name); + return true; +} + +bool GrGLShaderBuilder::VertexBuilder::addEffectAttribute(int attributeIndex, + GrSLType type, + const SkString& name) { + if (!this->addAttribute(type, name.c_str())) { + return false; + } + + fEffectAttributes.push_back().set(attributeIndex, name); + return true; +} + +void GrGLShaderBuilder::VertexBuilder::addVarying(GrSLType type, + const char* name, + const char** vsOutName, + const char** fsInName) { + fVSOutputs.push_back(); + fVSOutputs.back().setType(type); + fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); + fParent->nameVariable(fVSOutputs.back().accessName(), 'v', name); + + if (vsOutName) { + *vsOutName = fVSOutputs.back().getName().c_str(); + } + // input to FS comes either from VS or GS + const SkString* fsName; + if (fUsesGS) { + // if we have a GS take each varying in as an array + // and output as non-array. + fGSInputs.push_back(); + fGSInputs.back().setType(type); + fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier); + fGSInputs.back().setUnsizedArray(); + *fGSInputs.back().accessName() = fVSOutputs.back().getName(); + fGSOutputs.push_back(); + fGSOutputs.back().setType(type); + fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); + fParent->nameVariable(fGSOutputs.back().accessName(), 'g', name); + fsName = fGSOutputs.back().accessName(); + } else { + fsName = fVSOutputs.back().accessName(); + } + fParent->fsInputAppend().set(type, + GrGLShaderVar::kVaryingIn_TypeModifier, + *fsName); + if (fsInName) { + *fsInName = fsName->c_str(); + } +} + +void GrGLShaderBuilder::VertexBuilder::vsGetShader(SkString* shaderStr) const { + *shaderStr = GrGetGLSLVersionDecl(fParent->ctxInfo()); + fParent->appendUniformDecls(kVertex_Visibility, shaderStr); + fParent->appendDecls(fVSAttrs, shaderStr); + fParent->appendDecls(fVSOutputs, shaderStr); + shaderStr->append("void main() {\n"); + shaderStr->append(fVSCode); + shaderStr->append("}\n"); +} + +void GrGLShaderBuilder::VertexBuilder::gsGetShader(SkString* shaderStr) const { + if (!fUsesGS) { + shaderStr->reset(); + return; + } + + *shaderStr = GrGetGLSLVersionDecl(fParent->ctxInfo()); + shaderStr->append(fGSHeader); + fParent->appendDecls(fGSInputs, shaderStr); + fParent->appendDecls(fGSOutputs, shaderStr); + shaderStr->append("void main() {\n"); + shaderStr->append(fGSCode); + shaderStr->append("}\n"); +} + + +const SkString* GrGLShaderBuilder::VertexBuilder::getEffectAttributeName(int attributeIndex) const { const AttributePair* attribEnd = this->getEffectAttributes().end(); for (const AttributePair* attrib = this->getEffectAttributes().begin(); attrib != attribEnd; diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h index ad0d87ef31..28f1b3822a 100644 --- a/src/gpu/gl/GrGLShaderBuilder.h +++ b/src/gpu/gl/GrGLShaderBuilder.h @@ -96,6 +96,7 @@ public: }; typedef SkTArray<TextureSampler> TextureSamplerArray; + typedef GrTAllocator<GrGLShaderVar> VarArray; enum ShaderVisibility { kVertex_Visibility = 0x1, @@ -103,7 +104,10 @@ public: kFragment_Visibility = 0x4, }; - GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&, const GrGLProgramDesc&); + GrGLShaderBuilder(const GrGLContextInfo&, + GrGLUniformManager&, + const GrGLProgramDesc&, + bool needsVertexShader); /** * Use of these features may require a GLSL extension to be enabled. Shaders may not compile @@ -122,22 +126,8 @@ public: bool enableFeature(GLSLFeature); /** - * Called by GrGLEffects to add code to one of the shaders. + * Called by GrGLEffects to add code the fragment shader. */ - void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { - va_list args; - va_start(args, format); - fVSCode.appendf(format, args); - va_end(args); - } - - void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { - va_list args; - va_start(args, format); - fGSCode.appendf(format, args); - va_end(args); - } - void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { va_list args; va_start(args, format); @@ -145,8 +135,6 @@ public: va_end(args); } - void vsCodeAppend(const char* str) { fVSCode.append(str); } - void gsCodeAppend(const char* str) { fGSCode.append(str); } void fsCodeAppend(const char* str) { fFSCode.append(str); } /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or @@ -180,6 +168,12 @@ public: const char* body, SkString* outName); + /** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */ + GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); } + GrGLShaderVar& fsOutputAppend() { return fFSOutputs.push_back(); } + GrGLShaderVar& fsInputAppend(const GrGLShaderVar& var) { return fFSInputs.push_back(var); } + GrGLShaderVar& fsOutputAppend(const GrGLShaderVar& var) { return fFSOutputs.push_back(var); } + /** Generates a EffectKey for the shader code based on the texture access parameters and the capabilities of the GL context. This is useful for keying the shader programs that may have multiple representations, based on the type/format of textures used. */ @@ -233,50 +227,22 @@ public: return this->getUniformVariable(u).c_str(); } - /** Add a vertex attribute to the current program that is passed in from the vertex data. - Returns false if the attribute was already there, true otherwise. */ - bool addAttribute(GrSLType type, const char* name); - - /** 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); - /** Returns a variable name that represents the position of the fragment in the FS. The position is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */ const char* fragmentPosition(); - /** Returns a vertex attribute that represents the vertex position in the VS. This is the - pre-matrix position and is commonly used by effects to compute texture coords via a matrix. - */ - const GrGLShaderVar& positionAttribute() const { return *fPositionVar; } - - /** 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. */ - const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; } - /** Returns the color of the destination pixel. This may be NULL if no effect advertised that it will read the destination. */ const char* dstColor(); /** - * Are explicit local coordinates provided as input to the vertex shader. - */ - bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); } - - /** * Interfaces used by GrGLProgram. * TODO: Hide these from the GrEffects using friend or splitting this into two related classes. * Also, GrGLProgram's shader string construction should be moved to this class. */ - /** Called after building is complete to get the final shader string. */ - void vsGetShader(SkString*) const; - void gsGetShader(SkString*) const; + /** Called after building is complete to get the final shader string. To acces the vertex + and geometry shaders, use the VertexBuilder. */ void fsGetShader(SkString*) const; /** @@ -309,17 +275,103 @@ public: return fDstCopySampler.fSamplerUniform; } - struct AttributePair { - void set(int index, const SkString& name) { - fIndex = index; fName = name; + /** Helper class used to build the vertex and geometry shaders. This functionality + is kept separate from the rest of GrGLShaderBuilder to allow for shaders programs + that only use the fragment shader. */ + class VertexBuilder { + public: + VertexBuilder(GrGLShaderBuilder* parent, const GrGLProgramDesc&); + + /** + * Called by GrGLEffects to add code to one of the shaders. + */ + void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { + va_list args; + va_start(args, format); + fVSCode.appendf(format, args); + va_end(args); + } + + void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { + va_list args; + va_start(args, format); + fGSCode.appendf(format, args); + va_end(args); + } + + void vsCodeAppend(const char* str) { fVSCode.append(str); } + void gsCodeAppend(const char* str) { fGSCode.append(str); } + + /** Add a vertex attribute to the current program that is passed in from the vertex data. + Returns false if the attribute was already there, true otherwise. */ + bool addAttribute(GrSLType type, const char* name); + + /** 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); + + /** Returns a vertex attribute that represents the vertex position in the VS. This is the + pre-matrix position and is commonly used by effects to compute texture coords via a matrix. + */ + const GrGLShaderVar& positionAttribute() const { return *fPositionVar; } + + /** 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. */ + const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; } + + /** + * Are explicit local coordinates provided as input to the vertex shader. + */ + bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); } + + /** Called after building is complete to get the final shader string. */ + void vsGetShader(SkString*) const; + void gsGetShader(SkString*) const; + + struct AttributePair { + void set(int index, const SkString& name) { + fIndex = index; fName = name; + } + int fIndex; + SkString fName; + }; + const SkTArray<AttributePair, true>& getEffectAttributes() const { + return fEffectAttributes; } - int fIndex; - SkString fName; + bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name); + const SkString* getEffectAttributeName(int attributeIndex) const; + + // TODO: Everything below here private. + public: + + VarArray fVSAttrs; + VarArray fVSOutputs; + VarArray fGSInputs; + VarArray fGSOutputs; + SkString fGSHeader; // layout qualifiers specific to GS + + private: + GrGLShaderBuilder* fParent; + + bool fUsesGS; + + SkString fVSCode; + SkString fGSCode; + + SkSTArray<10, AttributePair, true> fEffectAttributes; + + GrGLShaderVar* fPositionVar; + GrGLShaderVar* fLocalCoordsVar; }; - const SkTArray<AttributePair, true>& getEffectAttributes() const { - return fEffectAttributes; - } - const SkString* getEffectAttributeName(int attributeIndex) const; + + /** Gets the vertex builder that is used to construct the vertex and geometry shaders. + It may be NULL if this shader program is only meant to have a fragment shader. */ + VertexBuilder* getVertexBuilder() const { return fVertexBuilder.get(); } // TODO: Make this do all the compiling, linking, etc. void finished(GrGLuint programID); @@ -327,25 +379,12 @@ public: const GrGLContextInfo& ctxInfo() const { return fCtxInfo; } private: - typedef GrTAllocator<GrGLShaderVar> VarArray; - void appendDecls(const VarArray&, SkString*) const; void appendUniformDecls(ShaderVisibility, SkString*) const; typedef GrGLUniformManager::BuilderUniform BuilderUniform; GrGLUniformManager::BuilderUniformArray fUniforms; - // TODO: Everything below here private. -public: - - VarArray fVSAttrs; - VarArray fVSOutputs; - VarArray fGSInputs; - VarArray fGSOutputs; - VarArray fFSInputs; - SkString fGSHeader; // layout qualifiers specific to GS - VarArray fFSOutputs; - private: class CodeStage : GrNoncopyable { public: @@ -436,12 +475,10 @@ private: uint32_t fFSFeaturesAddedMask; SkString fFSFunctions; SkString fFSExtensions; - - bool fUsesGS; + VarArray fFSInputs; + VarArray fFSOutputs; SkString fFSCode; - SkString fVSCode; - SkString fGSCode; bool fSetupFragPosition; TextureSampler fDstCopySampler; @@ -452,11 +489,7 @@ private: bool fTopLeftFragPosRead; - SkSTArray<10, AttributePair, true> fEffectAttributes; - - GrGLShaderVar* fPositionVar; - GrGLShaderVar* fLocalCoordsVar; - + SkAutoTDelete<VertexBuilder> fVertexBuilder; }; #endif |