]>
git.saurik.com Git - wxWidgets.git/blob - src/x11/glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxGLCanvas, for using OpenGL with wxWindows 2.0 for Motif.
4 // Uses the GLX extension.
5 // Author: Julian Smart and Wolfram Gloger
9 // Copyright: (c) Julian Smart, Wolfram Gloger
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
14 #pragma implementation "glcanvas.h"
21 #include "wx/glcanvas.h"
26 # pragma message disable nosimpint
30 # pragma message enable nosimpint
32 #include "wx/motif/private.h"
35 // workaround for bug in Mesa's glx.c
36 static int bitcount( unsigned long n
)
48 * GLContext implementation
51 IMPLEMENT_CLASS(wxGLContext
,wxObject
)
53 wxGLContext::wxGLContext( bool WXUNUSED(isRGB
), wxWindow
*win
,
54 const wxPalette
& WXUNUSED(palette
) )
57 // m_widget = win->m_wxwindow;
59 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
60 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
62 wxCHECK_RET( vi
, "invalid visual for OpenGl" );
64 m_glContext
= glXCreateContext( (Display
*)wxGetDisplay(), vi
,
67 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
70 wxGLContext::wxGLContext(
71 bool WXUNUSED(isRGB
), wxWindow
*win
,
72 const wxPalette
& WXUNUSED(palette
),
73 const wxGLContext
*other
/* for sharing display lists */
77 // m_widget = win->m_wxwindow;
79 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
80 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
82 wxCHECK_RET( vi
, "invalid visual for OpenGl" );
85 m_glContext
= glXCreateContext( (Display
*)wxGetDisplay(), vi
,
86 other
->m_glContext
, GL_TRUE
);
88 m_glContext
= glXCreateContext( (Display
*)wxGetDisplay(), vi
,
91 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
94 wxGLContext::~wxGLContext()
96 if (!m_glContext
) return;
98 if (m_glContext
== glXGetCurrentContext())
100 glXMakeCurrent( (Display
*) wxGetDisplay(), None
, NULL
);
103 glXDestroyContext( (Display
*) wxGetDisplay(), m_glContext
);
106 void wxGLContext::SwapBuffers()
110 Display
* display
= (Display
*) wxGetDisplay();
111 glXSwapBuffers(display
, (Window
) m_window
->GetClientWindow());
115 void wxGLContext::SetCurrent()
119 Display
* display
= (Display
*) wxGetDisplay();
120 glXMakeCurrent(display
, (Window
) m_window
->GetClientWindow(),
125 void wxGLContext::SetColour(const char *colour
)
127 wxColour
*the_colour
= wxTheColourDatabase
->FindColour(colour
);
130 glGetBooleanv(GL_RGBA_MODE
, &b
);
132 glColor3ub(the_colour
->Red(),
136 the_colour
->CalcPixel(wxTheApp
->GetMainColormap(wxGetDisplay()));
137 GLint pix
= (GLint
)the_colour
->GetPixel();
140 wxLogError("wxGLCanvas: cannot allocate color\n");
148 void wxGLContext::SetupPixelFormat()
152 void wxGLContext::SetupPalette( const wxPalette
& WXUNUSED(palette
) )
156 wxPalette
wxGLContext::CreateDefaultPalette()
158 return wxNullPalette
;
165 * GLCanvas implementation
168 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
)
170 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
)
171 // EVT_SIZE(wxGLCanvas::OnSize)
175 wxGLCanvas::wxGLCanvas( wxWindow
*parent
, wxWindowID id
,
176 const wxPoint
& pos
, const wxSize
& size
,
177 long style
, const wxString
& name
,
179 const wxPalette
& palette
)
180 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
182 Create( parent
, NULL
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
185 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
186 const wxGLContext
*shared
,
188 const wxPoint
& pos
, const wxSize
& size
,
189 long style
, const wxString
& name
,
191 const wxPalette
& palette
)
192 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
194 Create( parent
, shared
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
197 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
198 const wxGLCanvas
*shared
,
200 const wxPoint
& pos
, const wxSize
& size
,
201 long style
, const wxString
& name
,
203 const wxPalette
& palette
)
204 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
206 Create( parent
, NULL
, shared
, id
, pos
, size
, style
, name
, attribList
, palette
);
211 bool wxGLCanvas::Create(wxWindow *parent,
212 const wxGLContext *shared, const wxGLCanvas *shared_context_of,
213 wxWindowID id = -1, const wxPoint& pos,
214 const wxSize& size, long style,
215 const wxString& name, int *attribList, const wxPalette& palette):
216 wxScrolledWindow(parent, id, pos, size, style, name)
219 bool wxGLCanvas::Create( wxWindow
*parent
,
220 const wxGLContext
*shared
,
221 const wxGLCanvas
*shared_context_of
,
223 const wxPoint
& pos
, const wxSize
& size
,
224 long style
, const wxString
& name
,
226 const wxPalette
& palette
)
228 XVisualInfo
*vi
, vi_templ
;
229 XWindowAttributes xwa
;
232 m_sharedContext
= (wxGLContext
*)shared
; // const_cast
233 m_sharedContextOf
= (wxGLCanvas
*)shared_context_of
; // const_cast
234 m_glContext
= (wxGLContext
*) NULL
;
236 Display
* display
= (Display
*) wxGetDisplay();
238 // Check for the presence of the GLX extension
239 if(!glXQueryExtension(display
, NULL
, NULL
)) {
240 wxDebugMsg("wxGLCanvas: GLX extension is missing\n");
245 int data
[512], arg
=0, p
=0;
247 while( (attribList
[arg
]!=0) && (p
<512) )
249 switch( attribList
[arg
++] )
251 case WX_GL_RGBA
: data
[p
++] = GLX_RGBA
; break;
252 case WX_GL_BUFFER_SIZE
:
253 data
[p
++]=GLX_BUFFER_SIZE
; data
[p
++]=attribList
[arg
++]; break;
255 data
[p
++]=GLX_LEVEL
; data
[p
++]=attribList
[arg
++]; break;
256 case WX_GL_DOUBLEBUFFER
: data
[p
++] = GLX_DOUBLEBUFFER
; break;
257 case WX_GL_STEREO
: data
[p
++] = GLX_STEREO
; break;
258 case WX_GL_AUX_BUFFERS
:
259 data
[p
++]=GLX_AUX_BUFFERS
; data
[p
++]=attribList
[arg
++]; break;
261 data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
262 case WX_GL_MIN_GREEN
:
263 data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
265 data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
266 case WX_GL_MIN_ALPHA
:
267 data
[p
++]=GLX_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break;
268 case WX_GL_DEPTH_SIZE
:
269 data
[p
++]=GLX_DEPTH_SIZE
; data
[p
++]=attribList
[arg
++]; break;
270 case WX_GL_STENCIL_SIZE
:
271 data
[p
++]=GLX_STENCIL_SIZE
; data
[p
++]=attribList
[arg
++]; break;
272 case WX_GL_MIN_ACCUM_RED
:
273 data
[p
++]=GLX_ACCUM_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
274 case WX_GL_MIN_ACCUM_GREEN
:
275 data
[p
++]=GLX_ACCUM_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
276 case WX_GL_MIN_ACCUM_BLUE
:
277 data
[p
++]=GLX_ACCUM_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
278 case WX_GL_MIN_ACCUM_ALPHA
:
279 data
[p
++]=GLX_ACCUM_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break;
286 attribList
= (int*) data
;
287 // Get an appropriate visual
288 vi
= glXChooseVisual(display
, DefaultScreen(display
), attribList
);
289 if(!vi
) return false;
291 // Here we should make sure that vi is the same visual as the
292 // one used by the xwindow drawable in wxCanvas. However,
293 // there is currently no mechanism for this in wx_canvs.cc.
295 // By default, we use the visual of xwindow
296 // NI: is this really senseful ? opengl in e.g. color index mode ?
297 XGetWindowAttributes(display
, (Window
) GetClientWindow(), &xwa
);
298 vi_templ
.visualid
= XVisualIDFromVisual(xwa
.visual
);
299 vi
= XGetVisualInfo(display
, VisualIDMask
, &vi_templ
, &n
);
300 if(!vi
) return false;
301 glXGetConfig(display
, vi
, GLX_USE_GL
, &val
);
302 if(!val
) return false;
303 // Basically, this is it. It should be possible to use vi
304 // in glXCreateContext() below. But this fails with Mesa.
305 // I notified the Mesa author about it; there may be a fix.
307 // Construct an attribute list matching the visual
310 if(vi
->c_class
==TrueColor
|| vi
->c_class
==DirectColor
) { // RGBA visual
311 a_list
[n
++] = GLX_RGBA
;
312 a_list
[n
++] = GLX_RED_SIZE
;
313 a_list
[n
++] = bitcount(vi
->red_mask
);
314 a_list
[n
++] = GLX_GREEN_SIZE
;
315 a_list
[n
++] = bitcount(vi
->green_mask
);
316 a_list
[n
++] = GLX_BLUE_SIZE
;
317 a_list
[n
++] = bitcount(vi
->blue_mask
);
318 glXGetConfig(display
, vi
, GLX_ALPHA_SIZE
, &val
);
319 a_list
[n
++] = GLX_ALPHA_SIZE
;
321 } else { // Color index visual
322 glXGetConfig(display
, vi
, GLX_BUFFER_SIZE
, &val
);
323 a_list
[n
++] = GLX_BUFFER_SIZE
;
328 vi
= glXChooseVisual(display
, DefaultScreen(display
), a_list
);
329 if(!vi
) return false;
330 #endif /* OLD_MESA */
333 m_vi
= vi
; // safe for later use
335 wxCHECK_MSG( m_vi
, FALSE
, "required visual couldn't be found" );
337 // Create the GLX context and make it current
339 wxGLContext
*share
= m_sharedContext
;
340 if (share
==NULL
&& m_sharedContextOf
)
341 share
= m_sharedContextOf
->GetContext();
343 m_glContext
= new wxGLContext( TRUE
, this, wxNullPalette
, share
);
353 wxGLCanvas::~wxGLCanvas(void)
355 XVisualInfo
*vi
= (XVisualInfo
*) m_vi
;
358 if (m_glContext
) delete m_glContext
;
360 // Display* display = (Display*) GetXDisplay();
361 // if(glx_cx) glXDestroyContext(display, glx_cx);
364 void wxGLCanvas::SwapBuffers()
366 if( m_glContext
) m_glContext
->SwapBuffers();
368 // Display* display = (Display*) GetXDisplay();
369 // if(glx_cx) glXSwapBuffers(display, (Window) GetClientWindow());
372 void wxGLCanvas::SetCurrent()
374 if( m_glContext
) m_glContext
->SetCurrent();
376 // Display* display = (Display*) GetXDisplay();
377 // if(glx_cx) glXMakeCurrent(display, (Window) GetClientWindow(), glx_cx);
380 void wxGLCanvas::SetColour(const char *col
)
382 if( m_glContext
) m_glContext
->SetColour(col
);