TGLFBO.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLFBO.cxx 36675 2010-11-15 20:33:58Z matevz $
00002 // Author: Matevz Tadel, Aug 2009
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TGLFBO.h"
00013 #include <TMath.h>
00014 #include <TString.h>
00015 #include <TError.h>
00016 
00017 #include <GL/glew.h>
00018 
00019 #include <stdexcept>
00020 
00021 //______________________________________________________________________________
00022 // 
00023 // Frame-buffer object.
00024 //
00025 // Requires GL-1.5.
00026 //
00027 // Taken from Gled project, see:
00028 //   http://www.gled.org/cgi-bin/viewcvs.cgi/trunk/libsets/GledCore/Pupils/
00029 // See also:
00030 //   http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
00031 
00032 ClassImp(TGLFBO);
00033 
00034 Bool_t TGLFBO::fgRescaleToPow2       = kTRUE; // For ATI.
00035 Bool_t TGLFBO::fgMultiSampleNAWarned = kFALSE;
00036 
00037 TGLFBO::TGLFBO() :
00038    fFrameBuffer  (0),
00039    fColorTexture (0),
00040    fDepthBuffer  (0),
00041    fMSFrameBuffer(0),
00042    fMSColorBuffer(0),
00043    fW (-1),
00044    fH (-1),
00045    fMSSamples  (0),
00046    fMSCoverageSamples (0),
00047    fWScale     (1),
00048    fHScale     (1),
00049    fIsRescaled (kFALSE)
00050 {
00051    // Constructor.
00052 }
00053 
00054 //______________________________________________________________________________
00055 TGLFBO::~TGLFBO()
00056 {
00057    // Destructor.
00058 
00059    Release();
00060 }
00061 
00062 //______________________________________________________________________________
00063 void TGLFBO::Init(int w, int h, int ms_samples)
00064 {
00065    // Acquire GL resources for given width, height and number of
00066    // multi-sampling samples.
00067 
00068    static const std::string eh("TGLFBO::Init ");
00069 
00070    // Should be replaced with ARB_framebuffer_object (SLC6).
00071    if (!GLEW_EXT_framebuffer_object)
00072    {
00073       throw std::runtime_error(eh + "GL_EXT_framebuffer_object extension required for FBO.");
00074    }
00075 
00076    fIsRescaled = kFALSE;
00077    if (fgRescaleToPow2)
00078    {
00079       Int_t nw = 1 << TMath::CeilNint(TMath::Log2(w));
00080       Int_t nh = 1 << TMath::CeilNint(TMath::Log2(h));
00081       if (nw != w || nh != h)
00082       {
00083          fWScale = ((Float_t)w) / nw;
00084          fHScale = ((Float_t)h) / nh;
00085          w = nw; h = nh;
00086          fIsRescaled = kTRUE;
00087       }
00088    }
00089 
00090    if (ms_samples > 0 && ! GLEW_EXT_framebuffer_multisample)
00091    {
00092       if (!fgMultiSampleNAWarned)
00093       {
00094          Info(eh.c_str(), "GL implementation does not support multi-sampling for FBOs.");
00095          fgMultiSampleNAWarned = kTRUE;
00096       }
00097       ms_samples = 0;
00098    }
00099 
00100    if (fFrameBuffer != 0)
00101    {
00102       if (fW == w && fH == h && fMSSamples == ms_samples)
00103          return;
00104       Release();
00105    }
00106 
00107    Int_t maxSize;
00108    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &maxSize);
00109    if (w > maxSize || h > maxSize)
00110    {
00111       throw std::runtime_error(eh + Form("maximum size supported by GL implementation is %d.", maxSize));
00112    }
00113 
00114    fW = w; fH = h; fMSSamples = ms_samples;
00115 
00116    if (fMSSamples > 0)
00117    {
00118       if (GLEW_NV_framebuffer_multisample_coverage)
00119       {
00120          GLint n_modes;
00121          glGetIntegerv(GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV, &n_modes);
00122          GLint *modes = new GLint[2*n_modes];
00123          glGetIntegerv(GL_MULTISAMPLE_COVERAGE_MODES_NV, modes);
00124 
00125          for (int i = 0; i < n_modes; ++i)
00126          {
00127             if (modes[i*2+1] == fMSSamples && modes[i*2] > fMSCoverageSamples)
00128                fMSCoverageSamples = modes[i*2];
00129          }
00130 
00131          delete [] modes;
00132       }
00133       Info(eh.c_str(), "InitMultiSample coverage_samples=%d, color_samples=%d.", fMSCoverageSamples, fMSSamples);
00134       InitMultiSample();
00135    }
00136    else
00137    {
00138       printf("TGLFBO::Init InitStandard ...\n");
00139       InitStandard();
00140    }
00141 
00142    GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
00143 
00144    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT,  0);
00145    glBindTexture        (GL_TEXTURE_2D,       0);
00146 
00147    switch (status)
00148    {
00149       case GL_FRAMEBUFFER_COMPLETE_EXT:
00150          if (gDebug > 0)
00151             printf("%sConstructed TGLFBO ... all fine.\n", eh.c_str());
00152          break;
00153       case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
00154          Release();
00155          throw std::runtime_error(eh + "Constructed TGLFBO not supported, choose different formats.");
00156          break;
00157       default:
00158          Release();
00159          throw std::runtime_error(eh + "Constructed TGLFBO is not complete, unexpected error.");
00160          break;
00161    }
00162 }
00163 
00164 //______________________________________________________________________________
00165 void TGLFBO::Release()
00166 {
00167    // Release the allocated GL resources.
00168 
00169    glDeleteFramebuffersEXT (1, &fFrameBuffer);
00170    glDeleteRenderbuffersEXT(1, &fDepthBuffer);
00171 
00172    if (fMSFrameBuffer) glDeleteFramebuffersEXT (1, &fMSFrameBuffer);
00173    if (fMSColorBuffer) glDeleteRenderbuffersEXT(1, &fMSColorBuffer);
00174    if (fColorTexture)  glDeleteTextures        (1, &fColorTexture);
00175 
00176    fW = fH = -1; fMSSamples = fMSCoverageSamples = 0;
00177    fFrameBuffer = fColorTexture = fDepthBuffer = fMSFrameBuffer = fMSColorBuffer = 0;
00178 
00179 }
00180 
00181 //______________________________________________________________________________
00182 void TGLFBO::Bind()
00183 {
00184    // Bind the frame-buffer object.
00185 
00186    if (fMSSamples > 0) {
00187       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fMSFrameBuffer);
00188       // On by default
00189       //   glEnable(GL_MULTISAMPLE);
00190       // Experimenting:
00191       //   glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
00192       //   glEnable(GL_SAMPLE_COVERAGE_ARB);
00193    } else {
00194       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFrameBuffer);
00195    }
00196 }
00197 
00198 //______________________________________________________________________________
00199 void TGLFBO::Unbind()
00200 {
00201    // Unbind the frame-buffer object.
00202 
00203    if (fMSSamples > 0)
00204    {
00205       glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fMSFrameBuffer);
00206       glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fFrameBuffer);
00207       glBlitFramebufferEXT(0, 0, fW, fH, 0, 0, fW, fH, GL_COLOR_BUFFER_BIT, GL_NEAREST);
00208    }
00209 
00210    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00211 }
00212 
00213 //______________________________________________________________________________
00214 void TGLFBO::BindTexture()
00215 {
00216    // Bind texture.
00217 
00218    glPushAttrib(GL_TEXTURE_BIT);
00219    glBindTexture(GL_TEXTURE_2D, fColorTexture);
00220    glEnable(GL_TEXTURE_2D);
00221 
00222    if (fIsRescaled)
00223    {
00224       glMatrixMode(GL_TEXTURE);
00225       glPushMatrix();
00226       glScalef(fWScale, fHScale, 1);
00227       glMatrixMode(GL_MODELVIEW);
00228    }
00229 }
00230 
00231 //______________________________________________________________________________
00232 void TGLFBO::UnbindTexture()
00233 {
00234    // Unbind texture.
00235 
00236    if (fIsRescaled)
00237    {
00238       glMatrixMode(GL_TEXTURE);
00239       glPopMatrix();
00240       glMatrixMode(GL_MODELVIEW);
00241    }
00242 
00243    glPopAttrib();
00244 }
00245 
00246 //______________________________________________________________________________
00247 void TGLFBO::SetAsReadBuffer()
00248 {
00249    glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fFrameBuffer);
00250 }
00251 
00252 //==============================================================================
00253 
00254 //______________________________________________________________________________
00255 void TGLFBO::InitStandard()
00256 {
00257    glGenFramebuffersEXT(1, &fFrameBuffer);
00258    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFrameBuffer);
00259 
00260    fDepthBuffer  = CreateAndAttachRenderBuffer(GL_DEPTH_COMPONENT24, GL_DEPTH_ATTACHMENT);
00261    fColorTexture = CreateAndAttachColorTexture();
00262 }
00263 
00264 //______________________________________________________________________________
00265 void TGLFBO::InitMultiSample()
00266 {
00267    glGenFramebuffersEXT(1, &fMSFrameBuffer);
00268    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fMSFrameBuffer);
00269 
00270    fMSColorBuffer = CreateAndAttachRenderBuffer(GL_RGBA8,             GL_COLOR_ATTACHMENT0);
00271    fDepthBuffer   = CreateAndAttachRenderBuffer(GL_DEPTH_COMPONENT24, GL_DEPTH_ATTACHMENT);
00272    // fDepthBuffer   = CreateAndAttachRenderBuffer(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT);
00273 
00274    glGenFramebuffersEXT(1, &fFrameBuffer);
00275    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFrameBuffer);
00276 
00277    fColorTexture = CreateAndAttachColorTexture();
00278 }
00279 
00280 //______________________________________________________________________________
00281 UInt_t TGLFBO::CreateAndAttachRenderBuffer(Int_t format, Int_t type)
00282 {
00283    UInt_t id = 0;
00284 
00285    glGenRenderbuffersEXT(1, &id);
00286    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id);
00287 
00288    if (fMSSamples > 0)
00289    {
00290       if (fMSCoverageSamples > 0)
00291          glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, fMSCoverageSamples, fMSSamples, format, fW, fH);
00292       else
00293          glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, fMSSamples, format, fW, fH);
00294    }
00295    else
00296    {
00297       glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, fW, fH);
00298    }
00299 
00300    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, type, GL_RENDERBUFFER_EXT, id);
00301 
00302    return id;
00303 }
00304 
00305 //______________________________________________________________________________
00306 UInt_t TGLFBO::CreateAndAttachColorTexture()
00307 {
00308    // Initialize color-texture and attach it to current FB.
00309 
00310    UInt_t id = 0;
00311 
00312    glGenTextures(1, &id);
00313 
00314    glBindTexture(GL_TEXTURE_2D, id);
00315    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00316    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00317    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00318    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00319    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, fW, fH, 0, GL_RGBA,
00320                 GL_UNSIGNED_BYTE, NULL);
00321 
00322    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
00323                              GL_TEXTURE_2D, id, 0);
00324 
00325    return id;
00326 }

Generated on Tue Jul 5 14:18:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1