Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGLFormat.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Timur Pocheptsov, Jun 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, 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 <cassert>
13 #include <algorithm>
14 #include <set>
15 
16 #include "TGLFormat.h"
17 #include "TGLWSIncludes.h"
18 #include "TGLWidget.h"
19 
20 #include "TEnv.h"
21 #include "TError.h"
22 #include "TVirtualX.h"
23 #include "RConfigure.h"
24 
25 /** \class TGLFormat
26 \ingroup opengl
27 Encapsulation of format / contents of an OpenGL buffer.
28 */
29 
30 ClassImp(TGLFormat);
31 
32 std::vector<Int_t> TGLFormat::fgAvailableSamples;
33 
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 TGLFormat::TGLFormat() :
37  fDoubleBuffered(kTRUE),
38  fStereo(kFALSE),
39 #ifdef WIN32
40  fDepthSize(32),
41 #else
42  // 16-bits needed for some virtual machines (VirtualBox) and Xming-mesa
43  // (when running ssh from windows to linux).
44  // All others seem to have 24-bit depth-buffers only and use this anyway.
45  fDepthSize(16),
46 #endif
47  fAccumSize(0),
48  fStencilSize(8),
49  fSamples(GetDefaultSamples())
50 {
51  //Default ctor. Default surface is:
52  //-double buffered
53  //-RGBA
54  //-with depth buffer
55  //-no accumulation buffer
56  //-with stencil
57  //-multi-sampling depends on setting of "OpenGL.Framebuffer.Multisample"
58 }
59 
60 ////////////////////////////////////////////////////////////////////////////////
61 ///Define surface using options.
62 
63 TGLFormat::TGLFormat(Rgl::EFormatOptions opt) :
64  fDoubleBuffered(opt & Rgl::kDoubleBuffer),
65  fStereo(kFALSE),
66 #ifdef WIN32
67  fDepthSize(opt & Rgl::kDepth ? 32 : 0),
68 #else
69  fDepthSize(opt & Rgl::kDepth ? 16 : 0),//FIXFIX
70 #endif
71  fAccumSize(opt & Rgl::kAccum ? 8 : 0), //I've never tested accumulation buffer size.
72  fStencilSize(opt & Rgl::kStencil ? 8 : 0), //I've never tested stencil buffer size.
73  fSamples(opt & Rgl::kMultiSample ? GetDefaultSamples() : 0)
74 {
75 }
76 
77 ////////////////////////////////////////////////////////////////////////////////
78 ///Destructor.
79 
80 TGLFormat::~TGLFormat()
81 {
82 }
83 
84 ////////////////////////////////////////////////////////////////////////////////
85 ///Check if two formats are equal.
86 
87 Bool_t TGLFormat::operator == (const TGLFormat &rhs)const
88 {
89  return fDoubleBuffered == rhs.fDoubleBuffered && fDepthSize == rhs.fDepthSize &&
90  fAccumSize == rhs.fAccumSize && fStencilSize == rhs.fStencilSize;
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 ///Check for non-equality.
95 
96 Bool_t TGLFormat::operator != (const TGLFormat &rhs)const
97 {
98  return !(*this == rhs);
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
102 ///Get the size of depth buffer.
103 
104 Int_t TGLFormat::GetDepthSize()const
105 {
106  return fDepthSize;
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 ///Set the size of color buffer.
111 
112 void TGLFormat::SetDepthSize(Int_t depth)
113 {
114  assert(depth);
115  fDepthSize = depth;
116 }
117 
118 ////////////////////////////////////////////////////////////////////////////////
119 ///Check, if this surface has depth buffer.
120 
121 Bool_t TGLFormat::HasDepth()const
122 {
123  return GetDepthSize() != 0;
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 ///Get the size of stencil buffer.
128 
129 Int_t TGLFormat::GetStencilSize()const
130 {
131  return fStencilSize;
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 ///Set the size of stencil buffer.
136 
137 void TGLFormat::SetStencilSize(Int_t stencil)
138 {
139  assert(stencil);
140  fStencilSize = stencil;
141 }
142 
143 ////////////////////////////////////////////////////////////////////////////////
144 ///Check, if this surface has stencil buffer.
145 
146 Bool_t TGLFormat::HasStencil()const
147 {
148  return GetStencilSize() != 0;
149 }
150 
151 ////////////////////////////////////////////////////////////////////////////////
152 ///Get the size of accum buffer.
153 
154 Int_t TGLFormat::GetAccumSize()const
155 {
156  return fAccumSize;
157 }
158 
159 ////////////////////////////////////////////////////////////////////////////////
160 ///Set the size of accum buffer.
161 
162 void TGLFormat::SetAccumSize(Int_t accum)
163 {
164  assert(accum);
165  fAccumSize = accum;
166 }
167 
168 ////////////////////////////////////////////////////////////////////////////////
169 ///Check, if this surface has accumulation buffer.
170 
171 Bool_t TGLFormat::HasAccumBuffer()const
172 {
173  return GetAccumSize() != 0;
174 }
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 ///Check, if the surface is double buffered.
178 
179 Bool_t TGLFormat::IsDoubleBuffered()const
180 {
181  return fDoubleBuffered;
182 }
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 ///Set the surface as double/single buffered.
186 
187 void TGLFormat::SetDoubleBuffered(Bool_t db)
188 {
189  fDoubleBuffered = db;
190 }
191 
192 ////////////////////////////////////////////////////////////////////////////////
193 ///Check, if the surface is stereo buffered.
194 
195 Bool_t TGLFormat::IsStereo()const
196 {
197  return fStereo;
198 }
199 
200 ////////////////////////////////////////////////////////////////////////////////
201 ///Set the surface as stereo/non-stereo buffered.
202 
203 void TGLFormat::SetStereo(Bool_t db)
204 {
205  fStereo = db;
206 }
207 
208 ////////////////////////////////////////////////////////////////////////////////
209 ///Get the number of samples for multi-sampling.
210 
211 Int_t TGLFormat::GetSamples()const
212 {
213  return fSamples;
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 ///Set the number of samples for multi-sampling.
218 
219 void TGLFormat::SetSamples(Int_t samples)
220 {
221  fSamples = samples;
222 }
223 
224 ////////////////////////////////////////////////////////////////////////////////
225 ///Check, if multi-sampling is required.
226 
227 Bool_t TGLFormat::HasMultiSampling()const
228 {
229  return fSamples != 0;
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 /// Return default number of samples for multi-sampling.
234 
235 Int_t TGLFormat::GetDefaultSamples()
236 {
237  Int_t req = gEnv->GetValue("OpenGL.Framebuffer.Multisample", 0);
238 
239  // Avoid query of available multi-sample modes when not required.
240  // Over ssh, SLC5 lies about supporting the GLX_SAMPLES_ARB
241  // extension and then dies horribly when the query is made.
242  if (req == 0) {
243  return 0;
244  }
245 
246  if (fgAvailableSamples.empty())
247  InitAvailableSamples();
248 
249  std::vector<Int_t>::iterator i = fgAvailableSamples.begin();
250  while (i != fgAvailableSamples.end() - 1 && *i < req)
251  ++i;
252 
253  if (*i != req) {
254  Info("TGLFormat::GetDefaultSamples", "Requested multi-sampling %d not available, using %d. Adjusting default.", req, *i);
255  gEnv->SetValue("OpenGL.Framebuffer.Multisample", *i);
256  }
257 
258  return *i;
259 }
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 
263 void TGLFormat::InitAvailableSamples()
264 {
265  std::set<Int_t> ns_set;
266  ns_set.insert(0);
267 
268 #ifdef WIN32
269 
270  // Missing implementation.
271 #elif defined(R__HAS_COCOA)
272  ns_set.insert(8);
273  ns_set.insert(16);
274 #else
275  TGLWidget *widget = TGLWidget::CreateDummy();
276  widget->MakeCurrent();
277 
278  if (GLXEW_ARB_multisample)
279  {
280  Display *dpy = (Display*) gVirtualX->GetDisplay();
281  XVisualInfo tmpl; tmpl.screen = gVirtualX->GetScreen();
282  long mask = VisualScreenMask;
283  int numVisuals, use_gl, ms_ns;
284  XVisualInfo *vis = XGetVisualInfo(dpy, mask, &tmpl, &numVisuals);
285  for (int i = 0; i < numVisuals; i++)
286  {
287  if (glXGetConfig(dpy, &vis[i], GLX_USE_GL, &use_gl) == 0)
288  {
289  glXGetConfig(dpy, &vis[i], GLX_SAMPLES_ARB, &ms_ns);
290  ns_set.insert(ms_ns);
291  }
292  }
293  XFree(vis);
294  }
295 
296  delete widget;
297 #endif
298 
299  fgAvailableSamples.reserve(ns_set.size());
300  for (std::set<Int_t>::iterator i = ns_set.begin(); i != ns_set.end(); ++i)
301  {
302  fgAvailableSamples.push_back(*i);
303  }
304 }