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