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