]>
git.saurik.com Git - wxWidgets.git/blob - src/x11/glcanvas.cpp
1ecdd96f84c19fd13475138e8ae34c9d8fbe4e6b
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/x11/glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWidgets
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 // for compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
16 #if defined(__BORLANDC__)
22 #include "wx/glcanvas.h"
32 # pragma message disable nosimpint
36 # pragma message enable nosimpint
38 #include "wx/x11/private.h"
40 // DLL options compatibility check:
42 WX_CHECK_BUILD_OPTIONS("wxGL")
44 static inline WXWindow
wxGetClientAreaWindow(wxWindow
* win
)
47 return win
->GetClientXWindow();
49 return win
->GetClientAreaWindow();
54 // workaround for bug in Mesa's glx.c
55 static int bitcount( unsigned long n
)
68 * GLContext implementation
71 IMPLEMENT_CLASS(wxGLContext
,wxObject
)
73 wxGLContext::wxGLContext( bool WXUNUSED(isRGB
), wxWindow
*win
,
74 const wxPalette
& WXUNUSED(palette
) )
77 // m_widget = win->m_wxwindow;
79 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
80 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
82 wxCHECK_RET( vi
, wxT("invalid visual for OpenGL") );
84 m_glContext
= glXCreateContext( (Display
*)wxGetDisplay(), vi
,
87 wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGL context") );
90 wxGLContext::wxGLContext(
91 bool WXUNUSED(isRGB
), wxWindow
*win
,
92 const wxPalette
& WXUNUSED(palette
),
93 const wxGLContext
*other
/* for sharing display lists */
97 // m_widget = win->m_wxwindow;
99 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
100 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
102 wxCHECK_RET( vi
, wxT("invalid visual for OpenGL") );
105 m_glContext
= glXCreateContext( (Display
*)wxGetDisplay(), vi
,
106 other
->m_glContext
, GL_TRUE
);
108 m_glContext
= glXCreateContext( (Display
*)wxGetDisplay(), vi
,
111 wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGL context") );
114 wxGLContext::~wxGLContext()
116 if (!m_glContext
) return;
118 if (m_glContext
== glXGetCurrentContext())
120 glXMakeCurrent( (Display
*) wxGetDisplay(), None
, NULL
);
123 glXDestroyContext( (Display
*) wxGetDisplay(), m_glContext
);
126 void wxGLContext::SwapBuffers()
130 Display
* display
= (Display
*) wxGetDisplay();
131 glXSwapBuffers(display
, (Window
) wxGetClientAreaWindow(m_window
));
135 void wxGLContext::SetCurrent()
139 Display
* display
= (Display
*) wxGetDisplay();
140 glXMakeCurrent(display
, (Window
) wxGetClientAreaWindow(m_window
),
145 void wxGLContext::SetColour(const wxChar
*colour
)
147 wxColour the_colour
= wxTheColourDatabase
->Find(colour
);
151 glGetBooleanv(GL_RGBA_MODE
, &b
);
154 glColor3ub(the_colour
.Red(),
161 the_colour
.AllocColour(m_window
->GetXDisplay());
163 the_colour
.CalcPixel(wxTheApp
->GetMainColormap(wxGetDisplay()));
165 GLint pix
= (GLint
)the_colour
.GetPixel();
168 wxLogError(wxT("wxGLCanvas: cannot allocate color\n"));
176 void wxGLContext::SetupPixelFormat()
180 void wxGLContext::SetupPalette( const wxPalette
& WXUNUSED(palette
) )
184 wxPalette
wxGLContext::CreateDefaultPalette()
186 return wxNullPalette
;
193 * GLCanvas implementation
196 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
)
198 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
)
199 // EVT_SIZE(wxGLCanvas::OnSize)
203 wxGLCanvas::wxGLCanvas( wxWindow
*parent
, wxWindowID id
,
204 const wxPoint
& pos
, const wxSize
& size
,
205 long style
, const wxString
& name
,
207 const wxPalette
& palette
)
208 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
210 Create( parent
, NULL
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
213 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
214 const wxGLContext
*shared
,
216 const wxPoint
& pos
, const wxSize
& size
,
217 long style
, const wxString
& name
,
219 const wxPalette
& palette
)
220 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
222 Create( parent
, shared
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
225 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
226 const wxGLCanvas
*shared
,
228 const wxPoint
& pos
, const wxSize
& size
,
229 long style
, const wxString
& name
,
231 const wxPalette
& palette
)
232 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
234 Create( parent
, NULL
, shared
, id
, pos
, size
, style
, name
, attribList
, palette
);
239 bool wxGLCanvas::Create(wxWindow *parent,
240 const wxGLContext *shared, const wxGLCanvas *shared_context_of,
241 wxWindowID id = -1, const wxPoint& pos,
242 const wxSize& size, long style,
243 const wxString& name, int *attribList, const wxPalette& palette):
244 wxScrolledWindow(parent, id, pos, size, style, name)
247 bool wxGLCanvas::Create( wxWindow
*parent
,
248 const wxGLContext
*shared
,
249 const wxGLCanvas
*shared_context_of
,
251 const wxPoint
& pos
, const wxSize
& size
,
252 long style
, const wxString
& name
,
254 const wxPalette
& palette
)
256 XVisualInfo
*vi
, vi_templ
;
257 XWindowAttributes xwa
;
260 m_sharedContext
= (wxGLContext
*)shared
; // const_cast
261 m_sharedContextOf
= (wxGLCanvas
*)shared_context_of
; // const_cast
262 m_glContext
= (wxGLContext
*) NULL
;
264 Display
* display
= (Display
*) wxGetDisplay();
266 // Check for the presence of the GLX extension
267 if(!glXQueryExtension(display
, NULL
, NULL
))
269 wxLogDebug(wxT("wxGLCanvas: GLX extension is missing\n"));
274 int data
[512], arg
=0, p
=0;
276 while( (attribList
[arg
]!=0) && (p
<512) )
278 switch( attribList
[arg
++] )
280 case WX_GL_RGBA
: data
[p
++] = GLX_RGBA
; break;
281 case WX_GL_BUFFER_SIZE
:
282 data
[p
++]=GLX_BUFFER_SIZE
; data
[p
++]=attribList
[arg
++]; break;
284 data
[p
++]=GLX_LEVEL
; data
[p
++]=attribList
[arg
++]; break;
285 case WX_GL_DOUBLEBUFFER
: data
[p
++] = GLX_DOUBLEBUFFER
; break;
286 case WX_GL_STEREO
: data
[p
++] = GLX_STEREO
; break;
287 case WX_GL_AUX_BUFFERS
:
288 data
[p
++]=GLX_AUX_BUFFERS
; data
[p
++]=attribList
[arg
++]; break;
290 data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
291 case WX_GL_MIN_GREEN
:
292 data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
294 data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
295 case WX_GL_MIN_ALPHA
:
296 data
[p
++]=GLX_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break;
297 case WX_GL_DEPTH_SIZE
:
298 data
[p
++]=GLX_DEPTH_SIZE
; data
[p
++]=attribList
[arg
++]; break;
299 case WX_GL_STENCIL_SIZE
:
300 data
[p
++]=GLX_STENCIL_SIZE
; data
[p
++]=attribList
[arg
++]; break;
301 case WX_GL_MIN_ACCUM_RED
:
302 data
[p
++]=GLX_ACCUM_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
303 case WX_GL_MIN_ACCUM_GREEN
:
304 data
[p
++]=GLX_ACCUM_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
305 case WX_GL_MIN_ACCUM_BLUE
:
306 data
[p
++]=GLX_ACCUM_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
307 case WX_GL_MIN_ACCUM_ALPHA
:
308 data
[p
++]=GLX_ACCUM_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break;
315 attribList
= (int*) data
;
316 // Get an appropriate visual
317 vi
= glXChooseVisual(display
, DefaultScreen(display
), attribList
);
318 if(!vi
) return FALSE
;
320 // Here we should make sure that vi is the same visual as the
321 // one used by the xwindow drawable in wxCanvas. However,
322 // there is currently no mechanism for this in wx_canvs.cc.
324 // By default, we use the visual of xwindow
325 // NI: is this really senseful ? opengl in e.g. color index mode ?
326 XGetWindowAttributes(display
, (Window
)wxGetClientAreaWindow(this), &xwa
);
327 vi_templ
.visualid
= XVisualIDFromVisual(xwa
.visual
);
328 vi
= XGetVisualInfo(display
, VisualIDMask
, &vi_templ
, &n
);
329 if(!vi
) return FALSE
;
330 glXGetConfig(display
, vi
, GLX_USE_GL
, &val
);
331 if(!val
) return FALSE
;
332 // Basically, this is it. It should be possible to use vi
333 // in glXCreateContext() below. But this fails with Mesa.
334 // I notified the Mesa author about it; there may be a fix.
336 // Construct an attribute list matching the visual
339 if(vi
->c_class
==TrueColor
|| vi
->c_class
==DirectColor
) { // RGBA visual
340 a_list
[n
++] = GLX_RGBA
;
341 a_list
[n
++] = GLX_RED_SIZE
;
342 a_list
[n
++] = bitcount(vi
->red_mask
);
343 a_list
[n
++] = GLX_GREEN_SIZE
;
344 a_list
[n
++] = bitcount(vi
->green_mask
);
345 a_list
[n
++] = GLX_BLUE_SIZE
;
346 a_list
[n
++] = bitcount(vi
->blue_mask
);
347 glXGetConfig(display
, vi
, GLX_ALPHA_SIZE
, &val
);
348 a_list
[n
++] = GLX_ALPHA_SIZE
;
350 } else { // Color index visual
351 glXGetConfig(display
, vi
, GLX_BUFFER_SIZE
, &val
);
352 a_list
[n
++] = GLX_BUFFER_SIZE
;
357 vi
= glXChooseVisual(display
, DefaultScreen(display
), a_list
);
358 if(!vi
) return FALSE
;
359 #endif /* OLD_MESA */
362 m_vi
= vi
; // safe for later use
364 wxCHECK_MSG( m_vi
, FALSE
, wxT("required visual couldn't be found") );
366 // Create the GLX context and make it current
368 wxGLContext
*share
= m_sharedContext
;
369 if (share
==NULL
&& m_sharedContextOf
)
370 share
= m_sharedContextOf
->GetContext();
372 m_glContext
= new wxGLContext( TRUE
, this, wxNullPalette
, share
);
382 wxGLCanvas::~wxGLCanvas(void)
384 XVisualInfo
*vi
= (XVisualInfo
*) m_vi
;
387 if (m_glContext
) delete m_glContext
;
389 // Display* display = (Display*) GetXDisplay();
390 // if(glx_cx) glXDestroyContext(display, glx_cx);
393 void wxGLCanvas::SwapBuffers()
395 if( m_glContext
) m_glContext
->SwapBuffers();
397 // Display* display = (Display*) GetXDisplay();
398 // if(glx_cx) glXSwapBuffers(display, (Window) GetClientAreaWindow());
401 void wxGLCanvas::SetCurrent()
403 if( m_glContext
) m_glContext
->SetCurrent();
405 // Display* display = (Display*) GetXDisplay();
406 // if(glx_cx) glXMakeCurrent(display, (Window) GetClientAreaWindow(), glx_cx);
409 void wxGLCanvas::SetColour(const wxChar
*col
)
411 if( m_glContext
) m_glContext
->SetColour(col
);