1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxGLCanvas, for using OpenGL/Mesa with wxWindows and GTK
4 // Author: Robert Roebling
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "glcanvas.h"
20 #include "wx/glcanvas.h"
23 #include "wx/colour.h"
24 #include "wx/module.h"
33 #include "wx/gtk/win_gtk.h"
35 //---------------------------------------------------------------------------
37 //---------------------------------------------------------------------------
39 XVisualInfo
*g_vi
= (XVisualInfo
*) NULL
;
41 //-----------------------------------------------------------------------------
43 //-----------------------------------------------------------------------------
45 extern void wxapp_install_idle_handler();
48 //---------------------------------------------------------------------------
50 //---------------------------------------------------------------------------
52 IMPLEMENT_CLASS(wxGLContext
,wxObject
)
54 wxGLContext::wxGLContext( bool WXUNUSED(isRGB
), wxWindow
*win
, 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( GDK_DISPLAY(), vi
, None
, GL_TRUE
);
66 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
69 wxGLContext::wxGLContext(
70 bool WXUNUSED(isRGB
), wxWindow
*win
,
71 const wxPalette
& WXUNUSED(palette
),
72 const wxGLContext
*other
/* for sharing display lists */
76 m_widget
= win
->m_wxwindow
;
78 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
79 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
81 wxCHECK_RET( vi
, "invalid visual for OpenGl" );
84 m_glContext
= glXCreateContext( GDK_DISPLAY(), vi
, other
->m_glContext
, GL_TRUE
);
86 m_glContext
= glXCreateContext( GDK_DISPLAY(), vi
, None
, GL_TRUE
);
88 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
91 wxGLContext::~wxGLContext()
93 if (!m_glContext
) return;
95 if (m_glContext
== glXGetCurrentContext())
97 glXMakeCurrent( GDK_DISPLAY(), None
, NULL
);
100 glXDestroyContext( GDK_DISPLAY(), m_glContext
);
103 void wxGLContext::SwapBuffers()
107 GdkWindow
*window
= GTK_PIZZA(m_widget
)->bin_window
;
108 glXSwapBuffers( GDK_DISPLAY(), GDK_WINDOW_XWINDOW( window
) );
112 void wxGLContext::SetCurrent()
116 GdkWindow
*window
= GTK_PIZZA(m_widget
)->bin_window
;
117 glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window
), m_glContext
);
121 void wxGLContext::SetColour(const char *colour
)
126 wxColour
*col
= wxTheColourDatabase
->FindColour(colour
);
129 r
= (float)(col
->Red()/256.0);
130 g
= (float)(col
->Green()/256.0);
131 b
= (float)(col
->Blue()/256.0);
136 void wxGLContext::SetupPixelFormat()
140 void wxGLContext::SetupPalette( const wxPalette
& WXUNUSED(palette
) )
144 wxPalette
wxGLContext::CreateDefaultPalette()
146 return wxNullPalette
;
149 //-----------------------------------------------------------------------------
150 // "realize" from m_wxwindow
151 //-----------------------------------------------------------------------------
154 gtk_glwindow_realized_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
156 wxGLContext
*share
= win
->m_sharedContext
;
157 if (share
==NULL
&& win
->m_sharedContextOf
) share
=win
->m_sharedContextOf
->GetContext();
159 win
->m_glContext
= new wxGLContext( TRUE
, win
, wxNullPalette
, share
);
164 //-----------------------------------------------------------------------------
165 // "map" from m_wxwindow
166 //-----------------------------------------------------------------------------
169 gtk_glwindow_map_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
171 if (win
->m_glContext
/* && win->m_exposed*/)
173 wxPaintEvent
event( win
->GetId() );
174 event
.SetEventObject( win
);
175 win
->GetEventHandler()->ProcessEvent( event
);
177 win
->m_exposed
= FALSE
;
178 win
->GetUpdateRegion().Clear();
184 //-----------------------------------------------------------------------------
185 // "expose_event" of m_wxwindow
186 //-----------------------------------------------------------------------------
189 gtk_glwindow_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxGLCanvas
*win
)
192 wxapp_install_idle_handler();
194 win
->m_exposed
= TRUE
;
196 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
198 gdk_event
->area
.width
,
199 gdk_event
->area
.height
);
202 //-----------------------------------------------------------------------------
203 // "draw" of m_wxwindow
204 //-----------------------------------------------------------------------------
207 gtk_glwindow_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxGLCanvas
*win
)
210 wxapp_install_idle_handler();
212 win
->m_exposed
= TRUE
;
214 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
215 rect
->width
, rect
->height
);
218 //-----------------------------------------------------------------------------
219 // "size_allocate" of m_wxwindow
220 //-----------------------------------------------------------------------------
223 gtk_glcanvas_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxGLCanvas
*win
)
226 wxapp_install_idle_handler();
231 wxSizeEvent
event( wxSize(win
->m_width
,win
->m_height
), win
->GetId() );
232 event
.SetEventObject( win
);
233 win
->GetEventHandler()->ProcessEvent( event
);
236 //---------------------------------------------------------------------------
238 //---------------------------------------------------------------------------
240 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
)
242 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
)
243 EVT_SIZE(wxGLCanvas::OnSize
)
246 wxGLCanvas::wxGLCanvas( wxWindow
*parent
, wxWindowID id
,
247 const wxPoint
& pos
, const wxSize
& size
,
248 long style
, const wxString
& name
,
250 const wxPalette
& palette
)
252 Create( parent
, NULL
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
255 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
256 const wxGLContext
*shared
,
258 const wxPoint
& pos
, const wxSize
& size
,
259 long style
, const wxString
& name
,
261 const wxPalette
& palette
)
263 Create( parent
, shared
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
266 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
267 const wxGLCanvas
*shared
,
269 const wxPoint
& pos
, const wxSize
& size
,
270 long style
, const wxString
& name
,
272 const wxPalette
& palette
)
274 Create( parent
, NULL
, shared
, id
, pos
, size
, style
, name
, attribList
, palette
);
277 bool wxGLCanvas::Create( wxWindow
*parent
,
278 const wxGLContext
*shared
,
279 const wxGLCanvas
*shared_context_of
,
281 const wxPoint
& pos
, const wxSize
& size
,
282 long style
, const wxString
& name
,
284 const wxPalette
& palette
)
287 m_sharedContext
= (wxGLContext
*)shared
; // const_cast
288 m_sharedContextOf
= (wxGLCanvas
*)shared_context_of
; // const_cast
289 m_glContext
= (wxGLContext
*) NULL
;
293 m_nativeSizeEvent
= TRUE
;
297 // default settings if attriblist = 0
299 data
[1] = GLX_DOUBLEBUFFER
;
300 data
[2] = GLX_DEPTH_SIZE
; data
[3] = 1;
301 data
[4] = GLX_RED_SIZE
; data
[5] = 1;
302 data
[6] = GLX_GREEN_SIZE
; data
[7] = 1;
303 data
[8] = GLX_BLUE_SIZE
; data
[9] = 1;
304 data
[10] = GLX_ALPHA_SIZE
; data
[11] = 0;
307 attribList
= (int*) data
;
313 while( (attribList
[arg
]!=0) && (p
<510) )
315 switch( attribList
[arg
++] )
317 case WX_GL_RGBA
: data
[p
++] = GLX_RGBA
; break;
318 case WX_GL_BUFFER_SIZE
:
319 data
[p
++]=GLX_BUFFER_SIZE
; data
[p
++]=attribList
[arg
++]; break;
321 data
[p
++]=GLX_LEVEL
; data
[p
++]=attribList
[arg
++]; break;
322 case WX_GL_DOUBLEBUFFER
: data
[p
++] = GLX_DOUBLEBUFFER
; break;
323 case WX_GL_STEREO
: data
[p
++] = GLX_STEREO
; break;
324 case WX_GL_AUX_BUFFERS
:
325 data
[p
++]=GLX_AUX_BUFFERS
; data
[p
++]=attribList
[arg
++]; break;
327 data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
328 case WX_GL_MIN_GREEN
:
329 data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
331 data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
332 case WX_GL_MIN_ALPHA
:
333 data
[p
++]=GLX_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break;
334 case WX_GL_DEPTH_SIZE
:
335 data
[p
++]=GLX_DEPTH_SIZE
; data
[p
++]=attribList
[arg
++]; break;
336 case WX_GL_STENCIL_SIZE
:
337 data
[p
++]=GLX_STENCIL_SIZE
; data
[p
++]=attribList
[arg
++]; break;
338 case WX_GL_MIN_ACCUM_RED
:
339 data
[p
++]=GLX_ACCUM_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
340 case WX_GL_MIN_ACCUM_GREEN
:
341 data
[p
++]=GLX_ACCUM_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
342 case WX_GL_MIN_ACCUM_BLUE
:
343 data
[p
++]=GLX_ACCUM_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
344 case WX_GL_MIN_ACCUM_ALPHA
:
345 data
[p
++]=GLX_ACCUM_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break;
352 attribList
= (int*) data
;
356 Display
*dpy
= GDK_DISPLAY();
358 XVisualInfo
*vi
= glXChooseVisual( dpy
, DefaultScreen(dpy
), attribList
);
360 m_vi
= vi
; // safe for later use
362 wxCHECK_MSG( m_vi
, FALSE
, "required visual couldn't be found" );
364 GdkVisual
*visual
= gdkx_visual_get( vi
->visualid
);
365 GdkColormap
*colormap
= gdk_colormap_new( gdkx_visual_get(vi
->visualid
), TRUE
);
367 gtk_widget_push_colormap( colormap
);
368 gtk_widget_push_visual( visual
);
370 wxScrolledWindow::Create( parent
, id
, pos
, size
, style
, name
);
372 m_glWidget
= m_wxwindow
;
374 gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow
), FALSE
);
376 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
377 GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback
), (gpointer
) this );
379 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "map",
380 GTK_SIGNAL_FUNC(gtk_glwindow_map_callback
), (gpointer
) this );
382 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
383 GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback
), (gpointer
)this );
385 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
386 GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback
), (gpointer
)this );
388 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
389 GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback
), (gpointer
)this );
391 gtk_widget_pop_visual();
392 gtk_widget_pop_colormap();
394 if (GTK_WIDGET_REALIZED(m_wxwindow
))
395 gtk_glwindow_realized_callback( m_wxwindow
, this );
397 if (GTK_WIDGET_MAPPED(m_wxwindow
))
398 gtk_glwindow_map_callback( m_wxwindow
, this );
403 wxGLCanvas::~wxGLCanvas()
405 XVisualInfo
*vi
= (XVisualInfo
*) m_vi
;
408 if (m_glContext
) delete m_glContext
;
411 void wxGLCanvas::SwapBuffers()
413 if (m_glContext
) m_glContext
->SwapBuffers();
416 void wxGLCanvas::OnSize(wxSizeEvent
& WXUNUSED(event
))
419 GetClientSize( &width
, &height
);
421 if (m_glContext
&& GTK_WIDGET_REALIZED(m_glWidget
) )
425 glViewport(0, 0, (GLint
)width
, (GLint
)height
);
426 glMatrixMode(GL_PROJECTION
);
428 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
429 glMatrixMode(GL_MODELVIEW
);
433 void wxGLCanvas::SetCurrent()
435 if (m_glContext
) m_glContext
->SetCurrent();
438 void wxGLCanvas::SetColour( const char *colour
)
440 if (m_glContext
) m_glContext
->SetColour( colour
);
443 void wxGLCanvas::OnInternalIdle()
445 if (m_glContext
&& m_exposed
)
447 wxPaintEvent
event( GetId() );
448 event
.SetEventObject( this );
449 GetEventHandler()->ProcessEvent( event
);
452 GetUpdateRegion().Clear();
455 wxWindow::OnInternalIdle();