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