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