gKitGL
|
00001 00002 #ifndef _TP_BUFFER_H 00003 #define _TP_BUFFER_H 00004 00005 #include <cstdio> 00006 #include <cassert> 00007 00008 #include "GL/GLPlatform.h" 00009 #include "GLResource.h" 00010 #include "GL/TPProgramName.h" 00011 #include "GL/TPAttributes.h" 00012 00013 00014 namespace gk { 00015 00016 //! utilisation interne. representation d'un buffer openGL. 00017 class GLBuffer : public GLResource 00018 { 00019 // non copyable 00020 GLBuffer( const GLBuffer& ); 00021 GLBuffer& operator=( const GLBuffer& ); 00022 00023 protected: 00024 GLenum m_usage; 00025 unsigned int m_length; 00026 unsigned int m_count; 00027 00028 public: 00029 //! constructeur d'un buffer, un tableau de vecteurs de 'count' elements. 00030 //! \param count nombre de vecteurs, 00031 //! \param length longueur totale du buffer en OCTETS, 00032 //! \param data pointeur sur les donnees a transferer dans le buffer, ou NULL pour initialiser un buffer vide, 00033 //! \param usage decrit le type d'utilisation du buffer, cf glBufferData(). 00034 GLBuffer( const GLenum target, 00035 const unsigned int count, const unsigned int length, const void *data, const GLenum usage= GL_STATIC_DRAW ) 00036 : 00037 GLResource(), 00038 m_usage(usage), 00039 m_length(length), 00040 m_count(count) 00041 { 00042 glGenBuffers(1, &m_name); 00043 00044 glBindBuffer(target, m_name); 00045 glBufferData(target, m_length, data, m_usage); 00046 } 00047 00048 //! efface le contenu du buffer. 00049 int clear( const GLenum target ) 00050 { 00051 if(m_name == 0) 00052 return -1; 00053 00054 glBindBuffer(target, m_name); 00055 glBufferData(target, m_length, NULL, m_usage); 00056 00057 //! \todo GL4.3 glInvalidateBufferData(m_mane); 00058 return 0; 00059 } 00060 00061 //! modifie le contenu d'une partie du buffer. 00062 //! \param offset position du premier octet a modifier, 00063 //! \param length nombre d'octets a modifier. 00064 int update( const GLenum target, 00065 const unsigned long int offset, const unsigned long int length, const void *data ) 00066 { 00067 if(m_name == 0) 00068 return -1; 00069 if(offset + length > m_length) 00070 return -1; 00071 00072 glBindBuffer(target, m_name); 00073 glBufferSubData(target, offset, length, data); 00074 return 0; 00075 } 00076 00077 //! mappe le contenu du buffer en memoire host. 00078 //! cf. glMapBufferRange() pour les flags 'access'. 00079 void *map( const GLenum target, 00080 const unsigned long int offset, const unsigned int length, const GLbitfield access ) 00081 { 00082 if(m_name == 0) 00083 return NULL; 00084 if(offset + length > m_length) 00085 { 00086 printf("GLBuffer::map( ): offset + length > buffer length\n"); 00087 return NULL; 00088 } 00089 00090 glBindBuffer(target, m_name); 00091 return glMapBufferRange(target, offset, length, access); 00092 } 00093 00094 int unmap( const GLenum target ) 00095 { 00096 if(m_name == 0) 00097 return -1; 00098 glUnmapBuffer(target); 00099 return 0; 00100 } 00101 00102 int flush( const GLenum target, 00103 const unsigned long int offset, const unsigned int length ) 00104 { 00105 if(m_name == 0) 00106 return -1; 00107 if(offset + length > m_length) 00108 { 00109 printf("GLBuffer::flush( ): offset + length > buffer length\n"); 00110 return -1; 00111 } 00112 00113 glFlushMappedBufferRange(target, offset, length); 00114 return 0; 00115 } 00116 00117 00118 public: 00119 //! destructeur. 00120 virtual ~GLBuffer( ) 00121 { 00122 if(m_name != 0) 00123 glDeleteBuffers(1, &m_name); 00124 } 00125 00126 //! creation de la ressource openGL. 00127 int createGLResource( ) 00128 { 00129 return (m_name != 0) ? 0 : -1; 00130 } 00131 00132 //! destruction de la ressource openGL. 00133 int releaseGLResource( ) 00134 { 00135 return (m_name != 0) ? 0 : -1; 00136 } 00137 00138 //! renvoie le nombre de vecteurs alloues (valeur passee au contructeur, cf GLBuffer()). 00139 unsigned int count( ) const 00140 { 00141 if(m_name == 0) 00142 return 0; 00143 return m_count; 00144 } 00145 00146 //! renvoie le nombre d'octets alloues. 00147 unsigned long int length( ) const 00148 { 00149 return m_length; 00150 } 00151 }; 00152 00153 //! representation d'un buffer d'attribut. 00154 class GLAttributeBuffer : public GLBuffer 00155 { 00156 public: 00157 //! constructeur. 00158 GLAttributeBuffer( const unsigned int count, const unsigned int length, const void *data, const GLenum usage= GL_STATIC_DRAW ) 00159 : 00160 GLBuffer(GL_ARRAY_BUFFER, count, length, data, usage) 00161 {} 00162 00163 //! destructeur. 00164 ~GLAttributeBuffer( ) {} 00165 00166 //! renvoie l'identifiant des proprietes modifiees par le buffer. 00167 GLenum target( ) const 00168 { 00169 return GL_ARRAY_BUFFER; 00170 } 00171 00172 //! efface le contenu du buffer. 00173 int clear( ) 00174 { 00175 return GLBuffer::clear(GL_ARRAY_BUFFER); 00176 } 00177 00178 //! remplace une partie de contenu du buffer. 00179 int update( const unsigned long int offset, const unsigned long int length, const void *data ) 00180 { 00181 return GLBuffer::update(GL_ARRAY_BUFFER, offset, length, data ); 00182 } 00183 00184 //! mappe une partie du buffer en memoire centrale. 00185 //! cf. glMapBufferRange pour les flags 'access'. 00186 void *map( const unsigned long int offset, const unsigned long int length, const GLbitfield access ) 00187 { 00188 return GLBuffer::map(GL_ARRAY_BUFFER, offset, length, access ); 00189 } 00190 00191 //! termine le mapping du contenu du buffer en memoire centrale, les donnees modifiees sont transferees sur le gpu. 00192 int unmap( ) 00193 { 00194 return GLBuffer::unmap(GL_ARRAY_BUFFER); 00195 } 00196 00197 //! termine une partie du mapping du contenu du buffer en memoire centrale, les donnees modifiiees sont transferees sur le gpu. 00198 int flush( const unsigned long int offset, const unsigned long int length ) 00199 { 00200 return GLBuffer::flush(GL_ARRAY_BUFFER, offset, length); 00201 } 00202 }; 00203 00204 template < typename T > 00205 class ScopedMapAttributeBuffer 00206 { 00207 GLAttributeBuffer *m_buffer; 00208 T *m_begin; 00209 T *m_end; 00210 00211 ScopedMapAttributeBuffer( ); 00212 ScopedMapAttributeBuffer( const ScopedMapAttributeBuffer& ); 00213 ScopedMapAttributeBuffer& operator=( const ScopedMapAttributeBuffer& ); 00214 00215 public: 00216 //! cf. glMapBufferRange pour les flags 'access'. 00217 ScopedMapAttributeBuffer( GLAttributeBuffer *buffer, 00218 GLbitfield access= GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT, 00219 const unsigned long int offset= 0, const unsigned int _length= 0 ) 00220 : 00221 m_buffer(buffer), 00222 m_begin(NULL), 00223 m_end(NULL) 00224 { 00225 if(m_buffer == NULL) 00226 return; 00227 00228 int length= (_length == 0) ? m_buffer->length() : _length; 00229 m_begin= (T *) m_buffer->map(offset, length, access); 00230 m_end= m_begin + length / sizeof(T); 00231 } 00232 00233 T& operator[] ( const unsigned int id ) 00234 { 00235 assert(m_begin != NULL); 00236 assert(m_begin + id < m_end); 00237 return m_begin[id]; 00238 } 00239 00240 ~ScopedMapAttributeBuffer( ) 00241 { 00242 if(m_buffer == NULL) 00243 return; 00244 m_buffer->unmap(); 00245 } 00246 }; 00247 00248 00249 //! representation d'un buffer d'indexation. 00250 class GLIndexBuffer : public GLBuffer 00251 { 00252 public: 00253 GLIndexBuffer( const unsigned int count, const unsigned int length, const void *data, const GLenum usage= GL_STATIC_DRAW ) 00254 : 00255 GLBuffer(GL_ELEMENT_ARRAY_BUFFER, count, length, data, usage ) 00256 {} 00257 00258 ~GLIndexBuffer( ) {} 00259 00260 //! renvoie l'identifiant des proprietes modifiees par le buffer. 00261 GLenum target( ) const 00262 { 00263 return GL_ELEMENT_ARRAY_BUFFER; 00264 } 00265 00266 int clear( ) 00267 { 00268 return GLBuffer::clear(GL_ELEMENT_ARRAY_BUFFER); 00269 } 00270 00271 int update( const unsigned long int offset, const unsigned long int length, const void *data ) 00272 { 00273 return GLBuffer::update(GL_ELEMENT_ARRAY_BUFFER, offset, length, data ); 00274 } 00275 00276 //! cf. glMapBufferRange pour les flags 'access'. 00277 void *map( const unsigned long int offset, const unsigned long int length, const GLbitfield access ) 00278 { 00279 return GLBuffer::map(GL_ELEMENT_ARRAY_BUFFER, offset, length, access ); 00280 } 00281 00282 int unmap( ) 00283 { 00284 return GLBuffer::unmap(GL_ELEMENT_ARRAY_BUFFER); 00285 } 00286 00287 int flush( const unsigned long int offset, const unsigned long int length ) 00288 { 00289 return GLBuffer::flush(GL_ELEMENT_ARRAY_BUFFER, offset, length); 00290 } 00291 }; 00292 00293 00294 template < typename T > 00295 class ScopedMapIndexBuffer 00296 { 00297 GLIndexBuffer *m_buffer; 00298 T *m_begin; 00299 T *m_end; 00300 00301 ScopedMapIndexBuffer( ); 00302 ScopedMapIndexBuffer( const ScopedMapIndexBuffer& ); 00303 ScopedMapIndexBuffer& operator=( const ScopedMapIndexBuffer& ); 00304 00305 public: 00306 //! cf. glMapBufferRange pour les flags 'access'. 00307 ScopedMapIndexBuffer( GLIndexBuffer *buffer, 00308 GLbitfield access= GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT, 00309 const unsigned long int offset= 0, const unsigned int _length= 0 ) 00310 : 00311 m_buffer(buffer), 00312 m_begin(NULL), 00313 m_end(NULL) 00314 { 00315 if(m_buffer == NULL) 00316 return; 00317 00318 int length= (_length == 0) ? m_buffer->length() : _length; 00319 m_begin= (T *) m_buffer->map(offset, length, access); 00320 m_end= m_begin + length / sizeof(T); 00321 } 00322 00323 T& operator[] ( const unsigned int id ) 00324 { 00325 assert(m_begin != NULL); 00326 assert(m_begin + id < m_end); 00327 return m_begin[id]; 00328 } 00329 00330 ~ScopedMapIndexBuffer( ) 00331 { 00332 if(m_buffer == NULL) 00333 return; 00334 m_buffer->unmap(); 00335 } 00336 }; 00337 00338 //! organisation des donnees (attributs/indices) dans un buffer 00339 struct BufferLayout 00340 { 00341 int size; 00342 GLenum type; 00343 unsigned long int stride; 00344 unsigned long int offset; 00345 unsigned long int length; 00346 int divisor; 00347 bool normalize_flag; 00348 bool integer_flag; 00349 00350 enum 00351 { 00352 NORMALIZE_BIT= 1, 00353 INTEGER_BIT= 2 00354 }; 00355 00356 BufferLayout( ) 00357 : 00358 size(0), 00359 type(GL_NONE), 00360 stride(0), 00361 offset(0), 00362 length(0), 00363 divisor(0), 00364 normalize_flag(false), 00365 integer_flag(false) 00366 {} 00367 00368 BufferLayout( const int _size, const GLenum _type, const unsigned long int _stride, const unsigned long int _offset= 0, 00369 const int _divisor= 0, const unsigned int flags= 0 ) 00370 : 00371 size(_size), 00372 type(_type), 00373 stride(_stride), 00374 offset(_offset), 00375 length(0), 00376 divisor(_divisor), 00377 normalize_flag((flags & NORMALIZE_BIT)), 00378 integer_flag((flags & INTEGER_BIT)) 00379 { 00380 assert(stride != 0); 00381 } 00382 00383 const GLvoid *getOffset( const unsigned int begin= 0 ) 00384 { 00385 return (const GLvoid *) (offset + begin * stride); 00386 } 00387 00388 bool operator== ( const BufferLayout& b ) const 00389 { 00390 if(stride != b.stride) 00391 return false; 00392 if(offset != b.offset) 00393 return false; 00394 if(length != b.length) 00395 return false; 00396 if(size != b.size || type != b.type) 00397 return false; 00398 if(divisor != b.divisor) 00399 return false; 00400 00401 return true; 00402 } 00403 00404 bool operator!= ( const BufferLayout& b ) const 00405 { 00406 return !operator==(b); 00407 } 00408 00409 friend bool less( const BufferLayout& a, const BufferLayout& b ); 00410 bool operator< ( const BufferLayout& b ) const 00411 { 00412 return less(*this, b); 00413 } 00414 }; 00415 00416 inline 00417 bool less( const BufferLayout& a, const BufferLayout& b ) 00418 { 00419 if(a.stride >= b.stride) 00420 return false; 00421 if(a.offset >= b.offset) 00422 return false; 00423 if(a.length >= b.length) 00424 return false; 00425 if(a.size >= b.size) 00426 return false; 00427 if(a.type >= b.type) 00428 return false; 00429 if(a.divisor >= b.divisor) 00430 return false; 00431 00432 return true; 00433 } 00434 00435 00436 //! organisation d'uniforms dans un buffer 00437 struct BufferRange 00438 { 00439 unsigned long int offset; 00440 unsigned long int length; 00441 }; 00442 00443 00444 //! representation d'un vertex attrib array, 00445 //! necessaire en core profile pour stocker l'association des attributs du shader program et du contenu des vertex buffers. 00446 class GLVertexArray : public GLResource 00447 { 00448 // non copyable 00449 GLVertexArray( const GLVertexArray& ); 00450 GLVertexArray& operator= ( const GLVertexArray& ); 00451 00452 public: 00453 GLVertexArray( ) 00454 : 00455 GLResource() 00456 { 00457 glGenVertexArrays(1, &m_name); 00458 glBindVertexArray(m_name); 00459 } 00460 00461 ~GLVertexArray( ) 00462 { 00463 glDeleteVertexArrays(1, &m_name); 00464 } 00465 00466 int createGLResource( ) 00467 { 00468 return (m_name != 0) ? 0 : -1; 00469 } 00470 00471 int releaseGLResource( ) 00472 { 00473 return (m_name != 0) ? 0 : -1; 00474 } 00475 }; 00476 00477 } 00478 00479 #endif