Logo ROOT   6.12/07
Reference Guide
TGLFBO.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Matevz Tadel, Aug 2009
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TGLFBO.h"
13 #include "TGLIncludes.h"
14 #include <TMath.h>
15 #include <TString.h>
16 #include <TError.h>
17 
18 #include <stdexcept>
19 
20 /** \class TGLFBO
21 \ingroup opengl
22 Frame-buffer object.
23 
24 Requires GL-1.5.
25 
26 Taken from Gled project, see:
27 
28  http://www.gled.org/cgi-bin/viewcvs.cgi/trunk/libsets/GledCore/Pupils/
29 
30 See also:
31 
32  http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
33 */
34 
36 
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 /// Constructor.
42 
44  fFrameBuffer (0),
45  fColorTexture (0),
46  fDepthBuffer (0),
47  fMSFrameBuffer(0),
48  fMSColorBuffer(0),
49  fW (-1),
50  fH (-1),
51  fReqW (-1),
52  fReqH (-1),
53  fMSSamples (0),
54  fMSCoverageSamples (0),
55  fWScale (1),
56  fHScale (1),
57  fIsRescaled (kFALSE)
58 {
59 }
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// Destructor.
63 
65 {
66  Release();
67 }
68 
69 ////////////////////////////////////////////////////////////////////////////////
70 /// Acquire GL resources for given width, height and number of
71 /// multi-sampling samples.
72 
73 void TGLFBO::Init(int w, int h, int ms_samples)
74 {
75  static const std::string eh("TGLFBO::Init ");
76 
77  // Should be replaced with ARB_framebuffer_object (SLC6).
78  if (!GLEW_EXT_framebuffer_object)
79  {
80  throw std::runtime_error(eh + "GL_EXT_framebuffer_object extension required for FBO.");
81  }
82 
83  fReqW = w; fReqH = h;
84 
86  if (fgRescaleToPow2)
87  {
88  Int_t nw = 1 << TMath::CeilNint(TMath::Log2(w));
89  Int_t nh = 1 << TMath::CeilNint(TMath::Log2(h));
90  if (nw != w || nh != h)
91  {
92  fWScale = ((Float_t)w) / nw;
93  fHScale = ((Float_t)h) / nh;
94  w = nw; h = nh;
96  }
97  }
98 
99  if (ms_samples > 0 && ! GLEW_EXT_framebuffer_multisample)
100  {
102  {
103  Info(eh.c_str(), "GL implementation does not support multi-sampling for FBOs.");
105  }
106  ms_samples = 0;
107  }
108 
109  if (fFrameBuffer != 0)
110  {
111  if (fW == w && fH == h && fMSSamples == ms_samples)
112  return;
113  Release();
114  }
115 
116  Int_t maxSize;
117  glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &maxSize);
118  if (w > maxSize || h > maxSize)
119  {
120  throw std::runtime_error(eh + Form("maximum size supported by GL implementation is %d.", maxSize));
121  }
122 
123  fW = w; fH = h; fMSSamples = ms_samples;
124 
125  if (fMSSamples > 0)
126  {
127  if (GLEW_NV_framebuffer_multisample_coverage)
128  {
129  GLint n_modes;
130  glGetIntegerv(GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV, &n_modes);
131  GLint *modes = new GLint[2*n_modes];
132  glGetIntegerv(GL_MULTISAMPLE_COVERAGE_MODES_NV, modes);
133 
134  for (int i = 0; i < n_modes; ++i)
135  {
136  if (modes[i*2+1] == fMSSamples && modes[i*2] > fMSCoverageSamples)
137  fMSCoverageSamples = modes[i*2];
138  }
139 
140  delete [] modes;
141  }
142  if (gDebug > 0) {
143  Info(eh.c_str(), "InitMultiSample coverage_samples=%d, color_samples=%d.", fMSCoverageSamples, fMSSamples);
144  }
145  InitMultiSample();
146  }
147  else
148  {
149  if (gDebug > 0) {
150  Info(eh.c_str(), "InitStandard (no multi-sampling).");
151  }
152  InitStandard();
153  }
154 
155  GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
156 
157  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
158  glBindTexture (GL_TEXTURE_2D, 0);
159 
160  switch (status)
161  {
162  case GL_FRAMEBUFFER_COMPLETE_EXT:
163  if (gDebug > 0)
164  printf("%sConstructed TGLFBO ... all fine.\n", eh.c_str());
165  break;
166  case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
167  Release();
168  throw std::runtime_error(eh + "Constructed TGLFBO not supported, choose different formats.");
169  break;
170  default:
171  Release();
172  throw std::runtime_error(eh + "Constructed TGLFBO is not complete, unexpected error.");
173  break;
174  }
175 }
176 
177 ////////////////////////////////////////////////////////////////////////////////
178 /// Release the allocated GL resources.
179 
181 {
182  glDeleteFramebuffersEXT (1, &fFrameBuffer);
183  glDeleteRenderbuffersEXT(1, &fDepthBuffer);
184 
185  if (fMSFrameBuffer) glDeleteFramebuffersEXT (1, &fMSFrameBuffer);
186  if (fMSColorBuffer) glDeleteRenderbuffersEXT(1, &fMSColorBuffer);
187  if (fColorTexture) glDeleteTextures (1, &fColorTexture);
188 
189  fW = fH = -1; fMSSamples = fMSCoverageSamples = 0;
191 
192 }
193 
194 ////////////////////////////////////////////////////////////////////////////////
195 /// Bind the frame-buffer object.
196 
198 {
199  if (fMSSamples > 0) {
200  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fMSFrameBuffer);
201  // On by default
202  // glEnable(GL_MULTISAMPLE);
203  // Experimenting:
204  // glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
205  // glEnable(GL_SAMPLE_COVERAGE_ARB);
206  } else {
207  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFrameBuffer);
208  }
209 }
210 
211 ////////////////////////////////////////////////////////////////////////////////
212 /// Unbind the frame-buffer object.
213 
215 {
216  if (fMSSamples > 0)
217  {
218  glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fMSFrameBuffer);
219  glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fFrameBuffer);
220  glBlitFramebufferEXT(0, 0, fW, fH, 0, 0, fW, fH, GL_COLOR_BUFFER_BIT, GL_NEAREST);
221  }
222 
223  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
224 }
225 
226 ////////////////////////////////////////////////////////////////////////////////
227 /// Bind texture.
228 
230 {
231  glPushAttrib(GL_TEXTURE_BIT);
232  glBindTexture(GL_TEXTURE_2D, fColorTexture);
233  glEnable(GL_TEXTURE_2D);
234 
235  if (fIsRescaled)
236  {
237  glMatrixMode(GL_TEXTURE);
238  glPushMatrix();
239  glScalef(fWScale, fHScale, 1);
240  glMatrixMode(GL_MODELVIEW);
241  }
242 }
243 
244 ////////////////////////////////////////////////////////////////////////////////
245 /// Unbind texture.
246 
248 {
249  if (fIsRescaled)
250  {
251  glMatrixMode(GL_TEXTURE);
252  glPopMatrix();
253  glMatrixMode(GL_MODELVIEW);
254  }
255 
256  glPopAttrib();
257 }
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 
262 {
263  glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fFrameBuffer);
264 }
265 
266 //==============================================================================
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 
271 {
272  glGenFramebuffersEXT(1, &fFrameBuffer);
273  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFrameBuffer);
274 
275  fDepthBuffer = CreateAndAttachRenderBuffer(GL_DEPTH_COMPONENT24, GL_DEPTH_ATTACHMENT);
277 }
278 
279 ////////////////////////////////////////////////////////////////////////////////
280 
282 {
283  glGenFramebuffersEXT(1, &fMSFrameBuffer);
284  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fMSFrameBuffer);
285 
286  fMSColorBuffer = CreateAndAttachRenderBuffer(GL_RGBA8, GL_COLOR_ATTACHMENT0);
287  fDepthBuffer = CreateAndAttachRenderBuffer(GL_DEPTH_COMPONENT24, GL_DEPTH_ATTACHMENT);
288  // fDepthBuffer = CreateAndAttachRenderBuffer(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT);
289 
290  glGenFramebuffersEXT(1, &fFrameBuffer);
291  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFrameBuffer);
292 
294 }
295 
296 ////////////////////////////////////////////////////////////////////////////////
297 
299 {
300  UInt_t id = 0;
301 
302  glGenRenderbuffersEXT(1, &id);
303  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id);
304 
305  if (fMSSamples > 0)
306  {
307  if (fMSCoverageSamples > 0)
308  glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, fMSCoverageSamples, fMSSamples, format, fW, fH);
309  else
310  glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, fMSSamples, format, fW, fH);
311  }
312  else
313  {
314  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, fW, fH);
315  }
316 
317  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, type, GL_RENDERBUFFER_EXT, id);
318 
319  return id;
320 }
321 
322 ////////////////////////////////////////////////////////////////////////////////
323 /// Initialize color-texture and attach it to current FB.
324 
326 {
327  UInt_t id = 0;
328 
329  glGenTextures(1, &id);
330 
331  glBindTexture(GL_TEXTURE_2D, id);
332  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
333  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
334  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
335  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
336  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, fW, fH, 0, GL_RGBA,
337  GL_UNSIGNED_BYTE, NULL);
338 
339  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
340  GL_TEXTURE_2D, id, 0);
341 
342  return id;
343 }
344 
345 ////////////////////////////////////////////////////////////////////////////////
346 /// Return state of fgRescaleToPow2 static member.
347 
349 {
350  return fgRescaleToPow2;
351 }
352 
353 ////////////////////////////////////////////////////////////////////////////////
354 /// Set state of fgRescaleToPow2 static member.
355 /// Default is kTRUE as this works better on older hardware, especially ATI.
356 
358 {
359  fgRescaleToPow2 = r;
360 }
static void SetRescaleToPow2(Bool_t r)
Set state of fgRescaleToPow2 static member.
Definition: TGLFBO.cxx:357
UInt_t CreateAndAttachRenderBuffer(Int_t format, Int_t type)
Definition: TGLFBO.cxx:298
UInt_t CreateAndAttachColorTexture()
Initialize color-texture and attach it to current FB.
Definition: TGLFBO.cxx:325
Int_t fMSSamples
Definition: TGLFBO.h:30
float Float_t
Definition: RtypesCore.h:53
void Unbind()
Unbind the frame-buffer object.
Definition: TGLFBO.cxx:214
TGLFBO()
Constructor.
Definition: TGLFBO.cxx:43
Int_t fW
Definition: TGLFBO.h:30
TH1 * h
Definition: legend2.C:5
void Bind()
Bind the frame-buffer object.
Definition: TGLFBO.cxx:197
virtual ~TGLFBO()
Destructor.
Definition: TGLFBO.cxx:64
Double_t Log2(Double_t x)
Definition: TMath.cxx:104
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
void Release()
Release the allocated GL resources.
Definition: TGLFBO.cxx:180
void SetAsReadBuffer()
Definition: TGLFBO.cxx:261
static Bool_t GetRescaleToPow2()
Return state of fgRescaleToPow2 static member.
Definition: TGLFBO.cxx:348
void Info(const char *location, const char *msgfmt,...)
XFontStruct * id
Definition: TGX11.cxx:108
Float_t fHScale
Definition: TGLFBO.h:32
UInt_t fDepthBuffer
Definition: TGLFBO.h:26
ROOT::R::TRInterface & r
Definition: Object.C:4
void Init(int w, int h, int ms_samples=0)
Acquire GL resources for given width, height and number of multi-sampling samples.
Definition: TGLFBO.cxx:73
UInt_t fMSFrameBuffer
Definition: TGLFBO.h:27
unsigned int UInt_t
Definition: RtypesCore.h:42
Int_t fH
Definition: TGLFBO.h:30
char * Form(const char *fmt,...)
Float_t fWScale
Definition: TGLFBO.h:32
Bool_t fIsRescaled
Definition: TGLFBO.h:33
static Bool_t fgMultiSampleNAWarned
Definition: TGLFBO.h:36
const Bool_t kFALSE
Definition: RtypesCore.h:88
void InitMultiSample()
Definition: TGLFBO.cxx:281
void BindTexture()
Bind texture.
Definition: TGLFBO.cxx:229
#define ClassImp(name)
Definition: Rtypes.h:359
UInt_t fColorTexture
Definition: TGLFBO.h:25
int type
Definition: TGX11.cxx:120
Int_t fMSCoverageSamples
Definition: TGLFBO.h:30
Int_t fReqW
Definition: TGLFBO.h:30
void UnbindTexture()
Unbind texture.
Definition: TGLFBO.cxx:247
UInt_t fMSColorBuffer
Definition: TGLFBO.h:28
UInt_t fFrameBuffer
Definition: TGLFBO.h:24
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
static Bool_t fgRescaleToPow2
Definition: TGLFBO.h:35
Frame-buffer object.
Definition: TGLFBO.h:17
void InitStandard()
Definition: TGLFBO.cxx:270
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t CeilNint(Double_t x)
Definition: TMath.h:596
Int_t fReqH
Definition: TGLFBO.h:30