Index: src/gpu/gl/GrGLShaderBuilder.cpp |
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp |
index d11394a7b39371608b1ce113cbc7b8d1a49a4e78..f4ffb4dd2ce2f071743c9c3d08b3edb7abaa4d56 100644 |
--- a/src/gpu/gl/GrGLShaderBuilder.cpp |
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp |
@@ -9,7 +9,13 @@ |
#include "gl/GrGLProgram.h" |
#include "gl/GrGLUniformHandle.h" |
#include "GrDrawEffect.h" |
+#include "GrGpuGL.h" |
#include "GrTexture.h" |
+#include "SkRTConf.h" |
+#include "SkTrace.h" |
+ |
+#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) |
+#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X) |
// number of each input/output type in a single allocation block |
static const int kVarsPerBlock = 8; |
@@ -21,10 +27,18 @@ static const int kMaxFSOutputs = 2; |
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; |
typedef GrGLUniformManager::UniformHandle UniformHandle; |
+ |
+SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, |
+ "Print the source code for all shaders generated."); |
+ |
/////////////////////////////////////////////////////////////////////////////// |
namespace { |
+inline const char* color_attribute_name() { return "aColor"; } |
+inline const char* coverage_attribute_name() { return "aCoverage"; } |
+inline const char* declared_color_output_name() { return "fsColorOut"; } |
+inline const char* dual_source_output_name() { return "dualSourceOut"; } |
inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) { |
if (kVec2f_GrSLType == type) { |
return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D"; |
@@ -91,28 +105,32 @@ static const char kDstCopyColorName[] = "_dstColor"; |
/////////////////////////////////////////////////////////////////////////////// |
-GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, |
+GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu, |
GrGLUniformManager& uniformManager, |
const GrGLProgramDesc& desc, |
bool needsVertexShader) |
: fUniforms(kVarsPerBlock) |
- , fCtxInfo(ctxInfo) |
+ , fGpu(gpu) |
, fUniformManager(uniformManager) |
, fFSFeaturesAddedMask(0) |
, fFSInputs(kVarsPerBlock) |
, fFSOutputs(kMaxFSOutputs) |
, fSetupFragPosition(false) |
+ , fKnownColorValue(kNone_GrSLConstantVec) |
+ , fKnownCoverageValue(kNone_GrSLConstantVec) |
+ , fHasCustomColorOutput(false) |
+ , fHasSecondaryOutput(false) |
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) { |
const GrGLProgramDesc::KeyHeader& header = desc.getHeader(); |
if (needsVertexShader) { |
- fVertexBuilder.reset(SkNEW_ARGS(VertexBuilder, (this, desc))); |
+ fVertexBuilder.reset(SkNEW_ARGS(VertexBuilder, (this, fGpu, desc))); |
} |
// Emit code to read the dst copy textue if necessary. |
if (kNoDstRead_DstReadKey != header.fDstReadKey && |
- GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) { |
+ GrGLCaps::kNone_FBFetchType == fGpu->glCaps().fbFetchType()) { |
bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); |
const char* dstCopyTopLeftName; |
const char* dstCopyCoordScaleName; |
@@ -143,15 +161,76 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, |
this->fsAppendTextureLookup(fDstCopySampler, "_dstTexCoord"); |
this->fsCodeAppend(";\n\n"); |
} |
+ |
+ switch (header.fColorInput) { |
+ case GrGLProgramDesc::kAttribute_ColorInput: { |
+ SkASSERT(NULL != fVertexBuilder.get()); |
+ fVertexBuilder->addAttribute(kVec4f_GrSLType, color_attribute_name()); |
+ const char *vsName, *fsName; |
+ fVertexBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); |
+ fVertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsName, color_attribute_name()); |
+ fInputColor = fsName; |
+ break; |
+ } |
+ case GrGLProgramDesc::kUniform_ColorInput: { |
+ const char* name; |
+ fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
+ kVec4f_GrSLType, "Color", &name); |
+ fInputColor = name; |
+ break; |
+ } |
+ case GrGLProgramDesc::kTransBlack_ColorInput: |
+ fKnownColorValue = kZeros_GrSLConstantVec; |
+ break; |
+ case GrGLProgramDesc::kSolidWhite_ColorInput: |
+ fKnownColorValue = kOnes_GrSLConstantVec; |
+ break; |
+ default: |
+ GrCrash("Unknown color type."); |
+ } |
+ |
+ switch (header.fCoverageInput) { |
+ case GrGLProgramDesc::kAttribute_ColorInput: { |
+ SkASSERT(NULL != fVertexBuilder.get()); |
+ fVertexBuilder->addAttribute(kVec4f_GrSLType, coverage_attribute_name()); |
+ const char *vsName, *fsName; |
+ fVertexBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); |
+ fVertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name()); |
+ fInputCoverage = fsName; |
+ break; |
+ } |
+ case GrGLProgramDesc::kUniform_ColorInput: { |
+ const char* name; |
+ fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
+ kVec4f_GrSLType, "Coverage", &name); |
+ fInputCoverage = name; |
+ break; |
+ } |
+ case GrGLProgramDesc::kTransBlack_ColorInput: |
+ fKnownCoverageValue = kZeros_GrSLConstantVec; |
+ break; |
+ case GrGLProgramDesc::kSolidWhite_ColorInput: |
+ fKnownCoverageValue = kOnes_GrSLConstantVec; |
+ break; |
+ default: |
+ GrCrash("Unknown coverage type."); |
+ } |
+ |
+ if (k110_GrGLSLGeneration != fGpu->glslGeneration()) { |
+ fFSOutputs.push_back().set(kVec4f_GrSLType, |
+ GrGLShaderVar::kOut_TypeModifier, |
+ declared_color_output_name()); |
+ fHasCustomColorOutput = true; |
+ } |
} |
bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) { |
switch (feature) { |
case kStandardDerivatives_GLSLFeature: |
- if (!fCtxInfo.caps()->shaderDerivativeSupport()) { |
+ if (!fGpu->glCaps().shaderDerivativeSupport()) { |
return false; |
} |
- if (kES_GrGLBinding == fCtxInfo.binding()) { |
+ if (kES_GrGLBinding == fGpu->glBinding()) { |
this->addFSFeature(1 << kStandardDerivatives_GLSLFeature, |
"GL_OES_standard_derivatives"); |
} |
@@ -165,23 +244,23 @@ bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) { |
bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) { |
switch (feature) { |
case kFragCoordConventions_GLSLPrivateFeature: |
- if (!fCtxInfo.caps()->fragCoordConventionsSupport()) { |
+ if (!fGpu->glCaps().fragCoordConventionsSupport()) { |
return false; |
} |
- if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) { |
+ if (fGpu->glslGeneration() < k150_GrGLSLGeneration) { |
this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature, |
"GL_ARB_fragment_coord_conventions"); |
} |
return true; |
case kEXTShaderFramebufferFetch_GLSLPrivateFeature: |
- if (GrGLCaps::kEXT_FBFetchType != fCtxInfo.caps()->fbFetchType()) { |
+ if (GrGLCaps::kEXT_FBFetchType != fGpu->glCaps().fbFetchType()) { |
return false; |
} |
this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature, |
"GL_EXT_shader_framebuffer_fetch"); |
return true; |
case kNVShaderFramebufferFetch_GLSLPrivateFeature: |
- if (GrGLCaps::kNV_FBFetchType != fCtxInfo.caps()->fbFetchType()) { |
+ if (GrGLCaps::kNV_FBFetchType != fGpu->glCaps().fbFetchType()) { |
return false; |
} |
this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature, |
@@ -225,7 +304,7 @@ const char* GrGLShaderBuilder::dstColor() { |
} |
} |
static const char kFBFetchColorName[] = "gl_LastFragData[0]"; |
- GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType(); |
+ GrGLCaps::FBFetchType fetchType = fGpu->glCaps().fbFetchType(); |
if (GrGLCaps::kEXT_FBFetchType == fetchType) { |
SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature)); |
return kFBFetchColorName; |
@@ -246,10 +325,10 @@ void GrGLShaderBuilder::appendTextureLookup(SkString* out, |
SkASSERT(NULL != coordName); |
out->appendf("%s(%s, %s)", |
- sample_function_name(varyingType, fCtxInfo.glslGeneration()), |
+ sample_function_name(varyingType, fGpu->glslGeneration()), |
this->getUniformCStr(sampler.fSamplerUniform), |
coordName); |
- append_swizzle(out, sampler, *fCtxInfo.caps()); |
+ append_swizzle(out, sampler, fGpu->glCaps()); |
} |
void GrGLShaderBuilder::fsAppendTextureLookup(const GrGLShaderBuilder::TextureSampler& sampler, |
@@ -379,7 +458,7 @@ const char* GrGLShaderBuilder::fragmentPosition() { |
fSetupFragPosition = true; |
} |
return "gl_FragCoord"; |
- } else if (fCtxInfo.caps()->fragCoordConventionsSupport()) { |
+ } else if (fGpu->glCaps().fragCoordConventionsSupport()) { |
if (!fSetupFragPosition) { |
SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature)); |
fFSInputs.push_back().set(kVec4f_GrSLType, |
@@ -425,7 +504,7 @@ void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType, |
fFSFunctions.appendf(" %s", outName->c_str()); |
fFSFunctions.append("("); |
for (int i = 0; i < argCnt; ++i) { |
- args[i].appendDecl(fCtxInfo, &fFSFunctions); |
+ args[i].appendDecl(this->ctxInfo(), &fFSFunctions); |
if (i < argCnt - 1) { |
fFSFunctions.append(", "); |
} |
@@ -463,7 +542,7 @@ inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, |
void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { |
for (int i = 0; i < vars.count(); ++i) { |
- vars[i].appendDecl(fCtxInfo, out); |
+ vars[i].appendDecl(this->ctxInfo(), out); |
out->append(";\n"); |
} |
} |
@@ -472,33 +551,12 @@ void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility, |
SkString* out) const { |
for (int i = 0; i < fUniforms.count(); ++i) { |
if (fUniforms[i].fVisibility & visibility) { |
- fUniforms[i].fVariable.appendDecl(fCtxInfo, out); |
+ fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); |
out->append(";\n"); |
} |
} |
} |
-void GrGLShaderBuilder::fsGetShader(SkString* shaderStr) const { |
- *shaderStr = GrGetGLSLVersionDecl(fCtxInfo); |
- shaderStr->append(fFSExtensions); |
- append_default_precision_qualifier(kDefaultFragmentPrecision, |
- fCtxInfo.binding(), |
- shaderStr); |
- this->appendUniformDecls(kFragment_Visibility, shaderStr); |
- this->appendDecls(fFSInputs, shaderStr); |
- // We shouldn't have declared outputs on 1.10 |
- SkASSERT(k110_GrGLSLGeneration != fCtxInfo.glslGeneration() || fFSOutputs.empty()); |
- this->appendDecls(fFSOutputs, shaderStr); |
- shaderStr->append(fFSFunctions); |
- shaderStr->append("void main() {\n"); |
- shaderStr->append(fFSCode); |
- shaderStr->append("}\n"); |
-} |
- |
-void GrGLShaderBuilder::finished(GrGLuint programID) { |
- fUniformManager.getUniformLocations(programID, fUniforms); |
-} |
- |
void GrGLShaderBuilder::emitEffects( |
const GrEffectStage* effectStages[], |
const GrBackendEffectFactory::EffectKey effectKeys[], |
@@ -526,7 +584,7 @@ void GrGLShaderBuilder::emitEffects( |
textureSamplers[t].init(this, &effect->textureAccess(t), t); |
effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform); |
} |
- GrDrawEffect drawEffect(stage, fVertexBuilder.get() |
+ GrDrawEffect drawEffect(stage, NULL != fVertexBuilder.get() |
&& fVertexBuilder->hasExplicitLocalCoords()); |
int numAttributes = stage.getVertexAttribIndexCount(); |
@@ -534,7 +592,7 @@ void GrGLShaderBuilder::emitEffects( |
SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames; |
for (int a = 0; a < numAttributes; ++a) { |
// TODO: Make addAttribute mangle the name. |
- SkASSERT(fVertexBuilder.get()); |
+ SkASSERT(NULL != fVertexBuilder.get()); |
SkString attributeName("aAttr"); |
attributeName.appendS32(attributeIndices[a]); |
fVertexBuilder->addEffectAttribute(attributeIndices[a], |
@@ -557,7 +615,7 @@ 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()); |
- if (fVertexBuilder.get()) { |
+ if (NULL != fVertexBuilder.get()) { |
fVertexBuilder->vsCodeAppend(openBrace.c_str()); |
} |
this->fsCodeAppend(openBrace.c_str()); |
@@ -569,7 +627,7 @@ void GrGLShaderBuilder::emitEffects( |
inColor.isEmpty() ? NULL : inColor.c_str(), |
textureSamplers); |
- if (fVertexBuilder.get()) { |
+ if (NULL != fVertexBuilder.get()) { |
fVertexBuilder->vsCodeAppend("\t}\n"); |
} |
this->fsCodeAppend("\t}\n"); |
@@ -584,22 +642,170 @@ void GrGLShaderBuilder::emitEffects( |
} |
} |
+const char* GrGLShaderBuilder::getColorOutputName() const { |
+ return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; |
+} |
+ |
+const char* GrGLShaderBuilder::enableSecondaryOutput() { |
+ if (!fHasSecondaryOutput) { |
+ fFSOutputs.push_back().set(kVec4f_GrSLType, |
+ GrGLShaderVar::kOut_TypeModifier, |
+ dual_source_output_name()); |
+ fHasSecondaryOutput = true; |
+ } |
+ return dual_source_output_name(); |
+} |
+ |
+ |
+bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) { |
+ SK_TRACE_EVENT0("GrGLShaderBuilder::finish"); |
+ |
+ GrGLuint programId = 0; |
+ GL_CALL_RET(programId, CreateProgram()); |
+ if (!programId) { |
+ return false; |
+ } |
+ |
+ if (!this->compileAndAttachShaders(programId)) { |
+ GL_CALL(DeleteProgram(programId)); |
+ return false; |
+ } |
+ |
+ this->bindProgramLocations(programId); |
+ |
+ GL_CALL(LinkProgram(programId)); |
+ GrGLint linked = GR_GL_INIT_ZERO; |
+ GL_CALL(GetProgramiv(programId, GR_GL_LINK_STATUS, &linked)); |
+ if (!linked) { |
+ GrGLint infoLen = GR_GL_INIT_ZERO; |
+ GL_CALL(GetProgramiv(programId, GR_GL_INFO_LOG_LENGTH, &infoLen)); |
+ SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger |
+ if (infoLen > 0) { |
+ // retrieve length even though we don't need it to workaround |
+ // bug in chrome cmd buffer param validation. |
+ GrGLsizei length = GR_GL_INIT_ZERO; |
+ GL_CALL(GetProgramInfoLog(programId, |
+ infoLen+1, |
+ &length, |
+ (char*)log.get())); |
+ GrPrintf((char*)log.get()); |
+ } |
+ SkDEBUGFAIL("Error linking program"); |
+ GL_CALL(DeleteProgram(programId)); |
+ return false; |
+ } |
+ |
+ fUniformManager.getUniformLocations(programId, fUniforms); |
+ *outProgramId = programId; |
+ return true; |
+} |
+ |
+namespace { |
+// Compiles a GL shader, attaches it to a program, and releases the shader's reference. |
+// (That way there's no need to hang on to the GL shader id and delete it later.) |
+bool attach_shader(const GrGLInterface* gli, |
+ GrGLuint programId, |
+ GrGLenum type, |
+ const SkString& shaderSrc) { |
+ GrGLuint shaderId; |
+ GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); |
+ if (0 == shaderId) { |
+ return false; |
+ } |
+ |
+ const GrGLchar* sourceStr = shaderSrc.c_str(); |
+ int sourceLength = shaderSrc.size(); |
+ GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); |
+ |
+ GrGLint compiled = GR_GL_INIT_ZERO; |
+ GR_GL_CALL(gli, CompileShader(shaderId)); |
+ GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); |
+ |
+ if (!compiled) { |
+ GrGLint infoLen = GR_GL_INIT_ZERO; |
+ GR_GL_CALL(gli, GetShaderiv(shaderId, 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; |
+ GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, |
+ &length, (char*)log.get())); |
+ GrPrintf(shaderSrc.c_str()); |
+ GrPrintf("\n%s", log.get()); |
+ } |
+ SkDEBUGFAIL("Shader compilation failed!"); |
+ GR_GL_CALL(gli, DeleteShader(shaderId)); |
+ return false; |
+ } else if (c_PrintShaders) { |
+ GrPrintf(shaderSrc.c_str()); |
+ GrPrintf("\n"); |
+ } |
+ |
+ GR_GL_CALL(gli, AttachShader(programId, shaderId)); |
+ GR_GL_CALL(gli, DeleteShader(shaderId)); |
+ return true; |
+} |
+ |
+} |
+ |
+bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId) const { |
+ if (NULL != fVertexBuilder.get() && !fVertexBuilder->compileAndAttachShaders(programId)) { |
+ return false; |
+ } |
+ |
+ SkString fragShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); |
+ fragShaderSrc.append(fFSExtensions); |
+ append_default_precision_qualifier(kDefaultFragmentPrecision, |
+ fGpu->glBinding(), |
+ &fragShaderSrc); |
+ this->appendUniformDecls(kFragment_Visibility, &fragShaderSrc); |
+ this->appendDecls(fFSInputs, &fragShaderSrc); |
+ // We shouldn't have declared outputs on 1.10 |
+ SkASSERT(k110_GrGLSLGeneration != fGpu->glslGeneration() || fFSOutputs.empty()); |
+ this->appendDecls(fFSOutputs, &fragShaderSrc); |
+ fragShaderSrc.append(fFSFunctions); |
+ fragShaderSrc.append("void main() {\n"); |
+ fragShaderSrc.append(fFSCode); |
+ fragShaderSrc.append("}\n"); |
+ if (!attach_shader(fGpu->glInterface(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc)) { |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) const { |
+ if (NULL != fVertexBuilder.get()) { |
+ fVertexBuilder->bindProgramLocations(programId); |
+ } |
+ |
+ if (fHasCustomColorOutput) { |
+ GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); |
+ } |
+ if (fHasSecondaryOutput) { |
+ GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); |
+ } |
+} |
+ |
+const GrGLContextInfo& GrGLShaderBuilder::ctxInfo() const { |
+ return fGpu->ctxInfo(); |
+} |
+ |
//////////////////////////////////////////////////////////////////////////// |
GrGLShaderBuilder::VertexBuilder::VertexBuilder(GrGLShaderBuilder* parent, |
+ GrGpuGL* gpu, |
const GrGLProgramDesc& desc) |
- : fVSAttrs(kVarsPerBlock) |
+ : fParent(parent) |
+ , fGpu(gpu) |
+ , fDesc(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(); |
+ , fGSOutputs(kVarsPerBlock) { |
+ |
+ const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); |
fPositionVar = &fVSAttrs.push_back(); |
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); |
@@ -611,6 +817,23 @@ GrGLShaderBuilder::VertexBuilder::VertexBuilder(GrGLShaderBuilder* parent, |
} else { |
fLocalCoordsVar = fPositionVar; |
} |
+ |
+ const char* viewMName; |
+ fViewMatrixUniform = fParent->addUniform(GrGLShaderBuilder::kVertex_Visibility, |
+ kMat33f_GrSLType, "ViewM", &viewMName); |
+ |
+ this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n" |
+ "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", |
+ viewMName, fPositionVar->c_str()); |
+ |
+ // we output point size in the GS if present |
+ if (header.fEmitsPointSize |
+#if GR_GL_EXPERIMENTAL_GS |
+ && !header.fExperimentalGS |
+#endif |
+ ) { |
+ this->vsCodeAppend("\tgl_PointSize = 1.0;\n"); |
+ } |
} |
bool GrGLShaderBuilder::VertexBuilder::addAttribute(GrSLType type, |
@@ -654,7 +877,8 @@ void GrGLShaderBuilder::VertexBuilder::addVarying(GrSLType type, |
} |
// input to FS comes either from VS or GS |
const SkString* fsName; |
- if (fUsesGS) { |
+#if GR_GL_EXPERIMENTAL_GS |
+ if (fDesc.getHeader().fExperimentalGS) { |
// if we have a GS take each varying in as an array |
// and output as non-array. |
fGSInputs.push_back(); |
@@ -667,7 +891,9 @@ void GrGLShaderBuilder::VertexBuilder::addVarying(GrSLType type, |
fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); |
fParent->nameVariable(fGSOutputs.back().accessName(), 'g', name); |
fsName = fGSOutputs.back().accessName(); |
- } else { |
+ } else |
+#endif |
+ { |
fsName = fVSOutputs.back().accessName(); |
} |
fParent->fsInputAppend().set(type, |
@@ -678,41 +904,88 @@ void GrGLShaderBuilder::VertexBuilder::addVarying(GrSLType type, |
} |
} |
-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"); |
+const SkString* GrGLShaderBuilder::VertexBuilder::getEffectAttributeName(int attributeIndex) const { |
+ const AttributePair* attribEnd = fEffectAttributes.end(); |
+ for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { |
+ if (attrib->fIndex == attributeIndex) { |
+ return &attrib->fName; |
+ } |
+ } |
+ |
+ return NULL; |
} |
-void GrGLShaderBuilder::VertexBuilder::gsGetShader(SkString* shaderStr) const { |
- if (!fUsesGS) { |
- shaderStr->reset(); |
- return; |
+bool GrGLShaderBuilder::VertexBuilder::compileAndAttachShaders(GrGLuint programId) const { |
+ SkString vertShaderSrc(GrGetGLSLVersionDecl(fParent->ctxInfo())); |
+ fParent->appendUniformDecls(kVertex_Visibility, &vertShaderSrc); |
+ fParent->appendDecls(fVSAttrs, &vertShaderSrc); |
+ fParent->appendDecls(fVSOutputs, &vertShaderSrc); |
+ vertShaderSrc.append("void main() {\n"); |
+ vertShaderSrc.append(fVSCode); |
+ vertShaderSrc.append("}\n"); |
+ if (!attach_shader(fGpu->glInterface(), programId, GR_GL_VERTEX_SHADER, vertShaderSrc)) { |
+ return false; |
} |
- *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"); |
+#if GR_GL_EXPERIMENTAL_GS |
+ if (fDesc.getHeader().fExperimentalGS) { |
+ SkASSERT(fGpu->glslGeneration() >= k150_GrGLSLGeneration); |
+ SkString geomShaderSrc(GrGetGLSLVersionDecl(fParent->ctxInfo())); |
+ geomShaderSrc.append("layout(triangles) in;\n" |
+ "layout(triangle_strip, max_vertices = 6) out;\n"); |
+ fParent->appendDecls(fGSInputs, &geomShaderSrc); |
+ fParent->appendDecls(fGSOutputs, &geomShaderSrc); |
+ geomShaderSrc.append("void main() {\n"); |
+ geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n" |
+ "\t\tgl_Position = gl_in[i].gl_Position;\n"); |
+ if (fDesc.getHeader().fEmitsPointSize) { |
+ geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n"); |
+ } |
+ SkASSERT(fGSInputs.count() == fGSOutputs.count()); |
+ for (int i = 0; i < fGSInputs.count(); ++i) { |
+ geomShaderSrc.appendf("\t\t%s = %s[i];\n", |
+ fGSOutputs[i].getName().c_str(), |
+ fGSInputs[i].getName().c_str()); |
+ } |
+ geomShaderSrc.append("\t\tEmitVertex();\n" |
+ "\t}\n" |
+ "\tEndPrimitive();\n"); |
+ geomShaderSrc.append("}\n"); |
+ if (!attach_shader(fGpu->glInterface(), programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc)) { |
+ return false; |
+ } |
+ } |
+#endif |
+ |
+ return true; |
} |
+void GrGLShaderBuilder::VertexBuilder::bindProgramLocations(GrGLuint programId) const { |
+ const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); |
-const SkString* GrGLShaderBuilder::VertexBuilder::getEffectAttributeName(int attributeIndex) const { |
- const AttributePair* attribEnd = this->getEffectAttributes().end(); |
- for (const AttributePair* attrib = this->getEffectAttributes().begin(); |
- attrib != attribEnd; |
- ++attrib) { |
- if (attrib->fIndex == attributeIndex) { |
- return &attrib->fName; |
- } |
+ // Bind the attrib locations to same values for all shaders |
+ SkASSERT(-1 != header.fPositionAttributeIndex); |
+ GL_CALL(BindAttribLocation(programId, |
+ header.fPositionAttributeIndex, |
+ fPositionVar->c_str())); |
+ if (-1 != header.fLocalCoordAttributeIndex) { |
+ GL_CALL(BindAttribLocation(programId, |
+ header.fLocalCoordAttributeIndex, |
+ fLocalCoordsVar->c_str())); |
+ } |
+ if (-1 != header.fColorAttributeIndex) { |
+ GL_CALL(BindAttribLocation(programId, |
+ header.fColorAttributeIndex, |
+ color_attribute_name())); |
+ } |
+ if (-1 != header.fCoverageAttributeIndex) { |
+ GL_CALL(BindAttribLocation(programId, |
+ header.fCoverageAttributeIndex, |
+ coverage_attribute_name())); |
} |
- return NULL; |
+ const AttributePair* attribEnd = fEffectAttributes.end(); |
+ for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { |
+ GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str())); |
+ } |
} |