Move loops that chain together effects into GrGLShaderBuilder from GrGLProgram.
R=robertphillips@google.com Review URL: https://codereview.chromium.org/14925010 git-svn-id: http://skia.googlecode.com/svn/trunk@9073 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
be21431872
commit
504976ef6f
@ -87,7 +87,7 @@ GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder,
|
|||||||
&uniName);
|
&uniName);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* varyingName = "StageCoord";
|
const char* varyingName = "MatrixCoord";
|
||||||
SkString suffixedVaryingName;
|
SkString suffixedVaryingName;
|
||||||
if (NULL != suffix) {
|
if (NULL != suffix) {
|
||||||
suffixedVaryingName.append(varyingName);
|
suffixedVaryingName.append(varyingName);
|
||||||
|
@ -485,35 +485,21 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
|
|||||||
bool needColor, needFilterColor;
|
bool needColor, needFilterColor;
|
||||||
need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
|
need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
|
||||||
|
|
||||||
if (needColor) {
|
// used in order for builder to return the per-stage uniform handles.
|
||||||
///////////////////////////////////////////////////////////////////////////
|
SkTArray<GrGLUniformManager::UniformHandle, true>* stageUniformArrays[GrDrawState::kNumStages];
|
||||||
// compute the color
|
|
||||||
// if we have color stages string them together, feeding the output color
|
|
||||||
// of each to the next and generating code for each stage.
|
|
||||||
SkString outColor;
|
|
||||||
for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) {
|
|
||||||
if (GrGLEffect::kNoEffectKey != fDesc.fEffectKeys[s]) {
|
|
||||||
if (kZeros_GrSLConstantVec == knownColorValue) {
|
|
||||||
// Effects have no way to communicate zeros, they treat an empty string as ones.
|
|
||||||
inColor = "initialColor";
|
|
||||||
builder.fsCodeAppendf("\tvec4 %s = %s;\n", inColor.c_str(), GrGLSLZerosVecf(4));
|
|
||||||
}
|
|
||||||
// create var to hold stage result
|
|
||||||
outColor = "color";
|
|
||||||
outColor.appendS32(s);
|
|
||||||
builder.fsCodeAppendf("\tvec4 %s;\n", outColor.c_str());
|
|
||||||
|
|
||||||
builder.setCurrentStage(s);
|
if (needColor) {
|
||||||
fEffects[s] = builder.createAndEmitGLEffect(*stages[s],
|
for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) {
|
||||||
fDesc.fEffectKeys[s],
|
stageUniformArrays[s] = &fUniformHandles.fEffectSamplerUnis[s];
|
||||||
inColor.size() ? inColor.c_str() : NULL,
|
|
||||||
outColor.c_str(),
|
|
||||||
&fUniformHandles.fEffectSamplerUnis[s]);
|
|
||||||
builder.setNonStage();
|
|
||||||
inColor = outColor;
|
|
||||||
knownColorValue = kNone_GrSLConstantVec;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.emitEffects(stages,
|
||||||
|
fDesc.fEffectKeys,
|
||||||
|
fDesc.fFirstCoverageStage,
|
||||||
|
&inColor,
|
||||||
|
&knownColorValue,
|
||||||
|
stageUniformArrays,
|
||||||
|
fEffects);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the color filter. This will soon be replaced by a color effect.
|
// Insert the color filter. This will soon be replaced by a color effect.
|
||||||
@ -540,37 +526,21 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// compute the partial coverage
|
// compute the partial coverage
|
||||||
|
|
||||||
// incoming coverage to current stage being processed.
|
|
||||||
SkString inCoverage;
|
SkString inCoverage;
|
||||||
GrSLConstantVec knownCoverageValue = this->genInputCoverage(&builder, &inCoverage);
|
GrSLConstantVec knownCoverageValue = this->genInputCoverage(&builder, &inCoverage);
|
||||||
|
|
||||||
SkString outCoverage;
|
for (int s = fDesc.fFirstCoverageStage, i = 0; s < GrDrawState::kNumStages; ++s, ++i) {
|
||||||
for (int s = fDesc.fFirstCoverageStage; s < GrDrawState::kNumStages; ++s) {
|
stageUniformArrays[i] = &fUniformHandles.fEffectSamplerUnis[s];
|
||||||
if (fDesc.fEffectKeys[s]) {
|
|
||||||
if (kZeros_GrSLConstantVec == knownCoverageValue) {
|
|
||||||
// Effects have no way to communicate zeros, they treat an empty string as ones.
|
|
||||||
inCoverage = "initialCoverage";
|
|
||||||
builder.fsCodeAppendf("\tvec4 %s = %s;\n", inCoverage.c_str(), GrGLSLZerosVecf(4));
|
|
||||||
}
|
|
||||||
// create var to hold stage output
|
|
||||||
outCoverage = "coverage";
|
|
||||||
outCoverage.appendS32(s);
|
|
||||||
builder.fsCodeAppendf("\tvec4 %s;\n", outCoverage.c_str());
|
|
||||||
|
|
||||||
builder.setCurrentStage(s);
|
|
||||||
fEffects[s] = builder.createAndEmitGLEffect(
|
|
||||||
*stages[s],
|
|
||||||
fDesc.fEffectKeys[s],
|
|
||||||
inCoverage.size() ? inCoverage.c_str() : NULL,
|
|
||||||
outCoverage.c_str(),
|
|
||||||
&fUniformHandles.fEffectSamplerUnis[s]);
|
|
||||||
builder.setNonStage();
|
|
||||||
inCoverage = outCoverage;
|
|
||||||
knownCoverageValue = kNone_GrSLConstantVec;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.emitEffects(stages + fDesc.fFirstCoverageStage,
|
||||||
|
fDesc.fEffectKeys + fDesc.fFirstCoverageStage,
|
||||||
|
GrDrawState::kNumStages - fDesc.fFirstCoverageStage,
|
||||||
|
&inCoverage,
|
||||||
|
&knownCoverageValue,
|
||||||
|
stageUniformArrays,
|
||||||
|
fEffects + fDesc.fFirstCoverageStage);
|
||||||
|
|
||||||
// discard if coverage is zero
|
// discard if coverage is zero
|
||||||
if (fDesc.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) {
|
if (fDesc.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) {
|
||||||
if (kZeros_GrSLConstantVec == knownCoverageValue) {
|
if (kZeros_GrSLConstantVec == knownCoverageValue) {
|
||||||
|
@ -39,7 +39,7 @@ public:
|
|||||||
void setRandom(SkMWCRandom*,
|
void setRandom(SkMWCRandom*,
|
||||||
const GrGpuGL* gpu,
|
const GrGpuGL* gpu,
|
||||||
const GrTexture* dummyDstTexture,
|
const GrTexture* dummyDstTexture,
|
||||||
const GrEffectStage stages[GrDrawState::kNumStages],
|
const GrEffectStage* stages[GrDrawState::kNumStages],
|
||||||
int currAttribIndex);
|
int currAttribIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,7 +103,6 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
|
|||||||
, fFSOutputs(kMaxFSOutputs)
|
, fFSOutputs(kMaxFSOutputs)
|
||||||
, fCtxInfo(ctxInfo)
|
, fCtxInfo(ctxInfo)
|
||||||
, fUniformManager(uniformManager)
|
, fUniformManager(uniformManager)
|
||||||
, fCurrentStageIdx(kNonStageIdx)
|
|
||||||
, fFSFeaturesAddedMask(0)
|
, fFSFeaturesAddedMask(0)
|
||||||
#if GR_GL_EXPERIMENTAL_GS
|
#if GR_GL_EXPERIMENTAL_GS
|
||||||
, fUsesGS(desc.fExperimentalGS)
|
, fUsesGS(desc.fExperimentalGS)
|
||||||
@ -215,6 +214,21 @@ void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) {
|
||||||
|
if ('\0' == prefix) {
|
||||||
|
*out = name;
|
||||||
|
} else {
|
||||||
|
out->printf("%c%s", prefix, name);
|
||||||
|
}
|
||||||
|
if (fCodeStage.inStageCode()) {
|
||||||
|
if (out->endsWith('_')) {
|
||||||
|
// Names containing "__" are reserved.
|
||||||
|
out->append("x");
|
||||||
|
}
|
||||||
|
out->appendf("_Stage%d", fCodeStage.stageIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char* GrGLShaderBuilder::dstColor() {
|
const char* GrGLShaderBuilder::dstColor() {
|
||||||
static const char kFBFetchColorName[] = "gl_LastFragData[0]";
|
static const char kFBFetchColorName[] = "gl_LastFragData[0]";
|
||||||
GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType();
|
GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType();
|
||||||
@ -364,12 +378,7 @@ GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t vi
|
|||||||
GrAssert(h2 == h);
|
GrAssert(h2 == h);
|
||||||
uni.fVariable.setType(type);
|
uni.fVariable.setType(type);
|
||||||
uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
|
uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
|
||||||
SkString* uniName = uni.fVariable.accessName();
|
this->nameVariable(uni.fVariable.accessName(), 'u', name);
|
||||||
if (kNonStageIdx == fCurrentStageIdx) {
|
|
||||||
uniName->printf("u%s", name);
|
|
||||||
} else {
|
|
||||||
uniName->printf("u%s%d", name, fCurrentStageIdx);
|
|
||||||
}
|
|
||||||
uni.fVariable.setArrayCount(count);
|
uni.fVariable.setArrayCount(count);
|
||||||
uni.fVisibility = visibility;
|
uni.fVisibility = visibility;
|
||||||
|
|
||||||
@ -415,11 +424,8 @@ void GrGLShaderBuilder::addVarying(GrSLType type,
|
|||||||
fVSOutputs.push_back();
|
fVSOutputs.push_back();
|
||||||
fVSOutputs.back().setType(type);
|
fVSOutputs.back().setType(type);
|
||||||
fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
|
fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
|
||||||
if (kNonStageIdx == fCurrentStageIdx) {
|
this->nameVariable(fVSOutputs.back().accessName(), 'v', name);
|
||||||
fVSOutputs.back().accessName()->printf("v%s", name);
|
|
||||||
} else {
|
|
||||||
fVSOutputs.back().accessName()->printf("v%s%d", name, fCurrentStageIdx);
|
|
||||||
}
|
|
||||||
if (vsOutName) {
|
if (vsOutName) {
|
||||||
*vsOutName = fVSOutputs.back().getName().c_str();
|
*vsOutName = fVSOutputs.back().getName().c_str();
|
||||||
}
|
}
|
||||||
@ -436,11 +442,7 @@ void GrGLShaderBuilder::addVarying(GrSLType type,
|
|||||||
fGSOutputs.push_back();
|
fGSOutputs.push_back();
|
||||||
fGSOutputs.back().setType(type);
|
fGSOutputs.back().setType(type);
|
||||||
fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
|
fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
|
||||||
if (kNonStageIdx == fCurrentStageIdx) {
|
this->nameVariable(fGSOutputs.back().accessName(), 'g', name);
|
||||||
fGSOutputs.back().accessName()->printf("g%s", name);
|
|
||||||
} else {
|
|
||||||
fGSOutputs.back().accessName()->printf("g%s%d", name, fCurrentStageIdx);
|
|
||||||
}
|
|
||||||
fsName = fGSOutputs.back().accessName();
|
fsName = fGSOutputs.back().accessName();
|
||||||
} else {
|
} else {
|
||||||
fsName = fVSOutputs.back().accessName();
|
fsName = fVSOutputs.back().accessName();
|
||||||
@ -470,18 +472,16 @@ const char* GrGLShaderBuilder::fragmentPosition() {
|
|||||||
} else {
|
} else {
|
||||||
static const char* kCoordName = "fragCoordYDown";
|
static const char* kCoordName = "fragCoordYDown";
|
||||||
if (!fSetupFragPosition) {
|
if (!fSetupFragPosition) {
|
||||||
|
// temporarily change the stage index because we're inserting non-stage code.
|
||||||
|
CodeStage::AutoStageRestore csar(&fCodeStage, NULL);
|
||||||
|
|
||||||
GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform);
|
GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform);
|
||||||
const char* rtHeightName;
|
const char* rtHeightName;
|
||||||
|
|
||||||
// temporarily change the stage index because we're inserting a uniform whose name
|
|
||||||
// shouldn't be mangled to be stage-specific.
|
|
||||||
int oldStageIdx = fCurrentStageIdx;
|
|
||||||
fCurrentStageIdx = kNonStageIdx;
|
|
||||||
fRTHeightUniform = this->addUniform(kFragment_ShaderType,
|
fRTHeightUniform = this->addUniform(kFragment_ShaderType,
|
||||||
kFloat_GrSLType,
|
kFloat_GrSLType,
|
||||||
"RTHeight",
|
"RTHeight",
|
||||||
&rtHeightName);
|
&rtHeightName);
|
||||||
fCurrentStageIdx = oldStageIdx;
|
|
||||||
|
|
||||||
this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n",
|
this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n",
|
||||||
kCoordName, rtHeightName);
|
kCoordName, rtHeightName);
|
||||||
@ -514,11 +514,7 @@ void GrGLShaderBuilder::emitFunction(ShaderType shader,
|
|||||||
SkString* outName) {
|
SkString* outName) {
|
||||||
GrAssert(kFragment_ShaderType == shader);
|
GrAssert(kFragment_ShaderType == shader);
|
||||||
fFSFunctions.append(GrGLSLTypeString(returnType));
|
fFSFunctions.append(GrGLSLTypeString(returnType));
|
||||||
if (kNonStageIdx != fCurrentStageIdx) {
|
this->nameVariable(outName, '\0', name);
|
||||||
outName->printf("%s_%d", name, fCurrentStageIdx);
|
|
||||||
} else {
|
|
||||||
*outName = name;
|
|
||||||
}
|
|
||||||
fFSFunctions.appendf(" %s", outName->c_str());
|
fFSFunctions.appendf(" %s", outName->c_str());
|
||||||
fFSFunctions.append("(");
|
fFSFunctions.append("(");
|
||||||
for (int i = 0; i < argCnt; ++i) {
|
for (int i = 0; i < argCnt; ++i) {
|
||||||
@ -623,52 +619,86 @@ void GrGLShaderBuilder::finished(GrGLuint programID) {
|
|||||||
fUniformManager.getUniformLocations(programID, fUniforms);
|
fUniformManager.getUniformLocations(programID, fUniforms);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrGLEffect* GrGLShaderBuilder::createAndEmitGLEffect(
|
void GrGLShaderBuilder::emitEffects(
|
||||||
const GrEffectStage& stage,
|
const GrEffectStage* effectStages[],
|
||||||
GrGLEffect::EffectKey key,
|
const GrBackendEffectFactory::EffectKey effectKeys[],
|
||||||
const char* fsInColor,
|
int effectCnt,
|
||||||
const char* fsOutColor,
|
SkString* fsInOutColor,
|
||||||
SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles) {
|
GrSLConstantVec* fsInOutColorKnownValue,
|
||||||
GrAssert(NULL != stage.getEffect());
|
SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[],
|
||||||
|
GrGLEffect* glEffects[]) {
|
||||||
|
bool effectEmitted = false;
|
||||||
|
|
||||||
const GrEffectRef& effect = *stage.getEffect();
|
SkString inColor = *fsInOutColor;
|
||||||
int numTextures = effect->numTextures();
|
SkString outColor;
|
||||||
SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers;
|
|
||||||
textureSamplers.push_back_n(numTextures);
|
|
||||||
for (int i = 0; i < numTextures; ++i) {
|
|
||||||
textureSamplers[i].init(this, &effect->textureAccess(i), i);
|
|
||||||
samplerHandles->push_back(textureSamplers[i].fSamplerUniform);
|
|
||||||
}
|
|
||||||
GrDrawEffect drawEffect(stage, this->hasExplicitLocalCoords());
|
|
||||||
|
|
||||||
int numAttributes = stage.getVertexAttribIndexCount();
|
for (int e = 0; e < effectCnt; ++e) {
|
||||||
const int* attributeIndices = stage.getVertexAttribIndices();
|
if (NULL == effectStages[e] || GrGLEffect::kNoEffectKey == effectKeys[e]) {
|
||||||
SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames;
|
continue;
|
||||||
for (int i = 0; i < numAttributes; ++i) {
|
|
||||||
SkString attributeName("aAttr");
|
|
||||||
attributeName.appendS32(attributeIndices[i]);
|
|
||||||
|
|
||||||
if (this->addAttribute(effect->vertexAttribType(i), attributeName.c_str())) {
|
|
||||||
fEffectAttributes.push_back().set(attributeIndices[i], attributeName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GrAssert(NULL != effectStages[e]->getEffect());
|
||||||
|
const GrEffectStage& stage = *effectStages[e];
|
||||||
|
const GrEffectRef& effect = *stage.getEffect();
|
||||||
|
|
||||||
|
CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
|
||||||
|
|
||||||
|
int numTextures = effect->numTextures();
|
||||||
|
SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers;
|
||||||
|
textureSamplers.push_back_n(numTextures);
|
||||||
|
for (int t = 0; t < numTextures; ++t) {
|
||||||
|
textureSamplers[t].init(this, &effect->textureAccess(t), t);
|
||||||
|
effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform);
|
||||||
|
}
|
||||||
|
GrDrawEffect drawEffect(stage, this->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.
|
||||||
|
SkString attributeName("aAttr");
|
||||||
|
attributeName.appendS32(attributeIndices[a]);
|
||||||
|
if (this->addAttribute(effect->vertexAttribType(a), attributeName.c_str())) {
|
||||||
|
fEffectAttributes.push_back().set(attributeIndices[a], attributeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glEffects[e] = effect->getFactory().createGLInstance(drawEffect);
|
||||||
|
|
||||||
|
if (kZeros_GrSLConstantVec == *fsInOutColorKnownValue) {
|
||||||
|
// Effects have no way to communicate zeros, they treat an empty string as ones.
|
||||||
|
this->nameVariable(&inColor, '\0', "input");
|
||||||
|
this->fsCodeAppendf("\tvec4 %s = %s;\n", inColor.c_str(), GrGLSLZerosVecf(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
// create var to hold stage result
|
||||||
|
this->nameVariable(&outColor, '\0', "output");
|
||||||
|
this->fsCodeAppendf("\tvec4 %s;\n", outColor.c_str());
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
glEffects[e]->emitCode(this,
|
||||||
|
drawEffect,
|
||||||
|
effectKeys[e],
|
||||||
|
outColor.c_str(),
|
||||||
|
inColor.isEmpty() ? NULL : inColor.c_str(),
|
||||||
|
textureSamplers);
|
||||||
|
this->fVSCode.append("\t}\n");
|
||||||
|
this->fFSCode.append("\t}\n");
|
||||||
|
|
||||||
|
inColor = outColor;
|
||||||
|
*fsInOutColorKnownValue = kNone_GrSLConstantVec;
|
||||||
|
effectEmitted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
|
if (effectEmitted) {
|
||||||
|
*fsInOutColor = outColor;
|
||||||
// Enclose custom code in a block to avoid namespace conflicts
|
}
|
||||||
this->fVSCode.appendf("\t{ // %s\n", glEffect->name());
|
|
||||||
this->fFSCode.appendf("\t{ // %s \n", glEffect->name());
|
|
||||||
|
|
||||||
glEffect->emitCode(this,
|
|
||||||
drawEffect,
|
|
||||||
key,
|
|
||||||
fsOutColor,
|
|
||||||
fsInColor,
|
|
||||||
textureSamplers);
|
|
||||||
this->fVSCode.appendf("\t}\n");
|
|
||||||
this->fFSCode.appendf("\t}\n");
|
|
||||||
|
|
||||||
return glEffect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const {
|
const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const {
|
||||||
|
@ -71,7 +71,7 @@ public:
|
|||||||
|
|
||||||
GrAssert(NULL != builder);
|
GrAssert(NULL != builder);
|
||||||
SkString name;
|
SkString name;
|
||||||
name.printf("Sampler%d_", idx);
|
name.printf("Sampler%d", idx);
|
||||||
fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
||||||
kSampler2D_GrSLType,
|
kSampler2D_GrSLType,
|
||||||
name.c_str());
|
name.c_str());
|
||||||
@ -275,16 +275,24 @@ public:
|
|||||||
/** Called after building is complete to get the final shader string. */
|
/** Called after building is complete to get the final shader string. */
|
||||||
void getShader(ShaderType, SkString*) const;
|
void getShader(ShaderType, SkString*) const;
|
||||||
|
|
||||||
void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; }
|
/**
|
||||||
void setNonStage() { fCurrentStageIdx = kNonStageIdx; }
|
* Adds code for effects. effectStages contains the effects to add. effectKeys[i] is the key
|
||||||
// TODO: move remainder of shader code generation to this class and call this privately
|
* generated from effectStages[i]. An entry in effectStages can be NULL, in which case it is
|
||||||
// Handles of sampler uniforms generated for the effect are appended to samplerHandles.
|
* skipped. Moreover, if the corresponding key is GrGLEffect::NoEffectKey then it is skipped.
|
||||||
GrGLEffect* createAndEmitGLEffect(
|
* inOutFSColor specifies the input color to the first stage and is updated to be the
|
||||||
const GrEffectStage& stage,
|
* output color of the last stage. fsInOutColorKnownValue specifies whether the input color
|
||||||
GrBackendEffectFactory::EffectKey key,
|
* has a known constant value and is updated to refer to the status of the output color.
|
||||||
const char* fsInColor, // NULL means no incoming color
|
* The handles to texture samplers for effectStage[i] are added to effectSamplerHandles[i]. The
|
||||||
const char* fsOutColor,
|
* glEffects array is updated to contain the GrGLEffect generated for each entry in
|
||||||
SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles);
|
* effectStages.
|
||||||
|
*/
|
||||||
|
void emitEffects(const GrEffectStage* effectStages[],
|
||||||
|
const GrBackendEffectFactory::EffectKey effectKeys[],
|
||||||
|
int effectCnt,
|
||||||
|
SkString* inOutFSColor,
|
||||||
|
GrSLConstantVec* fsInOutColorKnownValue,
|
||||||
|
SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[],
|
||||||
|
GrGLEffect* glEffects[]);
|
||||||
|
|
||||||
GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
|
GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
|
||||||
GrGLUniformManager::UniformHandle getDstCopyTopLeftUniform() const {
|
GrGLUniformManager::UniformHandle getDstCopyTopLeftUniform() const {
|
||||||
@ -338,9 +346,56 @@ public:
|
|||||||
VarArray fFSOutputs;
|
VarArray fFSOutputs;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
class CodeStage : GrNoncopyable {
|
||||||
kNonStageIdx = -1,
|
public:
|
||||||
};
|
CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
|
||||||
|
|
||||||
|
bool inStageCode() const {
|
||||||
|
this->validate();
|
||||||
|
return NULL != fEffectStage;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GrEffectStage* effectStage() const {
|
||||||
|
this->validate();
|
||||||
|
return fEffectStage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stageIndex() const {
|
||||||
|
this->validate();
|
||||||
|
return fCurrentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AutoStageRestore : GrNoncopyable {
|
||||||
|
public:
|
||||||
|
AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
|
||||||
|
GrAssert(NULL != codeStage);
|
||||||
|
fSavedIndex = codeStage->fCurrentIndex;
|
||||||
|
fSavedEffectStage = codeStage->fEffectStage;
|
||||||
|
|
||||||
|
if (NULL == newStage) {
|
||||||
|
codeStage->fCurrentIndex = -1;
|
||||||
|
} else {
|
||||||
|
codeStage->fCurrentIndex = codeStage->fNextIndex++;
|
||||||
|
}
|
||||||
|
codeStage->fEffectStage = newStage;
|
||||||
|
|
||||||
|
fCodeStage = codeStage;
|
||||||
|
}
|
||||||
|
~AutoStageRestore() {
|
||||||
|
fCodeStage->fCurrentIndex = fSavedIndex;
|
||||||
|
fCodeStage->fEffectStage = fSavedEffectStage;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
CodeStage* fCodeStage;
|
||||||
|
int fSavedIndex;
|
||||||
|
const GrEffectStage* fSavedEffectStage;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
void validate() const { GrAssert((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
|
||||||
|
int fNextIndex;
|
||||||
|
int fCurrentIndex;
|
||||||
|
const GrEffectStage* fEffectStage;
|
||||||
|
} fCodeStage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Features that should only be enabled by GrGLShaderBuilder itself.
|
* Features that should only be enabled by GrGLShaderBuilder itself.
|
||||||
@ -356,6 +411,11 @@ private:
|
|||||||
// the enables separately for each shader.
|
// the enables separately for each shader.
|
||||||
void addFSFeature(uint32_t featureBit, const char* extensionName);
|
void addFSFeature(uint32_t featureBit, const char* extensionName);
|
||||||
|
|
||||||
|
// Generates a name for a variable. The generated string will be name prefixed by the prefix
|
||||||
|
// char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
|
||||||
|
// generating stage code.
|
||||||
|
void nameVariable(SkString* out, char prefix, const char* name);
|
||||||
|
|
||||||
// Interpretation of DstReadKey when generating code
|
// Interpretation of DstReadKey when generating code
|
||||||
enum {
|
enum {
|
||||||
kNoDstRead_DstReadKey = 0,
|
kNoDstRead_DstReadKey = 0,
|
||||||
@ -366,7 +426,6 @@ private:
|
|||||||
|
|
||||||
const GrGLContextInfo& fCtxInfo;
|
const GrGLContextInfo& fCtxInfo;
|
||||||
GrGLUniformManager& fUniformManager;
|
GrGLUniformManager& fUniformManager;
|
||||||
int fCurrentStageIdx;
|
|
||||||
uint32_t fFSFeaturesAddedMask;
|
uint32_t fFSFeaturesAddedMask;
|
||||||
SkString fFSFunctions;
|
SkString fFSFunctions;
|
||||||
SkString fFSExtensions;
|
SkString fFSExtensions;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
void GrGLProgramDesc::setRandom(SkMWCRandom* random,
|
void GrGLProgramDesc::setRandom(SkMWCRandom* random,
|
||||||
const GrGpuGL* gpu,
|
const GrGpuGL* gpu,
|
||||||
const GrTexture* dstTexture,
|
const GrTexture* dstTexture,
|
||||||
const GrEffectStage stages[GrDrawState::kNumStages],
|
const GrEffectStage* stages[GrDrawState::kNumStages],
|
||||||
int currAttribIndex) {
|
int currAttribIndex) {
|
||||||
fEmitsPointSize = random->nextBool();
|
fEmitsPointSize = random->nextBool();
|
||||||
|
|
||||||
@ -59,11 +59,11 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random,
|
|||||||
|
|
||||||
bool dstRead = false;
|
bool dstRead = false;
|
||||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||||
if (NULL != stages[s].getEffect()) {
|
if (NULL != stages[s]) {
|
||||||
const GrBackendEffectFactory& factory = (*stages[s].getEffect())->getFactory();
|
const GrBackendEffectFactory& factory = (*stages[s]->getEffect())->getFactory();
|
||||||
GrDrawEffect drawEffect(stages[s], useLocalCoords);
|
GrDrawEffect drawEffect(*stages[s], useLocalCoords);
|
||||||
fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
|
fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
|
||||||
if ((*stages[s].getEffect())->willReadDst()) {
|
if ((*stages[s]->getEffect())->willReadDst()) {
|
||||||
dstRead = true;
|
dstRead = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +113,8 @@ bool GrGpuGL::programUnitTest(int maxStages) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
GrGLProgramDesc pdesc;
|
GrGLProgramDesc pdesc;
|
||||||
GrEffectStage stages[GrDrawState::kNumStages];
|
const GrEffectStage* stages[GrDrawState::kNumStages];
|
||||||
|
memset(stages, 0, sizeof(stages));
|
||||||
|
|
||||||
int currAttribIndex = 1; // we need to always leave room for position
|
int currAttribIndex = 1; // we need to always leave room for position
|
||||||
int attribIndices[2];
|
int attribIndices[2];
|
||||||
@ -137,19 +138,20 @@ bool GrGpuGL::programUnitTest(int maxStages) {
|
|||||||
for (int i = 0; i < numAttribs; ++i) {
|
for (int i = 0; i < numAttribs; ++i) {
|
||||||
attribIndices[i] = currAttribIndex++;
|
attribIndices[i] = currAttribIndex++;
|
||||||
}
|
}
|
||||||
stages[s].setEffect(effect.get(), attribIndices[0], attribIndices[1]);
|
GrEffectStage* stage = SkNEW(GrEffectStage);
|
||||||
|
stage->setEffect(effect.get(), attribIndices[0], attribIndices[1]);
|
||||||
|
stages[s] = stage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1];
|
const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1];
|
||||||
pdesc.setRandom(&random, this, dstTexture, stages, currAttribIndex);
|
pdesc.setRandom(&random, this, dstTexture, stages, currAttribIndex);
|
||||||
|
|
||||||
const GrEffectStage* stagePtrs[GrDrawState::kNumStages];
|
|
||||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
|
||||||
stagePtrs[s] = &stages[s];
|
|
||||||
}
|
|
||||||
SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this->glContext(),
|
SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this->glContext(),
|
||||||
pdesc,
|
pdesc,
|
||||||
stagePtrs));
|
stages));
|
||||||
|
for (int s = 0; s < maxStages; ++s) {
|
||||||
|
SkDELETE(stages[s]);
|
||||||
|
}
|
||||||
if (NULL == program.get()) {
|
if (NULL == program.get()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user