//============================== // OvrGazeCursorLocal:: void OvrGazeCursorLocal::Shutdown() { LOG( "OvrGazeCursorLocal::Shutdown" ); DROID_ASSERT( Initialized == true, "GazeCursor" ); for ( int i = 0; i < CURSOR_STATE_MAX; ++i ) { if ( CursorTextureHandle[i] != 0 ) { glDeleteTextures( 1, &CursorTextureHandle[i] ); CursorTextureHandle[i] = 0; } } if ( TimerTextureHandle != 0 ) { glDeleteTextures( 1, & TimerTextureHandle ); TimerTextureHandle = 0; } if ( ColorTableHandle != 0 ) { glDeleteTextures( 1, &ColorTableHandle ); ColorTableHandle = 0; } DeleteProgram( CursorProgram ); DeleteProgram( TimerProgram ); Initialized = false; }
bool GrGLShaderBuilder::finish() { SkASSERT(0 == fOutput.fProgramID); GL_CALL_RET(fOutput.fProgramID, CreateProgram()); if (!fOutput.fProgramID) { return false; } SkTDArray<GrGLuint> shadersToDelete; if (!this->compileAndAttachShaders(fOutput.fProgramID, &shadersToDelete)) { GL_CALL(DeleteProgram(fOutput.fProgramID)); return false; } this->bindProgramLocations(fOutput.fProgramID); if (fUniformManager->isUsingBindUniform()) { fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms); } GL_CALL(LinkProgram(fOutput.fProgramID)); // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. bool checkLinked = !fGpu->ctxInfo().isChromium(); #ifdef SK_DEBUG checkLinked = true; #endif if (checkLinked) { GrGLint linked = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(fOutput.fProgramID, GR_GL_LINK_STATUS, &linked)); if (!linked) { GrGLint infoLen = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(fOutput.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(fOutput.fProgramID, infoLen+1, &length, (char*)log.get())); GrPrintf((char*)log.get()); } SkDEBUGFAIL("Error linking program"); GL_CALL(DeleteProgram(fOutput.fProgramID)); fOutput.fProgramID = 0; return false; } } if (!fUniformManager->isUsingBindUniform()) { fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms); } for (int i = 0; i < shadersToDelete.count(); ++i) { GL_CALL(DeleteShader(shadersToDelete[i])); } return true; }
void EyePostRender::Shutdown() { LOG( "EyePostRender::Shutdown()" ); CalibrationLines.Free(); VignetteSquare.Free(); DeleteProgram( UntexturedMvpProgram ); DeleteProgram( UntexturedScreenSpaceProgram ); }
bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) { SK_TRACE_EVENT0("GrGLShaderBuilder::finish"); GrGLuint programId = 0; GL_CALL_RET(programId, CreateProgram()); if (!programId) { return false; } if (!this->compileAndAttachShaders(programId)) { GL_CALL(DeleteProgram(programId)); return false; } this->bindProgramLocations(programId); GL_CALL(LinkProgram(programId)); // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. bool checkLinked = !fGpu->ctxInfo().isChromium(); #ifdef SK_DEBUG checkLinked = true; #endif if (checkLinked) { GrGLint linked = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programId, GR_GL_LINK_STATUS, &linked)); if (!linked) { GrGLint infoLen = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programId, 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(programId, infoLen+1, &length, (char*)log.get())); GrPrintf((char*)log.get()); } SkDEBUGFAIL("Error linking program"); GL_CALL(DeleteProgram(programId)); return false; } } fUniformManager.getUniformLocations(programId, fUniforms); *outProgramId = programId; return true; }
//================================== // VRMenuMgrLocal::Shutdown // // Shutdown the VRMenu syatem void VRMenuMgrLocal::Shutdown() { if ( !Initialized ) { return; } DeleteProgram( GUIProgramDiffuseOnly ); DeleteProgram( GUIProgramDiffusePlusAdditive ); DeleteProgram( GUIProgramDiffuseComposite ); DeleteProgram( GUIProgramDiffuseColorRamp ); DeleteProgram( GUIProgramDiffuseColorRampTarget ); Initialized = false; }
void Shader::Build() { this->program = glCreateProgram(); for (auto shader : this->shaders) { glAttachShader(this->program, shader); } glLinkProgram(this->program); GLint is_linked = 0; glGetProgramiv(this->program, GL_LINK_STATUS, (int *)&is_linked); if (is_linked == GL_FALSE) { GLint max_length = 0; glGetProgramiv(this->program, GL_INFO_LOG_LENGTH, &max_length); std::vector<GLchar> info_log(max_length); glGetProgramInfoLog(this->program, max_length, &max_length, &info_log[0]); std::copy(info_log.begin(), info_log.end(), std::ostream_iterator<GLchar>(std::cout, "")); DeleteProgram(); return; } for (auto shader : this->shaders) { glDetachShader(this->program, shader); } }
void MediaSurface::Shutdown() { LOG( "MediaSurface::Shutdown()" ); DeleteProgram( CopyMovieProgram ); UnitSquare.Free(); delete AndroidSurfaceTexture; AndroidSurfaceTexture = NULL; if ( Fbo ) { glDeleteFramebuffers( 1, &Fbo ); Fbo = 0; } if ( jni != NULL ) { if ( SurfaceObject != NULL ) { jni->DeleteGlobalRef( SurfaceObject ); SurfaceObject = NULL; } } }
GrGLProgram::~GrGLProgram() { if (fProgramID) { GL_CALL(DeleteProgram(fProgramID)); } for (int i = 0; i < fFragmentProcessors.count(); ++i) { delete fFragmentProcessors[i]; } }
void GLVec4ScalarBench::teardown(const GrGLInterface* gl) { GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0)); GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0)); GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); GR_GL_CALL(gl, DeleteTextures(1, &fFboTextureId)); GR_GL_CALL(gl, DeleteProgram(fProgram)); GR_GL_CALL(gl, DeleteBuffers(1, &fVboId)); }
void GrGpuGLShaders::DeleteProgram(const GrGLInterface* gl, CachedData* programData) { GR_GL_CALL(gl, DeleteShader(programData->fVShaderID)); if (programData->fGShaderID) { GR_GL_CALL(gl, DeleteShader(programData->fGShaderID)); } GR_GL_CALL(gl, DeleteShader(programData->fFShaderID)); GR_GL_CALL(gl, DeleteProgram(programData->fProgramID)); GR_DEBUGCODE(memset(programData, 0, sizeof(*programData));) }
void GLCpuPosInstancedArraysBench::teardown(const GrGLInterface* gl) { GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0)); GR_GL_CALL(gl, BindVertexArray(0)); GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0)); GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); GR_GL_CALL(gl, DeleteTextures(1, &fTexture)); GR_GL_CALL(gl, DeleteProgram(fProgram)); GR_GL_CALL(gl, DeleteBuffers(fBuffers.count(), fBuffers.begin())); GR_GL_CALL(gl, DeleteVertexArrays(1, &fVAO)); fBuffers.reset(); }
void ShaderProgram::CreateProgram() { //delete current program, if any DeleteProgram(); if (m_pFragmentShader && m_pVertexShader) { m_dwProgram = glCreateProgram(); glAttachShader(m_dwProgram, m_pFragmentShader->GetShader()); glAttachShader(m_dwProgram, m_pVertexShader->GetShader()); glLinkProgram(m_dwProgram); } }
void UberShader::ClearCache() { // Form lists of all programs and all shaders vector<ShaderProgram*> progs; vector<Shader*> shaders; for (auto it = code2program.begin(); it != code2program.end(); it++) progs.push_back(it->second); for (auto it = code2shader.begin(); it != code2shader.end(); it++) shaders.push_back(it->second); // Delete everything (programs first, to be safe) for (UINT i = 0; i < progs.size(); i++) DeleteProgram(progs[i]); for (UINT i = 0; i < shaders.size(); i++) CheckedDeleteShader(shaders[i]); }
ImageServer::~ImageServer() { LOG( "-------------------- Shutdown() --------------------" ); // Make sure any outstanding glReadPixels to the PBO on the image server // has actually completed. glFinish(); if ( serverThread ) { pthread_mutex_lock( &StartStopMutex ); // write to the socket to signal shutdown char data; write( ShutdownSocket, &data, 1 ); // also fire the condition, in case it was waiting // on TimeWarp to signal completion ImageServerResponse badResponse; badResponse.Data = NULL; badResponse.Resolution = -1; badResponse.Sequence = -1; Response.SetState( badResponse ); pthread_cond_signal( &ResponseCondition ); LOG( "Waiting on StartStopCondition." ); pthread_cond_wait( &StartStopCondition, &StartStopMutex ); pthread_mutex_unlock( &StartStopMutex ); LOG( "Thread stop acknowledged." ); } // free GL tools if ( UnitSquare.vertexArrayObject ) { UnitSquare.Free(); } if ( ResampleProg.program ) { DeleteProgram( ResampleProg ); } FreeBuffers(); LOG( "-------------------- Shutdown completed --------------------" ); }
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]; } }
bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { GrGLint linked = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); if (!linked) { SkDebugf("Program linking failed.\n"); GrGLint infoLen = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programID, 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(programID, infoLen+1, &length, (char*)log.get())); SkDebugf("%s", (char*)log.get()); } GL_CALL(DeleteProgram(programID)); programID = 0; } return SkToBool(linked); }
bool GrGpuGLShaders::programUnitTest() { GrGLSLGeneration glslGeneration = GetGLSLGeneration(this->glBinding(), this->glInterface()); static const int STAGE_OPTS[] = { 0, StageDesc::kNoPerspective_OptFlagBit, StageDesc::kIdentity_CoordMapping }; static const int IN_CONFIG_FLAGS[] = { StageDesc::kNone_InConfigFlag, StageDesc::kSwapRAndB_InConfigFlag, StageDesc::kSwapRAndB_InConfigFlag | StageDesc::kMulRGBByAlpha_InConfigFlag, StageDesc::kMulRGBByAlpha_InConfigFlag, StageDesc::kSmearAlpha_InConfigFlag, }; GrGLProgram program; ProgramDesc& pdesc = program.fProgramDesc; static const int NUM_TESTS = 512; GrRandom random; for (int t = 0; t < NUM_TESTS; ++t) { #if 0 GrPrintf("\nTest Program %d\n-------------\n", t); static const int stop = -1; if (t == stop) { int breakpointhere = 9; } #endif pdesc.fVertexLayout = 0; pdesc.fEmitsPointSize = random.nextF() > .5f; pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt); pdesc.fColorFilterXfermode = random_int(&random, SkXfermode::kCoeffModesCnt); pdesc.fFirstCoverageStage = random_int(&random, GrDrawState::kNumStages); pdesc.fVertexLayout |= random_bool(&random) ? GrDrawTarget::kCoverage_VertexLayoutBit : 0; #if GR_GL_EXPERIMENTAL_GS pdesc.fExperimentalGS = this->getCaps().fGeometryShaderSupport && random_bool(&random); #endif pdesc.fOutputPM = random_int(&random, ProgramDesc::kOutputPMCnt); bool edgeAA = random_bool(&random); if (edgeAA) { bool vertexEdgeAA = random_bool(&random); if (vertexEdgeAA) { pdesc.fVertexLayout |= GrDrawTarget::kEdge_VertexLayoutBit; if (this->getCaps().fShaderDerivativeSupport) { pdesc.fVertexEdgeType = random_bool(&random) ? GrDrawState::kHairQuad_EdgeType : GrDrawState::kHairLine_EdgeType; } else { pdesc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; } pdesc.fEdgeAANumEdges = 0; } else { pdesc.fEdgeAANumEdges = random_int(&random, 1, this->getMaxEdges()); pdesc.fEdgeAAConcave = random_bool(&random); } } else { pdesc.fEdgeAANumEdges = 0; } if (this->getCaps().fDualSourceBlendingSupport) { pdesc.fDualSrcOutput = random_int(&random, ProgramDesc::kDualSrcOutputCnt); } else { pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; } for (int s = 0; s < GrDrawState::kNumStages; ++s) { // enable the stage? if (random_bool(&random)) { // use separate tex coords? if (random_bool(&random)) { int t = random_int(&random, GrDrawState::kMaxTexCoords); pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t); } else { pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s); } } // use text-formatted verts? if (random_bool(&random)) { pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit; } StageDesc& stage = pdesc.fStages[s]; stage.fOptFlags = STAGE_OPTS[random_int(&random, GR_ARRAY_COUNT(STAGE_OPTS))]; stage.fInConfigFlags = IN_CONFIG_FLAGS[random_int(&random, GR_ARRAY_COUNT(IN_CONFIG_FLAGS))]; stage.fCoordMapping = random_int(&random, StageDesc::kCoordMappingCnt); stage.fFetchMode = random_int(&random, StageDesc::kFetchModeCnt); // convolution shaders don't work with persp tex matrix if (stage.fFetchMode == StageDesc::kConvolution_FetchMode) { stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; } stage.setEnabled(VertexUsesStage(s, pdesc.fVertexLayout)); switch (stage.fFetchMode) { case StageDesc::kSingle_FetchMode: stage.fKernelWidth = 0; break; case StageDesc::kConvolution_FetchMode: stage.fKernelWidth = random_int(&random, 2, 8); stage.fInConfigFlags &= ~StageDesc::kMulRGBByAlpha_InConfigFlag; break; case StageDesc::k2x2_FetchMode: stage.fKernelWidth = 0; stage.fInConfigFlags &= ~StageDesc::kMulRGBByAlpha_InConfigFlag; break; } } CachedData cachedData; if (!program.genProgram(this->glInterface(), glslGeneration, &cachedData)) { return false; } DeleteProgram(this->glInterface(), &cachedData); } return true; }
void GLCpuPosInstancedArraysBench::teardown(const GrGLInterface* gl) { GR_GL_CALL(gl, DeleteProgram(fProgram)); GR_GL_CALL(gl, DeleteBuffers(fBuffers.count(), fBuffers.begin())); GR_GL_CALL(gl, DeleteVertexArrays(1, &fVAO)); }
bool Shader::InitializeShader(string shaderVSFileName, string shaderPSFileName) { const char* shaderBuffer_VS = LoadShaderSourceFile("Shaders/" + shaderVSFileName); const char* shaderBuffer_PS = LoadShaderSourceFile("Shaders/" + shaderPSFileName); if (!shaderBuffer_VS) { cout << "Shader: " << shaderVSFileName << " could not be loaded" << endl; return false; } if (!shaderBuffer_PS) { cout << "Shader: " << shaderVSFileName << " could not be loaded" << endl; return false; } m_vertexID = glCreateShader(GL_VERTEX_SHADER); m_fragID = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(m_vertexID, 1, &shaderBuffer_VS, NULL); glShaderSource(m_fragID, 1, &shaderBuffer_PS, NULL); delete[] shaderBuffer_VS; delete[] shaderBuffer_PS; glCompileShader(m_vertexID); glCompileShader(m_fragID); int status; glGetShaderiv(m_vertexID, GL_COMPILE_STATUS, &status); if (status != 1) { OutputShaderErrorMessage(m_vertexID, (char*)shaderVSFileName.c_str()); return false; } glGetShaderiv(m_fragID, GL_COMPILE_STATUS, &status); if (status != 1) { OutputShaderErrorMessage(m_fragID, (char*)shaderPSFileName.c_str()); return false; } m_programID = glCreateProgram();//set the Program ID to the first element by default glAttachShader(m_programID, m_vertexID); glAttachShader(m_programID, m_fragID); glLinkProgram(m_programID); glGetProgramiv(m_programID, GL_LINK_STATUS, &status); if(status != 1) { // If it did not link then write the syntax error message out to a text file for review. OutputLinkerErrorMessage(m_programID); DeleteProgram(); return false; } return true; }
void GrGpuGLShaders::DeleteProgram(GrGLProgram::CachedData* programData) { GR_GL(DeleteShader(programData->fVShaderID)); GR_GL(DeleteShader(programData->fFShaderID)); GR_GL(DeleteProgram(programData->fProgramID)); GR_DEBUGCODE(memset(programData, 0, sizeof(*programData));) }
void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) { GL_CALL(DeleteProgram(programID)); this->cleanupShaders(shaderIDs); this->cleanupFragmentProcessors(); }
bool Shader::Compile(const std::string &vsData, const std::string &fsData) { DeleteProgram(); std::string defines; GetDefines(defines); std::string vsVersion, vsMain; GetVersionInfo(vsData, vsVersion, vsMain); vsVersion += "#define VERTEX_SHADER\n"; // compile vertex shader unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); if (vertexShader != 0) { const char *sources[3] = { vsVersion.c_str(), defines.c_str(), vsMain.c_str() }; const int counts[3] = { (int)vsVersion.size(), (int)defines.size(), (int)vsMain.size() }; glShaderSource(vertexShader, 3, sources, counts); glCompileShader(vertexShader); GLint status; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { vertexShader = 0; FURYE << m_Name << "'s vertex shader compile failed!"; return false; } } else { FURYE << "Failed to create vertex shader context!"; return false; } std::string fsVersion, fsMain; GetVersionInfo(fsData, fsVersion, fsMain); fsVersion += "#define FRAGMENT_SHADER\n"; // compile fragment shader unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); if (fragmentShader != 0) { const char *sources[3] = { fsVersion.c_str(), defines.c_str(), fsMain.c_str() }; const int counts[3] = { (int)fsVersion.size(), (int)defines.size(), (int)fsMain.size() }; glShaderSource(fragmentShader, 3, sources, counts); glCompileShader(fragmentShader); GLint status; glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { glDeleteShader(vertexShader); vertexShader = fragmentShader = 0; FURYE << m_Name << "'s fragment compile failed!"; return false; } } else { FURYE << "Failed to create fragment shader context!"; return false; } // link to program m_Program = glCreateProgram(); if (m_Program != 0) { glAttachShader(m_Program, vertexShader); glAttachShader(m_Program, fragmentShader); glLinkProgram(m_Program); glDetachShader(m_Program, vertexShader); glDetachShader(m_Program, fragmentShader); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); GLint status; glGetProgramiv(m_Program, GL_LINK_STATUS, &status); if (status != GL_TRUE) { glDeleteProgram(m_Program); m_Program = fragmentShader = vertexShader = 0; FURYE << m_Name << " link failed!"; return false; } } else { FURYE << "Failed to create shader program context!"; return false; } m_Dirty = false; FURYD << m_Name << " compile & link success!"; return true; }
GrGLProgram::~GrGLProgram() { if (fBuilderOutput.fProgramID) { GL_CALL(DeleteProgram(fBuilderOutput.fProgramID)); } }
GrGLProgram::~GrGLProgram() { if (fProgramID) { GL_CALL(DeleteProgram(fProgramID)); } }
void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) { GL_CALL(DeleteProgram(programID)); cleanupShaders(shaderIDs); }
ShaderProgram::~ShaderProgram() { DeleteProgram(); SetFragmentShader(0); SetVertexShader(0); }
void GrGLProgram::genProgram(GrGLProgram::CachedData* programData, const GrDrawTarget* target) const { ShaderCodeSegments segments; const uint32_t& layout = fProgramDesc.fVertexLayout; memset(&programData->fUniLocations, 0, sizeof(UniLocations)); bool haveColor = !(ProgramDesc::kVertexColorAllOnes_OptFlagBit & fProgramDesc.fOptFlags); #if ATTRIBUTE_MATRIX segments.fVSAttrs = "attribute mat3 " VIEW_MATRIX_NAME ";\n"; #else segments.fVSUnis = "uniform mat3 " VIEW_MATRIX_NAME ";\n"; segments.fVSAttrs = ""; #endif segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n"; if (haveColor) { segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n"; segments.fVaryings = "varying vec4 vColor;\n"; } else { segments.fVaryings = ""; } segments.fVSCode = "void main() {\n" "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n" "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n"; if (haveColor) { segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n"; } if (!(fProgramDesc.fOptFlags & ProgramDesc::kNotPoints_OptFlagBit)) { segments.fVSCode += "\tgl_PointSize = 1.0;\n"; } segments.fFSCode = "void main() {\n"; // add texture coordinates that are used to the list of vertex attr decls GrTokenString texCoordAttrs[GrDrawTarget::kMaxTexCoords]; for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) { if (target->VertexUsesTexCoordIdx(t, layout)) { tex_attr_name(t, texCoordAttrs + t); segments.fVSAttrs += "attribute vec2 "; segments.fVSAttrs += texCoordAttrs[t]; segments.fVSAttrs += ";\n"; } } // for each enabled stage figure out what the input coordinates are // and count the number of stages in use. const char* stageInCoords[GrDrawTarget::kNumStages]; int numActiveStages = 0; for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { if (fProgramDesc.fStages[s].fEnabled) { if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) { stageInCoords[s] = POS_ATTR_NAME; } else { int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout); // we better have input tex coordinates if stage is enabled. GrAssert(tcIdx >= 0); GrAssert(texCoordAttrs[tcIdx].length()); stageInCoords[s] = texCoordAttrs[tcIdx].cstr(); } ++numActiveStages; } } GrTokenString inColor = "vColor"; // if we have active stages string them together, feeding the output color // of each to the next and generating code for each stage. if (numActiveStages) { int currActiveStage = 0; for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { if (fProgramDesc.fStages[s].fEnabled) { GrTokenString outColor; if (currActiveStage < (numActiveStages - 1)) { outColor = "color"; outColor.appendInt(currActiveStage); segments.fFSCode += "\tvec4 "; segments.fFSCode += outColor; segments.fFSCode += ";\n"; } else { outColor = "gl_FragColor"; } genStageCode(s, fProgramDesc.fStages[s], haveColor ? inColor.cstr() : NULL, outColor.cstr(), stageInCoords[s], &segments, &programData->fUniLocations.fStages[s]); ++currActiveStage; inColor = outColor; haveColor = true; } } } else { segments.fFSCode += "\tgl_FragColor = "; if (haveColor) { segments.fFSCode += inColor; } else { segments.fFSCode += "vec4(1,1,1,1)"; } segments.fFSCode += ";\n"; } segments.fFSCode += "}\n"; segments.fVSCode += "}\n"; const char* strings[4]; int lengths[4]; int stringCnt = 0; if (segments.fVSUnis.length()) { strings[stringCnt] = segments.fVSUnis.cstr(); lengths[stringCnt] = segments.fVSUnis.length(); ++stringCnt; } if (segments.fVSAttrs.length()) { strings[stringCnt] = segments.fVSAttrs.cstr(); lengths[stringCnt] = segments.fVSAttrs.length(); ++stringCnt; } if (segments.fVaryings.length()) { strings[stringCnt] = segments.fVaryings.cstr(); lengths[stringCnt] = segments.fVaryings.length(); ++stringCnt; } GrAssert(segments.fVSCode.length()); strings[stringCnt] = segments.fVSCode.cstr(); lengths[stringCnt] = segments.fVSCode.length(); ++stringCnt; #if PRINT_SHADERS GrPrintf("%s%s%s%s\n", segments.fVSUnis.cstr(), segments.fVSAttrs.cstr(), segments.fVaryings.cstr(), segments.fVSCode.cstr()); #endif programData->fVShaderID = CompileShader(GR_GL_VERTEX_SHADER, stringCnt, strings, lengths); stringCnt = 0; if (strlen(GrShaderPrecision()) > 1) { strings[stringCnt] = GrShaderPrecision(); lengths[stringCnt] = strlen(GrShaderPrecision()); ++stringCnt; } if (segments.fFSUnis.length()) { strings[stringCnt] = segments.fFSUnis.cstr(); lengths[stringCnt] = segments.fFSUnis.length(); ++stringCnt; } if (segments.fVaryings.length()) { strings[stringCnt] = segments.fVaryings.cstr(); lengths[stringCnt] = segments.fVaryings.length(); ++stringCnt; } GrAssert(segments.fFSCode.length()); strings[stringCnt] = segments.fFSCode.cstr(); lengths[stringCnt] = segments.fFSCode.length(); ++stringCnt; #if PRINT_SHADERS GrPrintf("%s%s%s%s\n", GR_SHADER_PRECISION, segments.fFSUnis.cstr(), segments.fVaryings.cstr(), segments.fFSCode.cstr()); #endif programData->fFShaderID = CompileShader(GR_GL_FRAGMENT_SHADER, stringCnt, strings, lengths); programData->fProgramID = GR_GL(CreateProgram()); const GrGLint& progID = programData->fProgramID; GR_GL(AttachShader(progID, programData->fVShaderID)); GR_GL(AttachShader(progID, programData->fFShaderID)); // Bind the attrib locations to same values for all shaders GR_GL(BindAttribLocation(progID, POS_ATTR_LOCATION, POS_ATTR_NAME)); for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) { if (texCoordAttrs[t].length()) { GR_GL(BindAttribLocation(progID, TEX_ATTR_LOCATION(t), texCoordAttrs[t].cstr())); } } #if ATTRIBUTE_MATRIX // set unis to a bogus value so that checks against -1 before // flushing will pass. GR_GL(BindAttribLocation(progID, VIEWMAT_ATTR_LOCATION, VIEW_MATRIX_NAME)); program->fUniLocations.fViewMatrixUni = BOGUS_MATRIX_UNI_LOCATION; for (int s = 0; s < kNumStages; ++s) { if (fProgramDesc.fStages[s].fEnabled) { GrStringBuilder matName; tex_matrix_name(s, &matName); GR_GL(BindAttribLocation(progID, TEXMAT_ATTR_LOCATION(s), matName.cstr())); program->fUniLocations.fStages[s].fTextureMatrixUni = BOGUS_MATRIX_UNI_LOCATION; } } #endif GR_GL(BindAttribLocation(progID, COL_ATTR_LOCATION, COL_ATTR_NAME)); GR_GL(LinkProgram(progID)); GrGLint linked = GR_GL_INIT_ZERO; GR_GL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked)); if (!linked) { GrGLint infoLen = GR_GL_INIT_ZERO; GR_GL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen)); GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { GR_GL(GetProgramInfoLog(progID, infoLen+1, NULL, (char*)log.get())); GrPrintf((char*)log.get()); } GrAssert(!"Error linking program"); GR_GL(DeleteProgram(progID)); programData->fProgramID = 0; return; } // Get uniform locations #if !ATTRIBUTE_MATRIX programData->fUniLocations.fViewMatrixUni = GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME)); GrAssert(-1 != programData->fUniLocations.fViewMatrixUni); #endif for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { StageUniLocations& locations = programData->fUniLocations.fStages[s]; if (fProgramDesc.fStages[s].fEnabled) { #if !ATTRIBUTE_MATRIX if (locations.fTextureMatrixUni) { GrTokenString texMName; tex_matrix_name(s, &texMName); locations.fTextureMatrixUni = GR_GL(GetUniformLocation( progID, texMName.cstr())); GrAssert(-1 != locations.fTextureMatrixUni); } else { locations.fTextureMatrixUni = -1; } #endif if (locations.fSamplerUni) { GrTokenString samplerName; sampler_name(s, &samplerName); locations.fSamplerUni = GR_GL(GetUniformLocation( progID, samplerName.cstr())); GrAssert(-1 != locations.fSamplerUni); } else { locations.fSamplerUni = -1; } if (locations.fRadial2Uni) { GrTokenString radial2ParamName; radial2_param_name(s, &radial2ParamName); locations.fRadial2Uni = GR_GL(GetUniformLocation( progID, radial2ParamName.cstr())); GrAssert(-1 != locations.fRadial2Uni); } else { locations.fRadial2Uni = -1; } } else { locations.fSamplerUni = -1; locations.fRadial2Uni = -1; locations.fTextureMatrixUni = -1; } } GR_GL(UseProgram(progID)); // init sampler unis and set bogus values for state tracking for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { if (-1 != programData->fUniLocations.fStages[s].fSamplerUni) { GR_GL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s)); } programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix(); programData->fRadial2CenterX1[s] = GR_ScalarMax; programData->fRadial2Radius0[s] = -GR_ScalarMax; } programData->fViewMatrix = GrMatrix::InvalidMatrix(); }
Shader::~Shader() { DeleteProgram(); }
GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program) { CONTEXT_EXEC(DeleteProgram(program)); }
bool GrGpuGLShaders::programUnitTest() { GrGLSLGeneration glslGeneration = GrGetGLSLGeneration(this->glBinding(), this->glInterface()); static const int STAGE_OPTS[] = { 0, StageDesc::kNoPerspective_OptFlagBit, StageDesc::kIdentity_CoordMapping }; static const int IN_CONFIG_FLAGS[] = { StageDesc::kNone_InConfigFlag, StageDesc::kSwapRAndB_InConfigFlag, StageDesc::kSwapRAndB_InConfigFlag | StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag, StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag, StageDesc::kSmearAlpha_InConfigFlag, StageDesc::kSmearRed_InConfigFlag, }; GrGLProgram program; ProgramDesc& pdesc = program.fProgramDesc; static const int NUM_TESTS = 512; GrRandom random; for (int t = 0; t < NUM_TESTS; ++t) { #if 0 GrPrintf("\nTest Program %d\n-------------\n", t); static const int stop = -1; if (t == stop) { int breakpointhere = 9; } #endif pdesc.fVertexLayout = 0; pdesc.fEmitsPointSize = random.nextF() > .5f; pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt); pdesc.fCoverageInput = random_int(&random, ProgramDesc::kColorInputCnt); pdesc.fColorFilterXfermode = random_int(&random, SkXfermode::kCoeffModesCnt); pdesc.fFirstCoverageStage = random_int(&random, GrDrawState::kNumStages); pdesc.fVertexLayout |= random_bool(&random) ? GrDrawTarget::kCoverage_VertexLayoutBit : 0; #if GR_GL_EXPERIMENTAL_GS pdesc.fExperimentalGS = this->getCaps().fGeometryShaderSupport && random_bool(&random); #endif pdesc.fOutputConfig = random_int(&random, ProgramDesc::kOutputConfigCnt); bool edgeAA = random_bool(&random); if (edgeAA) { pdesc.fVertexLayout |= GrDrawTarget::kEdge_VertexLayoutBit; if (this->getCaps().fShaderDerivativeSupport) { pdesc.fVertexEdgeType = (GrDrawState::VertexEdgeType) random_int(&random, GrDrawState::kVertexEdgeTypeCnt); } else { pdesc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; } } else { } pdesc.fColorMatrixEnabled = random_bool(&random); if (this->getCaps().fDualSourceBlendingSupport) { pdesc.fDualSrcOutput = random_int(&random, ProgramDesc::kDualSrcOutputCnt); } else { pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; } GrCustomStage* customStages[GrDrawState::kNumStages]; for (int s = 0; s < GrDrawState::kNumStages; ++s) { // enable the stage? if (random_bool(&random)) { // use separate tex coords? if (random_bool(&random)) { int t = random_int(&random, GrDrawState::kMaxTexCoords); pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t); } else { pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s); } } // use text-formatted verts? if (random_bool(&random)) { pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit; } StageDesc& stage = pdesc.fStages[s]; stage.fCustomStageKey = 0; customStages[s] = NULL; stage.fOptFlags = STAGE_OPTS[random_int(&random, GR_ARRAY_COUNT(STAGE_OPTS))]; stage.fInConfigFlags = IN_CONFIG_FLAGS[random_int(&random, GR_ARRAY_COUNT(IN_CONFIG_FLAGS))]; stage.fCoordMapping = random_int(&random, StageDesc::kCoordMappingCnt); stage.fFetchMode = random_int(&random, StageDesc::kFetchModeCnt); // convolution shaders don't work with persp tex matrix if (stage.fFetchMode == StageDesc::kConvolution_FetchMode || stage.fFetchMode == StageDesc::kDilate_FetchMode || stage.fFetchMode == StageDesc::kErode_FetchMode) { stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; } stage.setEnabled(VertexUsesStage(s, pdesc.fVertexLayout)); static const uint32_t kMulByAlphaMask = StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag | StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag; switch (stage.fFetchMode) { case StageDesc::kSingle_FetchMode: stage.fKernelWidth = 0; break; case StageDesc::kConvolution_FetchMode: case StageDesc::kDilate_FetchMode: case StageDesc::kErode_FetchMode: stage.fKernelWidth = random_int(&random, 2, 8); stage.fInConfigFlags &= ~kMulByAlphaMask; break; case StageDesc::k2x2_FetchMode: stage.fKernelWidth = 0; stage.fInConfigFlags &= ~kMulByAlphaMask; break; } // TODO: is there a more elegant way to express this? if (stage.fFetchMode == StageDesc::kConvolution_FetchMode) { int direction = random_int(&random, 2); float kernel[MAX_KERNEL_WIDTH]; for (int i = 0; i < stage.fKernelWidth; i++) { kernel[i] = random.nextF(); } customStages[s] = new GrConvolutionEffect( (GrSamplerState::FilterDirection)direction, stage.fKernelWidth, kernel); stage.fCustomStageKey = customStages[s]->getFactory()->stageKey(customStages[s]); } } CachedData cachedData; if (!program.genProgram(this->glContextInfo(), customStages, &cachedData)) { return false; } DeleteProgram(this->glInterface(), &cachedData); } return true; }