]> git.saurik.com Git - wxWidgets.git/blame - src/unix/glx11.cpp
Deallocate wxThreadSpecificInfo when wxThread ends.
[wxWidgets.git] / src / unix / glx11.cpp
CommitLineData
498ace9e 1///////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/unix/glx11.cpp
498ace9e
VZ
3// Purpose: code common to all X11-based wxGLCanvas implementations
4// Author: Vadim Zeitlin
5// Created: 2007-04-15
498ace9e
VZ
6// Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
7// Licence: wxWindows licence
8///////////////////////////////////////////////////////////////////////////////
9
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
18// for compilers that support precompilation, includes "wx.h".
19#include "wx/wxprec.h"
20
21#if wxUSE_GLCANVAS
22
23#ifndef WX_PRECOMP
50c95f69 24 #include "wx/log.h"
498ace9e
VZ
25#endif //WX_PRECOMP
26
27#include "wx/glcanvas.h"
28
049c4f6c
VZ
29// IRIX headers call this differently
30#ifdef __SGI__
31 #ifndef GLX_SAMPLE_BUFFERS_ARB
32 #define GLX_SAMPLE_BUFFERS_ARB GLX_SAMPLE_BUFFERS_SGIS
33 #endif
34 #ifndef GLX_SAMPLES_ARB
35 #define GLX_SAMPLES_ARB GLX_SAMPLES_SGIS
36 #endif
37#endif // __SGI__
38
498ace9e
VZ
39// ============================================================================
40// wxGLContext implementation
41// ============================================================================
42
43IMPLEMENT_CLASS(wxGLContext, wxObject)
44
45wxGLContext::wxGLContext(wxGLCanvas *gc, const wxGLContext *other)
46{
47 if ( wxGLCanvas::GetGLXVersion() >= 13 )
48 {
49 GLXFBConfig *fbc = gc->GetGLXFBConfig();
9a83f860 50 wxCHECK_RET( fbc, wxT("invalid GLXFBConfig for OpenGL") );
498ace9e
VZ
51
52 m_glContext = glXCreateNewContext( wxGetX11Display(), fbc[0], GLX_RGBA_TYPE,
53 other ? other->m_glContext : None,
54 GL_TRUE );
55 }
56 else // GLX <= 1.2
57 {
58 XVisualInfo *vi = gc->GetXVisualInfo();
9a83f860 59 wxCHECK_RET( vi, wxT("invalid visual for OpenGL") );
498ace9e
VZ
60
61 m_glContext = glXCreateContext( wxGetX11Display(), vi,
62 other ? other->m_glContext : None,
63 GL_TRUE );
64 }
65
9a83f860 66 wxASSERT_MSG( m_glContext, wxT("Couldn't create OpenGL context") );
498ace9e
VZ
67}
68
69wxGLContext::~wxGLContext()
70{
71 if ( !m_glContext )
72 return;
73
74 if ( m_glContext == glXGetCurrentContext() )
75 MakeCurrent(None, NULL);
76
77 glXDestroyContext( wxGetX11Display(), m_glContext );
78}
79
5ec69e96 80bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
498ace9e
VZ
81{
82 if ( !m_glContext )
5ec69e96 83 return false;
498ace9e
VZ
84
85 const Window xid = win.GetXWindow();
9a83f860 86 wxCHECK2_MSG( xid, return false, wxT("window must be shown") );
498ace9e 87
5ec69e96 88 return MakeCurrent(xid, m_glContext);
498ace9e
VZ
89}
90
91// wrapper around glXMakeContextCurrent/glXMakeCurrent depending on GLX
92// version
93/* static */
5ec69e96 94bool wxGLContext::MakeCurrent(GLXDrawable drawable, GLXContext context)
498ace9e
VZ
95{
96 if (wxGLCanvas::GetGLXVersion() >= 13)
5ec69e96 97 return glXMakeContextCurrent( wxGetX11Display(), drawable, drawable, context);
498ace9e 98 else // GLX <= 1.2 doesn't have glXMakeContextCurrent()
5ec69e96 99 return glXMakeCurrent( wxGetX11Display(), drawable, context);
498ace9e
VZ
100}
101
102// ============================================================================
103// wxGLCanvasX11 implementation
104// ============================================================================
105
106// ----------------------------------------------------------------------------
107// initialization methods and dtor
108// ----------------------------------------------------------------------------
109
110wxGLCanvasX11::wxGLCanvasX11()
111{
112 m_fbc = NULL;
113 m_vi = NULL;
114}
115
116bool wxGLCanvasX11::InitVisual(const int *attribList)
117{
118 return InitXVisualInfo(attribList, &m_fbc, &m_vi);
119}
120
121wxGLCanvasX11::~wxGLCanvasX11()
122{
123 if ( m_fbc && m_fbc != ms_glFBCInfo )
124 XFree(m_fbc);
125
126 if ( m_vi && m_vi != ms_glVisualInfo )
127 XFree(m_vi);
128}
129
130// ----------------------------------------------------------------------------
131// working with GL attributes
132// ----------------------------------------------------------------------------
133
c39d2e0a
VZ
134/* static */
135bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
136{
137 Display * const dpy = wxGetX11Display();
138
139 return IsExtensionInList(glXQueryExtensionsString(dpy, DefaultScreen(dpy)),
140 extension);
141}
142
143
144/* static */
145bool wxGLCanvasX11::IsGLXMultiSampleAvailable()
146{
147 static int s_isMultiSampleAvailable = -1;
148 if ( s_isMultiSampleAvailable == -1 )
149 s_isMultiSampleAvailable = IsExtensionSupported("GLX_ARB_multisample");
150
151 return s_isMultiSampleAvailable != 0;
152}
153
498ace9e
VZ
154bool
155wxGLCanvasX11::ConvertWXAttrsToGL(const int *wxattrs, int *glattrs, size_t n)
156{
9a83f860 157 wxCHECK_MSG( n >= 16, false, wxT("GL attributes buffer too small") );
498ace9e 158
b73b2117
VZ
159 /*
160 Different versions of GLX API use rather different attributes lists, see
161 the following URLs:
162
163 - <= 1.2: http://www.opengl.org/sdk/docs/man/xhtml/glXChooseVisual.xml
164 - >= 1.3: http://www.opengl.org/sdk/docs/man/xhtml/glXChooseFBConfig.xml
165
166 Notice in particular that
167 - GLX_RGBA is boolean attribute in the old version of the API but a
168 value of GLX_RENDER_TYPE in the new one
169 - Boolean attributes such as GLX_DOUBLEBUFFER don't take values in the
170 old version but must be followed by True or False in the new one.
171 */
172
498ace9e
VZ
173 if ( !wxattrs )
174 {
06e6496e
VZ
175 size_t i = 0;
176
177 // use double-buffered true colour by default
b73b2117 178 glattrs[i++] = GLX_DOUBLEBUFFER;
06e6496e
VZ
179
180 if ( GetGLXVersion() < 13 )
498ace9e
VZ
181 {
182 // default settings if attriblist = 0
b73b2117 183 glattrs[i++] = GLX_RGBA;
498ace9e
VZ
184 glattrs[i++] = GLX_DEPTH_SIZE; glattrs[i++] = 1;
185 glattrs[i++] = GLX_RED_SIZE; glattrs[i++] = 1;
186 glattrs[i++] = GLX_GREEN_SIZE; glattrs[i++] = 1;
187 glattrs[i++] = GLX_BLUE_SIZE; glattrs[i++] = 1;
188 glattrs[i++] = GLX_ALPHA_SIZE; glattrs[i++] = 0;
498ace9e 189 }
b73b2117
VZ
190 else // recent GLX can choose the defaults on its own just fine
191 {
192 // we just need to have a value after GLX_DOUBLEBUFFER
193 glattrs[i++] = True;
194 }
06e6496e
VZ
195
196 glattrs[i] = None;
197
9a83f860 198 wxASSERT_MSG( i < n, wxT("GL attributes buffer too small") );
498ace9e
VZ
199 }
200 else // have non-default attributes
201 {
202 size_t p = 0;
203 for ( int arg = 0; wxattrs[arg] != 0; )
204 {
205 // check if we have any space left, knowing that we may insert 2
206 // more elements during this loop iteration and we always need to
207 // terminate the list with None (hence -3)
06e6496e 208 if ( p > n - 3 )
498ace9e
VZ
209 return false;
210
b73b2117
VZ
211 // indicates whether we have a boolean attribute
212 bool isBoolAttr = false;
213
498ace9e
VZ
214 switch ( wxattrs[arg++] )
215 {
498ace9e
VZ
216 case WX_GL_BUFFER_SIZE:
217 glattrs[p++] = GLX_BUFFER_SIZE;
218 break;
219
220 case WX_GL_LEVEL:
221 glattrs[p++] = GLX_LEVEL;
222 break;
223
06e6496e 224 case WX_GL_RGBA:
b73b2117
VZ
225 if ( GetGLXVersion() >= 13 )
226 {
227 // this is the default GLX_RENDER_TYPE anyhow
228 continue;
229 }
230
06e6496e 231 glattrs[p++] = GLX_RGBA;
b73b2117
VZ
232 isBoolAttr = true;
233 break;
06e6496e 234
498ace9e
VZ
235 case WX_GL_DOUBLEBUFFER:
236 glattrs[p++] = GLX_DOUBLEBUFFER;
b73b2117
VZ
237 isBoolAttr = true;
238 break;
498ace9e
VZ
239
240 case WX_GL_STEREO:
241 glattrs[p++] = GLX_STEREO;
b73b2117
VZ
242 isBoolAttr = true;
243 break;
498ace9e
VZ
244
245 case WX_GL_AUX_BUFFERS:
246 glattrs[p++] = GLX_AUX_BUFFERS;
247 break;
248
249 case WX_GL_MIN_RED:
250 glattrs[p++] = GLX_RED_SIZE;
251 break;
252
253 case WX_GL_MIN_GREEN:
254 glattrs[p++] = GLX_GREEN_SIZE;
255 break;
256
257 case WX_GL_MIN_BLUE:
258 glattrs[p++] = GLX_BLUE_SIZE;
259 break;
260
261 case WX_GL_MIN_ALPHA:
262 glattrs[p++] = GLX_ALPHA_SIZE;
263 break;
264
265 case WX_GL_DEPTH_SIZE:
266 glattrs[p++] = GLX_DEPTH_SIZE;
267 break;
268
269 case WX_GL_STENCIL_SIZE:
270 glattrs[p++] = GLX_STENCIL_SIZE;
271 break;
272
273 case WX_GL_MIN_ACCUM_RED:
274 glattrs[p++] = GLX_ACCUM_RED_SIZE;
275 break;
276
277 case WX_GL_MIN_ACCUM_GREEN:
278 glattrs[p++] = GLX_ACCUM_GREEN_SIZE;
279 break;
280
281 case WX_GL_MIN_ACCUM_BLUE:
282 glattrs[p++] = GLX_ACCUM_BLUE_SIZE;
283 break;
284
285 case WX_GL_MIN_ACCUM_ALPHA:
286 glattrs[p++] = GLX_ACCUM_ALPHA_SIZE;
287 break;
288
c39d2e0a 289 case WX_GL_SAMPLE_BUFFERS:
049c4f6c
VZ
290#ifdef GLX_SAMPLE_BUFFERS_ARB
291 if ( IsGLXMultiSampleAvailable() )
c39d2e0a 292 {
049c4f6c
VZ
293 glattrs[p++] = GLX_SAMPLE_BUFFERS_ARB;
294 break;
c39d2e0a 295 }
049c4f6c
VZ
296#endif // GLX_SAMPLE_BUFFERS_ARB
297 // if it was specified just to disable it, no problem
298 if ( !wxattrs[arg++] )
299 continue;
c39d2e0a 300
049c4f6c
VZ
301 // otherwise indicate that it's not supported
302 return false;
c39d2e0a
VZ
303
304 case WX_GL_SAMPLES:
049c4f6c
VZ
305#ifdef GLX_SAMPLES_ARB
306 if ( IsGLXMultiSampleAvailable() )
c39d2e0a 307 {
049c4f6c
VZ
308 glattrs[p++] = GLX_SAMPLES_ARB;
309 break;
c39d2e0a 310 }
049c4f6c 311#endif // GLX_SAMPLES_ARB
c39d2e0a 312
049c4f6c
VZ
313 if ( !wxattrs[arg++] )
314 continue;
315
316 return false;
c39d2e0a 317
498ace9e 318 default:
9a83f860 319 wxLogDebug(wxT("Unsupported OpenGL attribute %d"),
498ace9e
VZ
320 wxattrs[arg - 1]);
321 continue;
322 }
323
b73b2117
VZ
324 if ( isBoolAttr )
325 {
326 // as explained above, for pre 1.3 API the attribute just needs
327 // to be present so we only add its value when using the new API
328 if ( GetGLXVersion() >= 13 )
329 glattrs[p++] = True;
330 }
331 else // attribute with real (non-boolean) value
332 {
333 // copy attribute value as is
334 glattrs[p++] = wxattrs[arg++];
335 }
498ace9e
VZ
336 }
337
338 glattrs[p] = None;
339 }
340
341 return true;
342}
343
344/* static */
345bool
346wxGLCanvasX11::InitXVisualInfo(const int *attribList,
347 GLXFBConfig **pFBC,
348 XVisualInfo **pXVisual)
349{
350 int data[512];
351 if ( !ConvertWXAttrsToGL(attribList, data, WXSIZEOF(data)) )
352 return false;
353
354 Display * const dpy = wxGetX11Display();
355
356 if ( GetGLXVersion() >= 13 )
357 {
358 int returned;
359 *pFBC = glXChooseFBConfig(dpy, DefaultScreen(dpy), data, &returned);
360
361 if ( *pFBC )
362 {
363 *pXVisual = glXGetVisualFromFBConfig(wxGetX11Display(), **pFBC);
364 if ( !*pXVisual )
365 {
366 XFree(*pFBC);
367 *pFBC = NULL;
368 }
369 }
370 }
371 else // GLX <= 1.2
372 {
373 *pFBC = NULL;
374 *pXVisual = glXChooseVisual(dpy, DefaultScreen(dpy), data);
375 }
376
377 return *pXVisual != NULL;
378}
379
3f20f7d8
VZ
380/* static */
381bool
382wxGLCanvasBase::IsDisplaySupported(const int *attribList)
383{
384 GLXFBConfig *fbc = NULL;
385 XVisualInfo *vi = NULL;
386
387 const bool
388 isSupported = wxGLCanvasX11::InitXVisualInfo(attribList, &fbc, &vi);
389
390 if ( fbc )
391 XFree(fbc);
392 if ( vi )
393 XFree(vi);
394
395 return isSupported;
396}
397
498ace9e
VZ
398// ----------------------------------------------------------------------------
399// default visual management
400// ----------------------------------------------------------------------------
401
402XVisualInfo *wxGLCanvasX11::ms_glVisualInfo = NULL;
403GLXFBConfig *wxGLCanvasX11::ms_glFBCInfo = NULL;
404
405/* static */
406bool wxGLCanvasX11::InitDefaultVisualInfo(const int *attribList)
407{
408 FreeDefaultVisualInfo();
409
410 return InitXVisualInfo(attribList, &ms_glFBCInfo, &ms_glVisualInfo);
411}
412
413/* static */
414void wxGLCanvasX11::FreeDefaultVisualInfo()
415{
416 if ( ms_glFBCInfo )
417 {
418 XFree(ms_glFBCInfo);
419 ms_glFBCInfo = NULL;
420 }
421
422 if ( ms_glVisualInfo )
423 {
424 XFree(ms_glVisualInfo);
425 ms_glVisualInfo = NULL;
426 }
427}
428
429// ----------------------------------------------------------------------------
430// other GL methods
431// ----------------------------------------------------------------------------
432
433/* static */
434int wxGLCanvasX11::GetGLXVersion()
435{
436 static int s_glxVersion = 0;
437 if ( s_glxVersion == 0 )
438 {
439 // check the GLX version
440 int glxMajorVer, glxMinorVer;
441 bool ok = glXQueryVersion(wxGetX11Display(), &glxMajorVer, &glxMinorVer);
9a83f860 442 wxASSERT_MSG( ok, wxT("GLX version not found") );
498ace9e
VZ
443 if (!ok)
444 s_glxVersion = 10; // 1.0 by default
445 else
446 s_glxVersion = glxMajorVer*10 + glxMinorVer;
447 }
448
449 return s_glxVersion;
450}
451
5ec69e96 452bool wxGLCanvasX11::SwapBuffers()
498ace9e
VZ
453{
454 const Window xid = GetXWindow();
9a83f860 455 wxCHECK2_MSG( xid, return false, wxT("window must be shown") );
498ace9e
VZ
456
457 glXSwapBuffers(wxGetX11Display(), xid);
5ec69e96 458 return true;
498ace9e
VZ
459}
460
461bool wxGLCanvasX11::IsShownOnScreen() const
462{
463 return GetXWindow() && wxGLCanvasBase::IsShownOnScreen();
464}
465
466#endif // wxUSE_GLCANVAS
467