]> git.saurik.com Git - wxWidgets.git/blame - src/unix/glx11.cpp
wxchar.h doesn't have to be C file anymore, it's C++
[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
71void wxGLContext::SetCurrent(const wxGLCanvas& win) const
72{
73 if ( !m_glContext )
74 return;
75
76 const Window xid = win.GetXWindow();
77 wxCHECK_RET( xid, _T("window must be shown") );
78
79 MakeCurrent(xid, m_glContext);
80}
81
82// wrapper around glXMakeContextCurrent/glXMakeCurrent depending on GLX
83// version
84/* static */
85void wxGLContext::MakeCurrent(GLXDrawable drawable, GLXContext context)
86{
87 if (wxGLCanvas::GetGLXVersion() >= 13)
88 glXMakeContextCurrent( wxGetX11Display(), drawable, drawable, context);
89 else // GLX <= 1.2 doesn't have glXMakeContextCurrent()
90 glXMakeCurrent( wxGetX11Display(), drawable, context);
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
125bool
126wxGLCanvasX11::ConvertWXAttrsToGL(const int *wxattrs, int *glattrs, size_t n)
127{
128 wxCHECK_MSG( n >= 16, false, _T("GL attributes buffer too small") );
129
130 if ( !wxattrs )
131 {
132 if ( GetGLXVersion() >= 13 )
133 {
134 // leave GLX >= 1.3 choose the default attributes
135 glattrs[0] = None;
136 }
137 else // GLX < 1.3
138 {
139 // default settings if attriblist = 0
140 size_t i = 0;
141 glattrs[i++] = GLX_RGBA;
142 glattrs[i++] = GLX_DOUBLEBUFFER;
143 glattrs[i++] = GLX_DEPTH_SIZE; glattrs[i++] = 1;
144 glattrs[i++] = GLX_RED_SIZE; glattrs[i++] = 1;
145 glattrs[i++] = GLX_GREEN_SIZE; glattrs[i++] = 1;
146 glattrs[i++] = GLX_BLUE_SIZE; glattrs[i++] = 1;
147 glattrs[i++] = GLX_ALPHA_SIZE; glattrs[i++] = 0;
148 glattrs[i++] = None;
149
150 wxASSERT_MSG( i < n, _T("GL attributes buffer too small") );
151 }
152 }
153 else // have non-default attributes
154 {
155 size_t p = 0;
156 for ( int arg = 0; wxattrs[arg] != 0; )
157 {
158 // check if we have any space left, knowing that we may insert 2
159 // more elements during this loop iteration and we always need to
160 // terminate the list with None (hence -3)
161 if ( p >= n - 2 )
162 return false;
163
164 // notice that for boolean attributes we use "continue" in the
165 // switch to skip the assignment of the attribute value at the end
166 // of the loop which is done for integer attributes
167 switch ( wxattrs[arg++] )
168 {
169 case WX_GL_RGBA:
170 // for GLX >= 1.3, GLX_RGBA is useless and apparently
171 // harmful for some implementations
172 //
173 // FIXME: is this true?
174 if ( GetGLXVersion() <= 12 )
175 {
176 glattrs[p++] = GLX_RGBA;
177 }
178 continue;
179
180 case WX_GL_BUFFER_SIZE:
181 glattrs[p++] = GLX_BUFFER_SIZE;
182 break;
183
184 case WX_GL_LEVEL:
185 glattrs[p++] = GLX_LEVEL;
186 break;
187
188 case WX_GL_DOUBLEBUFFER:
189 glattrs[p++] = GLX_DOUBLEBUFFER;
190 continue;
191
192 case WX_GL_STEREO:
193 glattrs[p++] = GLX_STEREO;
194 break;
195
196 case WX_GL_AUX_BUFFERS:
197 glattrs[p++] = GLX_AUX_BUFFERS;
198 break;
199
200 case WX_GL_MIN_RED:
201 glattrs[p++] = GLX_RED_SIZE;
202 break;
203
204 case WX_GL_MIN_GREEN:
205 glattrs[p++] = GLX_GREEN_SIZE;
206 break;
207
208 case WX_GL_MIN_BLUE:
209 glattrs[p++] = GLX_BLUE_SIZE;
210 break;
211
212 case WX_GL_MIN_ALPHA:
213 glattrs[p++] = GLX_ALPHA_SIZE;
214 break;
215
216 case WX_GL_DEPTH_SIZE:
217 glattrs[p++] = GLX_DEPTH_SIZE;
218 break;
219
220 case WX_GL_STENCIL_SIZE:
221 glattrs[p++] = GLX_STENCIL_SIZE;
222 break;
223
224 case WX_GL_MIN_ACCUM_RED:
225 glattrs[p++] = GLX_ACCUM_RED_SIZE;
226 break;
227
228 case WX_GL_MIN_ACCUM_GREEN:
229 glattrs[p++] = GLX_ACCUM_GREEN_SIZE;
230 break;
231
232 case WX_GL_MIN_ACCUM_BLUE:
233 glattrs[p++] = GLX_ACCUM_BLUE_SIZE;
234 break;
235
236 case WX_GL_MIN_ACCUM_ALPHA:
237 glattrs[p++] = GLX_ACCUM_ALPHA_SIZE;
238 break;
239
240 default:
241 wxLogDebug(_T("Unsupported OpenGL attribute %d"),
242 wxattrs[arg - 1]);
243 continue;
244 }
245
246 // copy attribute value as is
247 glattrs[p++] = wxattrs[arg++];
248 }
249
250 glattrs[p] = None;
251 }
252
253 return true;
254}
255
256/* static */
257bool
258wxGLCanvasX11::InitXVisualInfo(const int *attribList,
259 GLXFBConfig **pFBC,
260 XVisualInfo **pXVisual)
261{
262 int data[512];
263 if ( !ConvertWXAttrsToGL(attribList, data, WXSIZEOF(data)) )
264 return false;
265
266 Display * const dpy = wxGetX11Display();
267
268 if ( GetGLXVersion() >= 13 )
269 {
270 int returned;
271 *pFBC = glXChooseFBConfig(dpy, DefaultScreen(dpy), data, &returned);
272
273 if ( *pFBC )
274 {
275 *pXVisual = glXGetVisualFromFBConfig(wxGetX11Display(), **pFBC);
276 if ( !*pXVisual )
277 {
278 XFree(*pFBC);
279 *pFBC = NULL;
280 }
281 }
282 }
283 else // GLX <= 1.2
284 {
285 *pFBC = NULL;
286 *pXVisual = glXChooseVisual(dpy, DefaultScreen(dpy), data);
287 }
288
289 return *pXVisual != NULL;
290}
291
292// ----------------------------------------------------------------------------
293// default visual management
294// ----------------------------------------------------------------------------
295
296XVisualInfo *wxGLCanvasX11::ms_glVisualInfo = NULL;
297GLXFBConfig *wxGLCanvasX11::ms_glFBCInfo = NULL;
298
299/* static */
300bool wxGLCanvasX11::InitDefaultVisualInfo(const int *attribList)
301{
302 FreeDefaultVisualInfo();
303
304 return InitXVisualInfo(attribList, &ms_glFBCInfo, &ms_glVisualInfo);
305}
306
307/* static */
308void wxGLCanvasX11::FreeDefaultVisualInfo()
309{
310 if ( ms_glFBCInfo )
311 {
312 XFree(ms_glFBCInfo);
313 ms_glFBCInfo = NULL;
314 }
315
316 if ( ms_glVisualInfo )
317 {
318 XFree(ms_glVisualInfo);
319 ms_glVisualInfo = NULL;
320 }
321}
322
323// ----------------------------------------------------------------------------
324// other GL methods
325// ----------------------------------------------------------------------------
326
327/* static */
328int wxGLCanvasX11::GetGLXVersion()
329{
330 static int s_glxVersion = 0;
331 if ( s_glxVersion == 0 )
332 {
333 // check the GLX version
334 int glxMajorVer, glxMinorVer;
335 bool ok = glXQueryVersion(wxGetX11Display(), &glxMajorVer, &glxMinorVer);
336 wxASSERT_MSG( ok, _T("GLX version not found") );
337 if (!ok)
338 s_glxVersion = 10; // 1.0 by default
339 else
340 s_glxVersion = glxMajorVer*10 + glxMinorVer;
341 }
342
343 return s_glxVersion;
344}
345
346void wxGLCanvasX11::SwapBuffers()
347{
348 const Window xid = GetXWindow();
349 wxCHECK_RET( xid, _T("window must be shown") );
350
351 glXSwapBuffers(wxGetX11Display(), xid);
352}
353
354bool wxGLCanvasX11::IsShownOnScreen() const
355{
356 return GetXWindow() && wxGLCanvasBase::IsShownOnScreen();
357}
358
359#endif // wxUSE_GLCANVAS
360