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:
bsalomon@google.com 2013-05-09 13:45:02 +00:00
parent be21431872
commit 504976ef6f
6 changed files with 211 additions and 150 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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);
/** /**

View File

@ -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 {

View File

@ -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;

View File

@ -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;
} }