]> git.saurik.com Git - wxWidgets.git/blame - src/x11/glcanvas.cpp
Committing in .
[wxWidgets.git] / src / x11 / glcanvas.cpp
CommitLineData
83df96d6
JS
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
09a1dffa 21// #error Sorry, wxGLCanvas does not work yet with wxX11
fd52ec65 22
83df96d6
JS
23#include "wx/glcanvas.h"
24#include "wx/utils.h"
25#include "wx/app.h"
0ace9095 26#include "wx/log.h"
83df96d6
JS
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
39static 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
54IMPLEMENT_CLASS(wxGLContext,wxObject)
55
56wxGLContext::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
33980f0d 67 m_glContext = glXCreateContext( (Display *)wxGetDisplay(), vi,
83df96d6
JS
68 None, GL_TRUE);
69
70 wxCHECK_RET( m_glContext, "Couldn't create OpenGl context" );
71}
72
73wxGLContext::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 )
33980f0d 88 m_glContext = glXCreateContext( (Display *)wxGetDisplay(), vi,
83df96d6
JS
89 other->m_glContext, GL_TRUE );
90 else
33980f0d 91 m_glContext = glXCreateContext( (Display *)wxGetDisplay(), vi,
83df96d6
JS
92 None, GL_TRUE );
93
94 wxCHECK_RET( m_glContext, "Couldn't create OpenGl context" );
95}
96
97wxGLContext::~wxGLContext()
98{
99 if (!m_glContext) return;
100
101 if (m_glContext == glXGetCurrentContext())
102 {
33980f0d 103 glXMakeCurrent( (Display*) wxGetDisplay(), None, NULL);
83df96d6
JS
104 }
105
33980f0d 106 glXDestroyContext( (Display*) wxGetDisplay(), m_glContext );
83df96d6
JS
107}
108
109void wxGLContext::SwapBuffers()
110{
111 if (m_glContext)
112 {
33980f0d 113 Display* display = (Display*) wxGetDisplay();
f41bc3e3 114 glXSwapBuffers(display, (Window) m_window->GetClientAreaWindow());
83df96d6
JS
115 }
116}
117
118void wxGLContext::SetCurrent()
119{
120 if (m_glContext)
121 {
33980f0d 122 Display* display = (Display*) wxGetDisplay();
f41bc3e3 123 glXMakeCurrent(display, (Window) m_window->GetClientAreaWindow(),
83df96d6
JS
124 m_glContext );;
125 }
126}
127
128void 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 {
33980f0d 139 the_colour->CalcPixel(wxTheApp->GetMainColormap(wxGetDisplay()));
e3baff1c
JS
140 GLint pix = (GLint)the_colour->GetPixel();
141 if(pix == -1)
142 {
143 wxLogError("wxGLCanvas: cannot allocate color\n");
144 return;
145 }
83df96d6
JS
146 glIndexi(pix);
147 }
148 }
149}
150
151void wxGLContext::SetupPixelFormat()
152{
153}
154
155void wxGLContext::SetupPalette( const wxPalette& WXUNUSED(palette) )
156{
157}
158
159wxPalette wxGLContext::CreateDefaultPalette()
160{
161 return wxNullPalette;
162}
163
164
165
166
167/*
168 * GLCanvas implementation
169 */
170
171IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
172
173BEGIN_EVENT_TABLE(wxGLCanvas, wxScrolledWindow)
174// EVT_SIZE(wxGLCanvas::OnSize)
175END_EVENT_TABLE()
176
177
178wxGLCanvas::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
188wxGLCanvas::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
200wxGLCanvas::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/*
214bool 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
222bool 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
33980f0d 239 Display* display = (Display*) wxGetDisplay();
83df96d6
JS
240
241 // Check for the presence of the GLX extension
242 if(!glXQueryExtension(display, NULL, NULL)) {
2b5f62a0
VZ
243 wxLogDebug("wxGLCanvas: GLX extension is missing\n");
244 return FALSE;
83df96d6
JS
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);
2b5f62a0 292 if(!vi) return FALSE;
83df96d6
JS
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 ?
f41bc3e3 300 XGetWindowAttributes(display, (Window) GetClientAreaWindow(), &xwa);
83df96d6
JS
301 vi_templ.visualid = XVisualIDFromVisual(xwa.visual);
302 vi = XGetVisualInfo(display, VisualIDMask, &vi_templ, &n);
2b5f62a0 303 if(!vi) return FALSE;
83df96d6 304 glXGetConfig(display, vi, GLX_USE_GL, &val);
2b5f62a0 305 if(!val) return FALSE;
83df96d6
JS
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);
2b5f62a0 332 if(!vi) return FALSE;
83df96d6
JS
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
2b5f62a0 353 return TRUE;
83df96d6
JS
354}
355
356wxGLCanvas::~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
367void wxGLCanvas::SwapBuffers()
368{
369 if( m_glContext ) m_glContext->SwapBuffers();
370
371 // Display* display = (Display*) GetXDisplay();
f41bc3e3 372 // if(glx_cx) glXSwapBuffers(display, (Window) GetClientAreaWindow());
83df96d6
JS
373}
374
375void wxGLCanvas::SetCurrent()
376{
377 if( m_glContext ) m_glContext->SetCurrent();
378
379 // Display* display = (Display*) GetXDisplay();
f41bc3e3 380 // if(glx_cx) glXMakeCurrent(display, (Window) GetClientAreaWindow(), glx_cx);
83df96d6
JS
381}
382
383void wxGLCanvas::SetColour(const char *col)
384{
385 if( m_glContext ) m_glContext->SetColour(col);
386}
387
388#endif
389 // wxUSE_GLCANVAS
390