]> git.saurik.com Git - wxWidgets.git/blame - src/x11/glcanvas.cpp
use own mutex for region iterator locking, not gui one
[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
21#include "wx/glcanvas.h"
22#include "wx/utils.h"
23#include "wx/app.h"
0ace9095 24#include "wx/log.h"
83df96d6
JS
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
37static 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
52IMPLEMENT_CLASS(wxGLContext,wxObject)
53
54wxGLContext::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
33980f0d 65 m_glContext = glXCreateContext( (Display *)wxGetDisplay(), vi,
83df96d6
JS
66 None, GL_TRUE);
67
68 wxCHECK_RET( m_glContext, "Couldn't create OpenGl context" );
69}
70
71wxGLContext::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 )
33980f0d 86 m_glContext = glXCreateContext( (Display *)wxGetDisplay(), vi,
83df96d6
JS
87 other->m_glContext, GL_TRUE );
88 else
33980f0d 89 m_glContext = glXCreateContext( (Display *)wxGetDisplay(), vi,
83df96d6
JS
90 None, GL_TRUE );
91
92 wxCHECK_RET( m_glContext, "Couldn't create OpenGl context" );
93}
94
95wxGLContext::~wxGLContext()
96{
97 if (!m_glContext) return;
98
99 if (m_glContext == glXGetCurrentContext())
100 {
33980f0d 101 glXMakeCurrent( (Display*) wxGetDisplay(), None, NULL);
83df96d6
JS
102 }
103
33980f0d 104 glXDestroyContext( (Display*) wxGetDisplay(), m_glContext );
83df96d6
JS
105}
106
107void wxGLContext::SwapBuffers()
108{
109 if (m_glContext)
110 {
33980f0d 111 Display* display = (Display*) wxGetDisplay();
f41bc3e3 112 glXSwapBuffers(display, (Window) m_window->GetClientAreaWindow());
83df96d6
JS
113 }
114}
115
116void wxGLContext::SetCurrent()
117{
118 if (m_glContext)
119 {
33980f0d 120 Display* display = (Display*) wxGetDisplay();
f41bc3e3 121 glXMakeCurrent(display, (Window) m_window->GetClientAreaWindow(),
83df96d6
JS
122 m_glContext );;
123 }
124}
125
126void 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 {
33980f0d 137 the_colour->CalcPixel(wxTheApp->GetMainColormap(wxGetDisplay()));
e3baff1c
JS
138 GLint pix = (GLint)the_colour->GetPixel();
139 if(pix == -1)
140 {
141 wxLogError("wxGLCanvas: cannot allocate color\n");
142 return;
143 }
83df96d6
JS
144 glIndexi(pix);
145 }
146 }
147}
148
149void wxGLContext::SetupPixelFormat()
150{
151}
152
153void wxGLContext::SetupPalette( const wxPalette& WXUNUSED(palette) )
154{
155}
156
157wxPalette wxGLContext::CreateDefaultPalette()
158{
159 return wxNullPalette;
160}
161
162
163
164
165/*
166 * GLCanvas implementation
167 */
168
169IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
170
171BEGIN_EVENT_TABLE(wxGLCanvas, wxScrolledWindow)
172// EVT_SIZE(wxGLCanvas::OnSize)
173END_EVENT_TABLE()
174
175
176wxGLCanvas::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
186wxGLCanvas::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
198wxGLCanvas::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/*
212bool 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
220bool 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
33980f0d 237 Display* display = (Display*) wxGetDisplay();
83df96d6
JS
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 ?
f41bc3e3 298 XGetWindowAttributes(display, (Window) GetClientAreaWindow(), &xwa);
83df96d6
JS
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
354wxGLCanvas::~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
365void wxGLCanvas::SwapBuffers()
366{
367 if( m_glContext ) m_glContext->SwapBuffers();
368
369 // Display* display = (Display*) GetXDisplay();
f41bc3e3 370 // if(glx_cx) glXSwapBuffers(display, (Window) GetClientAreaWindow());
83df96d6
JS
371}
372
373void wxGLCanvas::SetCurrent()
374{
375 if( m_glContext ) m_glContext->SetCurrent();
376
377 // Display* display = (Display*) GetXDisplay();
f41bc3e3 378 // if(glx_cx) glXMakeCurrent(display, (Window) GetClientAreaWindow(), glx_cx);
83df96d6
JS
379}
380
381void wxGLCanvas::SetColour(const char *col)
382{
383 if( m_glContext ) m_glContext->SetColour(col);
384}
385
386#endif
387 // wxUSE_GLCANVAS
388