frameBufferObject.cpp

00001 
00002 /* Copyright (c) 2008-2009, Cedric Stalder <cedric.stalder@gmail.com>
00003                  2009, Stefan Eilemann <eile@equalizergraphics.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 "frameBufferObject.h"
00020 
00021 #ifdef WIN32
00022 #  define bzero( ptr, size ) memset( ptr, 0, size );
00023 #endif
00024 
00025 namespace eq
00026 {
00027 
00028 FrameBufferObject::FrameBufferObject( GLEWContext* glewContext )
00029     : _fboID( 0 )
00030     , _width( 0 )
00031     , _height( 0 )
00032     , _depth( glewContext )
00033     , _stencil( glewContext )
00034     , _glewContext( glewContext )
00035     , _valid( false )
00036 {
00037     EQASSERT( GLEW_EXT_framebuffer_object );
00038 
00039     _colors.push_back( new Texture( glewContext ));
00040 
00041     _colors[0]->setFormat( GL_RGBA );
00042     _depth.setFormat( GL_DEPTH_COMPONENT );
00043     _stencil.setFormat( GL_STENCIL_INDEX );
00044 }
00045 
00046 FrameBufferObject::~FrameBufferObject()
00047 {
00048     exit();
00049     for( size_t i = 0; i < _colors.size(); ++i )
00050     {
00051         delete _colors[i];
00052         _colors[i] = 0;
00053     }
00054 }
00055 
00056 void FrameBufferObject::exit()
00057 {
00058     CHECK_THREAD( _thread );
00059     if( _fboID )
00060     {
00061         glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
00062         glDeleteFramebuffersEXT( 1, &_fboID );
00063         _fboID = 0;
00064     }
00065 
00066     for( size_t i = 0; i < _colors.size(); ++i )
00067         _colors[i]->flush();
00068     _depth.flush();
00069     _stencil.flush();
00070 }
00071 
00072 void FrameBufferObject::setColorFormat( const GLuint format )
00073 {
00074     for( size_t i = 0; i < _colors.size(); ++i )
00075         _colors[ i ]->setFormat( format );
00076 }
00077 
00078 bool FrameBufferObject::addColorTexture( )
00079 {
00080     if( _colors.size() >= 16 )
00081     {
00082         EQERROR << "Too many color textures, can't add another one";
00083         return false;
00084     }
00085 
00086     _colors.push_back( new Texture( _glewContext ));
00087     _colors.back()->setFormat( _colors.front()->getFormat( ));
00088 
00089     _valid = false;
00090     return true;
00091 }
00092 
00093 bool FrameBufferObject::init( const int width    , const int height,
00094                               const int depthSize, const int stencilSize )
00095 {
00096     CHECK_THREAD( _thread );
00097 
00098     if( _fboID )
00099     {
00100         _error = "FBO already initialized";
00101         EQWARN << _error << std::endl;
00102         return false;
00103     }
00104 
00105     // generate and bind the framebuffer
00106     glGenFramebuffersEXT( 1, &_fboID );
00107     glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _fboID );
00108 
00109     // create and bind textures
00110     for( size_t i = 0; i < _colors.size(); ++i )
00111         _colors[i]->bindToFBO( GL_COLOR_ATTACHMENT0 + i, width, height );
00112 
00113     if ( depthSize > 0 )
00114         _depth.bindToFBO( GL_DEPTH_ATTACHMENT, width, height );
00115 
00116   /*  if ( stencilSize > 0 )
00117         _stencil.bindToFBO( GL_STENCIL_ATTACHMENT, width, height );
00118 */
00119     _width  = width;
00120     _height = height;
00121     _valid  = true;
00122     return _checkFBOStatus();
00123 }
00124 
00125 bool FrameBufferObject::_checkFBOStatus()
00126 {
00127     switch( glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ))
00128     {
00129         case GL_FRAMEBUFFER_COMPLETE_EXT:
00130             EQVERB << "FBO supported and complete" << std::endl;
00131             return true;
00132 
00133         case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
00134             _error = "Unsupported framebuffer format";
00135             break;
00136         case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
00137             _error = "Framebuffer incomplete, missing attachment";
00138             break;
00139         case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
00140             _error = "Framebuffer incomplete, incomplete attachment";
00141             break;
00142         case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
00143             _error = "Framebuffer incomplete, \
00144                       attached images must have same dimensions";
00145             break;
00146         case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
00147             _error = "Framebuffer incomplete, \
00148                       attached images must have same format";
00149             break;
00150         case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
00151             _error = "Framebuffer incomplete, missing draw buffer";
00152             break;
00153         case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
00154             _error = "Framebuffer incomplete, missing read buffer";
00155             break;
00156         default:
00157             break;
00158     }
00159 
00160     EQERROR << _error << std::endl;
00161     return false;
00162 }
00163 
00164 void FrameBufferObject::bind()
00165 {
00166     CHECK_THREAD( _thread );
00167     EQASSERT( _fboID );
00168     glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _fboID );
00169 }
00170 
00171 void FrameBufferObject::unbind()
00172 {
00173     glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); 
00174 }
00175 
00176 bool FrameBufferObject::resize( const int width, const int height )
00177 {
00178     CHECK_THREAD( _thread );
00179     EQASSERT( width > 0 && height > 0 );
00180 
00181     if( _width == width && _height == height && _valid )
00182        return true;
00183 
00184     for( size_t i = 0; i < _colors.size(); ++i )
00185         _colors[i]->resize( width, height );
00186 
00187     if ( _depth.isValid( ))
00188         _depth.resize( width, height );
00189     
00190     if ( _stencil.isValid( ))
00191         _stencil.resize( width, height );
00192 
00193     _width  = width;
00194     _height = height;
00195     _valid  = true;
00196 
00197     return _checkFBOStatus();
00198 }
00199 
00200 PixelViewport FrameBufferObject::getPixelViewport() const
00201 {
00202     return PixelViewport( 0, 0, _width, _height );
00203 }
00204 
00205 }
00206 
Generated on Mon Aug 10 18:58:32 2009 for Equalizer 0.9 by  doxygen 1.5.8