Equalizer 1.0
|
00001 00002 /* Copyright (c) 2007-2010, Stefan Eilemann <eile@equalizergraphics.com> 00003 * Copyright (c) 2010, Cedric Stalder <cedric.stalder@gmail.com> 00004 * 00005 * This library is free software; you can redistribute it and/or modify it under 00006 * the terms of the GNU Lesser General Public License version 2.1 as published 00007 * by the Free Software Foundation. 00008 * 00009 * This library is distributed in the hope that it will be useful, but WITHOUT 00010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00011 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00012 * details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public License 00015 * along with this library; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00017 */ 00018 00019 #include "objectManager.h" 00020 00021 #include "accum.h" 00022 #include "bitmapFont.h" 00023 #include "frameBufferObject.h" 00024 #include "gpuCompressor.h" 00025 #include "texture.h" 00026 00027 #include <string.h> 00028 00029 // instantiate desired key types -- see objectManager.cpp 00030 00031 namespace eq 00032 { 00033 namespace util 00034 { 00035 template< class T > 00036 ObjectManager< T >::ObjectManager( const GLEWContext* const glewContext ) 00037 : _data( new SharedData( glewContext )) 00038 { 00039 EQASSERT( glewContext ); 00040 } 00041 00042 template< class T > 00043 ObjectManager< T >::ObjectManager( ObjectManager* shared ) 00044 : _data( shared->_data ) 00045 { 00046 EQASSERT( shared ); 00047 } 00048 00049 template< class T > 00050 ObjectManager<T>::~ObjectManager() 00051 { 00052 _data = 0; 00053 } 00054 00055 template< class T > 00056 ObjectManager<T>::SharedData::SharedData( const GLEWContext* gl ) 00057 : glewContext( new GLEWContext ) 00058 { 00059 EQASSERT( gl ); 00060 memcpy( glewContext, gl, sizeof( GLEWContext )); 00061 } 00062 00063 template< class T > 00064 ObjectManager<T>::SharedData::~SharedData() 00065 { 00066 // Do not delete GL objects, we may no longer have a GL context. 00067 if( !lists.empty( )) 00068 EQWARN << lists.size() 00069 << " lists still allocated in ObjectManager destructor" 00070 << std::endl; 00071 lists.clear(); 00072 00073 if( !textures.empty( )) 00074 EQWARN << textures.size() 00075 << " textures still allocated in ObjectManager destructor" 00076 << std::endl; 00077 textures.clear(); 00078 00079 if( !buffers.empty( )) 00080 EQWARN << buffers.size() 00081 << " buffers still allocated in ObjectManager destructor" 00082 << std::endl; 00083 buffers.clear(); 00084 00085 if( !programs.empty( )) 00086 EQWARN << programs.size() 00087 << " programs still allocated in ObjectManager destructor" 00088 << std::endl; 00089 programs.clear(); 00090 00091 if( !shaders.empty( )) 00092 EQWARN << shaders.size() 00093 << " shaders still allocated in ObjectManager destructor" 00094 << std::endl; 00095 shaders.clear(); 00096 00097 if( !eqTextures.empty( )) 00098 EQWARN << eqTextures.size() 00099 << " eq::Texture still allocated in ObjectManager destructor" 00100 << std::endl; 00101 eqTextures.clear(); 00102 00103 if( !eqFonts.empty( )) 00104 EQWARN << eqFonts.size() 00105 << " eq::BitmapFont still allocated in ObjectManager destructor" 00106 << std::endl; 00107 eqFonts.clear(); 00108 00109 if( !eqFrameBufferObjects.empty( )) 00110 EQWARN << eqFrameBufferObjects.size() 00111 << " eq::FrameBufferObject's still allocated in ObjectManager " 00112 << "destructor" << std::endl; 00113 eqFrameBufferObjects.clear(); 00114 00115 if( !eqUploaders.empty( )) 00116 EQWARN << eqUploaders.size() 00117 << " eq::GPUCompressor's still allocated in ObjectManager " 00118 << "destructor" << std::endl; 00119 eqUploaders.clear(); 00120 delete glewContext; 00121 } 00122 00123 template< class T > 00124 void ObjectManager<T>::deleteAll() 00125 { 00126 for( typename ObjectHash::const_iterator i = _data->lists.begin(); 00127 i != _data->lists.end(); ++i ) 00128 { 00129 const Object& object = i->second; 00130 EQVERB << "Delete list " << object.id << std::endl; 00131 glDeleteLists( object.id, object.num ); 00132 } 00133 _data->lists.clear(); 00134 00135 for( typename ObjectHash::const_iterator i = _data->textures.begin(); 00136 i != _data->textures.end(); ++i ) 00137 { 00138 const Object& object = i->second; 00139 EQVERB << "Delete texture " << object.id << std::endl; 00140 glDeleteTextures( 1, &object.id ); 00141 } 00142 _data->textures.clear(); 00143 00144 for( typename ObjectHash::const_iterator i = _data->buffers.begin(); 00145 i != _data->buffers.end(); ++i ) 00146 { 00147 const Object& object = i->second; 00148 EQVERB << "Delete buffer " << object.id << std::endl; 00149 glDeleteBuffers( 1, &object.id ); 00150 } 00151 _data->buffers.clear(); 00152 00153 for( typename ObjectHash::const_iterator i = _data->programs.begin(); 00154 i != _data->programs.end(); ++i ) 00155 { 00156 const Object& object = i->second; 00157 EQVERB << "Delete program " << object.id << std::endl; 00158 glDeleteProgram( object.id ); 00159 } 00160 _data->programs.clear(); 00161 00162 for( typename ObjectHash::const_iterator i = _data->shaders.begin(); 00163 i != _data->shaders.end(); ++i ) 00164 { 00165 const Object& object = i->second; 00166 EQVERB << "Delete shader " << object.id << std::endl; 00167 glDeleteShader( object.id ); 00168 } 00169 _data->shaders.clear(); 00170 00171 for( typename TextureHash::const_iterator i = _data->eqTextures.begin(); 00172 i != _data->eqTextures.end(); ++i ) 00173 { 00174 Texture* texture = i->second; 00175 EQVERB << "Delete eq::Texture " << i->first << " @" << (void*)texture 00176 << std::endl; 00177 texture->flush(); 00178 delete texture; 00179 } 00180 _data->eqTextures.clear(); 00181 00182 for( typename FontHash::const_iterator i = _data->eqFonts.begin(); 00183 i != _data->eqFonts.end(); ++i ) 00184 { 00185 util::BitmapFont< T >* font = i->second; 00186 EQVERB << "Delete eq::Font " << i->first << " @" << (void*)font 00187 << std::endl; 00188 font->exit(); 00189 delete font; 00190 } 00191 _data->eqFonts.clear(); 00192 00193 for( typename FBOHash::const_iterator i = 00194 _data->eqFrameBufferObjects.begin(); 00195 i != _data->eqFrameBufferObjects.end(); ++i ) 00196 { 00197 FrameBufferObject* frameBufferObject = i->second; 00198 EQVERB << "Delete eq::FrameBufferObject " << i->first << " @" 00199 << (void*)frameBufferObject << std::endl; 00200 frameBufferObject->exit(); 00201 delete frameBufferObject; 00202 } 00203 _data->eqFrameBufferObjects.clear(); 00204 00205 for( typename UploaderHash::const_iterator i = 00206 _data->eqUploaders.begin(); 00207 i != _data->eqUploaders.end(); ++i ) 00208 { 00209 GPUCompressor* uploader = i->second; 00210 EQVERB << "Delete eq::GPUCompressor " << i->first << " @" 00211 << (void*)uploader << std::endl; 00212 delete uploader; 00213 } 00214 _data->eqUploaders.clear(); 00215 } 00216 00217 // display list functions 00218 00219 template< class T > 00220 GLuint ObjectManager<T>::getList( const T& key ) const 00221 { 00222 typename ObjectHash::const_iterator i = _data->lists.find( key ); 00223 if( i == _data->lists.end( )) 00224 return INVALID; 00225 00226 const Object& object = i->second; 00227 return object.id; 00228 } 00229 00230 template< class T > 00231 GLuint ObjectManager<T>::newList( const T& key, const GLsizei num ) 00232 { 00233 if( _data->lists.find( key ) != _data->lists.end( )) 00234 { 00235 EQWARN << "Requested new list for existing key" << std::endl; 00236 return INVALID; 00237 } 00238 00239 const GLuint id = glGenLists( num ); 00240 if( !id ) 00241 { 00242 EQWARN << "glGenLists failed: " << glGetError() << std::endl; 00243 return INVALID; 00244 } 00245 00246 Object& object = _data->lists[ key ]; 00247 object.id = id; 00248 object.num = num; 00249 00250 return id; 00251 } 00252 00253 template< class T > 00254 GLuint ObjectManager<T>::obtainList( const T& key, const GLsizei num ) 00255 { 00256 const GLuint id = getList( key ); 00257 if( id != INVALID ) 00258 return id; 00259 return newList( key, num ); 00260 } 00261 00262 template< class T > 00263 void ObjectManager<T>::deleteList( const T& key ) 00264 { 00265 typename ObjectHash::iterator i = _data->lists.find( key ); 00266 if( i == _data->lists.end( )) 00267 return; 00268 00269 const Object& object = i->second; 00270 glDeleteLists( object.id, object.num ); 00271 _data->lists.erase( i ); 00272 } 00273 00274 // texture object functions 00275 00276 template< class T > 00277 GLuint ObjectManager<T>::getTexture( const T& key ) const 00278 { 00279 typename ObjectHash::const_iterator i = _data->textures.find( key ); 00280 if( i == _data->textures.end( )) 00281 return INVALID; 00282 00283 const Object& object = i->second; 00284 return object.id; 00285 } 00286 00287 template< class T > 00288 GLuint ObjectManager<T>::newTexture( const T& key ) 00289 { 00290 if( _data->textures.find( key ) != _data->textures.end( )) 00291 { 00292 EQWARN << "Requested new texture for existing key" << std::endl; 00293 return INVALID; 00294 } 00295 00296 GLuint id = INVALID; 00297 glGenTextures( 1, &id ); 00298 if( id == INVALID ) 00299 { 00300 EQWARN << "glGenTextures failed: " << glGetError() << std::endl; 00301 return INVALID; 00302 } 00303 00304 Object& object = _data->textures[ key ]; 00305 object.id = id; 00306 return id; 00307 } 00308 00309 template< class T > 00310 GLuint ObjectManager<T>::obtainTexture( const T& key ) 00311 { 00312 const GLuint id = getTexture( key ); 00313 if( id != INVALID ) 00314 return id; 00315 return newTexture( key ); 00316 } 00317 00318 template< class T > 00319 void ObjectManager<T>::deleteTexture( const T& key ) 00320 { 00321 typename ObjectHash::iterator i = _data->textures.find( key ); 00322 if( i == _data->textures.end( )) 00323 return; 00324 00325 const Object& object = i->second; 00326 glDeleteTextures( 1, &object.id ); 00327 _data->textures.erase( i ); 00328 } 00329 00330 // buffer object functions 00331 00332 template< class T > 00333 bool ObjectManager<T>::supportsBuffers() const 00334 { 00335 return ( GLEW_VERSION_1_5 ); 00336 } 00337 00338 template< class T > 00339 GLuint ObjectManager<T>::getBuffer( const T& key ) const 00340 { 00341 typename ObjectHash::const_iterator i = _data->buffers.find( key ); 00342 if( i == _data->buffers.end() ) 00343 return INVALID; 00344 00345 const Object& object = i->second; 00346 return object.id; 00347 } 00348 00349 template< class T > 00350 GLuint ObjectManager<T>::newBuffer( const T& key ) 00351 { 00352 if( !GLEW_VERSION_1_5 ) 00353 { 00354 EQWARN << "glGenBuffers not available" << std::endl; 00355 return INVALID; 00356 } 00357 00358 if( _data->buffers.find( key ) != _data->buffers.end() ) 00359 { 00360 EQWARN << "Requested new buffer for existing key" << std::endl; 00361 return INVALID; 00362 } 00363 00364 GLuint id = INVALID; 00365 glGenBuffers( 1, &id ); 00366 00367 if( id == INVALID ) 00368 { 00369 EQWARN << "glGenBuffers failed: " << glGetError() << std::endl; 00370 return INVALID; 00371 } 00372 00373 Object& object = _data->buffers[ key ]; 00374 object.id = id; 00375 return id; 00376 } 00377 00378 template< class T > 00379 GLuint ObjectManager<T>::obtainBuffer( const T& key ) 00380 { 00381 const GLuint id = getBuffer( key ); 00382 if( id != INVALID ) 00383 return id; 00384 return newBuffer( key ); 00385 } 00386 00387 template< class T > 00388 void ObjectManager<T>::deleteBuffer( const T& key ) 00389 { 00390 typename ObjectHash::iterator i = _data->buffers.find( key ); 00391 if( i == _data->buffers.end() ) 00392 return; 00393 00394 const Object& object = i->second; 00395 glDeleteBuffers( 1, &object.id ); 00396 _data->buffers.erase( i ); 00397 } 00398 00399 // program object functions 00400 00401 template< class T > 00402 bool ObjectManager<T>::supportsPrograms() const 00403 { 00404 return ( GLEW_VERSION_2_0 ); 00405 } 00406 00407 template< class T > 00408 GLuint ObjectManager<T>::getProgram( const T& key ) const 00409 { 00410 typename ObjectHash::const_iterator i = _data->programs.find( key ); 00411 if( i == _data->programs.end() ) 00412 return INVALID; 00413 00414 const Object& object = i->second; 00415 return object.id; 00416 } 00417 00418 template< class T > 00419 GLuint ObjectManager<T>::newProgram( const T& key ) 00420 { 00421 if( !GLEW_VERSION_2_0 ) 00422 { 00423 EQWARN << "glCreateProgram not available" << std::endl; 00424 return INVALID; 00425 } 00426 00427 if( _data->programs.find( key ) != _data->programs.end() ) 00428 { 00429 EQWARN << "Requested new program for existing key" << std::endl; 00430 return INVALID; 00431 } 00432 00433 const GLuint id = glCreateProgram(); 00434 if( !id ) 00435 { 00436 EQWARN << "glCreateProgram failed: " << glGetError() << std::endl; 00437 return INVALID; 00438 } 00439 00440 Object& object = _data->programs[ key ]; 00441 object.id = id; 00442 return id; 00443 } 00444 00445 template< class T > 00446 GLuint ObjectManager<T>::obtainProgram( const T& key ) 00447 { 00448 const GLuint id = getProgram( key ); 00449 if( id != INVALID ) 00450 return id; 00451 return newProgram( key ); 00452 } 00453 00454 template< class T > 00455 void ObjectManager<T>::deleteProgram( const T& key ) 00456 { 00457 typename ObjectHash::iterator i = _data->programs.find( key ); 00458 if( i == _data->programs.end() ) 00459 return; 00460 00461 const Object& object = i->second; 00462 glDeleteProgram( object.id ); 00463 _data->programs.erase( i ); 00464 } 00465 00466 // shader object functions 00467 00468 template< class T > 00469 bool ObjectManager<T>::supportsShaders() const 00470 { 00471 return ( GLEW_VERSION_2_0 ); 00472 } 00473 00474 template< class T > 00475 GLuint ObjectManager<T>::getShader( const T& key ) const 00476 { 00477 typename ObjectHash::const_iterator i = _data->shaders.find( key ); 00478 if( i == _data->shaders.end() ) 00479 return INVALID; 00480 00481 const Object& object = i->second; 00482 return object.id; 00483 } 00484 00485 template< class T > 00486 GLuint ObjectManager<T>::newShader( const T& key, const GLenum type ) 00487 { 00488 if( !GLEW_VERSION_2_0 ) 00489 { 00490 EQWARN << "glCreateShader not available" << std::endl; 00491 return INVALID; 00492 } 00493 00494 if( _data->shaders.find( key ) != _data->shaders.end() ) 00495 { 00496 EQWARN << "Requested new shader for existing key" << std::endl; 00497 return INVALID; 00498 } 00499 00500 const GLuint id = glCreateShader( type ); 00501 if( !id ) 00502 { 00503 EQWARN << "glCreateShader failed: " << glGetError() << std::endl; 00504 return INVALID; 00505 } 00506 00507 00508 Object& object = _data->shaders[ key ]; 00509 object.id = id; 00510 return id; 00511 } 00512 00513 template< class T > 00514 GLuint ObjectManager<T>::obtainShader( const T& key, const GLenum type ) 00515 { 00516 const GLuint id = getShader( key ); 00517 if( id != INVALID ) 00518 return id; 00519 return newShader( key, type ); 00520 } 00521 00522 template< class T > 00523 void ObjectManager<T>::deleteShader( const T& key ) 00524 { 00525 typename ObjectHash::iterator i = _data->shaders.find( key ); 00526 if( i == _data->shaders.end() ) 00527 return; 00528 00529 const Object& object = i->second; 00530 glDeleteShader( object.id ); 00531 _data->shaders.erase( i ); 00532 } 00533 00534 template< class T > 00535 Accum* ObjectManager<T>::getEqAccum( const T& key ) const 00536 { 00537 typename AccumHash::const_iterator i = _data->accums.find( key ); 00538 if( i == _data->accums.end( )) 00539 return 0; 00540 00541 return i->second; 00542 } 00543 00544 template< class T > 00545 Accum* ObjectManager<T>::newEqAccum( const T& key ) 00546 { 00547 if( _data->accums.find( key ) != _data->accums.end( )) 00548 { 00549 EQWARN << "Requested new Accumulation for existing key" << std::endl; 00550 return 0; 00551 } 00552 00553 Accum* accum = new Accum( _data->glewContext ); 00554 _data->accums[ key ] = accum; 00555 return accum; 00556 } 00557 00558 template< class T > 00559 Accum* ObjectManager<T>::obtainEqAccum( const T& key ) 00560 { 00561 Accum* accum = getEqAccum( key ); 00562 if( accum ) 00563 return accum; 00564 return newEqAccum( key ); 00565 } 00566 00567 template< class T > 00568 void ObjectManager<T>::deleteEqAccum( const T& key ) 00569 { 00570 typename AccumHash::iterator i = _data->accums.find( key ); 00571 if( i == _data->accums.end( )) 00572 return; 00573 00574 Accum* accum = i->second; 00575 _data->accums.erase( i ); 00576 00577 accum->exit(); 00578 delete accum; 00579 } 00580 00581 // eq::CompressorData object functions 00582 template< class T > 00583 GPUCompressor* ObjectManager<T>::getEqUploader( const T& key ) const 00584 { 00585 typename UploaderHash::const_iterator i = _data->eqUploaders.find( key ); 00586 if( i == _data->eqUploaders.end( )) 00587 return 0; 00588 00589 return i->second; 00590 } 00591 00592 template< class T > 00593 GPUCompressor* ObjectManager<T>::newEqUploader( const T& key ) 00594 { 00595 if( _data->eqUploaders.find( key ) != _data->eqUploaders.end( )) 00596 { 00597 EQWARN << "Requested new Accumulation for existing key" << std::endl; 00598 return 0; 00599 } 00600 00601 GPUCompressor* compressorData = new GPUCompressor( _data->glewContext ); 00602 _data->eqUploaders[ key ] = compressorData; 00603 return compressorData; 00604 } 00605 00606 template< class T > 00607 GPUCompressor* ObjectManager<T>::obtainEqUploader( const T& key ) 00608 { 00609 GPUCompressor* compressorData = getEqUploader( key ); 00610 if( compressorData ) 00611 return compressorData; 00612 return newEqUploader( key ); 00613 } 00614 00615 template< class T > 00616 void ObjectManager<T>::deleteEqUploader( const T& key ) 00617 { 00618 typename UploaderHash::iterator i = _data->eqUploaders.find( key ); 00619 if( i == _data->eqUploaders.end( )) 00620 return; 00621 00622 GPUCompressor* compressorData = i->second; 00623 _data->eqUploaders.erase( i ); 00624 00625 delete compressorData; 00626 } 00627 00628 // eq::Texture object functions 00629 template< class T > 00630 bool ObjectManager<T>::supportsEqTexture() const 00631 { 00632 return (GLEW_ARB_texture_rectangle); 00633 } 00634 00635 template< class T > 00636 Texture* ObjectManager<T>::getEqTexture( const T& key ) const 00637 { 00638 typename TextureHash::const_iterator i = _data->eqTextures.find( key ); 00639 if( i == _data->eqTextures.end( )) 00640 return 0; 00641 00642 return i->second; 00643 } 00644 00645 template< class T > 00646 Texture* ObjectManager<T>::newEqTexture( const T& key, const GLenum target ) 00647 { 00648 if( _data->eqTextures.find( key ) != _data->eqTextures.end( )) 00649 { 00650 EQWARN << "Requested new eqTexture for existing key" << std::endl; 00651 return 0; 00652 } 00653 00654 Texture* texture = new Texture( target, _data->glewContext ); 00655 _data->eqTextures[ key ] = texture; 00656 return texture; 00657 } 00658 00659 template< class T > 00660 Texture* ObjectManager<T>::obtainEqTexture( const T& key, const GLenum target ) 00661 { 00662 Texture* texture = getEqTexture( key ); 00663 if( texture ) 00664 return texture; 00665 return newEqTexture( key, target ); 00666 } 00667 00668 template< class T > 00669 void ObjectManager<T>::deleteEqTexture( const T& key ) 00670 { 00671 typename TextureHash::iterator i = _data->eqTextures.find( key ); 00672 if( i == _data->eqTextures.end( )) 00673 return; 00674 00675 Texture* texture = i->second; 00676 _data->eqTextures.erase( i ); 00677 00678 texture->flush(); 00679 delete texture; 00680 } 00681 00682 // eq::util::BitmapFont object functions 00683 template< class T > 00684 util::BitmapFont< T >* ObjectManager<T>::getEqBitmapFont( const T& key ) const 00685 { 00686 typename FontHash::const_iterator i = _data->eqFonts.find( key ); 00687 if( i == _data->eqFonts.end( )) 00688 return 0; 00689 00690 return i->second; 00691 } 00692 00693 template< class T > 00694 util::BitmapFont< T >* ObjectManager<T>::newEqBitmapFont( const T& key ) 00695 { 00696 if( _data->eqFonts.find( key ) != _data->eqFonts.end( )) 00697 { 00698 EQWARN << "Requested new eqFont for existing key" << std::endl; 00699 return 0; 00700 } 00701 00702 util::BitmapFont< T >* font = new util::BitmapFont<T>( *this, key ); 00703 _data->eqFonts[ key ] = font; 00704 return font; 00705 } 00706 00707 template< class T > 00708 util::BitmapFont< T >* ObjectManager<T>::obtainEqBitmapFont( const T& key ) 00709 { 00710 util::BitmapFont< T >* font = getEqBitmapFont( key ); 00711 if( font ) 00712 return font; 00713 return newEqBitmapFont( key ); 00714 } 00715 00716 template< class T > 00717 void ObjectManager<T>::deleteEqBitmapFont( const T& key ) 00718 { 00719 typename FontHash::iterator i = _data->eqFonts.find( key ); 00720 if( i == _data->eqFonts.end( )) 00721 return; 00722 00723 util::BitmapFont< T >* font = i->second; 00724 _data->eqFonts.erase( i ); 00725 00726 font->exit(); 00727 delete font; 00728 } 00729 00730 // eq::FrameBufferObject object functions 00731 template< class T > 00732 bool ObjectManager<T>::supportsEqFrameBufferObject() const 00733 { 00734 return (GLEW_EXT_framebuffer_object); 00735 } 00736 00737 template< class T > 00738 FrameBufferObject* ObjectManager<T>::getEqFrameBufferObject( const T& key ) 00739 const 00740 { 00741 typename FBOHash::const_iterator i = _data->eqFrameBufferObjects.find(key); 00742 if( i == _data->eqFrameBufferObjects.end( )) 00743 return 0; 00744 00745 return i->second; 00746 } 00747 00748 template< class T > 00749 FrameBufferObject* ObjectManager<T>::newEqFrameBufferObject( const T& key ) 00750 { 00751 if( _data->eqFrameBufferObjects.find( key ) != 00752 _data->eqFrameBufferObjects.end( )) 00753 { 00754 EQWARN << "Requested new eqFrameBufferObject for existing key" 00755 << std::endl; 00756 return 0; 00757 } 00758 00759 FrameBufferObject* frameBufferObject = 00760 new FrameBufferObject( _data->glewContext ); 00761 _data->eqFrameBufferObjects[ key ] = frameBufferObject; 00762 return frameBufferObject; 00763 } 00764 00765 template< class T > 00766 FrameBufferObject* ObjectManager<T>::obtainEqFrameBufferObject( const T& key ) 00767 { 00768 FrameBufferObject* frameBufferObject = getEqFrameBufferObject( key ); 00769 if( frameBufferObject ) 00770 return frameBufferObject; 00771 return newEqFrameBufferObject( key ); 00772 } 00773 00774 template< class T > 00775 void ObjectManager<T>::deleteEqFrameBufferObject( const T& key ) 00776 { 00777 typename FBOHash::iterator i = _data->eqFrameBufferObjects.find(key); 00778 if( i == _data->eqFrameBufferObjects.end( )) 00779 return; 00780 00781 FrameBufferObject* frameBufferObject = i->second; 00782 _data->eqFrameBufferObjects.erase( i ); 00783 00784 frameBufferObject->exit(); 00785 delete frameBufferObject; 00786 } 00787 00788 } 00789 }