diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-07-18 13:20:29 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-07-18 13:20:29 +0000 |
commit | ecb60aad5c6fe5b1dbcfc86ac00bfc9326103c8d (patch) | |
tree | afb61c24ca683260e40b6e0ad8e7ad0e297f27e6 /src/gpu | |
parent | 5836b6dec5563e6273099fcf23984dd3818a168f (diff) |
Factory method for creating GrGLProgram
Review URL: http://codereview.appspot.com/6407049/
git-svn-id: http://skia.googlecode.com/svn/trunk@4646 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 140 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 50 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 27 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_unittest.cpp | 6 |
5 files changed, 118 insertions, 108 deletions
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 49cb161652..52a4bd3b5c 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -18,6 +18,9 @@ SK_DEFINE_INST_COUNT(GrGLProgram) +#define GL_CALL(X) GR_GL_CALL(fContextInfo.interface(), X) +#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fContextInfo.interface(), R, X) + namespace { enum { @@ -88,15 +91,57 @@ inline void sampler_name(int stage, SkString* s) { } } -GrGLProgram::GrGLProgram() { +GrGLProgram* GrGLProgram::Create(const GrGLContextInfo& gl, + const Desc& desc, + GrCustomStage** customStages) { + GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, customStages)); + if (!program->succeeded()) { + delete program; + program = NULL; + } + return program; +} + +GrGLProgram::GrGLProgram(const GrGLContextInfo& gl, + const Desc& desc, + GrCustomStage** customStages) : fContextInfo(gl) { + fDesc = desc; + fVShaderID = 0; + fGShaderID = 0; + fFShaderID = 0; + fProgramID = 0; + for (int s = 0; s < GrDrawState::kNumStages; ++s) { + fProgramStage[s] = NULL; + } + this->genProgram(customStages); } GrGLProgram::~GrGLProgram() { + if (fVShaderID) { + GL_CALL(DeleteShader(fVShaderID)); + } + if (fGShaderID) { + GL_CALL(DeleteShader(fGShaderID)); + } + if (fFShaderID) { + GL_CALL(DeleteShader(fFShaderID)); + } + if (fProgramID) { + GL_CALL(DeleteProgram(fProgramID)); + } + for (int i = 0; i < GrDrawState::kNumStages; ++i) { delete fProgramStage[i]; } } +void GrGLProgram::abandon() { + fVShaderID = 0; + fGShaderID = 0; + fFShaderID = 0; + fProgramID = 0; +} + void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const { switch (fDesc.fDualSrcOutput) { @@ -280,8 +325,7 @@ static void addColorMatrix(SkString* fsCode, const char * outputVar, fsCode->appendf("\t%s.rgb *= %s.a;\n", outputVar, outputVar); } -void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl, - SkString* coverageVar, +void GrGLProgram::genEdgeCoverage(SkString* coverageVar, GrGLShaderBuilder* segments) const { if (fDesc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit) { const char *vsName, *fsName; @@ -309,7 +353,7 @@ void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl, segments->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); segments->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n" "\t}\n"); - if (kES2_GrGLBinding == gl.binding()) { + if (kES2_GrGLBinding == fContextInfo.binding()) { segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); } break; @@ -322,7 +366,7 @@ void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl, segments->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); segments->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); - if (kES2_GrGLBinding == gl.binding()) { + if (kES2_GrGLBinding == fContextInfo.binding()) { segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); } break; @@ -403,11 +447,10 @@ void gen_attribute_coverage(GrGLShaderBuilder* segments, } } -void GrGLProgram::genGeometryShader(const GrGLContextInfo& gl, - GrGLShaderBuilder* segments) const { +void GrGLProgram::genGeometryShader(GrGLShaderBuilder* segments) const { #if GR_GL_EXPERIMENTAL_GS if (fDesc.fExperimentalGS) { - GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration); + GrAssert(fContextInfo.glslGeneration() >= k150_GrGLSLGeneration); segments->fGSHeader.append("layout(triangles) in;\n" "layout(triangle_strip, max_vertices = 6) out;\n"); segments->fGSCode.append("void main() {\n" @@ -444,9 +487,6 @@ const char* GrGLProgram::adjustInColor(const SkString& inColor) const { } 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) - // prints a shader using params similar to glShaderSource void print_shader(GrGLint stringCnt, const GrGLchar** strings, @@ -470,31 +510,32 @@ GrGLuint compile_shader(const GrGLContextInfo& gl, "stringCount", SkStringPrintf("%i", stringCnt).c_str()); GrGLuint shader; - GL_CALL_RET(shader, CreateShader(type)); + GR_GL_CALL_RET(gl.interface(), shader, CreateShader(type)); if (0 == shader) { return 0; } + const GrGLInterface* gli = gl.interface(); GrGLint compiled = GR_GL_INIT_ZERO; - GL_CALL(ShaderSource(shader, stringCnt, strings, stringLengths)); - GL_CALL(CompileShader(shader)); - GL_CALL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled)); + GR_GL_CALL(gli, ShaderSource(shader, stringCnt, strings, stringLengths)); + GR_GL_CALL(gli, CompileShader(shader)); + GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled)); if (!compiled) { GrGLint infoLen = GR_GL_INIT_ZERO; - GL_CALL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen)); + GR_GL_CALL(gli, GetShaderiv(shader, 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(GetShaderInfoLog(shader, infoLen+1, - &length, (char*)log.get())); + GR_GL_CALL(gli, GetShaderInfoLog(shader, infoLen+1, + &length, (char*)log.get())); print_shader(stringCnt, strings, stringLengths); GrPrintf("\n%s", log.get()); } GrAssert(!"Shader compilation failed!"); - GL_CALL(DeleteShader(shader)); + GR_GL_CALL(gli, DeleteShader(shader)); return 0; } return shader; @@ -510,8 +551,7 @@ GrGLuint compile_shader(const GrGLContextInfo& gl, GrGLenum type, const SkString } // compiles all the shaders from builder and stores the shader IDs -bool GrGLProgram::compileShaders(const GrGLContextInfo& gl, - const GrGLShaderBuilder& builder) { +bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) { SkString shader; @@ -520,7 +560,7 @@ bool GrGLProgram::compileShaders(const GrGLContextInfo& gl, GrPrintf(shader.c_str()); GrPrintf("\n"); #endif - if (!(fVShaderID = compile_shader(gl, GR_GL_VERTEX_SHADER, shader))) { + if (!(fVShaderID = compile_shader(fContextInfo, GR_GL_VERTEX_SHADER, shader))) { return false; } @@ -530,7 +570,7 @@ bool GrGLProgram::compileShaders(const GrGLContextInfo& gl, GrPrintf(shader.c_str()); GrPrintf("\n"); #endif - if (!(fGShaderID = compile_shader(gl, GR_GL_GEOMETRY_SHADER, shader))) { + if (!(fGShaderID = compile_shader(fContextInfo, GR_GL_GEOMETRY_SHADER, shader))) { return false; } } else { @@ -542,7 +582,7 @@ bool GrGLProgram::compileShaders(const GrGLContextInfo& gl, GrPrintf(shader.c_str()); GrPrintf("\n"); #endif - if (!(fFShaderID = compile_shader(gl, GR_GL_FRAGMENT_SHADER, shader))) { + if (!(fFShaderID = compile_shader(fContextInfo, GR_GL_FRAGMENT_SHADER, shader))) { return false; } @@ -550,11 +590,10 @@ bool GrGLProgram::compileShaders(const GrGLContextInfo& gl, } -bool GrGLProgram::genProgram(const GrGLContextInfo& gl, - const Desc& desc, - GrCustomStage** customStages) { - fDesc = desc; - GrGLShaderBuilder builder(gl); +bool GrGLProgram::genProgram(GrCustomStage** customStages) { + GrAssert(0 == fProgramID); + + GrGLShaderBuilder builder(fContextInfo); const uint32_t& layout = fDesc.fVertexLayout; fUniLocations.reset(); @@ -608,11 +647,11 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, // the dual source output has no canonical var name, have to // declare an output, which is incompatible with gl_FragColor/gl_FragData. bool dualSourceOutputWritten = false; - builder.fHeader.append(GrGetGLSLVersionDecl(gl.binding(), - gl.glslGeneration())); + builder.fHeader.append(GrGetGLSLVersionDecl(fContextInfo.binding(), + fContextInfo.glslGeneration())); GrGLShaderVar colorOutput; - bool isColorDeclared = GrGLSLSetupFSColorOuput(gl.glslGeneration(), + bool isColorDeclared = GrGLSLSetupFSColorOuput(fContextInfo.glslGeneration(), declared_color_output_name(), &colorOutput); if (isColorDeclared) { @@ -657,15 +696,6 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, } /////////////////////////////////////////////////////////////////////////// - // We need to convert generic effect representations to GL-specific - // backends so they can be accesseed in genStageCode() and in subsequent, - // 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) { - fProgramStage[s] = NULL; - } - - /////////////////////////////////////////////////////////////////////////// // compute the final color // if we have color stages string them together, feeding the output color @@ -694,8 +724,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, const GrProgramStageFactory& factory = customStages[s]->getFactory(); fProgramStage[s] = factory.createGLInstance(*customStages[s]); } - this->genStageCode(gl, - s, + this->genStageCode(s, inColor.size() ? inColor.c_str() : NULL, outColor.c_str(), inCoords, @@ -761,7 +790,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { if (!coverageIsZero) { - this->genEdgeCoverage(gl, &inCoverage, &builder); + this->genEdgeCoverage(&inCoverage, &builder); switch (fDesc.fCoverageInput) { case Desc::kSolidWhite_ColorInput: @@ -804,8 +833,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, const GrProgramStageFactory& factory = customStages[s]->getFactory(); fProgramStage[s] = factory.createGLInstance(*customStages[s]); } - this->genStageCode(gl, - s, + this->genStageCode(s, inCoverage.size() ? inCoverage.c_str() : NULL, outCoverage.c_str(), inCoords, @@ -883,30 +911,28 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl, /////////////////////////////////////////////////////////////////////////// // insert GS #if GR_DEBUG - this->genGeometryShader(gl, &builder); + this->genGeometryShader(&builder); #endif /////////////////////////////////////////////////////////////////////////// // compile and setup attribs and unis - if (!this->compileShaders(gl, builder)) { + if (!this->compileShaders(builder)) { return false; } - if (!this->bindOutputsAttribsAndLinkProgram(gl, - texCoordAttrs, + if (!this->bindOutputsAttribsAndLinkProgram(texCoordAttrs, isColorDeclared, dualSourceOutputWritten)) { return false; } - this->getUniformLocationsAndInitCache(gl, builder); + this->getUniformLocationsAndInitCache(builder); return true; } -bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl, - SkString texCoordAttrNames[], +bool GrGLProgram::bindOutputsAttribsAndLinkProgram(SkString texCoordAttrNames[], bool bindColorOut, bool bindDualSrcOut) { GL_CALL_RET(fProgramID, CreateProgram()); @@ -967,8 +993,7 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl, return true; } -void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl, - const GrGLShaderBuilder& builder) { +void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder) { if (kUseUniform == fUniLocations.fViewMatrixUni) { GL_CALL_RET(fUniLocations.fViewMatrixUni, GetUniformLocation(fProgramID, VIEW_MATRIX_NAME)); @@ -1019,7 +1044,7 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl, } if (NULL != fProgramStage[s]) { - fProgramStage[s]->initUniforms(&builder, gl.interface(), fProgramID); + fProgramStage[s]->initUniforms(&builder, fContextInfo.interface(), fProgramID); } } } @@ -1044,8 +1069,7 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl, /////////////////////////////////////////////////////////////////////////////// // Stage code generation -void GrGLProgram::genStageCode(const GrGLContextInfo& gl, - int stageNum, +void GrGLProgram::genStageCode(int stageNum, const char* fsInColor, // NULL means no incoming color const char* fsOutColor, const char* vsInCoord, diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 9381cfbe7d..6b6454d4df 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -41,22 +41,21 @@ public: struct Desc; - GrGLProgram(); + static GrGLProgram* Create(const GrGLContextInfo& gl, + const Desc& desc, + GrCustomStage** customStages); + virtual ~GrGLProgram(); + /** Call to abandon GL objects owned by this program */ + void abandon(); + /** - * This is the heavy initilization routine for building a GLProgram. + * The shader may modify the blend coeffecients. Params are in/out */ - bool genProgram(const GrGLContextInfo& gl, - const Desc& desc, - GrCustomStage** customStages); + void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const; - /** - * The shader may modify the blend coeffecients. Params are in/out - */ - void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const; - - const Desc& getDesc() { return fDesc; } + const Desc& getDesc() { return fDesc; } /** * Attribute indices. These should not overlap. Matrices consume 3 slots. @@ -238,36 +237,42 @@ public: typedef Desc::StageDesc StageDesc; private: + GrGLProgram(const GrGLContextInfo& gl, + const Desc& desc, + GrCustomStage** customStages); + + bool succeeded() const { return 0 != fProgramID; } + + /** + * This is the heavy initilization routine for building a GLProgram. + */ + bool genProgram(GrCustomStage** customStages); + void genInputColor(GrGLShaderBuilder* builder, SkString* inColor); // Determines which uniforms will need to be bound. - void genStageCode(const GrGLContextInfo& gl, - int stageNum, + void genStageCode(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 genGeometryShader(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; + void genEdgeCoverage(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 bindOutputsAttribsAndLinkProgram(SkString texCoordAttrNames[GrDrawState::kMaxTexCoords], bool bindColorOut, bool bindDualSrcOut); // Binds uniforms; initializes cache to invalid values. - void getUniformLocationsAndInitCache(const GrGLContextInfo& gl, - const GrGLShaderBuilder& builder); + void getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder); - bool compileShaders(const GrGLContextInfo& gl, const GrGLShaderBuilder& builder); + bool compileShaders(const GrGLShaderBuilder& builder); const char* adjustInColor(const SkString& inColor) const; @@ -329,6 +334,7 @@ private: GrGLProgramStage* fProgramStage[GrDrawState::kNumStages]; Desc fDesc; + const GrGLContextInfo& fContextInfo; friend class GrGpuGL; // TODO: remove this by adding getters and moving functionality. diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index 5b33e0e47f..fb78ad2973 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -168,7 +168,6 @@ private: class ProgramCache : public ::GrNoncopyable { public: ProgramCache(const GrGLContextInfo& gl); - ~ProgramCache(); void abandon(); GrGLProgram* getProgram(const GrGLProgram::Desc& desc, GrCustomStage** stages); @@ -248,8 +247,6 @@ private: // flushing the scissor after that function is called. void flushScissor(); - static void DeleteProgram(const GrGLInterface* gl, GrGLProgram* programData); - void buildProgram(bool isPoints, BlendOptFlags blendOpts, GrBlendCoeff dstCoeff, diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index 7f982e724d..56a893dc3a 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -20,13 +20,12 @@ GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl) , fGL(gl) { } -GrGpuGL::ProgramCache::~ProgramCache() { +void GrGpuGL::ProgramCache::abandon() { for (int i = 0; i < fCount; ++i) { - GrGpuGL::DeleteProgram(fGL.interface(), fEntries[i].fProgram); + GrAssert(NULL != fEntries[i].fProgram.get()); + fEntries[i].fProgram->abandon(); + fEntries[i].fProgram.reset(NULL); } -} - -void GrGpuGL::ProgramCache::abandon() { fCount = 0; } @@ -36,8 +35,8 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc, GrCustom Entry* entry = fHashCache.find(newEntry.fKey); if (NULL == entry) { - newEntry.fProgram.reset(SkNEW(GrGLProgram)); - if (!newEntry.fProgram->genProgram(fGL, desc, stages)) { + newEntry.fProgram.reset(GrGLProgram::Create(fGL, desc, stages)); + if (NULL == newEntry.fProgram.get()) { return NULL; } if (fCount < kMaxEntries) { @@ -52,7 +51,6 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc, GrCustom } } fHashCache.remove(entry->fKey, entry); - GrGpuGL::DeleteProgram(fGL.interface(), entry->fProgram); } *entry = newEntry; fHashCache.insert(entry->fKey, entry); @@ -69,19 +67,6 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc, GrCustom return entry->fProgram; } -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(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); -} - //////////////////////////////////////////////////////////////////////////////// void GrGpuGL::abandonResources(){ diff --git a/src/gpu/gl/GrGpuGL_unittest.cpp b/src/gpu/gl/GrGpuGL_unittest.cpp index 9dd3e77178..e0aa5b56dc 100644 --- a/src/gpu/gl/GrGpuGL_unittest.cpp +++ b/src/gpu/gl/GrGpuGL_unittest.cpp @@ -319,12 +319,10 @@ bool GrGpuGL::programUnitTest() { GR_STATIC_ASSERT(sizeof(customStages) == GrDrawState::kNumStages * sizeof(GrCustomStage*)); GrCustomStage** stages = reinterpret_cast<GrCustomStage**>(&customStages); - SkAutoTUnref<GrGLProgram> program(SkNEW(GrGLProgram)); - - if (!program->genProgram(this->glContextInfo(), pdesc, stages)) { + SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this->glContextInfo(), pdesc, stages)); + if (NULL == program.get()) { return false; } - DeleteProgram(this->glInterface(), program); } return true; } |