ROOT logo
// @(#)root/eve:$Id: TGLFBO.cxx 31671 2009-12-08 15:22:31Z matevz $
// Author: Matevz Tadel, Aug 2009

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TGLFBO.h"
#include <TMath.h>
#include <TString.h>

#include <GL/glew.h>

#include <stdexcept>

//______________________________________________________________________________
// 
// Frame-buffer object.
//
// Requires GL-1.5.
//
// Taken from Gled project, see:
//   http://www.gled.org/cgi-bin/viewcvs.cgi/trunk/libsets/GledCore/Pupils/
// See also:
//   http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt

ClassImp(TGLFBO);

Bool_t TGLFBO::fgRescaleToPow2 = kTRUE; // For ATI.

TGLFBO::TGLFBO() :
   fFrameBuffer  (0),
   fColorTexture (0),
   fDepthBuffer  (0),
   fW (-1),
   fH (-1),
   fIsRescaled (kFALSE),
   fWScale     (1),
   fHScale     (1)
{
   // Constructor.
}

//______________________________________________________________________________
TGLFBO::~TGLFBO()
{
   // Destructor.

   Release();
}

//______________________________________________________________________________
void TGLFBO::Init(int w, int h)
{
   // Acquire GL resources for given width and height.

   static const std::string eh("TGLFBO::Init ");

   if (!GLEW_VERSION_1_5)
   {
      throw std::runtime_error(eh + "GL version 1.5 required for FBO.");
   }

   fIsRescaled = kFALSE;
   if (fgRescaleToPow2)
   {
      Int_t nw = 1 << TMath::CeilNint(TMath::Log2(w));
      Int_t nh = 1 << TMath::CeilNint(TMath::Log2(h));
      if (nw != w || nh != h)
      {
         fWScale = ((Float_t)w) / nw;
         fHScale = ((Float_t)h) / nh;
         w = nw; h = nh;
         fIsRescaled = kTRUE;
      }
   }

   if (fFrameBuffer != 0)
   {
      if (fW == w || fH == h)
         return;
      Release();
   }

   Int_t maxSize;
   glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &maxSize);
   if (w > maxSize || h > maxSize)
   {
      throw std::runtime_error(eh + Form("maximum size supported by GL implementation is %d.", maxSize));
   }

   fW = w; fH = h;

   glGenFramebuffersEXT (1, &fFrameBuffer);
   glGenTextures        (1, &fColorTexture);
   glGenRenderbuffersEXT(1, &fDepthBuffer);
   // glGenRenderbuffersEXT(1, &fStencilBuffer);

   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFrameBuffer);

   // initialize color texture
   glBindTexture(GL_TEXTURE_2D, fColorTexture);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, fW, fH, 0, GL_RGB,
                GL_UNSIGNED_BYTE, NULL);

   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                             GL_TEXTURE_2D, fColorTexture, 0);

   // initialize depth renderbuffer
   glBindRenderbufferEXT   (GL_RENDERBUFFER_EXT, fDepthBuffer);
   glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, fW, fH);

   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
                                GL_RENDERBUFFER_EXT, fDepthBuffer);

   /*
   // initialize stencil renderbuffer
   glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fStencilBuffer);
   glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, fW, fH);

   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
   GL_RENDERBUFFER_EXT, fStencilBuffer);
   */

   //-------------------------

   GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

   glBindFramebufferEXT (GL_FRAMEBUFFER_EXT,  0);
   glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); // ? is needed
   glBindTexture        (GL_TEXTURE_2D,       0);

   switch (status)
   {
      case GL_FRAMEBUFFER_COMPLETE_EXT:
         if (gDebug > 0)
            printf("%sConstructed TGLFBO ... all fine.\n", eh.c_str());
         break;
      case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
         Release();
         throw std::runtime_error(eh + "Constructed TGLFBO not supported, choose different formats.");
         break;
      default:
         Release();
         throw std::runtime_error(eh + "Constructed TGLFBO is crap, fix code in TGLFBO class.");
         break;
   }
}

//______________________________________________________________________________
void TGLFBO::Release()
{
   // Release the allocated GL resources.

   glDeleteFramebuffersEXT (1, &fFrameBuffer);
   glDeleteTextures        (1, &fColorTexture);
   glDeleteRenderbuffersEXT(1, &fDepthBuffer);
   //glDeleteRenderbuffersEXT(1, &fStencilBuffer);

   fColorTexture = fFrameBuffer = fDepthBuffer = 0;
   fW = fH = -1;
}

