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 win
->m_glContext
= new wxGLContext( TRUE
, win
, wxNullPalette
, win
->m_sharedContext
);
157 //-----------------------------------------------------------------------------
158 // "map" from m_wxwindow
159 //-----------------------------------------------------------------------------
162 gtk_glwindow_map_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
164 if (win
->m_glContext
/* && win->m_exposed*/)
166 wxPaintEvent
event( win
->GetId() );
167 event
.SetEventObject( win
);
168 win
->GetEventHandler()->ProcessEvent( event
);
170 win
->m_exposed
= FALSE
;
171 win
->GetUpdateRegion().Clear();
177 //-----------------------------------------------------------------------------
178 // "expose_event" of m_wxwindow
179 //-----------------------------------------------------------------------------
182 gtk_glwindow_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxGLCanvas
*win
)
185 wxapp_install_idle_handler();
187 win
->m_exposed
= TRUE
;
189 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
191 gdk_event
->area
.width
,
192 gdk_event
->area
.height
);
195 //-----------------------------------------------------------------------------
196 // "draw" of m_wxwindow
197 //-----------------------------------------------------------------------------
200 gtk_glwindow_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxGLCanvas
*win
)
203 wxapp_install_idle_handler();
205 win
->m_exposed
= TRUE
;
207 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
208 rect
->width
, rect
->height
);
211 //-----------------------------------------------------------------------------
212 // "size_allocate" of m_wxwindow
213 //-----------------------------------------------------------------------------
216 gtk_glcanvas_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxGLCanvas
*win
)
219 wxapp_install_idle_handler();
224 wxSizeEvent
event( wxSize(win
->m_width
,win
->m_height
), win
->GetId() );
225 event
.SetEventObject( win
);
226 win
->GetEventHandler()->ProcessEvent( event
);
229 //---------------------------------------------------------------------------
231 //---------------------------------------------------------------------------
233 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
)
235 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
)
236 EVT_SIZE(wxGLCanvas::OnSize
)
239 wxGLCanvas::wxGLCanvas( wxWindow
*parent
, wxWindowID id
,
240 const wxPoint
& pos
, const wxSize
& size
,
241 long style
, const wxString
& name
,
243 const wxPalette
& palette
)
245 Create( parent
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
248 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
249 const wxGLContext
*shared
,
251 const wxPoint
& pos
, const wxSize
& size
,
252 long style
, const wxString
& name
,
254 const wxPalette
& palette
)
256 Create( parent
, shared
, id
, pos
, size
, style
, name
, attribList
, palette
);
259 bool wxGLCanvas::Create( wxWindow
*parent
,
260 const wxGLContext
*shared
,
262 const wxPoint
& pos
, const wxSize
& size
,
263 long style
, const wxString
& name
,
265 const wxPalette
& palette
)
267 m_sharedContext
= (wxGLContext
*)shared
; // const_cast
268 m_glContext
= (wxGLContext
*) NULL
;
272 m_nativeSizeEvent
= TRUE
;
276 int data
[] = { GLX_RGBA
,
278 GLX_DEPTH_SIZE
, 1, // use largest available depth buffer
284 attribList
= (int*) data
;
288 int data
[512], arg
=0, p
=0;
290 while( (attribList
[arg
]!=0) && (p
<512) )
292 switch( attribList
[arg
++] )
294 case WX_GL_RGBA
: data
[p
++] = GLX_RGBA
; break;
295 case WX_GL_DOUBLEBUFFER
: data
[p
++] = GLX_DOUBLEBUFFER
; break;
296 case WX_GL_DEPTH_SIZE
:
297 data
[p
++]=GLX_DEPTH_SIZE
; data
[p
++]=attribList
[arg
++]; break;
299 data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
300 case WX_GL_MIN_GREEN
:
301 data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
303 data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
310 attribList
= (int*) data
;
314 Display
*dpy
= GDK_DISPLAY();
316 XVisualInfo
*vi
= glXChooseVisual( dpy
, DefaultScreen(dpy
), attribList
);
318 m_vi
= vi
; // safe for later use
320 wxCHECK_MSG( m_vi
, FALSE
, "required visual couldn't be found" );
322 GdkVisual
*visual
= gdkx_visual_get( vi
->visualid
);
323 GdkColormap
*colormap
= gdk_colormap_new( gdkx_visual_get(vi
->visualid
), TRUE
);
325 gtk_widget_push_colormap( colormap
);
326 gtk_widget_push_visual( visual
);
328 wxScrolledWindow::Create( parent
, id
, pos
, size
, style
, name
);
330 m_glWidget
= m_wxwindow
;
332 gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow
), FALSE
);
334 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
335 GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback
), (gpointer
) this );
337 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "map",
338 GTK_SIGNAL_FUNC(gtk_glwindow_map_callback
), (gpointer
) this );
340 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
341 GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback
), (gpointer
)this );
343 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
344 GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback
), (gpointer
)this );
346 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
347 GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback
), (gpointer
)this );
349 gtk_widget_pop_visual();
350 gtk_widget_pop_colormap();
355 wxGLCanvas::~wxGLCanvas()
357 XVisualInfo
*vi
= (XVisualInfo
*) m_vi
;
362 if (m_glContext
) delete m_glContext
;
365 void wxGLCanvas::SwapBuffers()
367 if (m_glContext
) m_glContext
->SwapBuffers();
370 void wxGLCanvas::OnSize(wxSizeEvent
& WXUNUSED(event
))
373 GetClientSize( &width
, &height
);
375 if (m_glContext
&& GTK_WIDGET_REALIZED(m_glWidget
) )
379 glViewport(0, 0, (GLint
)width
, (GLint
)height
);
380 glMatrixMode(GL_PROJECTION
);
382 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
383 glMatrixMode(GL_MODELVIEW
);
387 void wxGLCanvas::SetCurrent()
389 if (m_glContext
) m_glContext
->SetCurrent();
392 void wxGLCanvas::SetColour( const char *colour
)
394 if (m_glContext
) m_glContext
->SetColour( colour
);
397 void wxGLCanvas::OnInternalIdle()
399 if (m_glContext
&& m_exposed
)
401 wxPaintEvent
event( GetId() );
402 event
.SetEventObject( this );
403 GetEventHandler()->ProcessEvent( event
);
406 GetUpdateRegion().Clear();
409 wxWindow::OnInternalIdle();