]> git.saurik.com Git - wxWidgets.git/blob - src/x11/glcanvas.cpp
fix wxCheckListBox which was completely broken by the Unicode changes
[wxWidgets.git] / src / x11 / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWindows 2.0 for Motif.
4 // Uses the GLX extension.
5 // Author: Julian Smart and Wolfram Gloger
6 // Modified by:
7 // Created: 1995, 1999
8 // RCS-ID: $Id$
9 // Copyright: (c) Julian Smart, Wolfram Gloger
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #ifdef __GNUG__
14 #pragma implementation "glcanvas.h"
15 #endif
16
17 #include "wx/setup.h"
18
19 #if wxUSE_GLCANVAS
20
21 #include "wx/glcanvas.h"
22 #include "wx/utils.h"
23 #include "wx/app.h"
24 #include "wx/log.h"
25
26 #ifdef __VMS
27 # pragma message disable nosimpint
28 #endif
29 #include <Xm/Xm.h>
30 #ifdef __VMS
31 # pragma message enable nosimpint
32 #endif
33 #include "wx/motif/private.h"
34
35 #ifdef OLD_MESA
36 // workaround for bug in Mesa's glx.c
37 static int bitcount( unsigned long n )
38 {
39 int bits;
40 for (bits=0; n>0;) {
41 if(n & 1) bits++;
42 n = n >> 1;
43 }
44 return bits;
45 }
46 #endif
47
48 /*
49 * GLContext implementation
50 */
51
52 IMPLEMENT_CLASS(wxGLContext,wxObject)
53
54 wxGLContext::wxGLContext( bool WXUNUSED(isRGB), wxWindow *win,
55 const wxPalette& WXUNUSED(palette) )
56 {
57 m_window = win;
58 // m_widget = win->m_wxwindow;
59
60 wxGLCanvas *gc = (wxGLCanvas*) win;
61 XVisualInfo *vi = (XVisualInfo *) gc->m_vi;
62
63 wxCHECK_RET( vi, "invalid visual for OpenGl" );
64
65 m_glContext = glXCreateContext( (Display *)wxGetDisplay(), vi,
66 None, GL_TRUE);
67
68 wxCHECK_RET( m_glContext, "Couldn't create OpenGl context" );
69 }
70
71 wxGLContext::wxGLContext(
72 bool WXUNUSED(isRGB), wxWindow *win,
73 const wxPalette& WXUNUSED(palette),
74 const wxGLContext *other /* for sharing display lists */
75 )
76 {
77 m_window = win;
78 // m_widget = win->m_wxwindow;
79
80 wxGLCanvas *gc = (wxGLCanvas*) win;
81 XVisualInfo *vi = (XVisualInfo *) gc->m_vi;
82
83 wxCHECK_RET( vi, "invalid visual for OpenGl" );
84
85 if( other != 0 )
86 m_glContext = glXCreateContext( (Display *)wxGetDisplay(), vi,
87 other->m_glContext, GL_TRUE );
88 else
89 m_glContext = glXCreateContext( (Display *)wxGetDisplay(), vi,
90 None, GL_TRUE );
91
92 wxCHECK_RET( m_glContext, "Couldn't create OpenGl context" );
93 }
94
95 wxGLContext::~wxGLContext()
96 {
97 if (!m_glContext) return;
98
99 if (m_glContext == glXGetCurrentContext())
100 {
101 glXMakeCurrent( (Display*) wxGetDisplay(), None, NULL);
102 }
103
104 glXDestroyContext( (Display*) wxGetDisplay(), m_glContext );
105 }
106
107 void wxGLContext::SwapBuffers()
108 {
109 if (m_glContext)
110 {
111 Display* display = (Display*) wxGetDisplay();
112 glXSwapBuffers(display, (Window) m_window->GetClientAreaWindow());
113 }
114 }
115
116 void wxGLContext::SetCurrent()
117 {
118 if (m_glContext)
119 {
120 Display* display = (Display*) wxGetDisplay();
121 glXMakeCurrent(display, (Window) m_window->GetClientAreaWindow(),
122 m_glContext );;
123 }
124 }
125
126 void wxGLContext::SetColour(const char *colour)
127 {
128 wxColour *the_colour = wxTheColourDatabase->FindColour(colour);
129 if(the_colour) {
130 GLboolean b;
131 glGetBooleanv(GL_RGBA_MODE, &b);
132 if(b) {
133 glColor3ub(the_colour->Red(),
134 the_colour->Green(),
135 the_colour->Blue());
136 } else {
137 the_colour->CalcPixel(wxTheApp->GetMainColormap(wxGetDisplay()));
138 GLint pix = (GLint)the_colour->GetPixel();
139 if(pix == -1)
140 {
141 wxLogError("wxGLCanvas: cannot allocate color\n");
142 return;
143 }
144 glIndexi(pix);
145 }
146 }
147 }
148
149 void wxGLContext::SetupPixelFormat()
150 {
151 }
152
153 void wxGLContext::SetupPalette( const wxPalette& WXUNUSED(palette) )
154 {
155 }
156
157 wxPalette wxGLContext::CreateDefaultPalette()
158 {
159 return wxNullPalette;
160 }
161
162
163
164
165 /*
166 * GLCanvas implementation
167 */
168
169 IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
170
171 BEGIN_EVENT_TABLE(wxGLCanvas, wxScrolledWindow)
172 // EVT_SIZE(wxGLCanvas::OnSize)
173 END_EVENT_TABLE()
174
175
176 wxGLCanvas::wxGLCanvas( wxWindow *parent, wxWindowID id,
177 const wxPoint& pos, const wxSize& size,
178 long style, const wxString& name,
179 int *attribList,
180 const wxPalette& palette )
181 : wxScrolledWindow(parent, id, pos, size, style, name)
182 {
183 Create( parent, NULL, NULL, id, pos, size, style, name, attribList, palette );
184 }
185
186 wxGLCanvas::wxGLCanvas( wxWindow *parent,
187 const wxGLContext *shared,
188 wxWindowID id,
189 const wxPoint& pos, const wxSize& size,
190 long style, const wxString& name,
191 int *attribList,
192 const wxPalette& palette )
193 : wxScrolledWindow(parent, id, pos, size, style, name)
194 {
195 Create( parent, shared, NULL, id, pos, size, style, name, attribList, palette );
196 }
197
198 wxGLCanvas::wxGLCanvas( wxWindow *parent,
199 const wxGLCanvas *shared,
200 wxWindowID id,
201 const wxPoint& pos, const wxSize& size,
202 long style, const wxString& name,
203 int *attribList,
204 const wxPalette& palette )
205 : wxScrolledWindow(parent, id, pos, size, style, name)
206 {
207 Create( parent, NULL, shared, id, pos, size, style, name, attribList, palette );
208 }
209
210
211 /*
212 bool wxGLCanvas::Create(wxWindow *parent,
213 const wxGLContext *shared, const wxGLCanvas *shared_context_of,
214 wxWindowID id = -1, const wxPoint& pos,
215 const wxSize& size, long style,
216 const wxString& name, int *attribList, const wxPalette& palette):
217 wxScrolledWindow(parent, id, pos, size, style, name)
218 */
219
220 bool wxGLCanvas::Create( wxWindow *parent,
221 const wxGLContext *shared,
222 const wxGLCanvas *shared_context_of,
223 wxWindowID id,
224 const wxPoint& pos, const wxSize& size,
225 long style, const wxString& name,
226 int *attribList,
227 const wxPalette& palette)
228 {
229 XVisualInfo *vi, vi_templ;
230 XWindowAttributes xwa;
231 int val, n;
232
233 m_sharedContext = (wxGLContext*)shared; // const_cast
234 m_sharedContextOf = (wxGLCanvas*)shared_context_of; // const_cast
235 m_glContext = (wxGLContext*) NULL;
236
237 Display* display = (Display*) wxGetDisplay();
238
239 // Check for the presence of the GLX extension
240 if(!glXQueryExtension(display, NULL, NULL)) {
241 wxDebugMsg("wxGLCanvas: GLX extension is missing\n");
242 return false;
243 }
244
245 if(attribList) {
246 int data[512], arg=0, p=0;
247
248 while( (attribList[arg]!=0) && (p<512) )
249 {
250 switch( attribList[arg++] )
251 {
252 case WX_GL_RGBA: data[p++] = GLX_RGBA; break;
253 case WX_GL_BUFFER_SIZE:
254 data[p++]=GLX_BUFFER_SIZE; data[p++]=attribList[arg++]; break;
255 case WX_GL_LEVEL:
256 data[p++]=GLX_LEVEL; data[p++]=attribList[arg++]; break;
257 case WX_GL_DOUBLEBUFFER: data[p++] = GLX_DOUBLEBUFFER; break;
258 case WX_GL_STEREO: data[p++] = GLX_STEREO; break;
259 case WX_GL_AUX_BUFFERS:
260 data[p++]=GLX_AUX_BUFFERS; data[p++]=attribList[arg++]; break;
261 case WX_GL_MIN_RED:
262 data[p++]=GLX_RED_SIZE; data[p++]=attribList[arg++]; break;
263 case WX_GL_MIN_GREEN:
264 data[p++]=GLX_GREEN_SIZE; data[p++]=attribList[arg++]; break;
265 case WX_GL_MIN_BLUE:
266 data[p++]=GLX_BLUE_SIZE; data[p++]=attribList[arg++]; break;
267 case WX_GL_MIN_ALPHA:
268 data[p++]=GLX_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
269 case WX_GL_DEPTH_SIZE:
270 data[p++]=GLX_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
271 case WX_GL_STENCIL_SIZE:
272 data[p++]=GLX_STENCIL_SIZE; data[p++]=attribList[arg++]; break;
273 case WX_GL_MIN_ACCUM_RED:
274 data[p++]=GLX_ACCUM_RED_SIZE; data[p++]=attribList[arg++]; break;
275 case WX_GL_MIN_ACCUM_GREEN:
276 data[p++]=GLX_ACCUM_GREEN_SIZE; data[p++]=attribList[arg++]; break;
277 case WX_GL_MIN_ACCUM_BLUE:
278 data[p++]=GLX_ACCUM_BLUE_SIZE; data[p++]=attribList[arg++]; break;
279 case WX_GL_MIN_ACCUM_ALPHA:
280 data[p++]=GLX_ACCUM_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
281 default:
282 break;
283 }
284 }
285 data[p] = 0;
286
287 attribList = (int*) data;
288 // Get an appropriate visual
289 vi = glXChooseVisual(display, DefaultScreen(display), attribList);
290 if(!vi) return false;
291
292 // Here we should make sure that vi is the same visual as the
293 // one used by the xwindow drawable in wxCanvas. However,
294 // there is currently no mechanism for this in wx_canvs.cc.
295 } else {
296 // By default, we use the visual of xwindow
297 // NI: is this really senseful ? opengl in e.g. color index mode ?
298 XGetWindowAttributes(display, (Window) GetClientAreaWindow(), &xwa);
299 vi_templ.visualid = XVisualIDFromVisual(xwa.visual);
300 vi = XGetVisualInfo(display, VisualIDMask, &vi_templ, &n);
301 if(!vi) return false;
302 glXGetConfig(display, vi, GLX_USE_GL, &val);
303 if(!val) return false;
304 // Basically, this is it. It should be possible to use vi
305 // in glXCreateContext() below. But this fails with Mesa.
306 // I notified the Mesa author about it; there may be a fix.
307 #ifdef OLD_MESA
308 // Construct an attribute list matching the visual
309 int a_list[32];
310 n = 0;
311 if(vi->c_class==TrueColor || vi->c_class==DirectColor) { // RGBA visual
312 a_list[n++] = GLX_RGBA;
313 a_list[n++] = GLX_RED_SIZE;
314 a_list[n++] = bitcount(vi->red_mask);
315 a_list[n++] = GLX_GREEN_SIZE;
316 a_list[n++] = bitcount(vi->green_mask);
317 a_list[n++] = GLX_BLUE_SIZE;
318 a_list[n++] = bitcount(vi->blue_mask);
319 glXGetConfig(display, vi, GLX_ALPHA_SIZE, &val);
320 a_list[n++] = GLX_ALPHA_SIZE;
321 a_list[n++] = val;
322 } else { // Color index visual
323 glXGetConfig(display, vi, GLX_BUFFER_SIZE, &val);
324 a_list[n++] = GLX_BUFFER_SIZE;
325 a_list[n++] = val;
326 }
327 a_list[n] = None;
328 // XFree(vi);
329 vi = glXChooseVisual(display, DefaultScreen(display), a_list);
330 if(!vi) return false;
331 #endif /* OLD_MESA */
332 }
333
334 m_vi = vi; // safe for later use
335
336 wxCHECK_MSG( m_vi, FALSE, "required visual couldn't be found" );
337
338 // Create the GLX context and make it current
339
340 wxGLContext *share= m_sharedContext;
341 if (share==NULL && m_sharedContextOf)
342 share = m_sharedContextOf->GetContext();
343
344 m_glContext = new wxGLContext( TRUE, this, wxNullPalette, share );
345
346 #ifndef OLD_MESA
347 // XFree(vi);
348 #endif
349 SetCurrent();
350
351 return true;
352 }
353
354 wxGLCanvas::~wxGLCanvas(void)
355 {
356 XVisualInfo *vi = (XVisualInfo *) m_vi;
357
358 if (vi) XFree( vi );
359 if (m_glContext) delete m_glContext;
360
361 // Display* display = (Display*) GetXDisplay();
362 // if(glx_cx) glXDestroyContext(display, glx_cx);
363 }
364
365 void wxGLCanvas::SwapBuffers()
366 {
367 if( m_glContext ) m_glContext->SwapBuffers();
368
369 // Display* display = (Display*) GetXDisplay();
370 // if(glx_cx) glXSwapBuffers(display, (Window) GetClientAreaWindow());
371 }
372
373 void wxGLCanvas::SetCurrent()
374 {
375 if( m_glContext ) m_glContext->SetCurrent();
376
377 // Display* display = (Display*) GetXDisplay();
378 // if(glx_cx) glXMakeCurrent(display, (Window) GetClientAreaWindow(), glx_cx);
379 }
380
381 void wxGLCanvas::SetColour(const char *col)
382 {
383 if( m_glContext ) m_glContext->SetColour(col);
384 }
385
386 #endif
387 // wxUSE_GLCANVAS
388