//______________________________________________________________________________
void TGLFBO::Bind()
{
   // Bind the frame-buffer object.

   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFrameBuffer);
}

//______________________________________________________________________________
void TGLFBO::Unbind()
{
   // Unbind the frame-buffer object.

   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

//______________________________________________________________________________
void TGLFBO::BindTexture()
{
   // Bind texture.

   glPushAttrib(GL_TEXTURE_BIT);
   glBindTexture(GL_TEXTURE_2D, fColorTexture);
   glEnable(GL_TEXTURE_2D);

   glMatrixMode(GL_TEXTURE);
   glPushMatrix();
   glScalef(fWScale, fHScale, 1);
   glMatrixMode(GL_MODELVIEW);
}

//______________________________________________________________________________
void TGLFBO::UnbindTexture()
{
   // Unbind texture.

   glMatrixMode(GL_TEXTURE);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);

   glPopAttrib();
}
 TGLFBO.cxx:1
 TGLFBO.cxx:2
 TGLFBO.cxx:3
 TGLFBO.cxx:4
 TGLFBO.cxx:5
 TGLFBO.cxx:6
 TGLFBO.cxx:7
 TGLFBO.cxx:8
 TGLFBO.cxx:9
 TGLFBO.cxx:10
 TGLFBO.cxx:11
 TGLFBO.cxx:12
 TGLFBO.cxx:13
 TGLFBO.cxx:14
 TGLFBO.cxx:15
 TGLFBO.cxx:16
 TGLFBO.cxx:17
 TGLFBO.cxx:18
 TGLFBO.cxx:19
 TGLFBO.cxx:20
 TGLFBO.cxx:21
 TGLFBO.cxx:22
 TGLFBO.cxx:23
 TGLFBO.cxx:24
 TGLFBO.cxx:25
 TGLFBO.cxx:26
 TGLFBO.cxx:27
 TGLFBO.cxx:28
 TGLFBO.cxx:29
 TGLFBO.cxx:30
 TGLFBO.cxx:31
 TGLFBO.cxx:32
 TGLFBO.cxx:33
 TGLFBO.cxx:34
 TGLFBO.cxx:35
 TGLFBO.cxx:36
 TGLFBO.cxx:37
 TGLFBO.cxx:38
 TGLFBO.cxx:39
 TGLFBO.cxx:40
 TGLFBO.cxx:41
 TGLFBO.cxx:42
 TGLFBO.cxx:43
 TGLFBO.cxx:44
 TGLFBO.cxx:45
 TGLFBO.cxx:46
 TGLFBO.cxx:47
 TGLFBO.cxx:48
 TGLFBO.cxx:49
 TGLFBO.cxx:50
 TGLFBO.cxx:51
 TGLFBO.cxx:52
 TGLFBO.cxx:53
 TGLFBO.cxx:54
 TGLFBO.cxx:55
 TGLFBO.cxx:56
 TGLFBO.cxx:57
 TGLFBO.cxx:58
 TGLFBO.cxx:59
 TGLFBO.cxx:60
 TGLFBO.cxx:61
 TGLFBO.cxx:62
 TGLFBO.cxx:63
 TGLFBO.cxx:64
 TGLFBO.cxx:65
 TGLFBO.cxx:66
 TGLFBO.cxx:67
 TGLFBO.cxx:68
 TGLFBO.cxx:69
 TGLFBO.cxx:70
 TGLFBO.cxx:71
 TGLFBO.cxx:72
 TGLFBO.cxx:73
 TGLFBO.cxx:74
 TGLFBO.cxx:75
 TGLFBO.cxx:76
 TGLFBO.cxx:77
 TGLFBO.cxx:78
 TGLFBO.cxx:79
 TGLFBO.cxx:80
 TGLFBO.cxx:81
 TGLFBO.cxx:82
 TGLFBO.cxx:83
 TGLFBO.cxx:84
 TGLFBO.cxx:85
 TGLFBO.cxx:86
 TGLFBO.cxx:87
 TGLFBO.cxx:88
 TGLFBO.cxx:89
 TGLFBO.cxx:90
 TGLFBO.cxx:91
 TGLFBO.cxx:92
 TGLFBO.cxx:93
 TGLFBO.cxx:94
 TGLFBO.cxx:95
 TGLFBO.cxx:96
 TGLFBO.cxx:97
 TGLFBO.cxx:98
 TGLFBO.cxx:99
 TGLFBO.cxx:100
 TGLFBO.cxx:101
 TGLFBO.cxx:102
 TGLFBO.cxx:103
 TGLFBO.cxx:104
 TGLFBO.cxx:105
 TGLFBO.cxx:106
 TGLFBO.cxx:107
 TGLFBO.cxx:108
 TGLFBO.cxx:109
 TGLFBO.cxx:110
 TGLFBO.cxx:111
 TGLFBO.cxx:112
 TGLFBO.cxx:113
 TGLFBO.cxx:114
 TGLFBO.cxx:115
 TGLFBO.cxx:116
 TGLFBO.cxx:117
 TGLFBO.cxx:118
 TGLFBO.cxx:119
 TGLFBO.cxx:120
 TGLFBO.cxx:121
 TGLFBO.cxx:122
 TGLFBO.cxx:123
 TGLFBO.cxx:124
 TGLFBO.cxx:125
 TGLFBO.cxx:126
 TGLFBO.cxx:127
 TGLFBO.cxx:128
 TGLFBO.cxx:129
 TGLFBO.cxx:130
 TGLFBO.cxx:131
 TGLFBO.cxx:132
 TGLFBO.cxx:133
 TGLFBO.cxx:134
 TGLFBO.cxx:135
 TGLFBO.cxx:136
 TGLFBO.cxx:137
 TGLFBO.cxx:138
 TGLFBO.cxx:139
 TGLFBO.cxx:140
 TGLFBO.cxx:141
 TGLFBO.cxx:142
 TGLFBO.cxx:143
 TGLFBO.cxx:144
 TGLFBO.cxx:145
 TGLFBO.cxx:146
 TGLFBO.cxx:147
 TGLFBO.cxx:148
 TGLFBO.cxx:149
 TGLFBO.cxx:150
 TGLFBO.cxx:151
 TGLFBO.cxx:152
 TGLFBO.cxx:153
 TGLFBO.cxx:154
 TGLFBO.cxx:155
 TGLFBO.cxx:156
 TGLFBO.cxx:157
 TGLFBO.cxx:158
 TGLFBO.cxx:159
 TGLFBO.cxx:160
 TGLFBO.cxx:161
 TGLFBO.cxx:162
 TGLFBO.cxx:163
 TGLFBO.cxx:164
 TGLFBO.cxx:165
 TGLFBO.cxx:166
 TGLFBO.cxx:167
 TGLFBO.cxx:168
 TGLFBO.cxx:169
 TGLFBO.cxx:170
 TGLFBO.cxx:171
 TGLFBO.cxx:172
 TGLFBO.cxx:173
 TGLFBO.cxx:174
 TGLFBO.cxx:175
 TGLFBO.cxx:176
 TGLFBO.cxx:177
 TGLFBO.cxx:178
 TGLFBO.cxx:179
 TGLFBO.cxx:180
 TGLFBO.cxx:181
 TGLFBO.cxx:182
 TGLFBO.cxx:183
 TGLFBO.cxx:184
 TGLFBO.cxx:185
 TGLFBO.cxx:186
 TGLFBO.cxx:187
 TGLFBO.cxx:188
 TGLFBO.cxx:189
 TGLFBO.cxx:190
 TGLFBO.cxx:191
 TGLFBO.cxx:192
 TGLFBO.cxx:193
 TGLFBO.cxx:194
 TGLFBO.cxx:195
 TGLFBO.cxx:196
 TGLFBO.cxx:197
 TGLFBO.cxx:198
 TGLFBO.cxx:199
 TGLFBO.cxx:200
 TGLFBO.cxx:201
 TGLFBO.cxx:202
 TGLFBO.cxx:203
 TGLFBO.cxx:204
 TGLFBO.cxx:205
 TGLFBO.cxx:206
 TGLFBO.cxx:207
 TGLFBO.cxx:208
 TGLFBO.cxx:209
 TGLFBO.cxx:210
 TGLFBO.cxx:211
 TGLFBO.cxx:212
 TGLFBO.cxx:213