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
= ((wxGLCanvas
*)win
)->m_glWidget
;
55 wxCHECK_RET( g_vi
, "invalid visual for OpenGl" );
57 m_glContext
= glXCreateContext( GDK_DISPLAY(), g_vi
, None
, GL_TRUE
);
59 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
62 wxGLContext::wxGLContext(
63 bool WXUNUSED(isRGB
), wxWindow
*win
,
64 const wxPalette
& WXUNUSED(palette
),
65 const wxGLContext
*other
/* for sharing display lists */
69 m_widget
= ((wxGLCanvas
*)win
)->m_glWidget
;
71 wxCHECK_RET( g_vi
, "invalid visual for OpenGl" );
74 m_glContext
= glXCreateContext( GDK_DISPLAY(), g_vi
, other
->m_glContext
,
77 m_glContext
= glXCreateContext( GDK_DISPLAY(), g_vi
, None
, GL_TRUE
);
79 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
82 wxGLContext::~wxGLContext()
84 if (!m_glContext
) return;
86 if (m_glContext
== glXGetCurrentContext())
88 glXMakeCurrent( GDK_DISPLAY(), None
, NULL
);
91 glXDestroyContext( GDK_DISPLAY(), m_glContext
);
94 void wxGLContext::SwapBuffers()
98 GdkWindow
*window
= GTK_PIZZA(m_widget
)->bin_window
;
99 glXSwapBuffers( GDK_DISPLAY(), GDK_WINDOW_XWINDOW( window
) );
103 void wxGLContext::SetCurrent()
107 GdkWindow
*window
= GTK_PIZZA(m_widget
)->bin_window
;
108 glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window
), m_glContext
);
112 void wxGLContext::SetColour(const char *colour
)
117 wxColour
*col
= wxTheColourDatabase
->FindColour(colour
);
120 r
= (float)(col
->Red()/256.0);
121 g
= (float)(col
->Green()/256.0);
122 b
= (float)(col
->Blue()/256.0);
127 void wxGLContext::SetupPixelFormat()
131 void wxGLContext::SetupPalette( const wxPalette
& WXUNUSED(palette
) )
135 wxPalette
wxGLContext::CreateDefaultPalette()
137 return wxNullPalette
;
140 //-----------------------------------------------------------------------------
141 // "realize" from m_wxwindow
142 //-----------------------------------------------------------------------------
145 gtk_glwindow_realized_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
147 win
->m_glContext
= new wxGLContext( TRUE
, win
, wxNullPalette
, win
->m_sharedContext
);
150 g_vi
= (XVisualInfo
*) NULL
;
155 //-----------------------------------------------------------------------------
156 // "expose_event" of m_wxwindow
157 //-----------------------------------------------------------------------------
160 gtk_glwindow_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxGLCanvas
*win
)
163 wxapp_install_idle_handler();
165 win
->m_exposed
= TRUE
;
167 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
169 gdk_event
->area
.width
,
170 gdk_event
->area
.height
);
173 //-----------------------------------------------------------------------------
174 // "draw" of m_wxwindow
175 //-----------------------------------------------------------------------------
178 gtk_glwindow_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxGLCanvas
*win
)
181 wxapp_install_idle_handler();
183 win
->m_exposed
= TRUE
;
185 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
186 rect
->width
, rect
->height
);
189 //-----------------------------------------------------------------------------
190 // "size_allocate" of m_wxwindow
191 //-----------------------------------------------------------------------------
194 gtk_glcanvas_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxGLCanvas
*win
)
197 wxapp_install_idle_handler();
202 wxSizeEvent
event( wxSize(win
->m_width
,win
->m_height
), win
->GetId() );
203 event
.SetEventObject( win
);
204 win
->GetEventHandler()->ProcessEvent( event
);
207 //---------------------------------------------------------------------------
209 //---------------------------------------------------------------------------
211 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
)
213 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
)
214 EVT_SIZE(wxGLCanvas::OnSize
)
217 wxGLCanvas::wxGLCanvas( wxWindow
*parent
, wxWindowID id
,
218 const wxPoint
& pos
, const wxSize
& size
,
219 long style
, const wxString
& name
,
221 const wxPalette
& palette
)
223 Create( parent
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
226 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
227 const wxGLContext
*shared
,
229 const wxPoint
& pos
, const wxSize
& size
,
230 long style
, const wxString
& name
,
232 const wxPalette
& palette
)
234 Create( parent
, shared
, id
, pos
, size
, style
, name
, attribList
, palette
);
237 bool wxGLCanvas::Create( wxWindow
*parent
,
238 const wxGLContext
*shared
,
240 const wxPoint
& pos
, const wxSize
& size
,
241 long style
, const wxString
& name
,
243 const wxPalette
& palette
)
245 m_sharedContext
= (wxGLContext
*)shared
; // const_cast
249 m_nativeSizeEvent
= TRUE
;
253 int data
[] = { GLX_RGBA
,
255 GLX_DEPTH_SIZE
, 1, // use largest available depth buffer
261 attribList
= (int*) data
;
265 int data
[512], arg
=0, p
=0;
267 while( (attribList
[arg
]!=0) && (p
<512) )
269 switch( attribList
[arg
++] )
271 case WX_GL_RGBA
: data
[p
++] = GLX_RGBA
; break;
272 case WX_GL_DOUBLEBUFFER
: data
[p
++] = GLX_DOUBLEBUFFER
; break;
273 case WX_GL_DEPTH_SIZE
:
274 data
[p
++]=GLX_DEPTH_SIZE
; data
[p
++]=attribList
[arg
++]; break;
276 data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
277 case WX_GL_MIN_GREEN
:
278 data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
280 data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
287 attribList
= (int*) data
;
291 Display
*dpy
= GDK_DISPLAY();
293 g_vi
= glXChooseVisual( dpy
, DefaultScreen(dpy
), attribList
);
295 wxCHECK_MSG( g_vi
, FALSE
, "required visual couldn't be found" );
297 GdkVisual
*visual
= gdkx_visual_get( g_vi
->visualid
);
298 GdkColormap
*colormap
= gdk_colormap_new( gdkx_visual_get(g_vi
->visualid
), TRUE
);
300 gtk_widget_push_colormap( colormap
);
301 gtk_widget_push_visual( visual
);
303 wxScrolledWindow::Create( parent
, id
, pos
, size
, style
, name
);
305 m_glWidget
= m_wxwindow
;
307 gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow
), FALSE
);
309 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
310 GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback
), (gpointer
) this );
312 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
313 GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback
), (gpointer
)this );
315 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
316 GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback
), (gpointer
)this );
318 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
319 GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback
), (gpointer
)this );
321 gtk_widget_pop_visual();
322 gtk_widget_pop_colormap();
327 wxGLCanvas::~wxGLCanvas()
329 if (m_glContext
) delete m_glContext
;
332 void wxGLCanvas::SwapBuffers()
334 if (m_glContext
) m_glContext
->SwapBuffers();
337 void wxGLCanvas::OnSize(wxSizeEvent
& WXUNUSED(event
))
340 GetClientSize( &width
, &height
);
342 if (m_glContext
&& GTK_WIDGET_REALIZED(m_glWidget
) )
346 glViewport(0, 0, (GLint
)width
, (GLint
)height
);
347 glMatrixMode(GL_PROJECTION
);
349 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
350 glMatrixMode(GL_MODELVIEW
);
354 void wxGLCanvas::SetCurrent()
356 if (m_glContext
) m_glContext
->SetCurrent();
359 void wxGLCanvas::SetColour( const char *colour
)
361 if (m_glContext
) m_glContext
->SetColour( colour
);
364 void wxGLCanvas::OnInternalIdle()
366 if (m_glContext
&& m_exposed
)
368 wxPaintEvent
event( GetId() );
369 event
.SetEventObject( this );
370 GetEventHandler()->ProcessEvent( event
);
373 GetUpdateRegion().Clear();
376 wxWindow::OnInternalIdle();