Refactor all code common to X11 OpenGL implementations into glx11.h/.cpp
[wxWidgets.git] / src / gtk / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL/Mesa with wxWidgets and GTK
4 // Author: Robert Roebling
5 // Modified by:
6 // Created: 17/08/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #if wxUSE_GLCANVAS
16
17 #include "wx/glcanvas.h"
18
19 #ifndef WX_PRECOMP
20 #include "wx/app.h"
21 #include "wx/frame.h"
22 #include "wx/colour.h"
23 #include "wx/module.h"
24 #endif // WX_PRECOMP
25
26 extern "C"
27 {
28 #include "gtk/gtk.h"
29 #include "gdk/gdk.h"
30 #include "gdk/gdkx.h"
31 }
32
33 #include "wx/gtk/win_gtk.h"
34 #include "wx/gtk/private.h"
35
36 #if WXWIN_COMPATIBILITY_2_8
37
38 //-----------------------------------------------------------------------------
39 // "realize" from m_wxwindow: used to create m_glContext implicitly
40 //-----------------------------------------------------------------------------
41
42 extern "C" {
43 static gint
44 gtk_glwindow_realized_callback( GtkWidget *WXUNUSED(widget), wxGLCanvas *win )
45 {
46 win->GTKInitImplicitContext();
47
48 return FALSE;
49 }
50 }
51
52 #endif // WXWIN_COMPATIBILITY_2_8
53
54 //-----------------------------------------------------------------------------
55 // "map" from m_wxwindow
56 //-----------------------------------------------------------------------------
57
58 extern "C" {
59 static gint
60 gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
61 {
62 wxPaintEvent event( win->GetId() );
63 event.SetEventObject( win );
64 win->GetEventHandler()->ProcessEvent( event );
65
66 win->m_exposed = false;
67 win->GetUpdateRegion().Clear();
68
69 return FALSE;
70 }
71 }
72
73 //-----------------------------------------------------------------------------
74 // "expose_event" of m_wxwindow
75 //-----------------------------------------------------------------------------
76
77 extern "C" {
78 static gboolean
79 gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
80 {
81 // don't need to install idle handler, its done from "event" signal
82
83 win->m_exposed = true;
84
85 win->GetUpdateRegion().Union( gdk_event->area.x,
86 gdk_event->area.y,
87 gdk_event->area.width,
88 gdk_event->area.height );
89 return false;
90 }
91 }
92
93 //-----------------------------------------------------------------------------
94 // "size_allocate" of m_wxwindow
95 //-----------------------------------------------------------------------------
96
97 extern "C" {
98 static void
99 gtk_glcanvas_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxGLCanvas *win )
100 {
101 if (g_isIdle)
102 wxapp_install_idle_handler();
103
104 if (!win->m_hasVMT)
105 return;
106
107 wxSizeEvent event( wxSize(win->m_width,win->m_height), win->GetId() );
108 event.SetEventObject( win );
109 win->GetEventHandler()->ProcessEvent( event );
110 }
111 }
112
113 //---------------------------------------------------------------------------
114 // wxGlCanvas
115 //---------------------------------------------------------------------------
116
117 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
118
119 wxGLCanvas::wxGLCanvas(wxWindow *parent,
120 wxWindowID id,
121 const int *attribList,
122 const wxPoint& pos,
123 const wxSize& size,
124 long style,
125 const wxString& name,
126 const wxPalette& palette)
127 #if WXWIN_COMPATIBILITY_2_8
128 : m_createImplicitContext(false)
129 #endif
130 {
131 Create(parent, id, pos, size, style, name, attribList, palette);
132 }
133
134 #if WXWIN_COMPATIBILITY_2_8
135
136 wxGLCanvas::wxGLCanvas(wxWindow *parent,
137 wxWindowID id,
138 const wxPoint& pos,
139 const wxSize& size,
140 long style,
141 const wxString& name,
142 const int *attribList,
143 const wxPalette& palette)
144 : m_createImplicitContext(true)
145 {
146 Create(parent, id, pos, size, style, name, attribList, palette);
147 }
148
149 wxGLCanvas::wxGLCanvas(wxWindow *parent,
150 const wxGLContext *shared,
151 wxWindowID id,
152 const wxPoint& pos,
153 const wxSize& size,
154 long style,
155 const wxString& name,
156 const int *attribList,
157 const wxPalette& palette)
158 : m_createImplicitContext(true)
159 {
160 m_sharedContext = wx_const_cast(wxGLContext *, shared);
161
162 Create(parent, id, pos, size, style, name, attribList, palette);
163 }
164
165 wxGLCanvas::wxGLCanvas(wxWindow *parent,
166 const wxGLCanvas *shared,
167 wxWindowID id,
168 const wxPoint& pos, const wxSize& size,
169 long style, const wxString& name,
170 const int *attribList,
171 const wxPalette& palette )
172 : m_createImplicitContext(true)
173 {
174 m_sharedContextOf = wx_const_cast(wxGLCanvas *, shared);
175
176 Create(parent, id, pos, size, style, name, attribList, palette);
177 }
178
179 #endif // WXWIN_COMPATIBILITY_2_8
180
181 bool wxGLCanvas::Create(wxWindow *parent,
182 wxWindowID id,
183 const wxPoint& pos,
184 const wxSize& size,
185 long style,
186 const wxString& name,
187 const int *attribList,
188 const wxPalette& palette)
189 {
190 m_exposed = false;
191 m_noExpose = true;
192 m_nativeSizeEvent = true;
193
194 if ( !InitVisual(attribList) )
195 return false;
196
197 XVisualInfo * const xvi = GetXVisualInfo();
198
199 GdkVisual *visual;
200 GdkColormap *colormap;
201
202 // MR: This needs a fix for lower gtk+ versions too. Might need to rethink logic (FIXME)
203 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,2,0)
204 if (!gtk_check_version(2,2,0))
205 {
206 wxWindow::Create( parent, id, pos, size, style, name );
207
208 m_glWidget = m_wxwindow;
209
210 GdkScreen *screen = gtk_widget_get_screen( m_glWidget );
211 colormap = gdk_screen_get_default_colormap(screen);
212 visual = gdk_colormap_get_visual(colormap);
213
214 if (GDK_VISUAL_XVISUAL(visual)->visualid != xvi->visualid)
215 {
216 visual = gdk_x11_screen_lookup_visual( screen, xvi->visualid );
217 colormap = gdk_colormap_new(visual, FALSE);
218 }
219
220 gtk_widget_set_colormap( m_glWidget, colormap );
221 }
222 else
223 #endif // GTK+ >= 2.2
224 {
225 visual = gdkx_visual_get( xvi->visualid );
226 colormap = gdk_colormap_new( visual, TRUE );
227
228 gtk_widget_push_colormap( colormap );
229
230 wxWindow::Create( parent, id, pos, size, style, name );
231 m_glWidget = m_wxwindow;
232 }
233
234 gtk_widget_set_double_buffered( m_glWidget, FALSE );
235
236 #if WXWIN_COMPATIBILITY_2_8
237 g_signal_connect(m_wxwindow, "realize", G_CALLBACK(gtk_glwindow_realized_callback), this);
238 #endif // WXWIN_COMPATIBILITY_2_8
239 g_signal_connect(m_wxwindow, "map", G_CALLBACK(gtk_glwindow_map_callback), this);
240 g_signal_connect(m_wxwindow, "expose_event", G_CALLBACK(gtk_glwindow_expose_callback), this);
241 g_signal_connect(m_widget, "size_allocate", G_CALLBACK(gtk_glcanvas_size_callback), this);
242
243 if (gtk_check_version(2,2,0) != NULL)
244 {
245 gtk_widget_pop_colormap();
246 }
247
248 #if WXWIN_COMPATIBILITY_2_8
249 // if our parent window is already visible, we had been realized before we
250 // connected to the "realize" signal and hence our m_glContext hasn't been
251 // initialized yet and we have to do it now
252 if (GTK_WIDGET_REALIZED(m_wxwindow))
253 gtk_glwindow_realized_callback( m_wxwindow, this );
254 #endif // WXWIN_COMPATIBILITY_2_8
255
256 if (GTK_WIDGET_MAPPED(m_wxwindow))
257 gtk_glwindow_map_callback( m_wxwindow, this );
258
259 return true;
260 }
261
262 Window wxGLCanvas::GetXWindow() const
263 {
264 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
265 return window ? GDK_WINDOW_XWINDOW(window) : 0;
266 }
267
268 void wxGLCanvas::OnInternalIdle()
269 {
270 if (m_exposed)
271 {
272 wxPaintEvent event( GetId() );
273 event.SetEventObject( this );
274 GetEventHandler()->ProcessEvent( event );
275
276 m_exposed = false;
277 GetUpdateRegion().Clear();
278 }
279
280 wxWindow::OnInternalIdle();
281 }
282
283 #if WXWIN_COMPATIBILITY_2_8
284
285 void wxGLCanvas::GTKInitImplicitContext()
286 {
287 if ( !m_glContext && m_createImplicitContext )
288 {
289 wxGLContext *share = m_sharedContext;
290 if ( !share && m_sharedContextOf )
291 share = m_sharedContextOf->m_glContext;
292
293 m_glContext = new wxGLContext(this, share);
294 }
295 }
296
297 #endif // WXWIN_COMPATIBILITY_2_8
298
299 #endif // wxUSE_GLCANVAS