diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-05-09 13:45:02 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-05-09 13:45:02 +0000 |
commit | 504976ef6f1b969c2ac13ff1140ea1067f085ffa (patch) | |
tree | 8133727c6fdce7265bf1fa1ecb5f3dd9b2af483a | |
parent | be2143187244ead489ada7c3f9538902c0bc3231 (diff) |
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
-rw-r--r-- | src/gpu/gl/GrGLEffectMatrix.cpp | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 74 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramDesc.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.cpp | 166 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.h | 89 | ||||
-rw-r--r-- | tests/GLProgramsTest.cpp | 26 |
6 files changed, 210 insertions, 149 deletions
diff --git a/src/gpu/gl/GrGLEffectMatrix.cpp b/src/gpu/gl/GrGLEffectMatrix.cpp index 7e7a9c940a..523b37e72e 100644 --- a/src/gpu/gl/GrGLEffectMatrix.cpp +++ b/src/gpu/gl/GrGLEffectMatrix.cpp @@ -87,7 +87,7 @@ GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder, &uniName); } - const char* varyingName = "StageCoord"; + const char* varyingName = "MatrixCoord"; SkString suffixedVaryingName; if (NULL != suffix) { suffixedVaryingName.append(varyingName); diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 1b4baa40ea..1b9c3a293a 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -485,35 +485,21 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { bool needColor, needFilterColor; need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor); + // used in order for builder to return the per-stage uniform handles. + SkTArray<GrGLUniformManager::UniformHandle, true>* stageUniformArrays[GrDrawState::kNumStages]; + if (needColor) { - /////////////////////////////////////////////////////////////////////////// - // 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); - fEffects[s] = builder.createAndEmitGLEffect(*stages[s], - fDesc.fEffectKeys[s], - inColor.size() ? inColor.c_str() : NULL, - outColor.c_str(), - &fUniformHandles.fEffectSamplerUnis[s]); - builder.setNonStage(); - inColor = outColor; - knownColorValue = kNone_GrSLConstantVec; - } + stageUniformArrays[s] = &fUniformHandles.fEffectSamplerUnis[s]; } + + builder.emitEffects(stages, + fDesc.fEffectKeys, + fDesc.fFirstCoverageStage, + &inColor, + &knownColorValue, + stageUniformArrays, + fEffects); } // 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 - - // incoming coverage to current stage being processed. SkString inCoverage; GrSLConstantVec knownCoverageValue = this->genInputCoverage(&builder, &inCoverage); - SkString outCoverage; - for (int s = fDesc.fFirstCoverageStage; s < GrDrawState::kNumStages; ++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; - } + for (int s = fDesc.fFirstCoverageStage, i = 0; s < GrDrawState::kNumStages; ++s, ++i) { + stageUniformArrays[i] = &fUniformHandles.fEffectSamplerUnis[s]; } + builder.emitEffects(stages + fDesc.fFirstCoverageStage, + fDesc.fEffectKeys + fDesc.fFirstCoverageStage, + GrDrawState::kNumStages - fDesc.fFirstCoverageStage, + &inCoverage, + &knownCoverageValue, + stageUniformArrays, + fEffects + fDesc.fFirstCoverageStage); + // discard if coverage is zero if (fDesc.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) { if (kZeros_GrSLConstantVec == knownCoverageValue) { diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h index 8d7ca8d1bc..45714a0dc6 100644 --- a/src/gpu/gl/GrGLProgramDesc.h +++ b/src/gpu/gl/GrGLProgramDesc.h @@ -39,7 +39,7 @@ public: void setRandom(SkMWCRandom*, const GrGpuGL* gpu, const GrTexture* dummyDstTexture, - const GrEffectStage stages[GrDrawState::kNumStages], + const GrEffectStage* stages[GrDrawState::kNumStages], int currAttribIndex); /** diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp index b379c78432..c1732b20e7 100644 --- a/src/gpu/gl/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/GrGLShaderBuilder.cpp @@ -103,7 +103,6 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, , fFSOutputs(kMaxFSOutputs) , fCtxInfo(ctxInfo) , fUniformManager(uniformManager) - , fCurrentStageIdx(kNonStageIdx) , fFSFeaturesAddedMask(0) #if GR_GL_EXPERIMENTAL_GS , 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() { static const char kFBFetchColorName[] = "gl_LastFragData[0]"; GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType(); @@ -364,12 +378,7 @@ GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t vi GrAssert(h2 == h); uni.fVariable.setType(type); uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); - SkString* uniName = uni.fVariable.accessName(); - if (kNonStageIdx == fCurrentStageIdx) { - uniName->printf("u%s", name); - } else { - uniName->printf("u%s%d", name, fCurrentStageIdx); - } + this->nameVariable(uni.fVariable.accessName(), 'u', name); uni.fVariable.setArrayCount(count); uni.fVisibility = visibility; @@ -415,11 +424,8 @@ void GrGLShaderBuilder::addVarying(GrSLType type, fVSOutputs.push_back(); fVSOutputs.back().setType(type); fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); - if (kNonStageIdx == fCurrentStageIdx) { - fVSOutputs.back().accessName()->printf("v%s", name); - } else { - fVSOutputs.back().accessName()->printf("v%s%d", name, fCurrentStageIdx); - } + this->nameVariable(fVSOutputs.back().accessName(), 'v', name); + if (vsOutName) { *vsOutName = fVSOutputs.back().getName().c_str(); } @@ -436,11 +442,7 @@ void GrGLShaderBuilder::addVarying(GrSLType type, fGSOutputs.push_back(); fGSOutputs.back().setType(type); fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); - if (kNonStageIdx == fCurrentStageIdx) { - fGSOutputs.back().accessName()->printf("g%s", name); - } else { - fGSOutputs.back().accessName()->printf("g%s%d", name, fCurrentStageIdx); - } + this->nameVariable(fGSOutputs.back().accessName(), 'g', name); fsName = fGSOutputs.back().accessName(); } else { fsName = fVSOutputs.back().accessName(); @@ -470,18 +472,16 @@ const char* GrGLShaderBuilder::fragmentPosition() { } else { static const char* kCoordName = "fragCoordYDown"; if (!fSetupFragPosition) { + // temporarily change the stage index because we're inserting non-stage code. + CodeStage::AutoStageRestore csar(&fCodeStage, NULL); + GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform); 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, kFloat_GrSLType, "RTHeight", &rtHeightName); - fCurrentStageIdx = oldStageIdx; this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n", kCoordName, rtHeightName); @@ -514,11 +514,7 @@ void GrGLShaderBuilder::emitFunction(ShaderType shader, SkString* outName) { GrAssert(kFragment_ShaderType == shader); fFSFunctions.append(GrGLSLTypeString(returnType)); - if (kNonStageIdx != fCurrentStageIdx) { - outName->printf("%s_%d", name, fCurrentStageIdx); - } else { - *outName = name; - } + this->nameVariable(outName, '\0', name); fFSFunctions.appendf(" %s", outName->c_str()); fFSFunctions.append("("); for (int i = 0; i < argCnt; ++i) { @@ -623,52 +619,86 @@ void GrGLShaderBuilder::finished(GrGLuint programID) { fUniformManager.getUniformLocations(programID, fUniforms); } -GrGLEffect* GrGLShaderBuilder::createAndEmitGLEffect( - const GrEffectStage& stage, - GrGLEffect::EffectKey key, - const char* fsInColor, - const char* fsOutColor, - SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles) { - GrAssert(NULL != stage.getEffect()); - - const GrEffectRef& effect = *stage.getEffect(); - int numTextures = effect->numTextures(); - 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(); - const int* attributeIndices = stage.getVertexAttribIndices(); - SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames; - 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); +void GrGLShaderBuilder::emitEffects( + const GrEffectStage* effectStages[], + const GrBackendEffectFactory::EffectKey effectKeys[], + int effectCnt, + SkString* fsInOutColor, + GrSLConstantVec* fsInOutColorKnownValue, + SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[], + GrGLEffect* glEffects[]) { + bool effectEmitted = false; + + SkString inColor = *fsInOutColor; + SkString outColor; + + for (int e = 0; e < effectCnt; ++e) { + if (NULL == effectStages[e] || GrGLEffect::kNoEffectKey == effectKeys[e]) { + continue; + } + + 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)); } - } - GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); + // 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 - this->fVSCode.appendf("\t{ // %s\n", glEffect->name()); - this->fFSCode.appendf("\t{ // %s \n", glEffect->name()); + // 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); - glEffect->emitCode(this, - drawEffect, - key, - fsOutColor, - fsInColor, - textureSamplers); - this->fVSCode.appendf("\t}\n"); - this->fFSCode.appendf("\t}\n"); + 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"); - return glEffect; + inColor = outColor; + *fsInOutColorKnownValue = kNone_GrSLConstantVec; + effectEmitted = true; + } + + if (effectEmitted) { + *fsInOutColor = outColor; + } } const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const { diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h index 9021a0dee1..765a2edf8d 100644 --- a/src/gpu/gl/GrGLShaderBuilder.h +++ b/src/gpu/gl/GrGLShaderBuilder.h @@ -71,7 +71,7 @@ public: GrAssert(NULL != builder); SkString name; - name.printf("Sampler%d_", idx); + name.printf("Sampler%d", idx); fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kSampler2D_GrSLType, name.c_str()); @@ -275,16 +275,24 @@ public: /** Called after building is complete to get the final shader string. */ void getShader(ShaderType, SkString*) const; - void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; } - void setNonStage() { fCurrentStageIdx = kNonStageIdx; } - // TODO: move remainder of shader code generation to this class and call this privately - // Handles of sampler uniforms generated for the effect are appended to samplerHandles. - GrGLEffect* createAndEmitGLEffect( - const GrEffectStage& stage, - GrBackendEffectFactory::EffectKey key, - const char* fsInColor, // NULL means no incoming color - const char* fsOutColor, - SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles); + /** + * Adds code for effects. effectStages contains the effects to add. effectKeys[i] is the key + * generated from effectStages[i]. An entry in effectStages can be NULL, in which case it is + * skipped. Moreover, if the corresponding key is GrGLEffect::NoEffectKey then it is skipped. + * inOutFSColor specifies the input color to the first stage and is updated to be the + * output color of the last stage. fsInOutColorKnownValue specifies whether the input color + * has a known constant value and is updated to refer to the status of the output color. + * The handles to texture samplers for effectStage[i] are added to effectSamplerHandles[i]. The + * glEffects array is updated to contain the GrGLEffect generated for each entry in + * 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 getDstCopyTopLeftUniform() const { @@ -338,9 +346,56 @@ public: VarArray fFSOutputs; private: - enum { - kNonStageIdx = -1, - }; + class CodeStage : GrNoncopyable { + 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. @@ -356,6 +411,11 @@ private: // the enables separately for each shader. 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 enum { kNoDstRead_DstReadKey = 0, @@ -366,7 +426,6 @@ private: const GrGLContextInfo& fCtxInfo; GrGLUniformManager& fUniformManager; - int fCurrentStageIdx; uint32_t fFSFeaturesAddedMask; SkString fFSFunctions; SkString fFSExtensions; diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index ae6fe7b3c4..95187a6e39 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -24,7 +24,7 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random, const GrGpuGL* gpu, const GrTexture* dstTexture, - const GrEffectStage stages[GrDrawState::kNumStages], + const GrEffectStage* stages[GrDrawState::kNumStages], int currAttribIndex) { fEmitsPointSize = random->nextBool(); @@ -59,11 +59,11 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random, bool dstRead = false; for (int s = 0; s < GrDrawState::kNumStages; ++s) { - if (NULL != stages[s].getEffect()) { - const GrBackendEffectFactory& factory = (*stages[s].getEffect())->getFactory(); - GrDrawEffect drawEffect(stages[s], useLocalCoords); + if (NULL != stages[s]) { + const GrBackendEffectFactory& factory = (*stages[s]->getEffect())->getFactory(); + GrDrawEffect drawEffect(*stages[s], useLocalCoords); fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps()); - if ((*stages[s].getEffect())->willReadDst()) { + if ((*stages[s]->getEffect())->willReadDst()) { dstRead = true; } } @@ -113,7 +113,8 @@ bool GrGpuGL::programUnitTest(int maxStages) { #endif 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 attribIndices[2]; @@ -137,19 +138,20 @@ bool GrGpuGL::programUnitTest(int maxStages) { for (int i = 0; i < numAttribs; ++i) { 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]; 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(), pdesc, - stagePtrs)); + stages)); + for (int s = 0; s < maxStages; ++s) { + SkDELETE(stages[s]); + } if (NULL == program.get()) { return false; } |