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 IMPLEMENT_CLASS(wxGLContext
,wxObject
)
43 wxGLContext::wxGLContext( bool WXUNUSED(isRGB
), wxWindow
*win
, const wxPalette
& WXUNUSED(palette
) )
46 m_widget
= ((wxGLCanvas
*)win
)->m_glWidget
;
48 wxCHECK_RET( g_vi
, "invalid visual for OpenGl" );
50 m_glContext
= glXCreateContext( GDK_DISPLAY(), g_vi
, None
, GL_TRUE
);
52 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
55 wxGLContext::wxGLContext(
56 bool WXUNUSED(isRGB
), wxWindow
*win
,
57 const wxPalette
& WXUNUSED(palette
),
58 const wxGLContext
*other
/* for sharing display lists */
62 m_widget
= ((wxGLCanvas
*)win
)->m_glWidget
;
64 wxCHECK_RET( g_vi
, "invalid visual for OpenGl" );
67 m_glContext
= glXCreateContext( GDK_DISPLAY(), g_vi
, other
->m_glContext
,
70 m_glContext
= glXCreateContext( GDK_DISPLAY(), g_vi
, None
, GL_TRUE
);
72 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
75 wxGLContext::~wxGLContext()
77 if (!m_glContext
) return;
79 if (m_glContext
== glXGetCurrentContext())
81 glXMakeCurrent( GDK_DISPLAY(), None
, NULL
);
84 glXDestroyContext( GDK_DISPLAY(), m_glContext
);
87 void wxGLContext::SwapBuffers()
91 glXSwapBuffers( GDK_DISPLAY(), GDK_WINDOW_XWINDOW( m_widget
->window
) );
95 void wxGLContext::SetCurrent()
99 glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(m_widget
->window
), m_glContext
);
103 void wxGLContext::SetColour(const char *colour
)
108 wxColour
*col
= wxTheColourDatabase
->FindColour(colour
);
111 r
= (float)(col
->Red()/256.0);
112 g
= (float)(col
->Green()/256.0);
113 b
= (float)(col
->Blue()/256.0);
118 void wxGLContext::SetupPixelFormat()
122 void wxGLContext::SetupPalette( const wxPalette
& WXUNUSED(palette
) )
126 wxPalette
wxGLContext::CreateDefaultPalette()
128 return wxNullPalette
;
131 //-----------------------------------------------------------------------------
132 // "expose_event" of m_glWidget
133 //-----------------------------------------------------------------------------
135 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
137 if (!win
->HasVMT()) return;
139 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
141 gdk_event
->area
.width
,
142 gdk_event
->area
.height
);
144 if (gdk_event
->count
> 0) return;
147 printf( "OnExpose from " );
148 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
149 printf( win->GetClassInfo()->GetClassName() );
153 wxPaintEvent
event( win
->GetId() );
154 event
.SetEventObject( win
);
155 win
->GetEventHandler()->ProcessEvent( event
);
157 win
->m_updateRegion
.Clear();
160 //-----------------------------------------------------------------------------
161 // "draw" of m_glWidget
162 //-----------------------------------------------------------------------------
164 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
166 if (!win
->HasVMT()) return;
168 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
170 wxPaintEvent
event( win
->GetId() );
171 event
.SetEventObject( win
);
172 win
->GetEventHandler()->ProcessEvent( event
);
174 win
->m_updateRegion
.Clear();
177 //---------------------------------------------------------------------------
179 //---------------------------------------------------------------------------
181 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
)
183 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
)
184 EVT_SIZE(wxGLCanvas::OnSize
)
187 wxGLCanvas::wxGLCanvas( wxWindow
*parent
, wxWindowID id
,
188 const wxPoint
& pos
, const wxSize
& size
,
189 long style
, const wxString
& name
,
191 const wxPalette
& palette
)
193 Create( parent
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette
);
196 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
197 const wxGLContext
*shared
,
199 const wxPoint
& pos
, const wxSize
& size
,
200 long style
, const wxString
& name
,
202 const wxPalette
& palette
)
204 Create( parent
, shared
, id
, pos
, size
, style
, name
, attribList
, palette
);
207 bool wxGLCanvas::Create( wxWindow
*parent
,
208 const wxGLContext
*shared
,
210 const wxPoint
& pos
, const wxSize
& size
,
211 long style
, const wxString
& name
,
213 const wxPalette
& palette
)
217 int data
[] = { GLX_RGBA
,
219 GLX_DEPTH_SIZE
, 1, /* use largest available depth buffer */
221 attribList
= (int*) data
;
222 printf( "using default values\n" );
226 int data
[512], arg
=0, p
=0;
228 while( (attribList
[arg
]!=0) && (p
<512) )
230 switch( attribList
[arg
++] )
232 case WX_GL_RGBA
: data
[p
++] = GLX_RGBA
; break;
233 case WX_GL_DOUBLEBUFFER
: data
[p
++] = GLX_DOUBLEBUFFER
; break;
234 case WX_GL_DEPTH_SIZE
:
235 data
[p
++]=GLX_DEPTH_SIZE
; data
[p
++]=attribList
[arg
++]; break;
237 data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
238 case WX_GL_MIN_GREEN
:
239 data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
241 data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
248 attribList
= (int*) data
;
251 Display
*dpy
= GDK_DISPLAY();
253 g_vi
= glXChooseVisual( dpy
, DefaultScreen(dpy
), attribList
);
255 GdkVisual
*visual
= gdkx_visual_get( g_vi
->visualid
);
256 GdkColormap
*colormap
= gdk_colormap_new( gdkx_visual_get(g_vi
->visualid
), TRUE
);
258 gtk_widget_push_colormap( colormap
);
259 gtk_widget_push_visual( visual
);
261 m_glWidget
= gtk_myfixed_new();
263 gtk_widget_pop_visual();
264 gtk_widget_pop_colormap();
266 wxScrolledWindow::Create( parent
, id
, pos
, size
, style
, name
);
268 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
269 GTK_WIDGET_SET_FLAGS( m_glWidget
, GTK_CAN_FOCUS
);
271 gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), m_glWidget
, 0, 0, m_width
, m_height
);
273 gtk_signal_connect( GTK_OBJECT(m_glWidget
), "expose_event",
274 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
276 gtk_signal_connect( GTK_OBJECT(m_glWidget
), "draw",
277 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
279 /* connect to key press and mouse handlers etc. */
280 ConnectWidget( m_glWidget
);
283 /* must be realized for OpenGl output */
284 gtk_widget_realize( m_glWidget
);
286 gtk_widget_show( m_glWidget
);
288 m_glContext
= new wxGLContext( TRUE
, this, palette
, shared
);
291 g_vi
= (XVisualInfo
*) NULL
;
293 gdk_window_set_back_pixmap( m_glWidget
->window
, None
, 0 );
298 wxGLCanvas::~wxGLCanvas()
300 if (m_glContext
) delete m_glContext
;
303 void wxGLCanvas::SwapBuffers()
305 if (m_glContext
) m_glContext
->SwapBuffers();
308 void wxGLCanvas::OnSize(wxSizeEvent
& WXUNUSED(event
))
311 GetClientSize( &width
, &height
);
312 if (m_glContext
&& GTK_WIDGET_REALIZED(m_glWidget
) )
315 // gdk_window_set_back_pixmap( gtk_widget_get_parent_window(m_glWidget), None, 0 );
317 glViewport(0, 0, (GLint
)width
, (GLint
)height
);
318 glMatrixMode(GL_PROJECTION
);
320 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
321 glMatrixMode(GL_MODELVIEW
);
325 void wxGLCanvas::SetCurrent()
327 if (m_glContext
) m_glContext
->SetCurrent();
330 void wxGLCanvas::SetColour( const char *colour
)
332 if (m_glContext
) m_glContext
->SetColour( colour
);
335 void wxGLCanvas::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
337 if (m_resizing
) return; // I don't like recursions
340 if (m_parent
->m_wxwindow
== NULL
) // i.e. wxNotebook
342 // don't set the size for children of wxNotebook, just take the values.
350 int old_width
= m_width
;
351 int old_height
= m_height
;
353 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
355 if (x
!= -1) m_x
= x
;
356 if (y
!= -1) m_y
= y
;
357 if (width
!= -1) m_width
= width
;
358 if (height
!= -1) m_height
= height
;
368 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
370 if (width
== -1) m_width
= 80;
373 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
375 if (height
== -1) m_height
= 26;
378 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
379 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
380 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
381 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
383 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
390 gtk_myfixed_set_size( GTK_MYFIXED(m_wxwindow
),
400 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
401 event
.SetEventObject( this );
402 GetEventHandler()->ProcessEvent( event
);
407 GtkWidget
*wxGLCanvas::GetConnectWidget()
412 bool wxGLCanvas::IsOwnGtkWindow( GdkWindow
*window
)
414 return (window
== m_glWidget
->window
);