00001
00002 #include "Framebuffer.h"
00003 #include "Error.h"
00004 #include "Program.h"
00005 #include "Property.h"
00006 #include "Sampler.h"
00007 #include "PointerProperty.h"
00008 #include "Renderbuffer.h"
00009 #include "Rendergroup.h"
00010 #include "PropertyProxy.h"
00011 #include "XMLNode.h"
00012
00013 namespace RenderTools {
00014
00015 GLuint Framebuffer::s_defaultFramebufferID = 0;
00016 GLuint Framebuffer::s_defaultReadbufferID = 0;
00017 GLuint Framebuffer::s_defaultDrawbufferID = 0;
00018
00019 Framebuffer::Framebuffer( void ):
00020 AbstractPropertyContainer(),
00021 m_w(0),
00022 m_h(0),
00023 m_id(0){
00024
00025 }
00026
00027 PropertyPtr Framebuffer::create( const XMLNodePtr & xml ){
00028 FramebufferPtr p( new Framebuffer() );
00029 p->setName( xml );
00030 p->createProperties();
00031 p->setProperties( xml, false );
00032 return( dynamic_pointer_cast< AbstractProperty, Framebuffer >( p ) );
00033 }
00034
00035 void Framebuffer::createProperties( void ){
00036 AbstractPropertyContainer::createProperties();
00037 createProperty( this, "colorbuffers", & m_colorbuffers );
00038 createProperty( this, "depthbuffer", & m_depthbuffer );
00039 createProperty( this, "stencilbuffer", & m_stencilbuffer );
00040 createProperty( this, "width", & m_w );
00041 createProperty( this, "height", & m_h );
00042 }
00043
00044
00045 const string Framebuffer::getTypeName( bool ofComponent ) const {
00046 return( "Framebuffer" );
00047 }
00048
00052 Framebuffer::~Framebuffer( void ){
00053 if( isInitialized() ){
00054 glDeleteFramebuffers( 1, & m_id );
00055 }
00056 }
00057
00062 void Framebuffer::addRenderbuffer( const RenderbufferPtr buffer, bool send ){
00063
00064 if( ! buffer )Error::error( Error::NULL_POINTER, __FILE__, __LINE__ );
00065
00066 GLuint attachment = 0;
00067
00068
00069 switch( buffer->getType() ){
00070 case Renderbuffer::COLORBUFFER:
00071
00072 #ifdef GL_MAX_COLOR_ATTACHMENTS
00073 if( (int)m_colorbuffers->size() >= glGetInteger( GL_MAX_COLOR_ATTACHMENTS ) ){
00074 Error::warning( Error::TOO_MANY_COLORBUFFERS, __FILE__, __LINE__ );
00075 }
00076 #endif
00077
00078 attachment = GL_COLOR_ATTACHMENT0 + m_colorbuffers->size();
00079
00080 m_colorbuffers->addProperty( buffer, false );
00081 break;
00082 case Renderbuffer::STENCILBUFFER:
00083 if( m_stencilbuffer != NULL ){
00084 Error::warning( Error::STENCILBUFFER_ALREADY_EXISTS, __FILE__, __LINE__ );
00085 }
00086 #ifdef GL_STENCIL_ATTACHMENT
00087 attachment = GL_STENCIL_ATTACHMENT;
00088
00089 m_stencilbuffer->setPointer( buffer );
00090 #endif
00091 break;
00092 case Renderbuffer::DEPTHBUFFER:
00093 if( m_depthbuffer != NULL ){
00094 Error::warning( Error::DEPTHBUFFER_ALREADY_EXISTS, __FILE__, __LINE__ );
00095 }
00096
00097 #ifdef GL_DEPTH_ATTACHMENT
00098 attachment = GL_DEPTH_ATTACHMENT;
00099 m_depthbuffer->setPointer( buffer );
00100 #endif
00101 break;
00102 case Renderbuffer::DEPTHSTENCILBUFFER:
00104 if( m_depthbuffer != NULL ){
00105 Error::warning( Error::DEPTHBUFFER_ALREADY_EXISTS, __FILE__, __LINE__ );
00106 }
00107 if( m_stencilbuffer != NULL ){
00108 Error::warning( Error::STENCILBUFFER_ALREADY_EXISTS, __FILE__, __LINE__ );
00109 }
00110
00111 #ifdef GL_DEPTH_STENCIL
00112 m_depthbuffer->setPointer( buffer );
00113 m_stencilbuffer->setPointer( buffer );
00114 #endif
00115 break;
00116 case Renderbuffer::UNACCEPTABLE:
00117 Error::error( Error::RENDERBUFFER_UNACCEPTABLE_TYPE, __FILE__, __LINE__ );
00118 }
00119
00120 if( send ){
00121 sendPropertyEvent( PropertyEvent( PropertyEvent::CHANGED, PropertyPtr() ) );
00122 }
00123 }
00124
00125 void Framebuffer::onInitialize( void ){
00126
00128 if( glIsBuffer( m_id ) == GL_FALSE ){
00129 glGenFramebuffers( 1, & m_id );
00130 }
00131
00132 glBindFramebuffer( GL_FRAMEBUFFER, m_id );
00133
00134 for( unsigned int i = 0; i < m_colorbuffers->size(); i++ ){
00135 m_colorbuffers->getItem( i )->initialize( true );
00136 m_colorbuffers->getItem( i )->bind();
00137
00138 RenderbufferProxyPtr proxy = m_colorbuffers->getItem( i );
00139 const SamplerPtr sampler = proxy->getPointer()->getSamplerProxy()->getPointer();
00140
00141 Error::assertNoErrors( __FILE__, __LINE__ );
00142
00143 if( sampler ){
00144 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, sampler->getTarget(), sampler->getID(), 0 );
00145 }
00146 else{
00147 glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, m_colorbuffers->getItem( i )->getPointer()->getID() );
00148 }
00149 }
00150
00151 #ifdef GL_DEPTH_ATTACHMENT
00152 if( m_depthbuffer->getPointer() ){
00153 m_depthbuffer->bind();
00154
00155 SamplerPtr sampler = m_depthbuffer->getPointer()->getSamplerProxy()->getPointer();
00156 if( sampler ){
00157 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, sampler->getTarget(), sampler->getID(), 0 );
00158 }
00159 else{
00160 glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer->getPointer()->getID() );
00161 }
00162 }
00163 #endif
00164
00165 #ifdef GL_STENCIL_ATTACHMENT
00166 if( m_stencilbuffer->getPointer() ){
00167 m_stencilbuffer->bind();
00168
00169 SamplerPtr sampler = m_stencilbuffer->getPointer()->getSamplerProxy()->getPointer();
00170 if( sampler ){
00171 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, sampler->getTarget(), sampler->getID(), 0 );
00172 }
00173 else{
00174 glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilbuffer->getPointer()->getID() );
00175 }
00176 }
00177 #endif
00178
00180 Error::checkFramebufferStatus( __FILE__, __LINE__ );
00181
00183 unbind();
00184 }
00185
00186 void Framebuffer::onBind( int unit ){
00187 #ifdef GL_FRAMEBUFFER
00188 glBindFramebuffer( GL_FRAMEBUFFER, m_id );
00189 #endif
00190 #ifdef GL_READ_FRAMEBUFFER
00191 glBindFramebuffer( GL_READ_FRAMEBUFFER, m_id );
00192 #endif
00193 #ifdef GL_DRAW_FRAMEBUFFER
00194 glBindFramebuffer( GL_DRAW_FRAMEBUFFER, m_id );
00195 #endif
00196 #ifndef RT_GLES
00197 GLuint n = glGetInteger( GL_MAX_COLOR_ATTACHMENTS );
00198 GLenum * attachments = new GLenum[ n ];
00199 for( unsigned int i = 0; i < m_colorbuffers->size(); i++ ){
00200 attachments[i] = GL_COLOR_ATTACHMENT0 + i;
00201 }
00202 glDrawBuffers( m_colorbuffers->size(), attachments );
00203 delete [] attachments;
00204 #else
00205 for( unsigned int i = 0; i < m_colorbuffers->size(); i++ ){
00206 ( * m_colorbuffers )[ i ]->bind();
00207 }
00208 if( m_depthbuffer->getPointer() ){
00209 m_depthbuffer->bind();
00210 }
00211 if( m_stencilbuffer->getPointer() ){
00212 m_stencilbuffer->bind();
00213 }
00214 #endif
00215 Error::checkFramebufferStatus( __FILE__, __LINE__ );
00216 }
00217
00218 void Framebuffer::onUnbind( int unit ){
00219 #ifdef GL_FRAMEBUFFER
00220 glBindFramebuffer( GL_FRAMEBUFFER, s_defaultFramebufferID );
00221 #endif
00222 #ifdef GL_READ_FRAMEBUFFER
00223 glBindFramebuffer( GL_READ_FRAMEBUFFER, s_defaultReadbufferID );
00224 #endif
00225 #ifdef GL_DRAW_FRAMEBUFFER
00226 glBindFramebuffer( GL_DRAW_FRAMEBUFFER, s_defaultDrawbufferID );
00227 #endif
00228 }
00229
00236 void Framebuffer::copy( const FramebufferPtr from, const FramebufferPtr to ){
00237
00238 Error::assertNoErrors( __FILE__, __LINE__ );
00239
00240
00241 GLbitfield mask = 0x0;
00242 #ifdef GL_COLOR_BUFFER_BIT
00243 if( from->hasColorBuffer() ) mask |= GL_COLOR_BUFFER_BIT;
00244 #endif
00245 #ifdef GL_DEPTH_BUFFER_BIT
00246 if( from->hasDepthBuffer() ) mask |= GL_DEPTH_BUFFER_BIT;
00247 #endif
00248 #ifdef GL_STENCIL_BUFFER_BIT
00249 if( from->hasStencilBuffer() ) mask |= GL_STENCIL_BUFFER_BIT;
00250 #endif
00251
00252
00253 #ifdef GL_FRAMEBUFFER
00254 glBindFramebuffer( GL_FRAMEBUFFER, from->getID() );
00255 #endif
00256 #ifdef GL_READ_FRAMEBUFFER
00257 glBindFramebuffer( GL_READ_FRAMEBUFFER, from->getID() );
00258 #endif
00259 Error::assertNoErrors( __FILE__, __LINE__ );
00260 #ifdef GL_DRAW_FRAMEBUFFER
00261 glBindFramebuffer( GL_DRAW_FRAMEBUFFER, to->getID() );
00262 #endif
00263 Error::assertNoErrors( __FILE__, __LINE__ );
00264
00265 #if glBlitFramebuffer
00266 glBlitFramebuffer( 0, 0, from->getWidth(), from->getHeight(),
00267 0, 0, to->getWidth(), to->getHeight(),
00268 mask,
00269 GL_NEAREST );
00270 #endif
00271
00272 Error::assertNoErrors( __FILE__, __LINE__ );
00273
00274 }
00275
00276 void Framebuffer::copy( const SamplerPtr s, GLuint to ){
00278 }
00279
00280 bool Framebuffer::hasColorBuffer( void ) const {
00281 return( m_colorbuffers->size() > 0 );
00282 }
00283
00284 bool Framebuffer::hasStencilBuffer( void ) const {
00285 return( m_stencilbuffer != NULL );
00286 }
00287
00288 bool Framebuffer::hasDepthBuffer( void ) const {
00289 return( m_depthbuffer != NULL );
00290 }
00291
00292 GLuint Framebuffer::getID( void ) const {
00293 return( m_id ); }
00294
00295
00296 GLuint Framebuffer::getWidth( void ) const {
00297 return( m_w ); }
00298
00299
00300 GLuint Framebuffer::getHeight( void ) const {
00301 return( m_h );
00302 }
00303
00304 void Framebuffer::setDefaultFramebufferID( GLuint id ){
00305 s_defaultFramebufferID = id;
00306 }
00307
00308 void Framebuffer::setDefaultReadbufferID( GLuint id ){
00309 s_defaultReadbufferID = id;
00310 }
00311
00312 void Framebuffer::setDefaultDrawbufferID( GLuint id ){
00313 s_defaultDrawbufferID = id;
00314 }
00315
00316 GLuint Framebuffer::getDefaultFramebufferID( void ){
00317 return( s_defaultFramebufferID );
00318 }
00319
00320 GLuint Framebuffer::getDefaultReadbufferID( void ){
00321 return( s_defaultReadbufferID );
00322 }
00323
00324 GLuint Framebuffer::getDefaultDrawbufferID( void ){
00325 return( s_defaultDrawbufferID );
00326 }
00327
00328 };
00329