]>
git.saurik.com Git - wxWidgets.git/blob - src/motif/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 /////////////////////////////////////////////////////////////////////////////
13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
14 #pragma implementation "glcanvas.h"
21 #include "wx/glcanvas.h"
27 # pragma message disable nosimpint
31 # pragma message enable nosimpint
33 #include "wx/motif/private.h"
35 // DLL options compatibility check:
37 WX_CHECK_BUILD_OPTIONS("wxGL")
40 // workaround for bug in Mesa's glx.c
41 static int bitcount( unsigned long n
)
53 * GLContext implementation
56 IMPLEMENT_CLASS(wxGLContext
,wxObject
)
58 wxGLContext::wxGLContext( bool WXUNUSED(isRGB
), wxWindow
*win
,
59 const wxPalette
& WXUNUSED(palette
) )
62 // m_widget = win->m_wxwindow;
64 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
65 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
67 wxCHECK_RET( vi
, "invalid visual for OpenGl" );
69 m_glContext
= glXCreateContext( (Display
*)m_window
->GetXDisplay(), vi
,
72 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
75 wxGLContext::wxGLContext(
76 bool WXUNUSED(isRGB
), wxWindow
*win
,
77 const wxPalette
& WXUNUSED(palette
),
78 const wxGLContext
*other
/* for sharing display lists */
82 // m_widget = win->m_wxwindow;
84 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
85 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
87 wxCHECK_RET( vi
, "invalid visual for OpenGl" );
90 m_glContext
= glXCreateContext( (Display
*)m_window
->GetXDisplay(), vi
,
91 other
->m_glContext
, GL_TRUE
);
93 m_glContext
= glXCreateContext( (Display
*)m_window
->GetXDisplay(), vi
,
96 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
99 wxGLContext::~wxGLContext()
101 if (!m_glContext
) return;
103 if (m_glContext
== glXGetCurrentContext())
105 glXMakeCurrent( (Display
*) m_window
->GetXDisplay(), None
, NULL
);
108 glXDestroyContext( (Display
*) m_window
->GetXDisplay(), m_glContext
);
111 void wxGLContext::SwapBuffers()
115 Display
* display
= (Display
*) m_window
->GetXDisplay();
116 glXSwapBuffers(display
, (Window
) m_window
->GetXWindow());
120 void wxGLContext::SetCurrent()
124 Display
* display
= (Display
*) m_window
->GetXDisplay();
125 glXMakeCurrent(display
, (Window
) m_window
->GetXWindow(),
130 void wxGLContext::SetColour(const char *colour
)
132 wxColour
*the_colour
= wxTheColourDatabase
->FindColour(colour
);
135 glGetBooleanv(GL_RGBA_MODE
, &b
);
137 glColor3ub(the_colour
->Red(),
141 GLint pix
= (GLint
)the_colour
->m_pixel
;
144 exact_def
.red
= (unsigned short)the_colour
->Red() << 8;
145 exact_def
.green
= (unsigned short)the_colour
->Green() << 8;
146 exact_def
.blue
= (unsigned short)the_colour
->Blue() << 8;
147 exact_def
.flags
= DoRed
| DoGreen
| DoBlue
;
148 if(!XAllocColor((Display
*) m_window
->GetXDisplay(),
149 (Colormap
) wxTheApp
->GetMainColormap(m_window
->GetXDisplay()),
151 wxLogError("wxGLCanvas: cannot allocate color\n");
154 pix
= the_colour
->m_pixel
= exact_def
.pixel
;
161 void wxGLContext::SetupPixelFormat()
165 void wxGLContext::SetupPalette( const wxPalette
& WXUNUSED(palette
) )
169 wxPalette
wxGLContext::CreateDefaultPalette()
171 return wxNullPalette
;
178 * GLCanvas implementation
181 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
)
183 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
)
184 // EVT_SIZE(wxGLCanvas::OnSize)
188 wxGLCanvas::wxGLCanvas( wxWindow
*parent
, wxWindowID id
,
189 const wxPoint
& pos
, const wxSize
& size
,
190 long style
, const wxString
& name
,
192 const wxPalette
& palette
)
193 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
195 Create( parent
, NULL
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
198 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
199 const wxGLContext
*shared
,
201 const wxPoint
& pos
, const wxSize
& size
,
202 long style
, const wxString
& name
,
204 const wxPalette
& palette
)
205 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
207 Create( parent
, shared
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
210 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
211 const wxGLCanvas
*shared
,
213 const wxPoint
& pos
, const wxSize
& size
,
214 long style
, const wxString
& name
,
216 const wxPalette
& palette
)
217 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
219 Create( parent
, NULL
, shared
, id
, pos
, size
, style
, name
, attribList
, palette
);
224 bool wxGLCanvas::Create(wxWindow *parent,
225 const wxGLContext *shared, const wxGLCanvas *shared_context_of,
226 wxWindowID id = -1, const wxPoint& pos,
227 const wxSize& size, long style,
228 const wxString& name, int *attribList, const wxPalette& palette):
229 wxScrolledWindow(parent, id, pos, size, style, name)
232 bool wxGLCanvas::Create( wxWindow
*parent
,
233 const wxGLContext
*shared
,
234 const wxGLCanvas
*shared_context_of
,
236 const wxPoint
& pos
, const wxSize
& size
,
237 long style
, const wxString
& name
,
239 const wxPalette
& palette
)
241 XVisualInfo
*vi
, vi_templ
;
242 XWindowAttributes xwa
;
245 m_sharedContext
= (wxGLContext
*)shared
; // const_cast
246 m_sharedContextOf
= (wxGLCanvas
*)shared_context_of
; // const_cast
247 m_glContext
= (wxGLContext
*) NULL
;
249 Display
* display
= (Display
*) GetXDisplay();
251 // Check for the presence of the GLX extension
252 if(!glXQueryExtension(display
, NULL
, NULL
)) {
253 wxLogError("wxGLCanvas: GLX extension is missing\n");
258 int data
[512], arg
=0, p
=0;
260 while( (attribList
[arg
]!=0) && (p
<512) )
262 switch( attribList
[arg
++] )
264 case WX_GL_RGBA
: data
[p
++] = GLX_RGBA
; break;
265 case WX_GL_BUFFER_SIZE
:
266 data
[p
++]=GLX_BUFFER_SIZE
; data
[p
++]=attribList
[arg
++]; break;
268 data
[p
++]=GLX_LEVEL
; data
[p
++]=attribList
[arg
++]; break;
269 case WX_GL_DOUBLEBUFFER
: data
[p
++] = GLX_DOUBLEBUFFER
; break;
270 case WX_GL_STEREO
: data
[p
++] = GLX_STEREO
; break;
271 case WX_GL_AUX_BUFFERS
:
272 data
[p
++]=GLX_AUX_BUFFERS
; data
[p
++]=attribList
[arg
++]; break;
274 data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
275 case WX_GL_MIN_GREEN
:
276 data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
278 data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
279 case WX_GL_MIN_ALPHA
:
280 data
[p
++]=GLX_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break;
281 case WX_GL_DEPTH_SIZE
:
282 data
[p
++]=GLX_DEPTH_SIZE
; data
[p
++]=attribList
[arg
++]; break;
283 case WX_GL_STENCIL_SIZE
:
284 data
[p
++]=GLX_STENCIL_SIZE
; data
[p
++]=attribList
[arg
++]; break;
285 case WX_GL_MIN_ACCUM_RED
:
286 data
[p
++]=GLX_ACCUM_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
287 case WX_GL_MIN_ACCUM_GREEN
:
288 data
[p
++]=GLX_ACCUM_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
289 case WX_GL_MIN_ACCUM_BLUE
:
290 data
[p
++]=GLX_ACCUM_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
291 case WX_GL_MIN_ACCUM_ALPHA
:
292 data
[p
++]=GLX_ACCUM_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break;
299 attribList
= (int*) data
;
300 // Get an appropriate visual
301 vi
= glXChooseVisual(display
, DefaultScreen(display
), attribList
);
302 if(!vi
) return false;
304 // Here we should make sure that vi is the same visual as the
305 // one used by the xwindow drawable in wxCanvas. However,
306 // there is currently no mechanism for this in wx_canvs.cc.
308 // By default, we use the visual of xwindow
309 // NI: is this really senseful ? opengl in e.g. color index mode ?
310 XGetWindowAttributes(display
, (Window
) GetXWindow(), &xwa
);
311 vi_templ
.visualid
= XVisualIDFromVisual(xwa
.visual
);
312 vi
= XGetVisualInfo(display
, VisualIDMask
, &vi_templ
, &n
);
313 if(!vi
) return false;
314 glXGetConfig(display
, vi
, GLX_USE_GL
, &val
);
315 if(!val
) return false;
316 // Basically, this is it. It should be possible to use vi
317 // in glXCreateContext() below. But this fails with Mesa.
318 // I notified the Mesa author about it; there may be a fix.
320 // Construct an attribute list matching the visual
323 if(vi
->c_class
==TrueColor
|| vi
->c_class
==DirectColor
) { // RGBA visual
324 a_list
[n
++] = GLX_RGBA
;
325 a_list
[n
++] = GLX_RED_SIZE
;
326 a_list
[n
++] = bitcount(vi
->red_mask
);
327 a_list
[n
++] = GLX_GREEN_SIZE
;
328 a_list
[n
++] = bitcount(vi
->green_mask
);
329 a_list
[n
++] = GLX_BLUE_SIZE
;
330 a_list
[n
++] = bitcount(vi
->blue_mask
);
331 glXGetConfig(display
, vi
, GLX_ALPHA_SIZE
, &val
);
332 a_list
[n
++] = GLX_ALPHA_SIZE
;
334 } else { // Color index visual
335 glXGetConfig(display
, vi
, GLX_BUFFER_SIZE
, &val
);
336 a_list
[n
++] = GLX_BUFFER_SIZE
;
341 vi
= glXChooseVisual(display
, DefaultScreen(display
), a_list
);
342 if(!vi
) return false;
343 #endif /* OLD_MESA */
346 m_vi
= vi
; // safe for later use
348 wxCHECK_MSG( m_vi
, FALSE
, "required visual couldn't be found" );
350 // Create the GLX context and make it current
352 wxGLContext
*share
= m_sharedContext
;
353 if (share
==NULL
&& m_sharedContextOf
)
354 share
= m_sharedContextOf
->GetContext();
356 m_glContext
= new wxGLContext( TRUE
, this, wxNullPalette
, share
);
366 wxGLCanvas::~wxGLCanvas(void)
368 XVisualInfo
*vi
= (XVisualInfo
*) m_vi
;
371 if (m_glContext
) delete m_glContext
;
373 // Display* display = (Display*) GetXDisplay();
374 // if(glx_cx) glXDestroyContext(display, glx_cx);
377 void wxGLCanvas::SwapBuffers()
379 if( m_glContext
) m_glContext
->SwapBuffers();
381 // Display* display = (Display*) GetXDisplay();
382 // if(glx_cx) glXSwapBuffers(display, (Window) GetXWindow());
385 void wxGLCanvas::SetCurrent()
387 if( m_glContext
) m_glContext
->SetCurrent();
389 // Display* display = (Display*) GetXDisplay();
390 // if(glx_cx) glXMakeCurrent(display, (Window) GetXWindow(), glx_cx);
393 void wxGLCanvas::SetColour(const char *col
)
395 if( m_glContext
) m_glContext
->SetColour(col
);