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"
19 #include "wx/colour.h"
20 #include "wx/module.h"
29 #include "wx/gtk/win_gtk.h"
31 //---------------------------------------------------------------------------
33 //---------------------------------------------------------------------------
35 XVisualInfo
*g_vi
= (XVisualInfo
*) NULL
;
37 //-----------------------------------------------------------------------------
39 //-----------------------------------------------------------------------------
41 extern void wxapp_install_idle_handler();
44 //---------------------------------------------------------------------------
46 //---------------------------------------------------------------------------
48 IMPLEMENT_CLASS(wxGLContext
,wxObject
)
50 wxGLContext::wxGLContext( bool WXUNUSED(isRGB
), wxWindow
*win
, const wxPalette
& WXUNUSED(palette
) )
53 m_widget
= win
->m_wxwindow
;
55 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
56 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
58 wxCHECK_RET( vi
, "invalid visual for OpenGl" );
60 m_glContext
= glXCreateContext( GDK_DISPLAY(), vi
, None
, GL_TRUE
);
62 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
65 wxGLContext::wxGLContext(
66 bool WXUNUSED(isRGB
), wxWindow
*win
,
67 const wxPalette
& WXUNUSED(palette
),
68 const wxGLContext
*other
/* for sharing display lists */
72 m_widget
= win
->m_wxwindow
;
74 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
75 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
77 wxCHECK_RET( vi
, "invalid visual for OpenGl" );
80 m_glContext
= glXCreateContext( GDK_DISPLAY(), vi
, other
->m_glContext
, GL_TRUE
);
82 m_glContext
= glXCreateContext( GDK_DISPLAY(), vi
, None
, GL_TRUE
);
84 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
87 wxGLContext::~wxGLContext()
89 if (!m_glContext
) return;
91 if (m_glContext
== glXGetCurrentContext())
93 glXMakeCurrent( GDK_DISPLAY(), None
, NULL
);
96 glXDestroyContext( GDK_DISPLAY(), m_glContext
);
99 void wxGLContext::SwapBuffers()
103 GdkWindow
*window
= GTK_PIZZA(m_widget
)->bin_window
;
104 glXSwapBuffers( GDK_DISPLAY(), GDK_WINDOW_XWINDOW( window
) );
108 void wxGLContext::SetCurrent()
112 GdkWindow
*window
= GTK_PIZZA(m_widget
)->bin_window
;
113 glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window
), m_glContext
);
117 void wxGLContext::SetColour(const char *colour
)
122 wxColour
*col
= wxTheColourDatabase
->FindColour(colour
);
125 r
= (float)(col
->Red()/256.0);
126 g
= (float)(col
->Green()/256.0);
127 b
= (float)(col
->Blue()/256.0);
132 void wxGLContext::SetupPixelFormat()
136 void wxGLContext::SetupPalette( const wxPalette
& WXUNUSED(palette
) )
140 wxPalette
wxGLContext::CreateDefaultPalette()
142 return wxNullPalette
;
145 //-----------------------------------------------------------------------------
146 // "realize" from m_wxwindow
147 //-----------------------------------------------------------------------------
150 gtk_glwindow_realized_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
152 wxGLContext
*share
= win
->m_sharedContext
;
153 if (share
==NULL
&& win
->m_sharedContextOf
) share
=win
->m_sharedContextOf
->GetContext();
155 win
->m_glContext
= new wxGLContext( TRUE
, win
, wxNullPalette
, share
);
160 //-----------------------------------------------------------------------------
161 // "map" from m_wxwindow
162 //-----------------------------------------------------------------------------
165 gtk_glwindow_map_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
167 if (win
->m_glContext
/* && win->m_exposed*/)
169 wxPaintEvent
event( win
->GetId() );
170 event
.SetEventObject( win
);
171 win
->GetEventHandler()->ProcessEvent( event
);
173 win
->m_exposed
= FALSE
;
174 win
->GetUpdateRegion().Clear();
180 //-----------------------------------------------------------------------------
181 // "expose_event" of m_wxwindow
182 //-----------------------------------------------------------------------------
185 gtk_glwindow_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxGLCanvas
*win
)
188 wxapp_install_idle_handler();
190 win
->m_exposed
= TRUE
;
192 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
194 gdk_event
->area
.width
,
195 gdk_event
->area
.height
);
198 //-----------------------------------------------------------------------------
199 // "draw" of m_wxwindow
200 //-----------------------------------------------------------------------------
203 gtk_glwindow_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxGLCanvas
*win
)
206 wxapp_install_idle_handler();
208 win
->m_exposed
= TRUE
;
210 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
211 rect
->width
, rect
->height
);
214 //-----------------------------------------------------------------------------
215 // "size_allocate" of m_wxwindow
216 //-----------------------------------------------------------------------------
219 gtk_glcanvas_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxGLCanvas
*win
)
222 wxapp_install_idle_handler();
227 wxSizeEvent
event( wxSize(win
->m_width
,win
->m_height
), win
->GetId() );
228 event
.SetEventObject( win
);
229 win
->GetEventHandler()->ProcessEvent( event
);
232 //---------------------------------------------------------------------------
234 //---------------------------------------------------------------------------
236 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
)
238 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
)
239 EVT_SIZE(wxGLCanvas::OnSize
)
242 wxGLCanvas::wxGLCanvas( wxWindow
*parent
, wxWindowID id
,
243 const wxPoint
& pos
, const wxSize
& size
,
244 long style
, const wxString
& name
,
246 const wxPalette
& palette
)
248 Create( parent
, NULL
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
251 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
252 const wxGLContext
*shared
,
254 const wxPoint
& pos
, const wxSize
& size
,
255 long style
, const wxString
& name
,
257 const wxPalette
& palette
)
259 Create( parent
, shared
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
262 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
263 const wxGLCanvas
*shared
,
265 const wxPoint
& pos
, const wxSize
& size
,
266 long style
, const wxString
& name
,
268 const wxPalette
& palette
)
270 Create( parent
, NULL
, shared
, id
, pos
, size
, style
, name
, attribList
, palette
);
273 bool wxGLCanvas::Create( wxWindow
*parent
,
274 const wxGLContext
*shared
,
275 const wxGLCanvas
*shared_context_of
,
277 const wxPoint
& pos
, const wxSize
& size
,
278 long style
, const wxString
& name
,
280 const wxPalette
& palette
)
282 m_sharedContext
= (wxGLContext
*)shared
; // const_cast
283 m_sharedContextOf
= (wxGLCanvas
*)shared_context_of
; // const_cast
284 m_glContext
= (wxGLContext
*) NULL
;
288 m_nativeSizeEvent
= TRUE
;
292 int data
[] = { GLX_RGBA
,
294 GLX_DEPTH_SIZE
, 1, // use largest available depth buffer
300 attribList
= (int*) data
;
304 int data
[512], arg
=0, p
=0;
306 while( (attribList
[arg
]!=0) && (p
<512) )
308 switch( attribList
[arg
++] )
310 case WX_GL_RGBA
: data
[p
++] = GLX_RGBA
; break;
311 case WX_GL_DOUBLEBUFFER
: data
[p
++] = GLX_DOUBLEBUFFER
; break;
312 case WX_GL_DEPTH_SIZE
:
313 data
[p
++]=GLX_DEPTH_SIZE
; data
[p
++]=attribList
[arg
++]; break;
315 data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
316 case WX_GL_MIN_GREEN
:
317 data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
319 data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
326 attribList
= (int*) data
;
330 Display
*dpy
= GDK_DISPLAY();
332 XVisualInfo
*vi
= glXChooseVisual( dpy
, DefaultScreen(dpy
), attribList
);
334 m_vi
= vi
; // safe for later use
336 wxCHECK_MSG( m_vi
, FALSE
, "required visual couldn't be found" );
338 GdkVisual
*visual
= gdkx_visual_get( vi
->visualid
);
339 GdkColormap
*colormap
= gdk_colormap_new( gdkx_visual_get(vi
->visualid
), TRUE
);
341 gtk_widget_push_colormap( colormap
);
342 gtk_widget_push_visual( visual
);
344 wxScrolledWindow::Create( parent
, id
, pos
, size
, style
, name
);
346 m_glWidget
= m_wxwindow
;
348 gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow
), FALSE
);
350 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
351 GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback
), (gpointer
) this );
353 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "map",
354 GTK_SIGNAL_FUNC(gtk_glwindow_map_callback
), (gpointer
) this );
356 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
357 GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback
), (gpointer
)this );
359 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
360 GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback
), (gpointer
)this );
362 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
363 GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback
), (gpointer
)this );
365 gtk_widget_pop_visual();
366 gtk_widget_pop_colormap();
371 wxGLCanvas::~wxGLCanvas()
373 XVisualInfo
*vi
= (XVisualInfo
*) m_vi
;
376 if (m_glContext
) delete m_glContext
;
379 void wxGLCanvas::SwapBuffers()
381 if (m_glContext
) m_glContext
->SwapBuffers();
384 void wxGLCanvas::OnSize(wxSizeEvent
& WXUNUSED(event
))
387 GetClientSize( &width
, &height
);
389 if (m_glContext
&& GTK_WIDGET_REALIZED(m_glWidget
) )
393 glViewport(0, 0, (GLint
)width
, (GLint
)height
);
394 glMatrixMode(GL_PROJECTION
);
396 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
397 glMatrixMode(GL_MODELVIEW
);
401 void wxGLCanvas::SetCurrent()
403 if (m_glContext
) m_glContext
->SetCurrent();
406 void wxGLCanvas::SetColour( const char *colour
)
408 if (m_glContext
) m_glContext
->SetColour( colour
);
411 void wxGLCanvas::OnInternalIdle()
413 if (m_glContext
&& m_exposed
)
415 wxPaintEvent
event( GetId() );
416 event
.SetEventObject( this );
417 GetEventHandler()->ProcessEvent( event
);
420 GetUpdateRegion().Clear();
423 wxWindow::OnInternalIdle();