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();