1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/glcanvas.cpp
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"
34 #include "wx/gtk/win_gtk.h"
36 //---------------------------------------------------------------------------
38 //---------------------------------------------------------------------------
40 XVisualInfo
*g_vi
= (XVisualInfo
*) NULL
;
42 //-----------------------------------------------------------------------------
44 //-----------------------------------------------------------------------------
46 extern void wxapp_install_idle_handler();
49 //---------------------------------------------------------------------------
51 //---------------------------------------------------------------------------
53 IMPLEMENT_CLASS(wxGLContext
,wxObject
)
55 wxGLContext::wxGLContext( bool WXUNUSED(isRGB
), wxWindow
*win
, const wxPalette
& WXUNUSED(palette
) )
58 m_widget
= win
->m_wxwindow
;
60 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
61 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
63 wxCHECK_RET( vi
, _T("invalid visual for OpenGl") );
65 m_glContext
= glXCreateContext( GDK_DISPLAY(), vi
, None
, GL_TRUE
);
67 wxCHECK_RET( m_glContext
, _T("Couldn't create OpenGl context") );
70 wxGLContext::wxGLContext(
71 bool WXUNUSED(isRGB
), wxWindow
*win
,
72 const wxPalette
& WXUNUSED(palette
),
73 const wxGLContext
*other
/* for sharing display lists */
77 m_widget
= win
->m_wxwindow
;
79 wxGLCanvas
*gc
= (wxGLCanvas
*) win
;
80 XVisualInfo
*vi
= (XVisualInfo
*) gc
->m_vi
;
82 wxCHECK_RET( vi
, _T("invalid visual for OpenGl") );
84 m_glContext
= glXCreateContext( GDK_DISPLAY(), vi
,
85 other
? other
->m_glContext
: None
,
90 wxFAIL_MSG( _T("Couldn't create OpenGl context") );
94 wxGLContext::~wxGLContext()
96 if (!m_glContext
) return;
98 if (m_glContext
== glXGetCurrentContext())
100 glXMakeCurrent( GDK_DISPLAY(), None
, NULL
);
103 glXDestroyContext( GDK_DISPLAY(), m_glContext
);
106 void wxGLContext::SwapBuffers()
110 GdkWindow
*window
= GTK_PIZZA(m_widget
)->bin_window
;
111 glXSwapBuffers( GDK_DISPLAY(), GDK_WINDOW_XWINDOW( window
) );
115 void wxGLContext::SetCurrent()
119 GdkWindow
*window
= GTK_PIZZA(m_widget
)->bin_window
;
120 glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window
), m_glContext
);
124 void wxGLContext::SetColour(const wxChar
*colour
)
129 wxColour
*col
= wxTheColourDatabase
->FindColour(colour
);
132 r
= (float)(col
->Red()/256.0);
133 g
= (float)(col
->Green()/256.0);
134 b
= (float)(col
->Blue()/256.0);
139 void wxGLContext::SetupPixelFormat()
143 void wxGLContext::SetupPalette( const wxPalette
& WXUNUSED(palette
) )
147 wxPalette
wxGLContext::CreateDefaultPalette()
149 return wxNullPalette
;
152 //-----------------------------------------------------------------------------
153 // "realize" from m_wxwindow
154 //-----------------------------------------------------------------------------
157 gtk_glwindow_realized_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
159 wxGLContext
*share
= win
->m_sharedContext
;
160 if (share
==NULL
&& win
->m_sharedContextOf
) share
=win
->m_sharedContextOf
->GetContext();
162 win
->m_glContext
= new wxGLContext( TRUE
, win
, wxNullPalette
, share
);
167 //-----------------------------------------------------------------------------
168 // "map" from m_wxwindow
169 //-----------------------------------------------------------------------------
172 gtk_glwindow_map_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
174 if (win
->m_glContext
/* && win->m_exposed*/)
176 wxPaintEvent
event( win
->GetId() );
177 event
.SetEventObject( win
);
178 win
->GetEventHandler()->ProcessEvent( event
);
180 win
->m_exposed
= FALSE
;
181 win
->GetUpdateRegion().Clear();
187 //-----------------------------------------------------------------------------
188 // "expose_event" of m_wxwindow
189 //-----------------------------------------------------------------------------
192 gtk_glwindow_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxGLCanvas
*win
)
195 wxapp_install_idle_handler();
197 win
->m_exposed
= TRUE
;
199 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
201 gdk_event
->area
.width
,
202 gdk_event
->area
.height
);
205 //-----------------------------------------------------------------------------
206 // "draw" of m_wxwindow
207 //-----------------------------------------------------------------------------
211 gtk_glwindow_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxGLCanvas
*win
)
214 wxapp_install_idle_handler();
216 win
->m_exposed
= TRUE
;
218 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
219 rect
->width
, rect
->height
);
223 //-----------------------------------------------------------------------------
224 // "size_allocate" of m_wxwindow
225 //-----------------------------------------------------------------------------
228 gtk_glcanvas_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxGLCanvas
*win
)
231 wxapp_install_idle_handler();
236 wxSizeEvent
event( wxSize(win
->m_width
,win
->m_height
), win
->GetId() );
237 event
.SetEventObject( win
);
238 win
->GetEventHandler()->ProcessEvent( event
);
241 //---------------------------------------------------------------------------
243 //---------------------------------------------------------------------------
245 IMPLEMENT_CLASS(wxGLCanvas
, wxWindow
)
247 BEGIN_EVENT_TABLE(wxGLCanvas
, wxWindow
)
248 EVT_SIZE(wxGLCanvas::OnSize
)
251 wxGLCanvas::wxGLCanvas( wxWindow
*parent
, wxWindowID id
,
252 const wxPoint
& pos
, const wxSize
& size
,
253 long style
, const wxString
& name
,
255 const wxPalette
& palette
)
257 Create( parent
, NULL
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
260 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
261 const wxGLContext
*shared
,
263 const wxPoint
& pos
, const wxSize
& size
,
264 long style
, const wxString
& name
,
266 const wxPalette
& palette
)
268 Create( parent
, shared
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
271 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
272 const wxGLCanvas
*shared
,
274 const wxPoint
& pos
, const wxSize
& size
,
275 long style
, const wxString
& name
,
277 const wxPalette
& palette
)
279 Create( parent
, NULL
, shared
, id
, pos
, size
, style
, name
, attribList
, palette
);
282 bool wxGLCanvas::Create( wxWindow
*parent
,
283 const wxGLContext
*shared
,
284 const wxGLCanvas
*shared_context_of
,
286 const wxPoint
& pos
, const wxSize
& size
,
287 long style
, const wxString
& name
,
289 const wxPalette
& palette
)
291 m_sharedContext
= (wxGLContext
*)shared
; // const_cast
292 m_sharedContextOf
= (wxGLCanvas
*)shared_context_of
; // const_cast
293 m_glContext
= (wxGLContext
*) NULL
;
297 m_nativeSizeEvent
= TRUE
;
299 XVisualInfo
*vi
= NULL
;
300 if (wxTheApp
->m_glVisualInfo
!= NULL
)
302 vi
= (XVisualInfo
*) wxTheApp
->m_glVisualInfo
;
303 m_canFreeVi
= FALSE
; // owned by wxTheApp - don't free upon destruction
307 vi
= (XVisualInfo
*) ChooseGLVisual(attribList
);
310 m_vi
= vi
; // save for later use
312 wxCHECK_MSG( m_vi
, FALSE
, _T("required visual couldn't be found") );
314 GdkVisual
*visual
= gdkx_visual_get( vi
->visualid
);
315 GdkColormap
*colormap
= gdk_colormap_new( gdkx_visual_get(vi
->visualid
), TRUE
);
317 gtk_widget_push_colormap( colormap
);
318 gtk_widget_push_visual( visual
);
320 wxWindow::Create( parent
, id
, pos
, size
, style
, name
);
322 m_glWidget
= m_wxwindow
;
325 gtk_widget_set_double_buffered( m_glWidget
, FALSE
);
328 gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow
), FALSE
);
330 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
331 GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback
), (gpointer
) this );
333 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "map",
334 GTK_SIGNAL_FUNC(gtk_glwindow_map_callback
), (gpointer
) this );
336 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
337 GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback
), (gpointer
)this );
340 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
341 GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback
), (gpointer
)this );
344 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
345 GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback
), (gpointer
)this );
347 gtk_widget_pop_visual();
348 gtk_widget_pop_colormap();
350 if (GTK_WIDGET_REALIZED(m_wxwindow
))
351 gtk_glwindow_realized_callback( m_wxwindow
, this );
353 if (GTK_WIDGET_MAPPED(m_wxwindow
))
354 gtk_glwindow_map_callback( m_wxwindow
, this );
359 wxGLCanvas::~wxGLCanvas()
361 XVisualInfo
*vi
= (XVisualInfo
*) m_vi
;
363 if (vi
&& m_canFreeVi
) XFree( vi
);
364 if (m_glContext
) delete m_glContext
;
367 void* wxGLCanvas::ChooseGLVisual(int *attribList
)
372 // default settings if attriblist = 0
374 data
[1] = GLX_DOUBLEBUFFER
;
375 data
[2] = GLX_DEPTH_SIZE
; data
[3] = 1;
376 data
[4] = GLX_RED_SIZE
; data
[5] = 1;
377 data
[6] = GLX_GREEN_SIZE
; data
[7] = 1;
378 data
[8] = GLX_BLUE_SIZE
; data
[9] = 1;
379 data
[10] = GLX_ALPHA_SIZE
; data
[11] = 0;
382 attribList
= (int*) data
;
388 while( (attribList
[arg
]!=0) && (p
<510) )
390 switch( attribList
[arg
++] )
392 case WX_GL_RGBA
: data
[p
++] = GLX_RGBA
; break;
393 case WX_GL_BUFFER_SIZE
:
394 data
[p
++]=GLX_BUFFER_SIZE
; data
[p
++]=attribList
[arg
++]; break;
396 data
[p
++]=GLX_LEVEL
; data
[p
++]=attribList
[arg
++]; break;
397 case WX_GL_DOUBLEBUFFER
: data
[p
++] = GLX_DOUBLEBUFFER
; break;
398 case WX_GL_STEREO
: data
[p
++] = GLX_STEREO
; break;
399 case WX_GL_AUX_BUFFERS
:
400 data
[p
++]=GLX_AUX_BUFFERS
; data
[p
++]=attribList
[arg
++]; break;
402 data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
403 case WX_GL_MIN_GREEN
:
404 data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
406 data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
407 case WX_GL_MIN_ALPHA
:
408 data
[p
++]=GLX_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break;
409 case WX_GL_DEPTH_SIZE
:
410 data
[p
++]=GLX_DEPTH_SIZE
; data
[p
++]=attribList
[arg
++]; break;
411 case WX_GL_STENCIL_SIZE
:
412 data
[p
++]=GLX_STENCIL_SIZE
; data
[p
++]=attribList
[arg
++]; break;
413 case WX_GL_MIN_ACCUM_RED
:
414 data
[p
++]=GLX_ACCUM_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
415 case WX_GL_MIN_ACCUM_GREEN
:
416 data
[p
++]=GLX_ACCUM_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
417 case WX_GL_MIN_ACCUM_BLUE
:
418 data
[p
++]=GLX_ACCUM_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
419 case WX_GL_MIN_ACCUM_ALPHA
:
420 data
[p
++]=GLX_ACCUM_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break;
427 attribList
= (int*) data
;
431 Display
*dpy
= GDK_DISPLAY();
433 return glXChooseVisual( dpy
, DefaultScreen(dpy
), attribList
);
436 void wxGLCanvas::SwapBuffers()
439 m_glContext
->SwapBuffers();
442 void wxGLCanvas::OnSize(wxSizeEvent
& WXUNUSED(event
))
446 void wxGLCanvas::SetCurrent()
449 m_glContext
->SetCurrent();
452 void wxGLCanvas::SetColour( const wxChar
*colour
)
455 m_glContext
->SetColour( colour
);
458 void wxGLCanvas::OnInternalIdle()
460 if (m_glContext
&& m_exposed
)
462 wxPaintEvent
event( GetId() );
463 event
.SetEventObject( this );
464 GetEventHandler()->ProcessEvent( event
);
467 GetUpdateRegion().Clear();
470 wxWindow::OnInternalIdle();
475 //---------------------------------------------------------------------------
477 //---------------------------------------------------------------------------
479 IMPLEMENT_CLASS(wxGLApp
, wxApp
)
484 XFree(m_glVisualInfo
);
487 bool wxGLApp::InitGLVisual(int *attribList
)
490 XFree(m_glVisualInfo
);
492 m_glVisualInfo
= wxGLCanvas::ChooseGLVisual(attribList
);
494 return m_glVisualInfo
!= NULL
;