00001 #ifndef GLW_PROGRAM_H
00002 #define GLW_PROGRAM_H
00003
00004 #include <memory.h>
00005
00006 #include <string>
00007 #include <vector>
00008 #include <map>
00009
00010 #include "./vertexshader.h"
00011 #include "./geometryshader.h"
00012 #include "./fragmentshader.h"
00013
00014 namespace glw
00015 {
00016
00017 typedef std::vector<ShaderHandle> ShaderHandleVector;
00018
00019 class VertexAttributeBinding
00020 {
00021 public:
00022
00023 typedef void BaseType;
00024 typedef VertexAttributeBinding ThisType;
00025
00026 typedef std::map<std::string, GLuint> Map;
00027 typedef Map::const_iterator ConstIterator;
00028 typedef Map::iterator Iterator;
00029 typedef Map::value_type Value;
00030
00031 Map bindings;
00032
00033 VertexAttributeBinding(void)
00034 {
00035 this->clear();
00036 }
00037
00038 void clear(void)
00039 {
00040 this->bindings.clear();
00041 }
00042
00043 GLuint operator [] (const std::string & attributeName) const
00044 {
00045 return this->bindings.find(attributeName)->second;
00046 }
00047
00048 GLuint & operator [] (const std::string & attributeName)
00049 {
00050 return this->bindings[attributeName];
00051 }
00052 };
00053
00054 class GeometryStage
00055 {
00056 public:
00057
00058 typedef void BaseType;
00059 typedef GeometryStage ThisType;
00060
00061
00062
00063
00064
00065
00066
00067 GeometryStage(void)
00068 {
00069 this->clear();
00070 }
00071
00072 void clear(void)
00073 {
00074
00075
00076
00077
00078
00079 }
00080 };
00081
00082 class TransformFeedbackStream
00083 {
00084 public:
00085
00086 typedef void BaseType;
00087 typedef TransformFeedbackStream ThisType;
00088
00089 typedef std::vector<std::string> VaryingVector;
00090
00091 VaryingVector varyings;
00092 GLenum bufferMode;
00093
00094 TransformFeedbackStream(void)
00095 {
00096 this->clear();
00097 }
00098
00099 void clear(void)
00100 {
00101 this->varyings.clear();
00102 this->bufferMode = GL_INTERLEAVED_ATTRIBS;
00103 }
00104 };
00105
00106 class RasterizerSettings
00107 {
00108 public:
00109
00110 typedef void BaseType;
00111 typedef RasterizerSettings ThisType;
00112
00113 enum RasterizerExecution
00114 {
00115 DontCare = 0,
00116 Autodetect,
00117 ForceEnabled,
00118 ForceDisabled
00119 };
00120
00121
00122
00123
00124 RasterizerSettings(void)
00125 {
00126 this->clear();
00127 }
00128
00129 void clear(void)
00130 {
00131
00132 }
00133 };
00134
00135 class FragmentOutputBinding
00136 {
00137 public:
00138
00139 typedef void BaseType;
00140 typedef FragmentOutputBinding ThisType;
00141
00142 typedef std::map<std::string, GLuint> Map;
00143 typedef Map::const_iterator ConstIterator;
00144 typedef Map::iterator Iterator;
00145 typedef Map::value_type Value;
00146
00147 Map bindings;
00148
00149 FragmentOutputBinding(void)
00150 {
00151 this->clear();
00152 }
00153
00154 void clear(void)
00155 {
00156 this->bindings.clear();
00157 }
00158
00159 GLuint operator [] (const std::string & outName) const
00160 {
00161 return this->bindings.find(outName)->second;
00162 }
00163
00164 GLuint & operator [] (const std::string & outName)
00165 {
00166 return this->bindings[outName];
00167 }
00168 };
00169
00170 class ProgramArguments : public ObjectArguments
00171 {
00172 public:
00173
00174 typedef ObjectArguments BaseType;
00175 typedef ProgramArguments ThisType;
00176
00177 ShaderHandleVector shaders;
00178 VertexAttributeBinding vertexInputs;
00179 GeometryStage geometryStage;
00180 TransformFeedbackStream feedbackStream;
00181 RasterizerSettings rasterSettings;
00182 FragmentOutputBinding fragmentOutputs;
00183
00184 ProgramArguments(void)
00185 : BaseType()
00186 {
00187 ;
00188 }
00189
00190 void clear(void)
00191 {
00192 BaseType::clear();
00193 this->shaders .clear();
00194 this->vertexInputs .clear();
00195 this->geometryStage .clear();
00196 this->feedbackStream .clear();
00197 this->rasterSettings .clear();
00198 this->fragmentOutputs .clear();
00199 }
00200 };
00201
00202 class Program : public Object
00203 {
00204 friend class Context;
00205
00206 public:
00207
00208 typedef Object BaseType;
00209 typedef Program ThisType;
00210
00211 virtual ~Program(void)
00212 {
00213 this->destroy();
00214 }
00215
00216 virtual Type type(void) const
00217 {
00218 return ProgramType;
00219 }
00220
00221 const ProgramArguments & arguments(void) const
00222 {
00223 return this->m_arguments;
00224 }
00225
00226 const std::string & log(void) const
00227 {
00228 return this->m_log;
00229 }
00230
00231 const std::string & fullLog(void) const
00232 {
00233 return this->m_fullLog;
00234 }
00235
00236 bool isLinked(void) const
00237 {
00238 return this->m_linked;
00239 }
00240
00241 GLint getUniformLocation(const std::string & name) const
00242 {
00243 #if GLW_ASSERT_UNIFORM_LOCATION
00244 GLW_ASSERT(this->m_uniforms.count(name) > 0);
00245 #endif
00246 UniformMapConstIterator it = this->m_uniforms.find(name);
00247 if (it == this->m_uniforms.end()) return -1;
00248 return it->second.location;
00249 }
00250
00251 #define _GLW_IMPLEMENT_SCALAR_UNIFORM_(TYPE, FUNCION_SUFFIX) \
00252 void setUniform (const std::string & name, TYPE x ) { glUniform1 ## FUNCION_SUFFIX (this->getUniformLocation(name), x ); } \
00253 void setUniform (const std::string & name, TYPE x, TYPE y ) { glUniform2 ## FUNCION_SUFFIX (this->getUniformLocation(name), x, y ); } \
00254 void setUniform (const std::string & name, TYPE x, TYPE y, TYPE z ) { glUniform3 ## FUNCION_SUFFIX (this->getUniformLocation(name), x, y, z ); } \
00255 void setUniform (const std::string & name, TYPE x, TYPE y, TYPE z, TYPE w ) { glUniform4 ## FUNCION_SUFFIX (this->getUniformLocation(name), x, y, z, w); }
00256
00257 #define _GLW_IMPLEMENT_VECTOR_UNIFORM_(TYPE, FUNCION_SUFFIX) \
00258 void setUniform1 (const std::string & name, const TYPE * v, int count = 1) { glUniform1 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } \
00259 void setUniform2 (const std::string & name, const TYPE * v, int count = 1) { glUniform2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } \
00260 void setUniform3 (const std::string & name, const TYPE * v, int count = 1) { glUniform3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } \
00261 void setUniform4 (const std::string & name, const TYPE * v, int count = 1) { glUniform4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); }
00262
00263 #define _GLW_IMPLEMENT_MATRIX_UNIFORM_(TYPE, FUNCION_SUFFIX) \
00264 void setUniform2x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \
00265 void setUniform2x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix2x3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \
00266 void setUniform2x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix2x4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \
00267 void setUniform3x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix3x2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \
00268 void setUniform3x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \
00269 void setUniform3x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix3x4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \
00270 void setUniform4x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix4x2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \
00271 void setUniform4x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix4x3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \
00272 void setUniform4x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); }
00273
00274 _GLW_IMPLEMENT_SCALAR_UNIFORM_(int, i )
00275 _GLW_IMPLEMENT_SCALAR_UNIFORM_(unsigned int, ui)
00276 _GLW_IMPLEMENT_SCALAR_UNIFORM_(float, f )
00277
00278 _GLW_IMPLEMENT_VECTOR_UNIFORM_(int, i )
00279 _GLW_IMPLEMENT_VECTOR_UNIFORM_(unsigned int, ui)
00280 _GLW_IMPLEMENT_VECTOR_UNIFORM_(float, f )
00281
00282 _GLW_IMPLEMENT_MATRIX_UNIFORM_(float, f )
00283
00284
00285 GLW_IMPLEMENT_CUSTOM_UNIFORMS;
00286
00287 #undef _GLW_IMPLEMENT_SCALAR_UNIFORM_
00288 #undef _GLW_IMPLEMENT_VECTOR_UNIFORM_
00289 #undef _GLW_IMPLEMENT_MATRIX_UNIFORM_
00290
00291 protected:
00292
00293 Program(Context * ctx)
00294 : BaseType (ctx)
00295 , m_linked (false)
00296 {
00297 ;
00298 }
00299
00300 bool create(const ProgramArguments & args)
00301 {
00302 this->destroy();
00303
00304 this->m_arguments = args;
00305
00306 GLint boundName = 0;
00307 glGetIntegerv(GL_CURRENT_PROGRAM, &boundName);
00308
00309 this->m_name = glCreateProgram();
00310 this->m_fullLog = "";
00311
00312
00313 {
00314 for (size_t i=0; i<this->m_arguments.shaders.size(); ++i)
00315 {
00316 const ShaderHandle & shader = this->m_arguments.shaders[i];
00317 if (!shader) continue;
00318 this->m_fullLog += shader->log();
00319 if (!shader->isCompiled()) continue;
00320 glAttachShader(this->m_name, shader->name());
00321 }
00322 }
00323
00324
00325 {
00326 for (VertexAttributeBinding::ConstIterator it=this->m_arguments.vertexInputs.bindings.begin(); it!=this->m_arguments.vertexInputs.bindings.end(); ++it)
00327 {
00328 glBindAttribLocation(this->m_name, it->second, it->first.c_str());
00329 }
00330 }
00331
00332
00333 {
00334 ;
00335 }
00336
00337
00338 {
00339 const size_t count = this->m_arguments.feedbackStream.varyings.size();
00340 if (count > 0)
00341 {
00342 const char ** varyings = new const char * [count];
00343 for (size_t i=0; i<count; ++i)
00344 {
00345 varyings[i] = this->m_arguments.feedbackStream.varyings[i].c_str();
00346 }
00347 glTransformFeedbackVaryings(this->m_name, GLsizei(count), varyings, this->m_arguments.feedbackStream.bufferMode);
00348 delete [] varyings;
00349 }
00350 }
00351
00352
00353
00354 {
00355 ;
00356 }
00357
00358
00359 {
00360 for (FragmentOutputBinding::ConstIterator it=this->m_arguments.fragmentOutputs.bindings.begin(); it!=this->m_arguments.fragmentOutputs.bindings.end(); ++it)
00361 {
00362 glBindFragDataLocation(this->m_name, it->second, it->first.c_str());
00363 }
00364 }
00365
00366 glLinkProgram(this->m_name);
00367
00368 GLint linkStatus = 0;
00369 glGetProgramiv(this->m_name, GL_LINK_STATUS, &linkStatus);
00370
00371 this->m_log = ThisType::getInfoLog(this->m_name);
00372 this->m_fullLog += this->m_log;
00373 this->m_linked = (linkStatus != GL_FALSE);
00374
00375 #if GLW_PRINT_LOG_TO_STDERR
00376 std::cerr << "---------------------------" << std::endl;
00377 std::cerr << "[Program Link Log]: " << ((this->m_linked) ? ("OK") : ("FAILED")) << std::endl;
00378 std::cerr << this->m_log << std::endl;
00379 std::cerr << "---------------------------" << std::endl;
00380 #endif
00381
00382 if (this->m_linked)
00383 {
00384 this->postLink();
00385 }
00386
00387 glUseProgram(boundName);
00388
00389 return this->m_linked;
00390 }
00391
00392 virtual void doDestroy()
00393 {
00394 glDeleteProgram(this->m_name);
00395 this->m_arguments.clear();
00396 this->m_log.clear();
00397 this->m_fullLog.clear();
00398 this->m_linked = false;
00399 }
00400
00401 virtual bool doIsValid(void) const
00402 {
00403 return this->m_linked;
00404 }
00405
00406 private:
00407
00408 class UniformInfo
00409 {
00410 public:
00411
00412 typedef void BaseType;
00413 typedef UniformInfo ThisType;
00414
00415 std::string name;
00416 GLint location;
00417 GLenum type;
00418 GLint size;
00419
00420 UniformInfo(void)
00421 : location (-1)
00422 , type (GL_NONE)
00423 , size (0)
00424 {
00425 ;
00426 }
00427 };
00428
00429 typedef std::map<std::string, UniformInfo> UniformMap;
00430 typedef UniformMap::const_iterator UniformMapConstIterator;
00431 typedef UniformMap::iterator UniformMapIterator;
00432 typedef UniformMap::value_type UniformMapValue;
00433
00434 ProgramArguments m_arguments;
00435 UniformMap m_uniforms;
00436 std::string m_log;
00437 std::string m_fullLog;
00438 bool m_linked;
00439
00440 static std::string getInfoLog(GLuint Program)
00441 {
00442 std::string log;
00443 GLint logLen = 0;
00444 glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &logLen);
00445 if (logLen > 0)
00446 {
00447 char * sLog = new char[logLen + 1];
00448 glGetProgramInfoLog(Program, logLen, &logLen, sLog);
00449 if (logLen > 0)
00450 {
00451 if (sLog[0] != '\0')
00452 {
00453 sLog[logLen - 1] = '\0';
00454 log = sLog;
00455 }
00456 }
00457 delete [] sLog;
00458 }
00459 return log;
00460 }
00461
00462 void setupUniforms(void)
00463 {
00464 this->m_uniforms.clear();
00465
00466 GLint ucount = 0;
00467 glGetProgramiv(this->m_name, GL_ACTIVE_UNIFORMS, &ucount);
00468 if (ucount <= 0) return;
00469
00470 GLint ulen = 0;
00471 glGetProgramiv(this->m_name, GL_ACTIVE_UNIFORM_MAX_LENGTH, &ulen);
00472 ulen++;
00473 if (ulen <= 0) return;
00474
00475 UniformInfo info;
00476 GLchar * uname = new GLchar [ulen + 1];
00477 for (int i=0; i<int(ucount); ++i)
00478 {
00479 GLsizei length = 0;
00480 glGetActiveUniform(this->m_name, GLuint(i), GLsizei(ulen), &length, &(info.size), &(info.type), uname);
00481 info.name = uname;
00482 info.location = glGetUniformLocation(this->m_name, uname);
00483 this->m_uniforms.insert(UniformMapValue(info.name, info));
00484 }
00485 delete [] uname;
00486 }
00487
00488 void postLink(void)
00489 {
00490 this->setupUniforms();
00491 }
00492 };
00493
00494 namespace detail { template <> struct BaseOf <Program> { typedef Object Type; }; };
00495 typedef detail::ObjectSharedPointerTraits <Program> ::Type ProgramPtr;
00496
00497 class SafeProgram : public SafeObject
00498 {
00499 friend class Context;
00500 friend class BoundProgram;
00501
00502 public:
00503
00504 typedef SafeObject BaseType;
00505 typedef SafeProgram ThisType;
00506
00507 const ProgramArguments & arguments(void) const
00508 {
00509 return this->object()->arguments();
00510 }
00511
00512 const std::string & log(void) const
00513 {
00514 return this->object()->log();
00515 }
00516
00517 const std::string & fullLog(void) const
00518 {
00519 return this->object()->fullLog();
00520 }
00521
00522 bool isLinked(void) const
00523 {
00524 return this->object()->isLinked();
00525 }
00526
00527 protected:
00528
00529 SafeProgram(const ProgramPtr & program)
00530 : BaseType(program)
00531 {
00532 ;
00533 }
00534
00535 const ProgramPtr & object(void) const
00536 {
00537 return static_cast<const ProgramPtr &>(BaseType::object());
00538 }
00539
00540 ProgramPtr & object(void)
00541 {
00542 return static_cast<ProgramPtr &>(BaseType::object());
00543 }
00544 };
00545
00546 namespace detail { template <> struct BaseOf <SafeProgram> { typedef SafeObject Type; }; };
00547 namespace detail { template <> struct ObjectBase <SafeProgram> { typedef Program Type; }; };
00548 namespace detail { template <> struct ObjectSafe <Program > { typedef SafeProgram Type; }; };
00549 typedef detail::ObjectSharedPointerTraits <SafeProgram> ::Type ProgramHandle;
00550
00551 class ProgramBindingParams : public ObjectBindingParams
00552 {
00553 public:
00554
00555 typedef ObjectBindingParams BaseType;
00556 typedef ProgramBindingParams ThisType;
00557
00558 ProgramBindingParams(void)
00559 : BaseType(GL_CURRENT_PROGRAM, 0)
00560 {
00561 ;
00562 }
00563 };
00564
00565 class BoundProgram : public BoundObject
00566 {
00567 friend class Context;
00568
00569 public:
00570
00571 typedef BoundObject BaseType;
00572 typedef BoundProgram ThisType;
00573
00574 BoundProgram(void)
00575 : BaseType()
00576 {
00577 ;
00578 }
00579
00580 const ProgramHandle & handle(void) const
00581 {
00582 return static_cast<const ProgramHandle &>(BaseType::handle());
00583 }
00584
00585 ProgramHandle & handle(void)
00586 {
00587 return static_cast<ProgramHandle &>(BaseType::handle());
00588 }
00589
00590 #define _GLW_FORWARD_SCALAR_UNIFORM_(TYPE) \
00591 void setUniform (const std::string & name, TYPE x ) { this->object()->setUniform(name, x ); } \
00592 void setUniform (const std::string & name, TYPE x, TYPE y ) { this->object()->setUniform(name, x, y ); } \
00593 void setUniform (const std::string & name, TYPE x, TYPE y, TYPE z ) { this->object()->setUniform(name, x, y, z ); } \
00594 void setUniform (const std::string & name, TYPE x, TYPE y, TYPE z, TYPE w ) { this->object()->setUniform(name, x, y, z, w); }
00595
00596 #define _GLW_FORWARD_VECTOR_UNIFORM_(TYPE) \
00597 void setUniform1 (const std::string & name, const TYPE * v, int count = 1) { this->object()->setUniform1(name, v, count); } \
00598 void setUniform2 (const std::string & name, const TYPE * v, int count = 1) { this->object()->setUniform2(name, v, count); } \
00599 void setUniform3 (const std::string & name, const TYPE * v, int count = 1) { this->object()->setUniform3(name, v, count); } \
00600 void setUniform4 (const std::string & name, const TYPE * v, int count = 1) { this->object()->setUniform4(name, v, count); }
00601
00602 #define _GLW_FORWARD_MATRIX_UNIFORM_(TYPE) \
00603 void setUniform2x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform2x2(name, m, transpose, count); } \
00604 void setUniform2x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform2x3(name, m, transpose, count); } \
00605 void setUniform2x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform2x4(name, m, transpose, count); } \
00606 void setUniform3x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform3x2(name, m, transpose, count); } \
00607 void setUniform3x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform3x3(name, m, transpose, count); } \
00608 void setUniform3x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform3x4(name, m, transpose, count); } \
00609 void setUniform4x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform4x2(name, m, transpose, count); } \
00610 void setUniform4x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform4x3(name, m, transpose, count); } \
00611 void setUniform4x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform4x4(name, m, transpose, count); }
00612
00613 _GLW_FORWARD_SCALAR_UNIFORM_(int)
00614 _GLW_FORWARD_SCALAR_UNIFORM_(unsigned int)
00615 _GLW_FORWARD_SCALAR_UNIFORM_(float)
00616
00617 _GLW_FORWARD_VECTOR_UNIFORM_(int)
00618 _GLW_FORWARD_VECTOR_UNIFORM_(unsigned int)
00619 _GLW_FORWARD_VECTOR_UNIFORM_(float)
00620
00621 _GLW_FORWARD_MATRIX_UNIFORM_(float)
00622
00623
00624 #undef _GLW_FORWARD_SCALAR_UNIFORM_
00625 #undef _GLW_FORWARD_VECTOR_UNIFORM_
00626 #undef _GLW_FORWARD_MATRIX_UNIFORM_
00627
00628 protected:
00629
00630 BoundProgram(const ProgramHandle & handle, const ProgramBindingParams & params)
00631 : BaseType(handle, params)
00632 {
00633 ;
00634 }
00635
00636 const ProgramPtr & object(void) const
00637 {
00638 return this->handle()->object();
00639 }
00640
00641 ProgramPtr & object(void)
00642 {
00643 return this->handle()->object();
00644 }
00645
00646 virtual void bind(void)
00647 {
00648 glUseProgram(this->object()->name());
00649 }
00650
00651 virtual void unbind(void)
00652 {
00653 glUseProgram(0);
00654 }
00655 };
00656
00657 namespace detail { template <> struct ParamsOf <BoundProgram> { typedef ProgramBindingParams Type; }; };
00658 namespace detail { template <> struct BaseOf <BoundProgram> { typedef BoundObject Type; }; };
00659 namespace detail { template <> struct ObjectBase <BoundProgram> { typedef Program Type; }; };
00660 namespace detail { template <> struct ObjectBound <Program > { typedef BoundProgram Type; }; };
00661 typedef detail::ObjectSharedPointerTraits <BoundProgram> ::Type BoundProgramHandle;
00662
00663 };
00664
00665 #endif // GLW_PROGRAM_H