From 9ba4fa6f0fb8ef496d81ccac36e780aa806fea83 Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Mon, 16 Jul 2012 17:36:28 +0000 Subject: [PATCH] Remove GrGLProgram::CachedData, make GrGLProgram represent the program Review URL: http://codereview.appspot.com/6409043/ git-svn-id: http://skia.googlecode.com/svn/trunk@4627 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrBinHashKey.h | 48 ++-- src/gpu/gl/GrGLProgram.cpp | 396 +++++++++++++++----------------- src/gpu/gl/GrGLProgram.h | 192 +++++++--------- src/gpu/gl/GrGpuGL.cpp | 7 +- src/gpu/gl/GrGpuGL.h | 40 ++-- src/gpu/gl/GrGpuGL_program.cpp | 227 +++++++++--------- src/gpu/gl/GrGpuGL_unittest.cpp | 10 +- src/gpu/gr_unittests.cpp | 6 +- 8 files changed, 423 insertions(+), 503 deletions(-) diff --git a/src/gpu/GrBinHashKey.h b/src/gpu/GrBinHashKey.h index 028bb912b..d2194e947 100644 --- a/src/gpu/GrBinHashKey.h +++ b/src/gpu/GrBinHashKey.h @@ -13,30 +13,40 @@ #include "GrTypes.h" /** - * Hash function class that can take a data chunk of any predetermined - * length. The hash function used is the One-at-a-Time Hash - * (http://burtleburtle.net/bob/hash/doobs.html). + * Hash function class that can take a data chunk of any predetermined length. The hash function + * used is the One-at-a-Time Hash (http://burtleburtle.net/bob/hash/doobs.html). + * + * Keys are computed from Entry objects. Entry must be fully ordered by a member: + * int compare(const GrTBinHashKey& k); + * which returns negative if the Entry < k, 0 if it equals k, and positive if k < the Entry. + * Additionally, Entry must be flattenable into the key using setKeyData. + * + * This class satisfies the requirements to be a key for a GrTHashTable. */ template -class GrBinHashKey { +class GrTBinHashKey { public: - GrBinHashKey() - : fHash(0) -#if GR_DEBUG - , fIsValid(false) -#endif - {} + GrTBinHashKey() { + this->reset(); + } - GrBinHashKey(const GrBinHashKey& other) { + GrTBinHashKey(const GrTBinHashKey& other) { *this = other; } - GrBinHashKey& operator=(const GrBinHashKey& other) { + + GrTBinHashKey& operator=(const GrTBinHashKey& other) { memcpy(this, &other, sizeof(*this)); return *this; } - ~GrBinHashKey() { + ~GrTBinHashKey() { + } + + void reset() { + fHash = 0; +#if GR_DEBUG + fIsValid = false; +#endif } void setKeyData(const uint32_t* SK_RESTRICT data) { @@ -60,19 +70,17 @@ public: fHash = hash; } - int compare(const GrBinHashKey& key) const { + int compare(const GrTBinHashKey& key) const { GrAssert(fIsValid && key.fIsValid); return memcmp(fData, key.fData, KeySize); } - static bool - EQ(const Entry& entry, const GrBinHashKey& key) { + static bool EQ(const Entry& entry, const GrTBinHashKey& key) { GrAssert(key.fIsValid); return 0 == entry.compare(key); } - static bool - LT(const Entry& entry, const GrBinHashKey& key) { + static bool LT(const Entry& entry, const GrTBinHashKey& key) { GrAssert(key.fIsValid); return entry.compare(key) < 0; } @@ -84,7 +92,7 @@ public: private: uint32_t fHash; - uint8_t fData[KeySize]; //Buffer for key storage + uint8_t fData[KeySize]; // Buffer for key storage #if GR_DEBUG public: diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index d13620cb2..b2b26fa3c 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -16,6 +16,8 @@ #include "SkTrace.h" #include "SkXfermode.h" +SK_DEFINE_INST_COUNT(GrGLProgram) + namespace { enum { @@ -28,7 +30,7 @@ enum { #define PRINT_SHADERS 0 -typedef GrGLProgram::ProgramDesc::StageDesc StageDesc; +typedef GrGLProgram::Desc::StageDesc StageDesc; #define VIEW_MATRIX_NAME "uViewM" @@ -95,18 +97,21 @@ GrGLProgram::GrGLProgram() { } GrGLProgram::~GrGLProgram() { + for (int i = 0; i < GrDrawState::kNumStages; ++i) { + delete fProgramStage[i]; + } } void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const { - switch (fProgramDesc.fDualSrcOutput) { - case ProgramDesc::kNone_DualSrcOutput: + switch (fDesc.fDualSrcOutput) { + case Desc::kNone_DualSrcOutput: break; // the prog will write a coverage value to the secondary // output and the dst is blended by one minus that value. - case ProgramDesc::kCoverage_DualSrcOutput: - case ProgramDesc::kCoverageISA_DualSrcOutput: - case ProgramDesc::kCoverageISC_DualSrcOutput: + case Desc::kCoverage_DualSrcOutput: + case Desc::kCoverageISA_DualSrcOutput: + case Desc::kCoverageISC_DualSrcOutput: *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; break; default: @@ -281,17 +286,15 @@ static void addColorMatrix(SkString* fsCode, const char * outputVar, } void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl, - GrVertexLayout layout, - CachedData* programData, SkString* coverageVar, GrGLShaderBuilder* segments) const { - if (layout & GrDrawTarget::kEdge_VertexLayoutBit) { + if (fDesc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit) { const char *vsName, *fsName; segments->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName); segments->fVSAttrs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME); segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName); - switch (fProgramDesc.fVertexEdgeType) { + switch (fDesc.fVertexEdgeType) { case GrDrawState::kHairLine_EdgeType: segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName); segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); @@ -345,32 +348,27 @@ void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl, } } -namespace { - -void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput, - GrGLProgram::CachedData* programData, - GrGLShaderBuilder* segments, - SkString* inColor) { - switch (colorInput) { - case GrGLProgram::ProgramDesc::kAttribute_ColorInput: { - segments->fVSAttrs.push_back().set(kVec4f_GrSLType, +void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) { + switch (fDesc.fColorInput) { + case GrGLProgram::Desc::kAttribute_ColorInput: { + builder->fVSAttrs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, COL_ATTR_NAME); const char *vsName, *fsName; - segments->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); - segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName); + builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); + builder->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName); *inColor = fsName; } break; - case GrGLProgram::ProgramDesc::kUniform_ColorInput: - segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType, + case GrGLProgram::Desc::kUniform_ColorInput: + builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec4f_GrSLType, COL_UNI_NAME); - programData->fUniLocations.fColorUni = kUseUniform; + fUniLocations.fColorUni = kUseUniform; *inColor = COL_UNI_NAME; break; - case GrGLProgram::ProgramDesc::kTransBlack_ColorInput: + case GrGLProgram::Desc::kTransBlack_ColorInput: GrAssert(!"needComputedColor should be false."); break; - case GrGLProgram::ProgramDesc::kSolidWhite_ColorInput: + case GrGLProgram::Desc::kSolidWhite_ColorInput: break; default: GrCrash("Unknown color type."); @@ -378,8 +376,22 @@ void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput, } } -void genAttributeCoverage(GrGLShaderBuilder* segments, - SkString* inOutCoverage) { +void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) { + builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, + kVec4f_GrSLType, COV_UNI_NAME); + fUniLocations.fCoverageUni = kUseUniform; + if (inOutCoverage->size()) { + builder->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n", + COV_UNI_NAME, inOutCoverage->c_str()); + *inOutCoverage = "uniCoverage"; + } else { + *inOutCoverage = COV_UNI_NAME; + } +} + +namespace { +void gen_attribute_coverage(GrGLShaderBuilder* segments, + SkString* inOutCoverage) { segments->fVSAttrs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, COV_ATTR_NAME); @@ -394,35 +406,19 @@ void genAttributeCoverage(GrGLShaderBuilder* segments, *inOutCoverage = fsName; } } - -void genUniformCoverage(GrGLShaderBuilder* segments, - GrGLProgram::CachedData* programData, - SkString* inOutCoverage) { - segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType, - kVec4f_GrSLType, COV_UNI_NAME); - programData->fUniLocations.fCoverageUni = kUseUniform; - if (inOutCoverage->size()) { - segments->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n", - COV_UNI_NAME, inOutCoverage->c_str()); - *inOutCoverage = "uniCoverage"; - } else { - *inOutCoverage = COV_UNI_NAME; - } -} - } void GrGLProgram::genGeometryShader(const GrGLContextInfo& gl, GrGLShaderBuilder* segments) const { #if GR_GL_EXPERIMENTAL_GS - if (fProgramDesc.fExperimentalGS) { + if (fDesc.fExperimentalGS) { GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration); segments->fGSHeader.append("layout(triangles) in;\n" "layout(triangle_strip, max_vertices = 6) out;\n"); segments->fGSCode.append("void main() {\n" "\tfor (int i = 0; i < 3; ++i) {\n" "\t\tgl_Position = gl_in[i].gl_Position;\n"); - if (this->fProgramDesc.fEmitsPointSize) { + if (fDesc.fEmitsPointSize) { segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n"); } GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count()); @@ -444,7 +440,7 @@ const char* GrGLProgram::adjustInColor(const SkString& inColor) const { if (inColor.size()) { return inColor.c_str(); } else { - if (ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput) { + if (Desc::kSolidWhite_ColorInput == fDesc.fColorInput) { return all_ones_vec(4); } else { return all_zeros_vec(4); @@ -452,14 +448,6 @@ const char* GrGLProgram::adjustInColor(const SkString& inColor) const { } } -// If this destructor is in the header file, we must include GrGLProgramStage -// instead of just forward-declaring it. -GrGLProgram::CachedData::~CachedData() { - for (int i = 0; i < GrDrawState::kNumStages; ++i) { - delete fCustomStage[i]; - } -} - namespace { #define GL_CALL(X) GR_GL_CALL(gl.interface(), X) #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gl.interface(), R, X) @@ -524,10 +512,11 @@ GrGLuint compile_shader(const GrGLContextInfo& gl, GrGLenum type, const SkString return compile_shader(gl, type, 1, &str, &length); } -// compiles all the shaders from builder and stores the shader IDs in programData. -bool compile_shaders(const GrGLContextInfo& gl, - const GrGLShaderBuilder& builder, - GrGLProgram::CachedData* programData) { +} + +// compiles all the shaders from builder and stores the shader IDs +bool GrGLProgram::compileShaders(const GrGLContextInfo& gl, + const GrGLShaderBuilder& builder) { SkString shader; @@ -536,7 +525,7 @@ bool compile_shaders(const GrGLContextInfo& gl, GrPrintf(shader.c_str()); GrPrintf("\n"); #endif - if (!(programData->fVShaderID = compile_shader(gl, GR_GL_VERTEX_SHADER, shader))) { + if (!(fVShaderID = compile_shader(gl, GR_GL_VERTEX_SHADER, shader))) { return false; } @@ -546,11 +535,11 @@ bool compile_shaders(const GrGLContextInfo& gl, GrPrintf(shader.c_str()); GrPrintf("\n"); #endif - if (!(programData->fGShaderID = compile_shader(gl, GR_GL_GEOMETRY_SHADER, shader))) { + if (!(fGShaderID = compile_shader(gl, GR_GL_GEOMETRY_SHADER, shader))) { return false; } } else { - programData->fGShaderID = 0; + fGShaderID = 0; } builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader); @@ -558,34 +547,34 @@ bool compile_shaders(const GrGLContextInfo& gl, GrPrintf(shader.c_str()); GrPrintf("\n"); #endif - if (!(programData->fFShaderID = compile_shader(gl, GR_GL_FRAGMENT_SHADER, shader))) { + if (!(fFShaderID = compile_shader(gl, GR_GL_FRAGMENT_SHADER, shader))) { return false; } return true; } -} bool GrGLProgram::genProgram(const GrGLContextInfo& gl, - GrCustomStage** customStages, - GrGLProgram::CachedData* programData) const { + const Desc& desc, + GrCustomStage** customStages) { + fDesc = desc; GrGLShaderBuilder builder(gl); - const uint32_t& layout = fProgramDesc.fVertexLayout; + const uint32_t& layout = fDesc.fVertexLayout; - programData->fUniLocations.reset(); + fUniLocations.reset(); #if GR_GL_EXPERIMENTAL_GS - builder.fUsesGS = fProgramDesc.fExperimentalGS; + builder.fUsesGS = fDesc.fExperimentalGS; #endif SkXfermode::Coeff colorCoeff, uniformCoeff; - bool applyColorMatrix = SkToBool(fProgramDesc.fColorMatrixEnabled); + bool applyColorMatrix = SkToBool(fDesc.fColorMatrixEnabled); // The rest of transfer mode color filters have not been implemented - if (fProgramDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) { + if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) { GR_DEBUGCODE(bool success =) SkXfermode::ModeAsCoeff(static_cast - (fProgramDesc.fColorFilterXfermode), + (fDesc.fColorFilterXfermode), &uniformCoeff, &colorCoeff); GR_DEBUGASSERT(success); } else { @@ -596,7 +585,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, // no need to do the color filter / matrix at all if coverage is 0. The // output color is scaled by the coverage. All the dual source outputs are // scaled by the coverage as well. - if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fCoverageInput) { + if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) { colorCoeff = SkXfermode::kZero_Coeff; uniformCoeff = SkXfermode::kZero_Coeff; applyColorMatrix = false; @@ -605,7 +594,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, // If we know the final color is going to be all zeros then we can // simplify the color filter coeffecients. needComputedColor will then // come out false below. - if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fColorInput) { + if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) { colorCoeff = SkXfermode::kZero_Coeff; if (SkXfermode::kDC_Coeff == uniformCoeff || SkXfermode::kDA_Coeff == uniformCoeff) { @@ -637,7 +626,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType, kMat33f_GrSLType, VIEW_MATRIX_NAME); - programData->fUniLocations.fViewMatrixUni = kUseUniform; + fUniLocations.fViewMatrixUni = kUseUniform; builder.fVSAttrs.push_back().set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, @@ -651,12 +640,11 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, SkString inColor; if (needComputedColor) { - genInputColor((ProgramDesc::ColorInput) fProgramDesc.fColorInput, - programData, &builder, &inColor); + this->genInputColor(&builder, &inColor); } // we output point size in the GS if present - if (fProgramDesc.fEmitsPointSize && !builder.fUsesGS){ + if (fDesc.fEmitsPointSize && !builder.fUsesGS){ builder.fVSCode.append("\tgl_PointSize = 1.0;\n"); } @@ -679,7 +667,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, // uses of programData, but it's safest to do so below when we're *sure* // we need them. for (int s = 0; s < GrDrawState::kNumStages; ++s) { - programData->fCustomStage[s] = NULL; + fProgramStage[s] = NULL; } /////////////////////////////////////////////////////////////////////////// @@ -689,8 +677,8 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, // of each to the next and generating code for each stage. if (needComputedColor) { SkString outColor; - for (int s = 0; s < fProgramDesc.fFirstCoverageStage; ++s) { - if (fProgramDesc.fStages[s].isEnabled()) { + for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) { + if (fDesc.fStages[s].isEnabled()) { // create var to hold stage result outColor = "color"; outColor.appendS32(s); @@ -708,20 +696,15 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, } if (NULL != customStages[s]) { - const GrProgramStageFactory& factory = - customStages[s]->getFactory(); - programData->fCustomStage[s] = - factory.createGLInstance(*customStages[s]); + const GrProgramStageFactory& factory = customStages[s]->getFactory(); + fProgramStage[s] = factory.createGLInstance(*customStages[s]); } this->genStageCode(gl, s, - fProgramDesc.fStages[s], inColor.size() ? inColor.c_str() : NULL, outColor.c_str(), inCoords, - &builder, - &programData->fUniLocations.fStages[s], - programData->fCustomStage[s]); + &builder); inColor = outColor; } } @@ -730,7 +713,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, // if have all ones or zeros for the "dst" input to the color filter then we // may be able to make additional optimizations. if (needColorFilterUniform && needComputedColor && !inColor.size()) { - GrAssert(ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput); + GrAssert(Desc::kSolidWhite_ColorInput == fDesc.fColorInput); bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff || SkXfermode::kIDA_Coeff == uniformCoeff; if (uniformCoeffIsZero) { @@ -743,7 +726,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, if (needColorFilterUniform) { builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec4f_GrSLType, COL_FILTER_UNI_NAME); - programData->fUniLocations.fColorFilterUni = kUseUniform; + fUniLocations.fColorFilterUni = kUseUniform; } bool wroteFragColorZero = false; if (SkXfermode::kZero_Coeff == uniformCoeff && @@ -753,7 +736,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, colorOutput.getName().c_str(), all_zeros_vec(4)); wroteFragColorZero = true; - } else if (SkXfermode::kDst_Mode != fProgramDesc.fColorFilterXfermode) { + } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) { builder.fFSCode.append("\tvec4 filteredColor;\n"); const char* color = adjustInColor(inColor); addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff, @@ -765,8 +748,8 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, kMat44f_GrSLType, COL_MATRIX_UNI_NAME); builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec4f_GrSLType, COL_MATRIX_VEC_UNI_NAME); - programData->fUniLocations.fColorMatrixUni = kUseUniform; - programData->fUniLocations.fColorMatrixVecUni = kUseUniform; + fUniLocations.fColorMatrixUni = kUseUniform; + fUniLocations.fColorMatrixVecUni = kUseUniform; builder.fFSCode.append("\tvec4 matrixedColor;\n"); const char* color = adjustInColor(inColor); addColorMatrix(&builder.fFSCode, "matrixedColor", color); @@ -777,34 +760,32 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, // compute the partial coverage (coverage stages and edge aa) SkString inCoverage; - bool coverageIsZero = ProgramDesc::kTransBlack_ColorInput == - fProgramDesc.fCoverageInput; + bool coverageIsZero = Desc::kTransBlack_ColorInput == fDesc.fCoverageInput; // we don't need to compute coverage at all if we know the final shader // output will be zero and we don't have a dual src blend output. - if (!wroteFragColorZero || - ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) { + if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { if (!coverageIsZero) { - this->genEdgeCoverage(gl, layout, programData, &inCoverage, &builder); + this->genEdgeCoverage(gl, &inCoverage, &builder); - switch (fProgramDesc.fCoverageInput) { - case ProgramDesc::kSolidWhite_ColorInput: + switch (fDesc.fCoverageInput) { + case Desc::kSolidWhite_ColorInput: // empty string implies solid white break; - case ProgramDesc::kAttribute_ColorInput: - genAttributeCoverage(&builder, &inCoverage); + case Desc::kAttribute_ColorInput: + gen_attribute_coverage(&builder, &inCoverage); break; - case ProgramDesc::kUniform_ColorInput: - genUniformCoverage(&builder, programData, &inCoverage); + case Desc::kUniform_ColorInput: + this->genUniformCoverage(&builder, &inCoverage); break; default: GrCrash("Unexpected input coverage."); } SkString outCoverage; - const int& startStage = fProgramDesc.fFirstCoverageStage; + const int& startStage = fDesc.fFirstCoverageStage; for (int s = startStage; s < GrDrawState::kNumStages; ++s) { - if (fProgramDesc.fStages[s].isEnabled()) { + if (fDesc.fStages[s].isEnabled()) { // create var to hold stage output outCoverage = "coverage"; outCoverage.appendS32(s); @@ -825,37 +806,31 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, } if (NULL != customStages[s]) { - const GrProgramStageFactory& factory = - customStages[s]->getFactory(); - programData->fCustomStage[s] = - factory.createGLInstance(*customStages[s]); + const GrProgramStageFactory& factory = customStages[s]->getFactory(); + fProgramStage[s] = factory.createGLInstance(*customStages[s]); } - this->genStageCode(gl, s, - fProgramDesc.fStages[s], - inCoverage.size() ? inCoverage.c_str() : NULL, - outCoverage.c_str(), - inCoords, - &builder, - &programData->fUniLocations.fStages[s], - programData->fCustomStage[s]); + this->genStageCode(gl, + s, + inCoverage.size() ? inCoverage.c_str() : NULL, + outCoverage.c_str(), + inCoords, + &builder); inCoverage = outCoverage; } } } - if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) { + if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { builder.fFSOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier, dual_source_output_name()); bool outputIsZero = coverageIsZero; SkString coeff; if (!outputIsZero && - ProgramDesc::kCoverage_DualSrcOutput != - fProgramDesc.fDualSrcOutput && !wroteFragColorZero) { + Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) { if (!inColor.size()) { outputIsZero = true; } else { - if (fProgramDesc.fDualSrcOutput == - ProgramDesc::kCoverageISA_DualSrcOutput) { + if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) { coeff.printf("(1 - %s.a)", inColor.c_str()); } else { coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str()); @@ -890,16 +865,14 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, inCoverage.c_str(), &builder.fFSCode); } - if (ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig == - fProgramDesc.fOutputConfig) { + if (Desc::kUnpremultiplied_RoundDown_OutputConfig == fDesc.fOutputConfig) { builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n", colorOutput.getName().c_str(), colorOutput.getName().c_str(), colorOutput.getName().c_str(), colorOutput.getName().c_str(), colorOutput.getName().c_str()); - } else if (ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig == - fProgramDesc.fOutputConfig) { + } else if (Desc::kUnpremultiplied_RoundUp_OutputConfig == fDesc.fOutputConfig) { builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n", colorOutput.getName().c_str(), colorOutput.getName().c_str(), @@ -921,132 +894,124 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, /////////////////////////////////////////////////////////////////////////// // compile and setup attribs and unis - if (!compile_shaders(gl, builder, programData)) { + if (!this->compileShaders(gl, builder)) { return false; } - if (!this->bindOutputsAttribsAndLinkProgram(gl, texCoordAttrs, + if (!this->bindOutputsAttribsAndLinkProgram(gl, + texCoordAttrs, isColorDeclared, - dualSourceOutputWritten, - programData)) { + dualSourceOutputWritten)) { return false; } - this->getUniformLocationsAndInitCache(builder, gl, programData); + this->getUniformLocationsAndInitCache(gl, builder); return true; } bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl, - SkString texCoordAttrNames[], - bool bindColorOut, - bool bindDualSrcOut, - CachedData* programData) const { - GL_CALL_RET(programData->fProgramID, CreateProgram()); - if (!programData->fProgramID) { + SkString texCoordAttrNames[], + bool bindColorOut, + bool bindDualSrcOut) { + GL_CALL_RET(fProgramID, CreateProgram()); + if (!fProgramID) { return false; } - const GrGLint& progID = programData->fProgramID; - GL_CALL(AttachShader(progID, programData->fVShaderID)); - if (programData->fGShaderID) { - GL_CALL(AttachShader(progID, programData->fGShaderID)); + GL_CALL(AttachShader(fProgramID, fVShaderID)); + if (fGShaderID) { + GL_CALL(AttachShader(fProgramID, fGShaderID)); } - GL_CALL(AttachShader(progID, programData->fFShaderID)); + GL_CALL(AttachShader(fProgramID, fFShaderID)); if (bindColorOut) { - GL_CALL(BindFragDataLocation(programData->fProgramID, - 0, declared_color_output_name())); + GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name())); } if (bindDualSrcOut) { - GL_CALL(BindFragDataLocationIndexed(programData->fProgramID, - 0, 1, dual_source_output_name())); + GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name())); } // Bind the attrib locations to same values for all shaders - GL_CALL(BindAttribLocation(progID, PositionAttributeIdx(), POS_ATTR_NAME)); + GL_CALL(BindAttribLocation(fProgramID, PositionAttributeIdx(), POS_ATTR_NAME)); for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { if (texCoordAttrNames[t].size()) { - GL_CALL(BindAttribLocation(progID, + GL_CALL(BindAttribLocation(fProgramID, TexCoordAttributeIdx(t), texCoordAttrNames[t].c_str())); } } - GL_CALL(BindAttribLocation(progID, ColorAttributeIdx(), COL_ATTR_NAME)); - GL_CALL(BindAttribLocation(progID, CoverageAttributeIdx(), COV_ATTR_NAME)); - GL_CALL(BindAttribLocation(progID, EdgeAttributeIdx(), EDGE_ATTR_NAME)); + GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME)); + GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME)); + GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME)); - GL_CALL(LinkProgram(progID)); + GL_CALL(LinkProgram(fProgramID)); GrGLint linked = GR_GL_INIT_ZERO; - GL_CALL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked)); + GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); if (!linked) { GrGLint infoLen = GR_GL_INIT_ZERO; - GL_CALL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen)); + GL_CALL(GetProgramiv(fProgramID, 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(progID, + GL_CALL(GetProgramInfoLog(fProgramID, infoLen+1, &length, (char*)log.get())); GrPrintf((char*)log.get()); } GrAssert(!"Error linking program"); - GL_CALL(DeleteProgram(progID)); - programData->fProgramID = 0; + GL_CALL(DeleteProgram(fProgramID)); + fProgramID = 0; return false; } return true; } -void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder, - const GrGLContextInfo& gl, - CachedData* programData) const { - const GrGLint& progID = programData->fProgramID; +void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl, + const GrGLShaderBuilder& builder) { - if (kUseUniform == programData->fUniLocations.fViewMatrixUni) { - GL_CALL_RET(programData->fUniLocations.fViewMatrixUni, - GetUniformLocation(progID, VIEW_MATRIX_NAME)); - GrAssert(kUnusedUniform != programData->fUniLocations.fViewMatrixUni); + if (kUseUniform == fUniLocations.fViewMatrixUni) { + GL_CALL_RET(fUniLocations.fViewMatrixUni, GetUniformLocation(fProgramID, VIEW_MATRIX_NAME)); + GrAssert(kUnusedUniform != fUniLocations.fViewMatrixUni); } - if (kUseUniform == programData->fUniLocations.fColorUni) { - GL_CALL_RET(programData->fUniLocations.fColorUni, - GetUniformLocation(progID, COL_UNI_NAME)); - GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni); + if (kUseUniform == fUniLocations.fColorUni) { + GL_CALL_RET(fUniLocations.fColorUni, GetUniformLocation(fProgramID, COL_UNI_NAME)); + GrAssert(kUnusedUniform != fUniLocations.fColorUni); } - if (kUseUniform == programData->fUniLocations.fColorFilterUni) { - GL_CALL_RET(programData->fUniLocations.fColorFilterUni, - GetUniformLocation(progID, COL_FILTER_UNI_NAME)); - GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni); + if (kUseUniform == fUniLocations.fColorFilterUni) { + GL_CALL_RET(fUniLocations.fColorFilterUni, + GetUniformLocation(fProgramID, COL_FILTER_UNI_NAME)); + GrAssert(kUnusedUniform != fUniLocations.fColorFilterUni); } - if (kUseUniform == programData->fUniLocations.fColorMatrixUni) { - GL_CALL_RET(programData->fUniLocations.fColorMatrixUni, - GetUniformLocation(progID, COL_MATRIX_UNI_NAME)); + if (kUseUniform == fUniLocations.fColorMatrixUni) { + GL_CALL_RET(fUniLocations.fColorMatrixUni, + GetUniformLocation(fProgramID, COL_MATRIX_UNI_NAME)); + GrAssert(kUnusedUniform != fUniLocations.fColorMatrixUni); } - if (kUseUniform == programData->fUniLocations.fColorMatrixVecUni) { - GL_CALL_RET(programData->fUniLocations.fColorMatrixVecUni, - GetUniformLocation(progID, COL_MATRIX_VEC_UNI_NAME)); + if (kUseUniform == fUniLocations.fColorMatrixVecUni) { + GL_CALL_RET(fUniLocations.fColorMatrixVecUni, + GetUniformLocation(fProgramID, COL_MATRIX_VEC_UNI_NAME)); + GrAssert(kUnusedUniform != fUniLocations.fColorMatrixVecUni); } - if (kUseUniform == programData->fUniLocations.fCoverageUni) { - GL_CALL_RET(programData->fUniLocations.fCoverageUni, - GetUniformLocation(progID, COV_UNI_NAME)); - GrAssert(kUnusedUniform != programData->fUniLocations.fCoverageUni); + if (kUseUniform == fUniLocations.fCoverageUni) { + GrAssert(kUnusedUniform != fUniLocations.fCoverageUni); } for (int s = 0; s < GrDrawState::kNumStages; ++s) { - StageUniLocations& locations = programData->fUniLocations.fStages[s]; - if (fProgramDesc.fStages[s].isEnabled()) { + StageUniLocations& locations = fUniLocations.fStages[s]; + if (fDesc.fStages[s].isEnabled()) { if (kUseUniform == locations.fTextureMatrixUni) { SkString texMName; tex_matrix_name(s, &texMName); GL_CALL_RET(locations.fTextureMatrixUni, - GetUniformLocation(progID, texMName.c_str())); + GetUniformLocation(fProgramID, texMName.c_str())); GrAssert(kUnusedUniform != locations.fTextureMatrixUni); } @@ -1054,7 +1019,7 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& build SkString samplerName; sampler_name(s, &samplerName); GL_CALL_RET(locations.fSamplerUni, - GetUniformLocation(progID,samplerName.c_str())); + GetUniformLocation(fProgramID,samplerName.c_str())); GrAssert(kUnusedUniform != locations.fSamplerUni); } @@ -1062,33 +1027,32 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& build SkString texDomName; tex_domain_name(s, &texDomName); GL_CALL_RET(locations.fTexDomUni, - GetUniformLocation(progID, texDomName.c_str())); + GetUniformLocation(fProgramID, texDomName.c_str())); GrAssert(kUnusedUniform != locations.fTexDomUni); } - if (NULL != programData->fCustomStage[s]) { - programData->fCustomStage[s]->initUniforms(&builder, gl.interface(), progID); + if (NULL != fProgramStage[s]) { + fProgramStage[s]->initUniforms(&builder, gl.interface(), fProgramID); } } } - GL_CALL(UseProgram(progID)); + GL_CALL(UseProgram(fProgramID)); // init sampler unis and set bogus values for state tracking for (int s = 0; s < GrDrawState::kNumStages; ++s) { - if (kUnusedUniform != programData->fUniLocations.fStages[s].fSamplerUni) { - GL_CALL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s)); + if (kUnusedUniform != fUniLocations.fStages[s].fSamplerUni) { + GL_CALL(Uniform1i(fUniLocations.fStages[s].fSamplerUni, s)); } - programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix(); - programData->fTextureDomain[s].setEmpty(); + fTextureMatrices[s] = GrMatrix::InvalidMatrix(); + fTextureDomain[s].setEmpty(); // this is arbitrary, just initialize to something - programData->fTextureOrientation[s] = - GrGLTexture::kBottomUp_Orientation; + fTextureOrientation[s] = GrGLTexture::kBottomUp_Orientation; // Must not reset fStageOverride[] here. } - programData->fViewMatrix = GrMatrix::InvalidMatrix(); - programData->fViewportSize.set(-1, -1); - programData->fColor = GrColor_ILLEGAL; - programData->fColorFilterColor = GrColor_ILLEGAL; + fViewMatrix = GrMatrix::InvalidMatrix(); + fViewportSize.set(-1, -1); + fColor = GrColor_ILLEGAL; + fColorFilterColor = GrColor_ILLEGAL; } /////////////////////////////////////////////////////////////////////////////// @@ -1096,17 +1060,17 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& build void GrGLProgram::genStageCode(const GrGLContextInfo& gl, int stageNum, - const GrGLProgram::StageDesc& desc, const char* fsInColor, // NULL means no incoming color const char* fsOutColor, const char* vsInCoord, - GrGLShaderBuilder* segments, - StageUniLocations* locations, - GrGLProgramStage* customStage) const { - + GrGLShaderBuilder* segments) { GrAssert(stageNum >= 0 && stageNum <= GrDrawState::kNumStages); - GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) == - desc.fInConfigFlags); + + const GrGLProgram::StageDesc& desc = fDesc.fStages[stageNum]; + StageUniLocations& locations = fUniLocations.fStages[stageNum]; + GrGLProgramStage* customStage = fProgramStage[stageNum]; + + GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) == desc.fInConfigFlags); /// Vertex Shader Stuff @@ -1124,7 +1088,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, const GrGLShaderVar& mat = segments->getUniformVariable(m); // Can't use texMatName.c_str() because it's on the stack! matName = mat.getName().c_str(); - locations->fTextureMatrixUni = kUseUniform; + locations.fTextureMatrixUni = kUseUniform; if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) { segments->fVaryingDims = segments->fCoordDims; @@ -1143,14 +1107,14 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, sampler_name(stageNum, &samplerName); segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kSampler2D_GrSLType, samplerName.c_str()); - locations->fSamplerUni = kUseUniform; + locations.fSamplerUni = kUseUniform; const char *varyingVSName, *varyingFSName; segments->addVarying(GrSLFloatVectorType(segments->fVaryingDims), "Stage", - stageNum, - &varyingVSName, - &varyingFSName); + stageNum, + &varyingVSName, + &varyingFSName); if (!matName) { GrAssert(segments->fVaryingDims == segments->fCoordDims); @@ -1203,7 +1167,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, texDomainName.c_str(), texDomainName.c_str()); segments->fSampleCoords = coordVar; - locations->fTexDomUni = kUseUniform; + locations.fTexDomUni = kUseUniform; } // NOTE: GrGLProgramStages are now responsible for fetching diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index bebaa58e0..c397d741c 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -13,7 +13,7 @@ #include "GrGLContextInfo.h" #include "GrGLSL.h" #include "GrGLTexture.h" -#include "GrGpu.h" +//#include "GrGpu.h" #include "SkString.h" #include "SkXfermode.h" @@ -35,28 +35,29 @@ class GrGLShaderBuilder; * Uniforms are program-local so we can't rely on fHWState to hold the * previous uniform state after a program change. */ -class GrGLProgram { +class GrGLProgram : public GrRefCnt { public: + SK_DECLARE_INST_COUNT(GrGLProgram) - class CachedData; + struct Desc; GrGLProgram(); - ~GrGLProgram(); + virtual ~GrGLProgram(); /** * This is the heavy initilization routine for building a GLProgram. - * The result of heavy init is not stored in datamembers of GrGLProgam, - * but in a separate cacheable container. */ bool genProgram(const GrGLContextInfo& gl, - GrCustomStage** customStages, - CachedData* programData) const; + const Desc& desc, + GrCustomStage** customStages); /** * The shader may modify the blend coeffecients. Params are in/out */ void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const; + const Desc& getDesc() { return fDesc; } + /** * Attribute indices. These should not overlap. Matrices consume 3 slots. */ @@ -75,16 +76,23 @@ public: return 7 + GrDrawState::kMaxTexCoords + 3 * stage; } -public: + enum { + kUnusedUniform = -1, + }; // Parameters that affect code generation // These structs should be kept compact; they are the input to an // expensive hash key generator. - struct ProgramDesc { - ProgramDesc() { + struct Desc { + Desc() { // since we use this as part of a key we can't have any unitialized // padding - memset(this, 0, sizeof(ProgramDesc)); + memset(this, 0, sizeof(Desc)); + } + + // returns this as a uint32_t array to be used as a key in the program cache + const uint32_t* asKey() const { + return reinterpret_cast(this); } enum OutputConfig { @@ -224,23 +232,46 @@ public: uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode int8_t fPadding[1]; - - } fProgramDesc; - GR_STATIC_ASSERT(!(sizeof(ProgramDesc) % 4)); + }; + GR_STATIC_ASSERT(!(sizeof(Desc) % 4)); // for code readability - typedef ProgramDesc::StageDesc StageDesc; + typedef Desc::StageDesc StageDesc; private: + void genInputColor(GrGLShaderBuilder* builder, SkString* inColor); + + // Determines which uniforms will need to be bound. + void genStageCode(const GrGLContextInfo& gl, + int stageNum, + const char* fsInColor, // NULL means no incoming color + const char* fsOutColor, + const char* vsInCoord, + GrGLShaderBuilder* builder); + + void genGeometryShader(const GrGLContextInfo& gl, GrGLShaderBuilder* segments) const; + + void genUniformCoverage(GrGLShaderBuilder* segments, SkString* inOutCoverage); + + // generates code to compute coverage based on edge AA. + void genEdgeCoverage(const GrGLContextInfo& gl, + SkString* coverageVar, + GrGLShaderBuilder* builder) const; + + // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program + bool bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl, + SkString texCoordAttrNames[GrDrawState::kMaxTexCoords], + bool bindColorOut, + bool bindDualSrcOut); + + // Binds uniforms; initializes cache to invalid values. + void getUniformLocationsAndInitCache(const GrGLContextInfo& gl, + const GrGLShaderBuilder& builder); + + bool compileShaders(const GrGLContextInfo& gl, const GrGLShaderBuilder& builder); - const ProgramDesc& getDesc() { return fProgramDesc; } const char* adjustInColor(const SkString& inColor) const; -public: - enum { - kUnusedUniform = -1, - }; - struct StageUniLocations { GrGLint fTextureMatrixUni; GrGLint fSamplerUni; @@ -273,104 +304,37 @@ public: } }; - class CachedData : public ::GrNoncopyable { - public: - CachedData() { - for (int i = 0; i < GrDrawState::kNumStages; ++i) { - fCustomStage[i] = NULL; - } - } + // IDs + GrGLuint fVShaderID; + GrGLuint fGShaderID; + GrGLuint fFShaderID; + GrGLuint fProgramID; + // shader uniform locations (-1 if shader doesn't use them) + UniLocations fUniLocations; - ~CachedData(); + // The matrix sent to GL is determined by both the client's matrix and + // the size of the viewport. + GrMatrix fViewMatrix; + SkISize fViewportSize; - void copyAndTakeOwnership(CachedData& other) { - memcpy(this, &other, sizeof(*this)); - for (int i = 0; i < GrDrawState::kNumStages; ++i) { - other.fCustomStage[i] = NULL; - } - } + // these reflect the current values of uniforms + // (GL uniform values travel with program) + GrColor fColor; + GrColor fCoverage; + GrColor fColorFilterColor; + GrMatrix fTextureMatrices[GrDrawState::kNumStages]; + GrRect fTextureDomain[GrDrawState::kNumStages]; + // The texture domain and texture matrix sent to GL depend upon the + // orientation. + GrGLTexture::Orientation fTextureOrientation[GrDrawState::kNumStages]; - public: + GrGLProgramStage* fProgramStage[GrDrawState::kNumStages]; - // IDs - GrGLuint fVShaderID; - GrGLuint fGShaderID; - GrGLuint fFShaderID; - GrGLuint fProgramID; - // shader uniform locations (-1 if shader doesn't use them) - UniLocations fUniLocations; + Desc fDesc; - // The matrix sent to GL is determined by both the client's matrix and - // the size of the viewport. - GrMatrix fViewMatrix; - SkISize fViewportSize; + friend class GrGpuGL; // TODO: remove this by adding getters and moving functionality. - // these reflect the current values of uniforms - // (GL uniform values travel with program) - GrColor fColor; - GrColor fCoverage; - GrColor fColorFilterColor; - GrMatrix fTextureMatrices[GrDrawState::kNumStages]; - GrRect fTextureDomain[GrDrawState::kNumStages]; - // The texture domain and texture matrix sent to GL depend upon the - // orientation. - GrGLTexture::Orientation fTextureOrientation[GrDrawState::kNumStages]; - - GrGLProgramStage* fCustomStage[GrDrawState::kNumStages]; - - private: - enum Constants { - kUniLocationPreAllocSize = 8 - }; - - }; // CachedData - - enum Constants { - kProgramKeySize = sizeof(ProgramDesc) - }; - - // Provide an opaque ProgramDesc - const uint32_t* keyData() const{ - return reinterpret_cast(&fProgramDesc); - } - -private: - - // Determines which uniforms will need to be bound. - void genStageCode(const GrGLContextInfo& gl, - int stageNum, - const ProgramDesc::StageDesc& desc, - const char* fsInColor, // NULL means no incoming color - const char* fsOutColor, - const char* vsInCoord, - GrGLShaderBuilder* segments, - StageUniLocations* locations, - GrGLProgramStage* override) const; - - void genGeometryShader(const GrGLContextInfo& gl, - GrGLShaderBuilder* segments) const; - - // generates code to compute coverage based on edge AA. - void genEdgeCoverage(const GrGLContextInfo& gl, - GrVertexLayout layout, - CachedData* programData, - SkString* coverageVar, - GrGLShaderBuilder* segments) const; - - // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program - bool bindOutputsAttribsAndLinkProgram( - const GrGLContextInfo& gl, - SkString texCoordAttrNames[GrDrawState::kMaxTexCoords], - bool bindColorOut, - bool bindDualSrcOut, - CachedData* programData) const; - - // Binds uniforms; initializes cache to invalid values. - void getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder, - const GrGLContextInfo& gl, - CachedData* programData) const; - - friend class GrGpuGL; + typedef GrRefCnt INHERITED; }; #endif diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 4a63b3322..21cf3b888 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -175,7 +175,6 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) { this->initCaps(); - fProgramData = NULL; fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContextInfo())); fLastSuccessfulStencilFmtIdx = 0; @@ -186,16 +185,14 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) { } GrGpuGL::~GrGpuGL() { - if (fProgramData && 0 != fHWProgramID) { + if (0 != fHWProgramID) { // detach the current program so there is no confusion on OpenGL's part // that we want it to be deleted - GrAssert(fHWProgramID == fProgramData->fProgramID); + GrAssert(fHWProgramID == fCurrentProgram->fProgramID); GL_CALL(UseProgram(0)); } delete fProgramCache; - fProgramCache = NULL; - fProgramData = NULL; // This must be called by before the GrDrawTarget destructor this->releaseGeometry(); diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index 0871a57b7..5b33e0e47 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -162,9 +162,8 @@ private: static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff); // for readability of function impls - typedef GrGLProgram::ProgramDesc ProgramDesc; + typedef GrGLProgram::Desc ProgramDesc; typedef ProgramDesc::StageDesc StageDesc; - typedef GrGLProgram::CachedData CachedData; class ProgramCache : public ::GrNoncopyable { public: @@ -172,31 +171,37 @@ private: ~ProgramCache(); void abandon(); - CachedData* getProgramData(const GrGLProgram& desc, - GrCustomStage** stages); + GrGLProgram* getProgram(const GrGLProgram::Desc& desc, GrCustomStage** stages); private: enum { - kKeySize = GrGLProgram::kProgramKeySize, - // We may actually have kMaxEntries+1 shaders in the GL context - // because we create a new shader before evicting from the cache. + kKeySize = sizeof(ProgramDesc), + // We may actually have kMaxEntries+1 shaders in the GL context because we create a new + // shader before evicting from the cache. kMaxEntries = 32 }; class Entry; - typedef GrBinHashKey ProgramHashKey; + // The value of the hash key is based on the ProgramDesc. + typedef GrTBinHashKey ProgramHashKey; class Entry : public ::GrNoncopyable { public: - Entry() {} - void copyAndTakeOwnership(Entry& entry); + Entry() : fProgram(NULL), fLRUStamp(0) {} + Entry& operator = (const Entry& entry) { + GrSafeRef(entry.fProgram.get()); + fProgram.reset(entry.fProgram.get()); + fKey = entry.fKey; + fLRUStamp = entry.fLRUStamp; + return *this; + } int compare(const ProgramHashKey& key) const { return fKey.compare(key); } public: - CachedData fProgramData; - ProgramHashKey fKey; - unsigned int fLRUStamp; + SkAutoTUnref fProgram; + ProgramHashKey fKey; + unsigned int fLRUStamp; // Move outside entry? }; GrTHashTable fHashCache; @@ -243,13 +248,13 @@ private: // flushing the scissor after that function is called. void flushScissor(); - static void DeleteProgram(const GrGLInterface* gl, - CachedData* programData); + static void DeleteProgram(const GrGLInterface* gl, GrGLProgram* programData); void buildProgram(bool isPoints, BlendOptFlags blendOpts, GrBlendCoeff dstCoeff, - GrCustomStage** customStages); + GrCustomStage** customStages, + ProgramDesc* desc); // Inits GrDrawTarget::Caps, sublcass may enable additional caps. void initCaps(); @@ -304,8 +309,7 @@ private: // GL program-related state ProgramCache* fProgramCache; - CachedData* fProgramData; - GrGLProgram fCurrentProgram; + SkAutoTUnref fCurrentProgram; /////////////////////////////////////////////////////////////////////////// ///@name Caching of GL State diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index af9bb054a..077f80772 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -14,12 +14,6 @@ #define SKIP_CACHE_CHECK true #define GR_UINT32_MAX static_cast(-1) -void GrGpuGL::ProgramCache::Entry::copyAndTakeOwnership(Entry& entry) { - fProgramData.copyAndTakeOwnership(entry.fProgramData); - fKey = entry.fKey; // ownership transfer - fLRUStamp = entry.fLRUStamp; -} - GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl) : fCount(0) , fCurrLRUStamp(0) @@ -28,8 +22,7 @@ GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl) GrGpuGL::ProgramCache::~ProgramCache() { for (int i = 0; i < fCount; ++i) { - GrGpuGL::DeleteProgram(fGL.interface(), - &fEntries[i].fProgramData); + GrGpuGL::DeleteProgram(fGL.interface(), fEntries[i].fProgram); } } @@ -37,15 +30,14 @@ void GrGpuGL::ProgramCache::abandon() { fCount = 0; } -GrGLProgram::CachedData* GrGpuGL::ProgramCache::getProgramData( - const GrGLProgram& desc, - GrCustomStage** stages) { +GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc, GrCustomStage** stages) { Entry newEntry; - newEntry.fKey.setKeyData(desc.keyData()); - + newEntry.fKey.setKeyData(desc.asKey()); + Entry* entry = fHashCache.find(newEntry.fKey); if (NULL == entry) { - if (!desc.genProgram(fGL, stages, &newEntry.fProgramData)) { + newEntry.fProgram.reset(SkNEW(GrGLProgram)); + if (!newEntry.fProgram->genProgram(fGL, desc, stages)) { return NULL; } if (fCount < kMaxEntries) { @@ -60,10 +52,9 @@ GrGLProgram::CachedData* GrGpuGL::ProgramCache::getProgramData( } } fHashCache.remove(entry->fKey, entry); - GrGpuGL::DeleteProgram(fGL.interface(), - &entry->fProgramData); + GrGpuGL::DeleteProgram(fGL.interface(), entry->fProgram); } - entry->copyAndTakeOwnership(newEntry); + *entry = newEntry; fHashCache.insert(entry->fKey, entry); } @@ -75,21 +66,20 @@ GrGLProgram::CachedData* GrGpuGL::ProgramCache::getProgramData( } } ++fCurrLRUStamp; - return &entry->fProgramData; + return entry->fProgram; } -void GrGpuGL::DeleteProgram(const GrGLInterface* gl, - CachedData* programData) { - GR_GL_CALL(gl, DeleteShader(programData->fVShaderID)); - if (programData->fGShaderID) { - GR_GL_CALL(gl, DeleteShader(programData->fGShaderID)); +void GrGpuGL::DeleteProgram(const GrGLInterface* gl, GrGLProgram* program) { + GR_GL_CALL(gl, DeleteShader(program->fVShaderID)); + if (program->fGShaderID) { + GR_GL_CALL(gl, DeleteShader(program->fGShaderID)); } - GR_GL_CALL(gl, DeleteShader(programData->fFShaderID)); - GR_GL_CALL(gl, DeleteProgram(programData->fProgramID)); - GR_DEBUGCODE(programData->fVShaderID = 0); - GR_DEBUGCODE(programData->fGShaderID = 0); - GR_DEBUGCODE(programData->fFShaderID = 0); - GR_DEBUGCODE(programData->fProgramID = 0); + GR_GL_CALL(gl, DeleteShader(program->fFShaderID)); + GR_GL_CALL(gl, DeleteProgram(program->fProgramID)); + GR_DEBUGCODE(program->fVShaderID = 0); + GR_DEBUGCODE(program->fGShaderID = 0); + GR_DEBUGCODE(program->fFShaderID = 0); + GR_DEBUGCODE(program->fProgramID = 0); } //////////////////////////////////////////////////////////////////////////////// @@ -150,8 +140,8 @@ void GrGpuGL::flushViewMatrix(DrawType type) { fHWPathMatrixState.fViewMatrix = vm; fHWPathMatrixState.fRTSize = viewportSize; } - } else if (!fProgramData->fViewMatrix.cheapEqualTo(vm) || - fProgramData->fViewportSize != viewportSize) { + } else if (!fCurrentProgram->fViewMatrix.cheapEqualTo(vm) || + fCurrentProgram->fViewportSize != viewportSize) { GrMatrix m; m.setAll( GrIntToScalar(2) / viewportSize.fWidth, 0, -GR_Scalar1, @@ -174,11 +164,11 @@ void GrGpuGL::flushViewMatrix(DrawType type) { }; GrAssert(GrGLProgram::kUnusedUniform != - fProgramData->fUniLocations.fViewMatrixUni); - GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni, + fCurrentProgram->fUniLocations.fViewMatrixUni); + GL_CALL(UniformMatrix3fv(fCurrentProgram->fUniLocations.fViewMatrixUni, 1, false, mt)); - fProgramData->fViewMatrix = vm; - fProgramData->fViewportSize = viewportSize; + fCurrentProgram->fViewMatrix = vm; + fCurrentProgram->fViewportSize = viewportSize; } } @@ -225,13 +215,13 @@ void GrGpuGL::flushTextureMatrixAndDomain(int s) { static_cast(drawState.getTexture(s)); if (NULL != texture) { - bool orientationChange = fProgramData->fTextureOrientation[s] != + bool orientationChange = fCurrentProgram->fTextureOrientation[s] != texture->orientation(); const GrGLint& matrixUni = - fProgramData->fUniLocations.fStages[s].fTextureMatrixUni; + fCurrentProgram->fUniLocations.fStages[s].fTextureMatrixUni; - const GrMatrix& hwMatrix = fProgramData->fTextureMatrices[s]; + const GrMatrix& hwMatrix = fCurrentProgram->fTextureMatrices[s]; const GrMatrix& samplerMatrix = drawState.getSampler(s).getMatrix(); if (GrGLProgram::kUnusedUniform != matrixUni && @@ -255,16 +245,15 @@ void GrGpuGL::flushTextureMatrixAndDomain(int s) { }; GL_CALL(UniformMatrix3fv(matrixUni, 1, false, mt)); - fProgramData->fTextureMatrices[s] = samplerMatrix; + fCurrentProgram->fTextureMatrices[s] = samplerMatrix; } - const GrGLint& domUni = - fProgramData->fUniLocations.fStages[s].fTexDomUni; + const GrGLint& domUni = fCurrentProgram->fUniLocations.fStages[s].fTexDomUni; const GrRect &texDom = drawState.getSampler(s).getTextureDomain(); if (GrGLProgram::kUnusedUniform != domUni && - (orientationChange ||fProgramData->fTextureDomain[s] != texDom)) { + (orientationChange ||fCurrentProgram->fTextureDomain[s] != texDom)) { - fProgramData->fTextureDomain[s] = texDom; + fCurrentProgram->fTextureDomain[s] = texDom; float values[4] = { GrScalarToFloat(texDom.left()), @@ -283,15 +272,14 @@ void GrGpuGL::flushTextureMatrixAndDomain(int s) { } GL_CALL(Uniform4fv(domUni, 1, values)); } - fProgramData->fTextureOrientation[s] = texture->orientation(); + fCurrentProgram->fTextureOrientation[s] = texture->orientation(); } } void GrGpuGL::flushColorMatrix() { - // const ProgramDesc& desc = fCurrentProgram.getDesc(); - int matrixUni = fProgramData->fUniLocations.fColorMatrixUni; - int vecUni = fProgramData->fUniLocations.fColorMatrixVecUni; + int matrixUni = fCurrentProgram->fUniLocations.fColorMatrixUni; + int vecUni = fCurrentProgram->fUniLocations.fColorMatrixVecUni; if (GrGLProgram::kUnusedUniform != matrixUni && GrGLProgram::kUnusedUniform != vecUni) { const float* m = this->getDrawState().getColorMatrix(); @@ -320,7 +308,7 @@ static const float ONE_OVER_255 = 1.f / 255.f; } void GrGpuGL::flushColor(GrColor color) { - const ProgramDesc& desc = fCurrentProgram.getDesc(); + const ProgramDesc& desc = fCurrentProgram->getDesc(); const GrDrawState& drawState = this->getDrawState(); if (this->getVertexLayout() & kColor_VertexLayoutBit) { @@ -340,15 +328,14 @@ void GrGpuGL::flushColor(GrColor color) { } break; case ProgramDesc::kUniform_ColorInput: - if (fProgramData->fColor != color) { + if (fCurrentProgram->fColor != color) { // OpenGL ES doesn't support unsigned byte varieties of // glUniform float c[] = GR_COLOR_TO_VEC4(color); GrAssert(GrGLProgram::kUnusedUniform != - fProgramData->fUniLocations.fColorUni); - GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorUni, - 1, c)); - fProgramData->fColor = color; + fCurrentProgram->fUniLocations.fColorUni); + GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fColorUni, 1, c)); + fCurrentProgram->fColor = color; } break; case ProgramDesc::kSolidWhite_ColorInput: @@ -358,18 +345,18 @@ void GrGpuGL::flushColor(GrColor color) { GrCrash("Unknown color type."); } } - if (fProgramData->fUniLocations.fColorFilterUni + if (fCurrentProgram->fUniLocations.fColorFilterUni != GrGLProgram::kUnusedUniform - && fProgramData->fColorFilterColor + && fCurrentProgram->fColorFilterColor != drawState.getColorFilterColor()) { float c[] = GR_COLOR_TO_VEC4(drawState.getColorFilterColor()); - GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c)); - fProgramData->fColorFilterColor = drawState.getColorFilterColor(); + GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fColorFilterUni, 1, c)); + fCurrentProgram->fColorFilterColor = drawState.getColorFilterColor(); } } void GrGpuGL::flushCoverage(GrColor coverage) { - const ProgramDesc& desc = fCurrentProgram.getDesc(); + const ProgramDesc& desc = fCurrentProgram->getDesc(); // const GrDrawState& drawState = this->getDrawState(); @@ -390,15 +377,14 @@ void GrGpuGL::flushCoverage(GrColor coverage) { } break; case ProgramDesc::kUniform_ColorInput: - if (fProgramData->fCoverage != coverage) { + if (fCurrentProgram->fCoverage != coverage) { // OpenGL ES doesn't support unsigned byte varieties of // glUniform float c[] = GR_COLOR_TO_VEC4(coverage); GrAssert(GrGLProgram::kUnusedUniform != - fProgramData->fUniLocations.fCoverageUni); - GL_CALL(Uniform4fv(fProgramData->fUniLocations.fCoverageUni, - 1, c)); - fProgramData->fCoverage = coverage; + fCurrentProgram->fUniLocations.fCoverageUni); + GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fCoverageUni, 1, c)); + fCurrentProgram->fCoverage = coverage; } break; case ProgramDesc::kSolidWhite_ColorInput: @@ -428,20 +414,21 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { } GrCustomStage* customStages [GrDrawState::kNumStages]; - this->buildProgram(kDrawPoints_DrawType == type, - blendOpts, dstCoeff, customStages); - fProgramData = fProgramCache->getProgramData(fCurrentProgram, - customStages); - if (NULL == fProgramData) { + GrGLProgram::Desc desc; + this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, customStages, &desc); + + fCurrentProgram.reset(fProgramCache->getProgram(desc, customStages)); + if (NULL == fCurrentProgram.get()) { GrAssert(!"Failed to create program!"); return false; } + fCurrentProgram.get()->ref(); - if (fHWProgramID != fProgramData->fProgramID) { - GL_CALL(UseProgram(fProgramData->fProgramID)); - fHWProgramID = fProgramData->fProgramID; + if (fHWProgramID != fCurrentProgram->fProgramID) { + GL_CALL(UseProgram(fCurrentProgram->fProgramID)); + fHWProgramID = fCurrentProgram->fProgramID; } - fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff); + fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); GrColor color; @@ -472,16 +459,13 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { this->flushTextureMatrixAndDomain(s); - if (NULL != fProgramData->fCustomStage[s]) { - const GrSamplerState& sampler = - this->getDrawState().getSampler(s); - const GrGLTexture* texture = - static_cast( - this->getDrawState().getTexture(s)); - fProgramData->fCustomStage[s]->setData( - this->glInterface(), - *sampler.getCustomStage(), - drawState.getRenderTarget(), s); + if (NULL != fCurrentProgram->fProgramStage[s]) { + const GrSamplerState& sampler = this->getDrawState().getSampler(s); + const GrGLTexture* texture = static_cast( + this->getDrawState().getTexture(s)); + fCurrentProgram->fProgramStage[s]->setData(this->glInterface(), + *sampler.getCustomStage(), + drawState.getRenderTarget(), s); } } } @@ -658,7 +642,7 @@ void GrGpuGL::setupGeometry(int* startVertex, namespace { -void setup_custom_stage(GrGLProgram::ProgramDesc::StageDesc* stage, +void setup_custom_stage(GrGLProgram::Desc::StageDesc* stage, const GrSamplerState& sampler, GrCustomStage** customStages, GrGLProgram* program, int index) { @@ -678,8 +662,8 @@ void setup_custom_stage(GrGLProgram::ProgramDesc::StageDesc* stage, void GrGpuGL::buildProgram(bool isPoints, BlendOptFlags blendOpts, GrBlendCoeff dstCoeff, - GrCustomStage** customStages) { - ProgramDesc& desc = fCurrentProgram.fProgramDesc; + GrCustomStage** customStages, + ProgramDesc* desc) { const GrDrawState& drawState = this->getDrawState(); // This should already have been caught @@ -696,31 +680,31 @@ void GrGpuGL::buildProgram(bool isPoints, // to a canonical value to avoid duplicate programs with different keys. // Must initialize all fields or cache will have false negatives! - desc.fVertexLayout = this->getVertexLayout(); + desc->fVertexLayout = this->getVertexLayout(); - desc.fEmitsPointSize = isPoints; + desc->fEmitsPointSize = isPoints; bool requiresAttributeColors = - !skipColor && SkToBool(desc.fVertexLayout & kColor_VertexLayoutBit); + !skipColor && SkToBool(desc->fVertexLayout & kColor_VertexLayoutBit); bool requiresAttributeCoverage = - !skipCoverage && SkToBool(desc.fVertexLayout & + !skipCoverage && SkToBool(desc->fVertexLayout & kCoverage_VertexLayoutBit); // fColorInput/fCoverageInput records how colors are specified for the. // program. So we strip the bits from the layout to avoid false negatives // when searching for an existing program in the cache. - desc.fVertexLayout &= ~(kColor_VertexLayoutBit | kCoverage_VertexLayoutBit); + desc->fVertexLayout &= ~(kColor_VertexLayoutBit | kCoverage_VertexLayoutBit); - desc.fColorFilterXfermode = skipColor ? + desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode(); - desc.fColorMatrixEnabled = drawState.isStateFlagEnabled(GrDrawState::kColorMatrix_StateBit); + desc->fColorMatrixEnabled = drawState.isStateFlagEnabled(GrDrawState::kColorMatrix_StateBit); // no reason to do edge aa or look at per-vertex coverage if coverage is // ignored if (skipCoverage) { - desc.fVertexLayout &= ~(kEdge_VertexLayoutBit | + desc->fVertexLayout &= ~(kEdge_VertexLayoutBit | kCoverage_VertexLayoutBit); } @@ -729,40 +713,40 @@ void GrGpuGL::buildProgram(bool isPoints, (!requiresAttributeColors && 0xffffffff == drawState.getColor()); if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) { - desc.fColorInput = ProgramDesc::kTransBlack_ColorInput; + desc->fColorInput = ProgramDesc::kTransBlack_ColorInput; } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) { - desc.fColorInput = ProgramDesc::kSolidWhite_ColorInput; + desc->fColorInput = ProgramDesc::kSolidWhite_ColorInput; } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) { - desc.fColorInput = ProgramDesc::kUniform_ColorInput; + desc->fColorInput = ProgramDesc::kUniform_ColorInput; } else { - desc.fColorInput = ProgramDesc::kAttribute_ColorInput; + desc->fColorInput = ProgramDesc::kAttribute_ColorInput; } bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage(); if (skipCoverage) { - desc.fCoverageInput = ProgramDesc::kTransBlack_ColorInput; + desc->fCoverageInput = ProgramDesc::kTransBlack_ColorInput; } else if (covIsSolidWhite) { - desc.fCoverageInput = ProgramDesc::kSolidWhite_ColorInput; + desc->fCoverageInput = ProgramDesc::kSolidWhite_ColorInput; } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) { - desc.fCoverageInput = ProgramDesc::kUniform_ColorInput; + desc->fCoverageInput = ProgramDesc::kUniform_ColorInput; } else { - desc.fCoverageInput = ProgramDesc::kAttribute_ColorInput; + desc->fCoverageInput = ProgramDesc::kAttribute_ColorInput; } int lastEnabledStage = -1; - if (!skipCoverage && (desc.fVertexLayout & + if (!skipCoverage && (desc->fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit)) { - desc.fVertexEdgeType = drawState.getVertexEdgeType(); + desc->fVertexEdgeType = drawState.getVertexEdgeType(); } else { // use canonical value when not set to avoid cache misses - desc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; + desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType; } for (int s = 0; s < GrDrawState::kNumStages; ++s) { - StageDesc& stage = desc.fStages[s]; + StageDesc& stage = desc->fStages[s]; stage.fOptFlags = 0; stage.setEnabled(this->isStageEnabled(s)); @@ -825,8 +809,7 @@ void GrGpuGL::buildProgram(bool isPoints, } } - setup_custom_stage(&stage, sampler, customStages, - &fCurrentProgram, s); + setup_custom_stage(&stage, sampler, customStages, fCurrentProgram.get(), s); } else { stage.fOptFlags = 0; @@ -841,23 +824,23 @@ void GrGpuGL::buildProgram(bool isPoints, // when rounding. GrAssert(4 == GrBytesPerPixel(drawState.getRenderTarget()->config())); if (kUpOnWrite_DownOnRead_UnpremulConversion == fUnpremulConversion) { - desc.fOutputConfig = + desc->fOutputConfig = ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig; } else { - desc.fOutputConfig = + desc->fOutputConfig = ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig; } } else { - desc.fOutputConfig = ProgramDesc::kPremultiplied_OutputConfig; + desc->fOutputConfig = ProgramDesc::kPremultiplied_OutputConfig; } - desc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; + desc->fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; // currently the experimental GS will only work with triangle prims // (and it doesn't do anything other than pass through values from // the VS to the FS anyway). #if 0 && GR_GL_EXPERIMENTAL_GS - desc.fExperimentalGS = this->getCaps().fGeometryShaderSupport; + desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport; #endif // we want to avoid generating programs with different "first cov stage" @@ -866,7 +849,7 @@ void GrGpuGL::buildProgram(bool isPoints, // coverage stages or the distinction between coverage and color is // immaterial. int firstCoverageStage = GrDrawState::kNumStages; - desc.fFirstCoverageStage = GrDrawState::kNumStages; + desc->fFirstCoverageStage = GrDrawState::kNumStages; bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage; if (hasCoverage) { firstCoverageStage = drawState.getFirstCoverageStage(); @@ -876,13 +859,13 @@ void GrGpuGL::buildProgram(bool isPoints, if (!hasCoverage) { hasCoverage = requiresAttributeCoverage || - (desc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit); + (desc->fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit); } if (hasCoverage) { // color filter is applied between color/coverage computation - if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) { - desc.fFirstCoverageStage = firstCoverageStage; + if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) { + desc->fFirstCoverageStage = firstCoverageStage; } if (this->getCaps().fDualSourceBlendingSupport && @@ -890,18 +873,18 @@ void GrGpuGL::buildProgram(bool isPoints, kCoverageAsAlpha_BlendOptFlag))) { if (kZero_GrBlendCoeff == dstCoeff) { // write the coverage value to second color - desc.fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput; - desc.fFirstCoverageStage = firstCoverageStage; + desc->fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput; + desc->fFirstCoverageStage = firstCoverageStage; } else if (kSA_GrBlendCoeff == dstCoeff) { // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially // cover - desc.fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput; - desc.fFirstCoverageStage = firstCoverageStage; + desc->fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput; + desc->fFirstCoverageStage = firstCoverageStage; } else if (kSC_GrBlendCoeff == dstCoeff) { // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially // cover - desc.fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput; - desc.fFirstCoverageStage = firstCoverageStage; + desc->fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput; + desc->fFirstCoverageStage = firstCoverageStage; } } } diff --git a/src/gpu/gl/GrGpuGL_unittest.cpp b/src/gpu/gl/GrGpuGL_unittest.cpp index 004013a55..9dd3e7717 100644 --- a/src/gpu/gl/GrGpuGL_unittest.cpp +++ b/src/gpu/gl/GrGpuGL_unittest.cpp @@ -231,8 +231,6 @@ bool GrGpuGL::programUnitTest() { StageDesc::kSmearAlpha_InConfigFlag, StageDesc::kSmearRed_InConfigFlag, }; - GrGLProgram program; - ProgramDesc& pdesc = program.fProgramDesc; static const int NUM_TESTS = 512; @@ -247,6 +245,7 @@ bool GrGpuGL::programUnitTest() { } #endif + ProgramDesc pdesc; pdesc.fVertexLayout = 0; pdesc.fEmitsPointSize = random.nextF() > .5f; pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt); @@ -317,14 +316,15 @@ bool GrGpuGL::programUnitTest() { } } } - CachedData cachedData; GR_STATIC_ASSERT(sizeof(customStages) == GrDrawState::kNumStages * sizeof(GrCustomStage*)); GrCustomStage** stages = reinterpret_cast(&customStages); - if (!program.genProgram(this->glContextInfo(), stages, &cachedData)) { + SkAutoTUnref program(SkNEW(GrGLProgram)); + + if (!program->genProgram(this->glContextInfo(), pdesc, stages)) { return false; } - DeleteProgram(this->glInterface(), &cachedData); + DeleteProgram(this->glInterface(), program); } return true; } diff --git a/src/gpu/gr_unittests.cpp b/src/gpu/gr_unittests.cpp index d55486130..4d11721c3 100644 --- a/src/gpu/gr_unittests.cpp +++ b/src/gpu/gr_unittests.cpp @@ -87,10 +87,10 @@ static void test_binHashKey() kDataLenUsedForKey = 8 }; - GrBinHashKey keyA; + GrTBinHashKey keyA; keyA.setKeyData(testStringA); // test copy constructor and comparison - GrBinHashKey keyA2(keyA); + GrTBinHashKey keyA2(keyA); GrAssert(keyA.compare(keyA2) == 0); GrAssert(keyA.getHash() == keyA2.getHash()); // test re-init @@ -98,7 +98,7 @@ static void test_binHashKey() GrAssert(keyA.compare(keyA2) == 0); GrAssert(keyA.getHash() == keyA2.getHash()); // test sorting - GrBinHashKey keyB; + GrTBinHashKey keyB; keyB.setKeyData(testStringB); GrAssert(keyA.compare(keyB) < 0); GrAssert(keyA.getHash() != keyB.getHash());