program.cpp

Go to the documentation of this file.
00001 /*
00002     RenderStack  Support library for OpenGL 3+
00003     Copyright (C) 2010  Timo Suoranta
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Lesser General Public
00007     License as published by the Free Software Foundation; either
00008     version 2.1 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Lesser General Public License for more details.
00014 
00015     You should have received a copy of the GNU Lesser General Public
00016     License along with this library; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 */
00019 
00027 #include "renderstack/program.hpp"
00028 #include "renderstack/rs_log.h"
00029 #include "renderstack/rs_gl.h"
00030 
00031 namespace renderstack {
00032 
00033 void program_attribute::debug() const
00034 {
00035     ::rs_log(
00036         "attribute %s type %s size %d slot %d\n",
00037         &m_name[0],
00038         ::rs_gl_enum_string(m_gl_type_code),
00039         m_size,
00040         m_gl_slot
00041     );
00042 }
00043 
00044 void shader::print_source() const
00045 {
00046     int         line = 1;
00047     const char  *head = m_source.c_str();
00048     char        c;
00049 
00050     ::rs_log("%3d: ", line);
00051     for(;;)
00052     {
00053         c = *head;
00054         ++head;
00055         if(c == 0)
00056         {
00057             break;
00058         }
00059         if(c == '\n')
00060         {
00061             ++line;
00062             ::rs_log("\n%3d: ", line);
00063             continue;
00064         }
00065         ::rs_log("%c", c);
00066     }
00067 }
00068 
00069 shader::shader(
00070     int                 shader_type,
00071     std::string const   &source
00072 )
00073 :   m_source(source)
00074 ,   m_gl_shader_object((int)(~0))
00075 {
00076     int         status;
00077     const char  *source0     = m_source.c_str();
00078     const char  **source_ptr = &source0;
00079 
00080     m_gl_shader_object = ::rs_gl_create_shader(shader_type);
00081 
00082     ::rs_gl_shader_source (m_gl_shader_object, 1, source_ptr, NULL);
00083     ::rs_gl_compile_shader(m_gl_shader_object);
00084     ::rs_gl_get_shader_iv (m_gl_shader_object, GL_COMPILE_STATUS, &status);
00085 
00086     if(status == GL_FALSE)
00087     {
00088         char      info_log[4096];
00089         ::GLsizei length = 0;
00090 
00091         ::memset(&info_log[0], 0, 4096);
00092 
00093         ::rs_gl_get_shader_info_log(m_gl_shader_object, 4096, &length, &info_log[0]);
00094         ::rs_gl_delete_shader      (m_gl_shader_object);
00095 
00096         ::rs_log("shader compilation failed:\n%s", info_log);
00097 
00098         print_source();
00099         ::rs_log("\nerrors\n");
00100     }
00101 }
00102 
00103 void program::make_shader(
00104     int                shader_type,
00105     std::string const &source
00106 )
00107 {
00108     class shader shader(shader_type, source);
00109     ::rs_gl_attach_shader(m_gl_program_object, shader.gl_shader_object());
00110 
00111     /*  calls copy constructor  */ 
00112     m_shaders.push_back(shader);
00113 }
00114 
00115 program::program()
00116 :   m_mesh_mode(mesh_mode_polygon_fill)
00117 ,   m_gl_program_object((int)(~0))
00118 {
00119     m_gl_program_object = (int)(~0);
00120 }
00121 
00122 program::program(
00123     std::string const   &vertex_shader_source,
00124     std::string const   &fragment_shader_source,
00125     enum mesh_mode      mode
00126 )
00127 :   m_mesh_mode(mode)
00128 ,   m_gl_program_object((int)(~0))
00129 {
00130     create();
00131     make_shader(GL_VERTEX_SHADER,    vertex_shader_source);
00132     make_shader(GL_FRAGMENT_SHADER,  fragment_shader_source);
00133     link();
00134 }
00135 
00136 void program::set(
00137     std::string const &vertex_shader, 
00138     std::string const &fragment_shader, 
00139     enum mesh_mode mode
00140 )
00141 {
00142     m_mesh_mode = mode;
00143     create();
00144     make_shader(GL_VERTEX_SHADER,    vertex_shader);
00145     make_shader(GL_FRAGMENT_SHADER,  fragment_shader);
00146     link();
00147 }
00148 
00149 void program::create()
00150 {
00151     ::GLboolean is_program = ::rs_gl_is_program(m_gl_program_object);
00152     if(is_program != GL_FALSE)
00153     {
00154         ::rs_gl_delete_program(m_gl_program_object);
00155     }
00156     m_gl_program_object = ::rs_gl_create_program();
00157 }
00158 
00159 void program::link()
00160 {
00161     int link_status;
00162     ::rs_gl_link_program  (m_gl_program_object);
00163     ::rs_gl_get_program_iv(m_gl_program_object, GL_LINK_STATUS, &link_status);
00164 
00165     if(link_status == GL_FALSE)
00166     {
00167         char      info_log[4096];
00168         ::GLsizei length = 0;
00169 
00170         ::memset(&info_log[0], 0, 4096);
00171 
00172         ::rs_gl_get_program_info_log(m_gl_program_object, 4096, &length, &info_log[0]);
00173         ::rs_gl_delete_program(m_gl_program_object);
00174 
00175         ::rs_log("program linking failed:\n%s", info_log);
00176     }
00177     ::rs_gl_use_program(m_gl_program_object);
00178     map_attributes();
00179     map_uniforms();
00180 }
00181 
00182 void program::map_attributes()
00183 {
00184     int i;
00185 
00186     int attribute_count = 0;
00187 
00188     ::rs_gl_get_program_iv(m_gl_program_object, GL_ACTIVE_ATTRIBUTES, &attribute_count);
00189 
00190     for(i = 0; i < attribute_count; ++i)
00191     {
00192         ::GLint   size;
00193         ::GLenum  gl_type_code;
00194         ::GLchar  name[RS_NAME_LENGTH];
00195 
00196         ::rs_gl_get_active_attrib(
00197             m_gl_program_object,    /*  GLuint  program  */ 
00198             i,                      /*  GLuint  index    */ 
00199             RS_NAME_LENGTH,         /*  GLsizei bufSize  */ 
00200             NULL,                   /*  GLsizei *length  */ 
00201             &size,                  /*  GLint   *size    */ 
00202             &gl_type_code,          /*  GLenum  *type    */ 
00203             &name[0]                /*  GLchar  *name    */ 
00204         );
00205 
00206         ::GLint gl_slot = ::rs_gl_get_attrib_location(m_gl_program_object, &name[0]);
00207 
00208         program_attribute attribute(name, gl_slot, size, gl_type_code);
00209 
00210         /*  calls copy constructor  */ 
00211         m_attributes.push_back(attribute);
00212     }
00213 }
00214 
00215 void program::map_uniforms()
00216 {
00217     int uniform_count = 0;
00218 
00219     ::rs_gl_get_program_iv(m_gl_program_object, GL_ACTIVE_UNIFORMS, &uniform_count);
00220 
00221     for(int i = 0; i < uniform_count; ++i)
00222     {
00223         ::GLint   size;
00224         ::GLenum  gl_type_code;
00225         ::GLchar  name[RS_NAME_LENGTH];
00226 
00227         ::rs_gl_get_active_uniform(
00228             m_gl_program_object, 
00229             i, 
00230             RS_NAME_LENGTH, 
00231             NULL, 
00232             &size, 
00233             &gl_type_code, 
00234             &name[0]
00235         );
00236 
00237         ::GLint gl_slot = ::rs_gl_get_uniform_location(m_gl_program_object, &name[0]);
00238 
00239         class uniform uniform(name, gl_slot, size, gl_type_code);
00240 
00241         m_uniforms.push_back(uniform);
00242     }
00243 }
00244 
00245 void program::use() const
00246 {
00247     ::rs_gl_use_program(m_gl_program_object);
00248 }
00249 
00250 bool program::has_attribute(std::string const &name) const
00251 {
00252     for(
00253         std::vector<program_attribute>::const_iterator i = m_attributes.begin(); 
00254         i != m_attributes.end();
00255         ++i
00256     )
00257     {
00258         program_attribute const &attribute = *i;
00259         int diff = attribute.name().compare(name);
00260 
00261         if(diff == 0)
00262         {
00263             return true;
00264         }
00265     }
00266 
00267     return false;
00268 }
00269 
00270 program_attribute const &program::attribute(std::string const &name) const
00271 {
00272     for(
00273         std::vector<program_attribute>::const_iterator i = m_attributes.begin(); 
00274         i != m_attributes.end();
00275         ++i
00276     )
00277     {
00278         program_attribute const &attribute = *i;
00279         int diff = attribute.name().compare(name);
00280 
00281         if(diff == 0)
00282         {
00283             return attribute;
00284         }
00285     }
00286 
00287     throw program_attribute_not_found_exception();
00288 }
00289 
00290 program_attribute &program::attribute(std::string const &name)
00291 {
00292     for(
00293         std::vector<program_attribute>::iterator i = m_attributes.begin(); 
00294         i != m_attributes.end();
00295         ++i
00296     )
00297     {
00298         program_attribute &attribute = *i;
00299         int diff = attribute.name().compare(name);
00300 
00301         if(diff == 0)
00302         {
00303             return attribute;
00304         }
00305     }
00306 
00307     throw program_attribute_not_found_exception();
00308 }
00309 
00310 bool program::has_uniform(std::string const &name) const
00311 {
00312     for(
00313         std::vector<class uniform>::const_iterator i = m_uniforms.begin(); 
00314         i != m_uniforms.end();
00315         ++i
00316     )
00317     {
00318         class uniform const& uniform = *i;
00319         int diff = uniform.name().compare(name);
00320 
00321         if(diff == 0)
00322         {
00323             return true;
00324         }
00325     }
00326 
00327     return false;
00328 }
00329 
00330 uniform const &program::uniform(std::string const &name) const
00331 {
00332     for(
00333         std::vector<class uniform>::const_iterator i = m_uniforms.begin(); 
00334         i != m_uniforms.end();
00335         ++i
00336     )
00337     {
00338         class uniform const &uniform = *i;
00339         int diff = uniform.name().compare(name);
00340 
00341         if(diff == 0)
00342         {
00343             return uniform;
00344         }
00345     }
00346 
00347     throw uniform_not_found_exception();
00348 }
00349 
00350 uniform &program::uniform(std::string const &name)
00351 {
00352     for(
00353         std::vector<class uniform>::iterator i = m_uniforms.begin(); 
00354         i != m_uniforms.end();
00355         ++i
00356     )
00357     {
00358         class uniform &uniform = *i;
00359         int diff = uniform.name().compare(name);
00360 
00361         if(diff == 0)
00362         {
00363             return uniform;
00364         }
00365     }
00366 
00367     throw uniform_not_found_exception();
00368 }
00369 
00370 }
00371 
Generated on Sun Apr 11 12:23:08 2010 for RenderStack by  doxygen 1.6.3