Visualization Library 2.1.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
FramebufferObject.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
35 #include <vlCore/Say.hpp>
36 #include <vlCore/Log.hpp>
37 
38 using namespace vl;
39 
40 namespace
41 {
42  class ScopedFBOBinding
43  {
44  GLint mPrevFBO;
45  public:
46  ScopedFBOBinding( FramebufferObject* fbo )
47  {
48  VL_CHECK( fbo );
49  VL_CHECK( fbo->handle() );
50  /*if ( !fbo->handle() )
51  fbo->create();*/
52 
53  // saves current FBO
54  mPrevFBO = 0;
55  glGetIntegerv( GL_FRAMEBUFFER_BINDING, &mPrevFBO ); VL_CHECK_OGL()
56 
57  // binds this FBO
58  VL_glBindFramebuffer( GL_FRAMEBUFFER, fbo->handle() ); VL_CHECK_OGL()
59  }
60 
61  ~ScopedFBOBinding()
62  {
63  // restore the FBO
64  VL_glBindFramebuffer( GL_FRAMEBUFFER, mPrevFBO ); VL_CHECK_OGL()
65  }
66  };
67 }
68 //-----------------------------------------------------------------------------
69 // FramebufferObject
70 //-----------------------------------------------------------------------------
72 {
73  std::map<int, const char*> fbo_attachments;
74 
75  fbo_attachments[GL_NONE] = "GL_NONE";
76  fbo_attachments[GL_BACK_LEFT] = "GL_BACK_LEFT";
77  fbo_attachments[GL_BACK_RIGHT] = "GL_BACK_RIGHT";
78  fbo_attachments[GL_FRONT_LEFT] = "GL_FRONT_LEFT";
79  fbo_attachments[GL_FRONT_RIGHT] = "GL_FRONT_RIGHT";
80  fbo_attachments[GL_AUX0] = "GL_AUX0";
81  fbo_attachments[GL_AUX1] = "GL_AUX1";
82  fbo_attachments[GL_AUX2] = "GL_AUX2";
83  fbo_attachments[GL_AUX3] = "GL_AUX3";
84  fbo_attachments[GL_COLOR_ATTACHMENT0] = "GL_COLOR_ATTACHMENT0";
85  fbo_attachments[GL_COLOR_ATTACHMENT1] = "GL_COLOR_ATTACHMENT1";
86  fbo_attachments[GL_COLOR_ATTACHMENT2] = "GL_COLOR_ATTACHMENT2";
87  fbo_attachments[GL_COLOR_ATTACHMENT3] = "GL_COLOR_ATTACHMENT3";
88  fbo_attachments[GL_COLOR_ATTACHMENT4] = "GL_COLOR_ATTACHMENT4";
89  fbo_attachments[GL_COLOR_ATTACHMENT5] = "GL_COLOR_ATTACHMENT5";
90  fbo_attachments[GL_COLOR_ATTACHMENT6] = "GL_COLOR_ATTACHMENT6";
91  fbo_attachments[GL_COLOR_ATTACHMENT7] = "GL_COLOR_ATTACHMENT7";
92  fbo_attachments[GL_COLOR_ATTACHMENT8] = "GL_COLOR_ATTACHMENT8";
93  fbo_attachments[GL_COLOR_ATTACHMENT9] = "GL_COLOR_ATTACHMENT9";
94  fbo_attachments[GL_COLOR_ATTACHMENT10] = "GL_COLOR_ATTACHMENT10";
95  fbo_attachments[GL_COLOR_ATTACHMENT11] = "GL_COLOR_ATTACHMENT11";
96  fbo_attachments[GL_COLOR_ATTACHMENT12] = "GL_COLOR_ATTACHMENT12";
97  fbo_attachments[GL_COLOR_ATTACHMENT13] = "GL_COLOR_ATTACHMENT13";
98  fbo_attachments[GL_COLOR_ATTACHMENT14] = "GL_COLOR_ATTACHMENT14";
99  fbo_attachments[GL_COLOR_ATTACHMENT15] = "GL_COLOR_ATTACHMENT15";
100 
101  int fbo = 0;
102  if (Has_GL_EXT_framebuffer_object||Has_GL_ARB_framebuffer_object)
103  glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
104 
105  if (fbo)
106  {
107  std::set<GLenum> legal;
108  legal.insert(GL_NONE);
109  legal.insert(GL_COLOR_ATTACHMENT0);
110  legal.insert(GL_COLOR_ATTACHMENT1);
111  legal.insert(GL_COLOR_ATTACHMENT2);
112  legal.insert(GL_COLOR_ATTACHMENT3);
113  legal.insert(GL_COLOR_ATTACHMENT4);
114  legal.insert(GL_COLOR_ATTACHMENT5);
115  legal.insert(GL_COLOR_ATTACHMENT6);
116  legal.insert(GL_COLOR_ATTACHMENT7);
117  legal.insert(GL_COLOR_ATTACHMENT8);
118  legal.insert(GL_COLOR_ATTACHMENT9);
119  legal.insert(GL_COLOR_ATTACHMENT10);
120  legal.insert(GL_COLOR_ATTACHMENT11);
121  legal.insert(GL_COLOR_ATTACHMENT12);
122  legal.insert(GL_COLOR_ATTACHMENT13);
123  legal.insert(GL_COLOR_ATTACHMENT14);
124  legal.insert(GL_COLOR_ATTACHMENT15);
125  for(unsigned i=0; i<mDrawBuffers.size(); ++i)
126  {
127  if(legal.find(mDrawBuffers[i]) == legal.end())
128  {
129  Log::error(Say("FBO bound but FramebufferObject::setDrawBuffers() called with non FBO compatible draw buffer '%s'.\n") << fbo_attachments[mDrawBuffers[i]]);
130  return false;
131  }
132  }
133  }
134  else
135  {
136  std::set<GLenum> legal;
137  legal.insert(GL_NONE);
138  legal.insert(GL_BACK_LEFT);
139  legal.insert(GL_BACK_RIGHT);
140  legal.insert(GL_FRONT_LEFT);
141  legal.insert(GL_FRONT_RIGHT);
142  legal.insert(GL_AUX0);
143  legal.insert(GL_AUX1);
144  legal.insert(GL_AUX2);
145  legal.insert(GL_AUX3);
146  for(unsigned i=0; i<mDrawBuffers.size(); ++i)
147  {
148  if(legal.find(mDrawBuffers[i]) == legal.end())
149  {
150  Log::error(Say("FBO not bound or not supported but FramebufferObject::setDrawBuffers() called with FBO specific draw buffer '%s'.\n") << fbo_attachments[mDrawBuffers[i]]);
151  return false;
152  }
153  }
154  }
155  return true;
156 }
157 //-----------------------------------------------------------------------------
159 {
160  VL_CHECK_OGL()
161 
162  VL_CHECK(!mDrawBuffers.empty())
163 
164  #ifndef NDEBUG
165  checkDrawBuffers();
166  #endif
167 
168  if (mDrawBuffers.size() > 1 && (Has_GL_ARB_draw_buffers||Has_GL_Version_2_0))
169  {
170  glDrawBuffers( (GLsizei)mDrawBuffers.size(), (const GLenum*)&mDrawBuffers[0] );
171  VL_CHECK_OGL() // If you are using RDB_BACK_LEFT/RIGHT make sure sure you have a double buffered gl context.
172  // Otherwise use FramebufferObject::setDrawBuffer(RDB_FRONT_LEFT).
173  }
174  else
175  {
176  glDrawBuffer( mDrawBuffers[0] );
177  VL_CHECK_OGL() // If you are using RDB_BACK_LEFT/RIGHT make sure sure you have a double buffered gl context.
178  // Otherwise use FramebufferObject::setDrawBuffer(RDB_FRONT_LEFT).
179  if ( mDrawBuffers.size() > 1 )
180  {
181  Log::error( "FramebufferObject::bindDrawBuffers() error:\nglDrawBuffers() not supported by the current OpenGL driver. GL_ARB_draw_buffers or OpenGL 2.0 required.\n" );
182  }
183  }
184 }
185 //-----------------------------------------------------------------------------
187 {
188  VL_CHECK_OGL();
189 
190  glReadBuffer( readBuffer() );
191 
192  VL_CHECK_OGL();
193 }
194 //-----------------------------------------------------------------------------
196 {
197  VL_CHECK_OGL();
198  VL_CHECK(openglContext());
199  openglContext()->makeCurrent(); VL_CHECK_OGL();
200 
201  if ( !mHandle )
202  {
203  VL_glGenFramebuffers( 1, ( unsigned int* )&mHandle ); VL_CHECK_OGL();
204  }
205  VL_CHECK( mHandle )
206 }
207 //-----------------------------------------------------------------------------
209 {
210  VL_CHECK_OGL();
211  VL_CHECK(openglContext());
212  openglContext()->makeCurrent(); VL_CHECK_OGL();
213 
214  removeAllAttachments();
215  if ( handle() )
216  {
217  VL_glBindFramebuffer( GL_FRAMEBUFFER, 0 ); VL_CHECK_OGL();
218  VL_glDeleteFramebuffers( 1, &mHandle ); VL_CHECK_OGL();
219  mHandle = 0;
220  }
221  setWidth( 0 );
222  setHeight( 0 );
223 }
224 //-----------------------------------------------------------------------------
226 {
227  VL_CHECK_OGL();
228  VL_CHECK(openglContext());
229  openglContext()->makeCurrent(); VL_CHECK_OGL();
230 
231  if ( externallyManaged() ) {
232  return;
233  }
234 
235  if ( !Has_FBO )
236  {
237  Log::error( "FramebufferObject::bindFramebuffer(): framebuffer object not supported.\n" );
238  return;
239  }
240 
241  if ( width() <= 0 || height() <= 0 )
242  {
243  Log::error( Say( "FramebufferObject::bindFramebuffer() called with illegal dimensions: width = %n, height = %n\n" ) << width() << height() );
244  VL_TRAP()
245  }
246 
247  // This is an error only if not default framebuffer
248  if ( handle() != 0 && mFBOAttachments.empty() )
249  {
250  Log::error( "FramebufferObject::bindFramebuffer() called with no attachment points!\n" );
251  VL_TRAP()
252  }
253 
254  /* handle() == 0: default framebuffer
255  if ( !handle() )
256  {
257  Log::error( "FramebufferObject::bindFramebuffer() called but handle() == NULL!\n" );
258  VL_TRAP()
259  }
260  */
261 
262  VL_glBindFramebuffer( target, handle() ); VL_CHECK_OGL()
263 
264 #if defined(VL_OPENGL)
265  // bind draw buffers
266  if ( target == FBB_FRAMEBUFFER || target == FBB_DRAW_FRAMEBUFFER )
267  {
268  bindDrawBuffers();
269  }
270 
271  // bind read buffer
272  if ( target == FBB_FRAMEBUFFER || target == FBB_READ_FRAMEBUFFER )
273  {
274  bindReadBuffer();
275  }
276 #endif
277 
278  #ifndef NDEBUG
279  if ( handle() )
280  {
281  GLenum status = VL_glCheckFramebufferStatus( GL_FRAMEBUFFER ); VL_CHECK_OGL()
282  if ( status != GL_FRAMEBUFFER_COMPLETE )
283  {
284  printFramebufferError( status );
285  VL_glBindFramebuffer( GL_FRAMEBUFFER, 0 ); VL_CHECK_OGL()
286  }
287  }
288  #endif
289 }
290 //-----------------------------------------------------------------------------
293 {
294  VL_CHECK_OGL();
295  VL_CHECK(openglContext());
296  openglContext()->makeCurrent(); VL_CHECK_OGL();
297 
298  if ( !Has_FBO )
299  {
300  Log::error( "FramebufferObject::checkFramebufferStatus(): framebuffer object not supported.\n" );
301  return 0;
302  }
303 
304  if ( width() <= 0 || height() <= 0 )
305  {
306  Log::error( Say( "FramebufferObject::checkFramebufferStatus() called with illegal dimensions: width = %n, height = %n\n" ) << width() << height() );
307  return 0;
308  }
309 
310  if ( mFBOAttachments.empty() )
311  {
312  Log::error( "FramebufferObject::checkFramebufferStatus() called with no attachment points!\n" );
313  return 0;
314  }
315 
316  if ( !handle() )
317  {
318  Log::error( "FramebufferObject::checkFramebufferStatus() called but handle() == NULL!\n" );
319  return 0;
320  }
321 
322  // binds the FBO for this function call
323  ScopedFBOBinding fbo_bind( this );
324 
325  // checks error
326  GLenum status = VL_glCheckFramebufferStatus( GL_FRAMEBUFFER ); VL_CHECK_OGL()
327 
328  // restore the FBO
329  if ( globalSettings()->verbosityLevel() >= vl::VEL_VERBOSITY_NORMAL )
330  printFramebufferError( status );
331 
332  VL_CHECK( status == GL_FRAMEBUFFER_COMPLETE )
333 
334  return status;
335 }
336 //-----------------------------------------------------------------------------
337 void FramebufferObject::printFramebufferError( GLenum status ) const
338 {
339  switch( status )
340  {
341  case GL_FRAMEBUFFER_COMPLETE:
342  break;
343  case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
344  Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\n" ); VL_TRAP()
345  break;
346  case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
347  Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\n" ); VL_TRAP()
348  break;
349  case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
350  Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n" ); VL_TRAP()
351  break;
352  case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
353  Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n" ); VL_TRAP()
354  break;
355  case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
356  Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER\n" ); VL_TRAP()
357  break;
358  case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
359  Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER\n" ); VL_TRAP()
360  break;
361  case GL_FRAMEBUFFER_UNSUPPORTED:
362  Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_UNSUPPORTED\n" ); VL_TRAP()
363  break;
364  case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB:
365  Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB\n" ); VL_TRAP()
366  break;
367  case GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB:
368  Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB\n" ); VL_TRAP()
369  break;
370  case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
371  Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE\n" ); VL_TRAP()
372  break;
373  }
374 }
375 //-----------------------------------------------------------------------------
377 {
378  VL_CHECK( attach_point >= AP_COLOR_ATTACHMENT0 && attach_point <= AP_COLOR_ATTACHMENT15 );
379  VL_CHECK( Has_FBO )
380  if( !Has_FBO )
381  return;
382  removeAttachment( attach_point );
383  mFBOAttachments[attach_point] = attachment;
384  attachment->mFramebufferObjects.insert( this );
385  attachment->bindAttachment( this, attach_point );
386 }
387 //-----------------------------------------------------------------------------
389 {
390  VL_CHECK( attach_point >= AP_COLOR_ATTACHMENT0 && attach_point <= AP_COLOR_ATTACHMENT15 );
391  VL_CHECK( Has_FBO )
392  if( !Has_FBO )
393  return;
394  removeAttachment( attach_point );
395  mFBOAttachments[attach_point] = attachment;
396  attachment->mFramebufferObjects.insert( this );
397  attachment->bindAttachment( this, attach_point );
398 }
399 //-----------------------------------------------------------------------------
401 {
402  VL_CHECK( Has_FBO )
403  if( !Has_FBO )
404  return;
405  removeAttachment( AP_DEPTH_ATTACHMENT );
406  mFBOAttachments[AP_DEPTH_ATTACHMENT] = attachment;
407  attachment->mFramebufferObjects.insert( this );
408  attachment->bindAttachment( this, AP_DEPTH_ATTACHMENT );
409 }
410 //-----------------------------------------------------------------------------
412 {
413  VL_CHECK( Has_FBO )
414  if( !Has_FBO )
415  return;
416  removeAttachment( AP_STENCIL_ATTACHMENT );
417  mFBOAttachments[AP_STENCIL_ATTACHMENT] = attachment;
418  attachment->mFramebufferObjects.insert( this );
419  attachment->bindAttachment( this, AP_STENCIL_ATTACHMENT );
420 }
421 //-----------------------------------------------------------------------------
423 {
424  VL_CHECK( Has_FBO )
425  if( !Has_FBO )
426  return;
427  removeAttachment( AP_DEPTH_STENCIL_ATTACHMENT );
428  mFBOAttachments[AP_DEPTH_STENCIL_ATTACHMENT] = attachment;
429  attachment->mFramebufferObjects.insert( this );
430  attachment->bindAttachment( this, AP_DEPTH_STENCIL_ATTACHMENT );
431 }
432 //-----------------------------------------------------------------------------
434 {
435  VL_CHECK( Has_FBO )
436  if( !Has_FBO )
437  return;
438  // collect for all the attachment points
439  std::vector<EAttachmentPoint> attachment_points;
440  std::map< EAttachmentPoint, ref<FBOAbstractAttachment> >::iterator it = mFBOAttachments.begin();
441  for( ; it != mFBOAttachments.end(); ++it )
442  if ( it->second == attachment )
443  attachment_points.push_back( it->first );
444 
445  // remove it from all the attachment points
446  for( unsigned i=0; i<attachment_points.size(); ++i )
447  removeAttachment( attachment_points[i] );
448 }
449 //-----------------------------------------------------------------------------
451 {
452  VL_CHECK_OGL();
453  VL_CHECK(openglContext());
454  openglContext()->makeCurrent(); VL_CHECK_OGL();
455 
456  VL_CHECK( Has_FBO )
457  if( !Has_FBO )
458  return;
459  if ( handle() )
460  {
461  // save current fbo
462  int fbo = -1;
463  glGetIntegerv( GL_FRAMEBUFFER_BINDING, &fbo ); VL_CHECK_OGL()
464  // bind this fbo
465  VL_glBindFramebuffer( GL_FRAMEBUFFER, handle() ); VL_CHECK_OGL()
466  // detach should work for any kind of buffer and texture
467  VL_glFramebufferRenderbuffer( GL_FRAMEBUFFER, attach_point, GL_RENDERBUFFER, 0 ); VL_CHECK_OGL()
468  // restore fbo
469  VL_glBindFramebuffer( GL_FRAMEBUFFER, fbo ); VL_CHECK_OGL()
470  }
471  // remove FramebufferObject from FBOAbstractAttachment
472  FBOAbstractAttachment* fbo_attachment = /* mFBOAttachments.find( attachment ) != mFBOAttachments.end() ? */ mFBOAttachments[attach_point].get() /* : NULL */;
473  if ( fbo_attachment )
474  fbo_attachment->mFramebufferObjects.erase( this );
475  mFBOAttachments.erase( attach_point );
476 }
477 //-----------------------------------------------------------------------------
479 {
480  VL_CHECK( Has_FBO )
481  if( !Has_FBO )
482  return;
483  // look for all the attachment points
484  std::vector<EAttachmentPoint> attachment_points;
485  std::map< EAttachmentPoint, ref<FBOAbstractAttachment> >::iterator it = mFBOAttachments.begin();
486  for( ; it != mFBOAttachments.end(); ++it )
487  attachment_points.push_back( it->first );
488 
489  // remove attachment points
490  for( unsigned i=0; i<attachment_points.size(); ++i )
491  removeAttachment( attachment_points[i] );
492 }
493 //-----------------------------------------------------------------------------
495 {
496  VL_CHECK_OGL()
497  VL_CHECK( Has_FBO )
498  if( !Has_FBO )
499  return;
500  VL_CHECK( texture() )
501  VL_CHECK( texture()->handle() )
502  VL_CHECK( texture()->dimension() == GL_TEXTURE_1D )
503  VL_CHECK( fbo->width() == texture()->width() );
504 
505  // binds the FBO for this function call
506  ScopedFBOBinding fbo_bind( fbo );
507 
508  VL_glFramebufferTexture1D( GL_FRAMEBUFFER, attach_point, GL_TEXTURE_1D, texture()->handle(), mipmapLevel() ); VL_CHECK_OGL()
509 
510  // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442
511  glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL()
512  glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL()
513  glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL()
514 }
515 //-----------------------------------------------------------------------------
517 {
518  VL_CHECK_OGL()
519  VL_CHECK( Has_FBO )
520  if( !Has_FBO )
521  return;
522  VL_CHECK( texture() )
523  VL_CHECK( texture()->handle() )
524  // VL_CHECK( texture()->dimension() == GL_TEXTURE_2D )
525  VL_CHECK( fbo->width() <= texture()->width() );
526  VL_CHECK( fbo->height() <= texture()->height() );
527 
528  // binds the FBO for this function call
529  ScopedFBOBinding fbo_bind( fbo );
530 
531  int target = texture()->dimension() == TD_TEXTURE_CUBE_MAP ? ( int )textureTarget() : texture()->dimension();
532  #ifndef NDEBUG
533  if( !( texture()->dimension() == TD_TEXTURE_CUBE_MAP || ( int )textureTarget() == ( int )texture()->dimension() ) )
534  {
535  Log::bug( "FBOTexture2DAttachment::init(): textureTarget() doens't match texture()->dimension().\n" );
536  }
537  #endif
538 
539  VL_glFramebufferTexture2D( GL_FRAMEBUFFER, attach_point, target, texture()->handle(), mipmapLevel() ); VL_CHECK_OGL()
540 
541  // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442
542  if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE )
543  {
544  glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL()
545  glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL()
546  glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL()
547  }
548 }
549 //-----------------------------------------------------------------------------
551 {
552  VL_CHECK_OGL()
553  VL_CHECK( Has_GL_NV_geometry_shader4||Has_GL_EXT_geometry_shader4||Has_GL_ARB_geometry_shader4||Has_GL_Version_3_2||Has_GL_Version_4_0 )
554  VL_CHECK( texture() )
555  VL_CHECK( texture()->handle() )
556 
557  // binds the FBO for this function call
558  ScopedFBOBinding fbo_bind( fbo );
559 
560  VL_glFramebufferTexture( GL_FRAMEBUFFER, attach_point, texture()->handle(), mipmapLevel() ); VL_CHECK_OGL()
561 
562  // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442
563  if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE )
564  {
565  glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL()
566  glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL()
567  glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL()
568  }
569 }
570 //-----------------------------------------------------------------------------
572 {
573  VL_CHECK_OGL()
574  VL_CHECK( Has_FBO )
575  if( !Has_FBO )
576  return;
577  VL_CHECK( texture() )
578  VL_CHECK( texture()->handle() )
579  VL_CHECK( fbo->width() <= texture()->width() );
580  VL_CHECK( fbo->height() <= texture()->height() );
581  VL_CHECK( layer() <= texture()->depth() );
582  VL_CHECK( texture()->dimension() == GL_TEXTURE_3D )
583 
584  // binds the FBO for this function call
585  ScopedFBOBinding fbo_bind( fbo );
586 
587  VL_glFramebufferTexture3D( GL_FRAMEBUFFER, attach_point, texture()->dimension(), texture()->handle(), mipmapLevel(), layer() ); VL_CHECK_OGL()
588 
589  // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442
590  if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE_ARRAY )
591  {
592  glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL()
593  glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL()
594  glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL()
595  }
596 }
597 //-----------------------------------------------------------------------------
599 {
600  VL_CHECK_OGL()
601  VL_CHECK( Has_FBO )
602  VL_CHECK( Has_GL_EXT_texture_array||Has_GL_NV_geometry_shader4||Has_GL_ARB_geometry_shader4||Has_GL_EXT_geometry_shader4||Has_GL_Version_3_2||Has_GL_Version_4_0 )
603  if( !Has_FBO )
604  return;
605  if( !( Has_GL_EXT_texture_array||Has_GL_NV_geometry_shader4||Has_GL_ARB_geometry_shader4||Has_GL_EXT_geometry_shader4||Has_GL_Version_3_2||Has_GL_Version_4_0 ) )
606  return;
607  VL_CHECK( texture() )
608  VL_CHECK( texture()->handle() )
609  VL_CHECK( texture()->dimension() == GL_TEXTURE_2D_ARRAY || texture()->dimension() == GL_TEXTURE_1D_ARRAY )
610  VL_CHECK( fbo->width() <= texture()->width() );
611  VL_CHECK( fbo->height() <= texture()->height() );
612  // VL_CHECK( layer() <= texture()->depth() );
613 
614  // binds the FBO for this function call
615  ScopedFBOBinding fbo_bind( fbo );
616 
617  VL_glFramebufferTextureLayer( GL_FRAMEBUFFER, attach_point, texture()->handle(), mipmapLevel(), layer() ); VL_CHECK_OGL()
618 
619  // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442
620  if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE_ARRAY )
621  {
622  glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL()
623  glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL()
624  glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL()
625  }
626 }
627 //-----------------------------------------------------------------------------
629 {
630  std::set< ref<FramebufferObject> > fbos = fboFramebuffers();
631  for( std::set< ref<FramebufferObject> >::iterator it = fbos.begin(); it != fbos.end(); ++it )
632  it->get_writable()->removeAttachment( this );
633 }
634 //-----------------------------------------------------------------------------
636 {
637  VL_CHECK_OGL()
638  VL_CHECK( Has_FBO )
639  if( !Has_FBO )
640  return;
641  if ( !mHandle )
642  {
643  VL_glGenRenderbuffers( 1, &mHandle ); VL_CHECK_OGL()
644  mReallocateRenderbuffer = true;
645  }
646  VL_CHECK( mHandle )
647 }
648 //-----------------------------------------------------------------------------
650 {
651  VL_CHECK_OGL()
652  VL_CHECK( Has_FBO )
653  if( !Has_FBO )
654  return;
655 
656  unbindFromAllFBO();
657 
658  mWidth = 0;
659  mHeight = 0;
660  if ( mHandle )
661  {
662  VL_glDeleteRenderbuffers( 1, &mHandle ); VL_CHECK_OGL()
663  mHandle = 0;
664  mReallocateRenderbuffer = true;
665  }
666 }
667 //-----------------------------------------------------------------------------
668 void FBORenderbufferAttachment::initStorage( int w, int h, int samp )
669 {
670  VL_CHECK_OGL()
671  VL_CHECK( handle() );
672  VL_CHECK( w>0 && h>0 );
673  VL_CHECK( Has_FBO )
674  if( !Has_FBO )
675  return;
676 
677  if ( w != width() || h != height() || samp != samples() || mReallocateRenderbuffer )
678  {
679  mWidth = w;
680  mHeight = h;
681  mSamples = samp;
682  VL_glBindRenderbuffer( GL_RENDERBUFFER, handle() ); VL_CHECK_OGL()
683  if ( Has_FBO_Multisample )
684  {
685  VL_glRenderbufferStorageMultisample( GL_RENDERBUFFER, samples(), internalType(), width(), height() ); VL_CHECK_OGL()
686  }
687  else
688  {
689  VL_CHECK(samples() == 0)
690  if (samples())
691  Log::error("FBORenderbufferAttachment::initStorage() requesting multisampling storage but current OpenGL implementation does not support it!\n");
692  VL_glRenderbufferStorage( GL_RENDERBUFFER, internalType(), width(), height() ); VL_CHECK_OGL()
693  }
694  VL_glBindRenderbuffer( GL_RENDERBUFFER, 0 ); VL_CHECK_OGL()
695  mReallocateRenderbuffer = false;
696  }
697 }
698 //-----------------------------------------------------------------------------
700 {
701  VL_CHECK_OGL()
702  VL_CHECK( Has_FBO )
703  if( !Has_FBO )
704  return;
705 
706  if (!handle())
707  createRenderBuffer();
708 
709  // binds the FBO for this function call
710  ScopedFBOBinding fbo_bind( fbo );
711 
712  // choose the maximum dimension
713  int actual_w = width() == 0 ? fbo->width() : width();
714  int actual_h = height() == 0 ? fbo->height() : height();
715  VL_CHECK( actual_w >= fbo->width() );
716  VL_CHECK( actual_h >= fbo->height() );
717  initStorage( actual_w, actual_h, samples() );
718 
719  // attach the renderbuffer to the framebuffer's attachment point
720  VL_glFramebufferRenderbuffer( GL_FRAMEBUFFER, attach_point, GL_RENDERBUFFER, handle() ); VL_CHECK_OGL()
721 }
virtual void bindAttachment(FramebufferObject *fbo, EAttachmentPoint attach_point)
EAttachmentPoint
virtual void bindAttachment(FramebufferObject *fbo, EAttachmentPoint attach_point)=0
A simple String formatting class.
Definition: Say.hpp:124
Abstract class that represents a framebuffer object attachment to be used with FramebufferObject.
virtual void bindAttachment(FramebufferObject *fbo, EAttachmentPoint attach_point)
Base class for all the framebuffer texture attachments (see also FramebufferObject).
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
virtual void bindAttachment(FramebufferObject *fbo, EAttachmentPoint attach_point)
bool Has_GL_Version_4_0
Definition: OpenGL.cpp:60
virtual void bindAttachment(FramebufferObject *fbo, EAttachmentPoint attach_point)
int width() const
The width of a render target.
bool checkDrawBuffers() const
Returns true if the draw buffers bound to this render target are legal for this render target type...
void createRenderBuffer()
Creates a renderbuffer object calling glGenRenderbuffers().
< Outputs normal information messages, plus all error messages.
void deleteRenderBuffer()
Deletes the renderbuffer object created with the createRenderBuffer() method.
virtual void unbindFromAllFBO()
Removes the FBO attachment from all bound FBO render targets.
void addDepthAttachment(FBOAbstractAttachment *attachment)
Binds a depth attachment to a framebuffer object.
Visualization Library main namespace.
void addDepthStencilAttachment(FBOAbstractAttachment *attachment)
Binds a depth-stencil attachment to a framebuffer object.
void addTextureAttachment(EAttachmentPoint attach_point, FBOAbstractTextureAttachment *attachment)
Binds a texture attachment to a framebuffer object.
static void bug(const String &message)
Use this function to provide information about programming errors: wrong parameter initialization...
Definition: Log.cpp:175
#define VL_TRAP()
Definition: checks.hpp:70
void removeAttachment(FBOAbstractAttachment *attachment)
Unbinds the given attachments from a framebuffer object.
void removeAllAttachments()
Unbinds all attachments bound to a framebuffer object.
void addColorAttachment(EAttachmentPoint attach_point, FBOColorBufferAttachment *attachment)
Binds a color attachment to a framebuffer object.
void bindAttachment(FramebufferObject *fbo, EAttachmentPoint attach_point)
bool Has_GL_Version_3_2
Definition: OpenGL.cpp:58
A color renderbuffer to be attached to a FramebufferObject.
void createFBO()
Creates a framebuffer object by calling glGenFramebuffers().
void deleteFBO()
Deletes a framebuffer object by calling glDeleteFramebuffers().
void initStorage()
The same as calling initStorage( width(), height() )
void addStencilAttachment(FBOAbstractAttachment *attachment)
Binds a stencil attachment to a framebuffer object.
void printFramebufferError(GLenum status) const
Prints a human readable description of the error code as returned by glCheckFramebufferStatus() ...
EFramebufferBind
#define VL_CHECK_OGL()
Definition: OpenGL.hpp:156
void bindReadBuffer()
Binds to the currently active framebuffer object (including the 0 one) the read buffer specified by s...
virtual void bindFramebuffer(EFramebufferBind target=FBB_FRAMEBUFFER)
Makes the framebuffer the current rendering target calling glBindFramebuffer( GL_FRAMEBUFFER, FramebufferObject::handle() ) and initializes all the previously defined attachment points.
Implements a framebuffer object to be used as a rendering target as specified by the ARB_framebuffer_...
GLenum checkFramebufferStatus()
Checks the framebuffer status and returns the value of glCheckFramebufferStatus() ...
virtual void bindAttachment(FramebufferObject *fbo, EAttachmentPoint attach_point)
bool Has_GL_Version_2_0
Definition: OpenGL.cpp:54
std::set< ref< FramebufferObject > > mFramebufferObjects
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
bool Has_FBO
Definition: OpenGL.cpp:83
#define VL_CHECK(expr)
Definition: checks.hpp:73
int height() const
The height of a render target.
void bindDrawBuffers() const
Binds to the currently active framebuffer object (including the 0 one) the draw buffers specified by ...
bool Has_FBO_Multisample
Definition: OpenGL.cpp:85
virtual GLuint handle() const
The handle of the framebuffer object as returned by glGenFramebuffers.
VLCORE_EXPORT GlobalSettings * globalSettings()
Returns VisulizationLibrary&#39;s global settings.
Definition: pimpl.cpp:52