X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogram.cpp;h=d8827ab5d0f5f095fed0d53424571aff7147f472;hp=111cf64b1d31886e3d33cf831d89c01642a18a6e;hb=HEAD;hpb=ee377487a2853046085e91fa41c62ea42066d168 diff --git a/source/program.cpp b/source/program.cpp deleted file mode 100644 index 111cf64b..00000000 --- a/source/program.cpp +++ /dev/null @@ -1,325 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "buffer.h" -#include "error.h" -#include "program.h" -#include "shader.h" - -using namespace std; - -namespace Msp { -namespace GL { - -Program::Program() -{ - init(); -} - -Program::Program(const ProgramBuilder::StandardFeatures &features) -{ - init(); - - ProgramBuilder builder(features); - builder.add_shaders(*this); - if(!features.transform) - link(); -} - -Program::Program(const string &vert, const string &frag) -{ - init(); - - attach_shader_owned(new VertexShader(vert)); - attach_shader_owned(new FragmentShader(frag)); - link(); -} - -void Program::init() -{ - static Require _req(ARB_shader_objects); - - linked = false; - id = glCreateProgram(); -} - -Program::~Program() -{ - for(ShaderList::iterator i=owned_data.begin(); i!=owned_data.end(); ++i) - delete *i; - glDeleteProgram(id); -} - -void Program::attach_shader(Shader &shader) -{ - if(find(shaders.begin(), shaders.end(), &shader)==shaders.end()) - { - glAttachShader(id, shader.get_id()); - shaders.push_back(&shader); - } -} - -void Program::attach_shader_owned(Shader *shader) -{ - attach_shader(*shader); - if(find(owned_data.begin(), owned_data.end(), shader)==owned_data.end()) - owned_data.push_back(shader); -} - -void Program::detach_shader(Shader &shader) -{ - ShaderList::iterator i = remove(shaders.begin(), shaders.end(), &shader); - if(i!=shaders.end()) - { - shaders.erase(i, shaders.end()); - glDetachShader(id, shader.get_id()); - } -} - -void Program::bind_attribute(unsigned index, const string &name) -{ - static Require _req(ARB_vertex_shader); - glBindAttribLocation(id, index, name.c_str()); -} - -void Program::link() -{ - for(ShaderList::iterator i=shaders.begin(); i!=shaders.end(); ++i) - if(!(*i)->is_compiled()) - (*i)->compile(); - - uniforms.clear(); - - glLinkProgram(id); - int value; - glGetProgramiv(id, GL_LINK_STATUS, &value); - if(!(linked = value)) - throw compile_error(get_info_log()); - - int count; - glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &count); - vector uniforms_by_index(count); - for(int i=0; i3 && !strcmp(name+len-3, "[0]")) - name[len-3] = 0; - - UniformInfo &info = uniforms[name]; - info.block = 0; - info.name = name; - info.size = size; - info.array_stride = 0; - info.matrix_stride = 0; - info.type = type; - uniforms_by_index[i] = &info; - } - } - - if(ARB_uniform_buffer_object) - { - glGetProgramiv(id, GL_ACTIVE_UNIFORM_BLOCKS, &count); - for(int i=0; i indices(value); - glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, &indices[0]); - for(vector::iterator j=indices.begin(); j!=indices.end(); ++j) - { - if(!uniforms_by_index[*j]) - throw logic_error("Program::link"); - info.uniforms.push_back(uniforms_by_index[*j]); - uniforms_by_index[*j]->block = &info; - } - - vector indices2(indices.begin(), indices.end()); - vector values(indices.size()); - glGetActiveUniformsiv(id, indices.size(), &indices2[0], GL_UNIFORM_OFFSET, &values[0]); - for(unsigned j=0; jlocation = values[j]; - - indices2.clear(); - for(vector::iterator j=indices.begin(); j!=indices.end(); ++j) - if(uniforms_by_index[*j]->size>1) - indices2.push_back(*j); - if(!indices2.empty()) - { - glGetActiveUniformsiv(id, indices2.size(), &indices2[0], GL_UNIFORM_ARRAY_STRIDE, &values[0]); - for(unsigned j=0; jarray_stride = values[j]; - } - - indices2.clear(); - for(vector::iterator j=indices.begin(); j!=indices.end(); ++j) - { - GLenum t = uniforms_by_index[*j]->type; - if(t==GL_FLOAT_MAT4 || t==GL_FLOAT_MAT3 || t==GL_FLOAT_MAT2 || - t==GL_FLOAT_MAT2x3 || t==GL_FLOAT_MAT2x4 || t==GL_FLOAT_MAT3x2 || - t==GL_FLOAT_MAT3x4 || t==GL_FLOAT_MAT4x2 || t==GL_FLOAT_MAT4x3) - indices2.push_back(*j); - } - if(!indices2.empty()) - { - glGetActiveUniformsiv(id, indices2.size(), &indices2[0], GL_UNIFORM_MATRIX_STRIDE, &values[0]); - for(unsigned j=0; jmatrix_stride = values[j]; - } - - sort(info.uniforms.begin(), info.uniforms.end(), uniform_location_compare); - info.layout_hash = compute_layout_hash(info.uniforms); - info.bind_point = info.layout_hash%BufferRange::get_n_uniform_buffer_bindings(); - glUniformBlockBinding(id, i, info.bind_point); - } - } - - vector blockless_uniforms; - for(UniformMap::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) - if(!i->second.block) - { - i->second.location = glGetUniformLocation(id, i->second.name.c_str()); - blockless_uniforms.push_back(&i->second); - } - - uniform_layout_hash = compute_layout_hash(blockless_uniforms); -} - -unsigned Program::compute_layout_hash(const vector &uniforms) -{ - string layout_descriptor; - for(vector::const_iterator i = uniforms.begin(); i!=uniforms.end(); ++i) - layout_descriptor += format("%d:%s:%x:%d\n", (*i)->location, (*i)->name, (*i)->type, (*i)->size); - return hash32(layout_descriptor); -} - -bool Program::uniform_location_compare(const UniformInfo *uni1, const UniformInfo *uni2) -{ - return uni1->locationlocation; -} - -string Program::get_info_log() const -{ - GLsizei len = 0; - glGetProgramiv(id, GL_INFO_LOG_LENGTH, &len); - char *buf = new char[len+1]; - glGetProgramInfoLog(id, len+1, &len, buf); - string log(buf, len); - delete[] buf; - return log; -} - -const Program::UniformBlockInfo &Program::get_uniform_block_info(const string &name) const -{ - return get_item(uniform_blocks, name); -} - -const Program::UniformInfo &Program::get_uniform_info(const string &name) const -{ - return get_item(uniforms, name); -} - -int Program::get_uniform_location(const string &n) const -{ - UniformMap::const_iterator i = uniforms.find(n); - if(i==uniforms.end()) - { - if(n[n.size()-1]==']') - { - string::size_type open_bracket = n.rfind('['); - if(open_bracket!=string::npos) - { - /* The requested name looks like an array. glGetActiveUniform only - gives us the first element of the array, so try to look that up and - add an offset. */ - unsigned offset = lexical_cast(n.substr(open_bracket+1, n.size()-2-open_bracket)); - i = uniforms.find(n.substr(0, open_bracket)); - if(i!=uniforms.end() && !i->second.block && offsetsecond.size) - return i->second.location+offset; - } - } - return -1; - } - - return i->second.block ? -1 : i->second.location; -} - -void Program::bind() const -{ - if(!linked) - throw invalid_operation("Program::bind"); - - if(!set_current(this)) - return; - - glUseProgram(id); -} - -void Program::unbind() -{ - if(!set_current(0)) - return; - - glUseProgram(0); -} - - -Program::Loader::Loader(Program &p): - DataFile::ObjectLoader(p) -{ - add("attribute", &Loader::attribute); - add("fragment_shader", &Loader::fragment_shader); - add("standard", &Loader::standard); - add("vertex_shader", &Loader::vertex_shader); -} - -void Program::Loader::finish() -{ - obj.link(); -} - -void Program::Loader::attribute(unsigned i, const string &n) -{ - obj.bind_attribute(i, n); -} - -void Program::Loader::fragment_shader(const string &src) -{ - obj.attach_shader_owned(new FragmentShader(src)); -} - -void Program::Loader::standard() -{ - ProgramBuilder::StandardFeatures feat; - load_sub(feat); - ProgramBuilder builder(feat); - builder.add_shaders(obj); -} - -void Program::Loader::vertex_shader(const string &src) -{ - obj.attach_shader_owned(new VertexShader(src)); -} - -} // namespace GL -} // namespace Msp