00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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,
00198 i,
00199 RS_NAME_LENGTH,
00200 NULL,
00201 &size,
00202 &gl_type_code,
00203 &name[0]
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
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