1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk1/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: glcanvas.cpp 48536 2007-09-03 22:35:43Z VZ $
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/gtk1/win_gtk.h"
34 
35 // DLL options compatibility check:
36 #include "wx/build.h"
37 WX_CHECK_BUILD_OPTIONS("wxGL")
38 
39 
40 //---------------------------------------------------------------------------
41 // static variables
42 //---------------------------------------------------------------------------
43 int wxGLCanvas::m_glxVersion = 0;
44 
45 //---------------------------------------------------------------------------
46 // global data
47 //---------------------------------------------------------------------------
48 
49 XVisualInfo *g_vi = (XVisualInfo*) NULL;
50 //-----------------------------------------------------------------------------
51 // idle system
52 //-----------------------------------------------------------------------------
53 
54 extern void wxapp_install_idle_handler();
55 extern bool g_isIdle;
56 
57 //---------------------------------------------------------------------------
58 // wxGLContext
59 //---------------------------------------------------------------------------
60 
IMPLEMENT_CLASS(wxGLContext,wxObject)61 IMPLEMENT_CLASS(wxGLContext,wxObject)
62 
63 wxGLContext::wxGLContext( bool WXUNUSED(isRGB), wxWindow *win, const wxPalette& WXUNUSED(palette) )
64 {
65     m_window = win;
66     m_widget = win->m_wxwindow;
67 
68     wxGLCanvas *gc = (wxGLCanvas*) win;
69 
70     if (wxGLCanvas::GetGLXVersion() >= 13)
71     {
72         // GLX >= 1.3
73         GLXFBConfig *fbc = gc->m_fbc;
74         wxCHECK_RET( fbc, _T("invalid GLXFBConfig for OpenGl") );
75         m_glContext = glXCreateNewContext( GDK_DISPLAY(), fbc[0], GLX_RGBA_TYPE, None, GL_TRUE );
76     }
77     else
78     {
79         // GLX <= 1.2
80         XVisualInfo *vi = (XVisualInfo *) gc->m_vi;
81         wxCHECK_RET( vi, _T("invalid visual for OpenGl") );
82         m_glContext = glXCreateContext( GDK_DISPLAY(), vi, None, GL_TRUE );
83     }
84 
85     wxCHECK_RET( m_glContext, _T("Couldn't create OpenGl context") );
86 }
87 
wxGLContext(bool WXUNUSED (isRGB),wxWindow * win,const wxPalette & WXUNUSED (palette),const wxGLContext * other)88 wxGLContext::wxGLContext(
89                bool WXUNUSED(isRGB), wxWindow *win,
90                const wxPalette& WXUNUSED(palette),
91                const wxGLContext *other        /* for sharing display lists */
92 )
93 {
94     m_window = win;
95     m_widget = win->m_wxwindow;
96 
97     wxGLCanvas *gc = (wxGLCanvas*) win;
98 
99     if (wxGLCanvas::GetGLXVersion() >= 13)
100     {
101         // GLX >= 1.3
102         GLXFBConfig *fbc = gc->m_fbc;
103         wxCHECK_RET( fbc, _T("invalid GLXFBConfig for OpenGl") );
104         m_glContext = glXCreateNewContext( GDK_DISPLAY(), fbc[0], GLX_RGBA_TYPE,
105                                            other ? other->m_glContext : None,
106                                            GL_TRUE );
107     }
108     else
109     {
110         // GLX <= 1.2
111         XVisualInfo *vi = (XVisualInfo *) gc->m_vi;
112         wxCHECK_RET( vi, _T("invalid visual for OpenGl") );
113         m_glContext = glXCreateContext( GDK_DISPLAY(), vi,
114                                         other ? other->m_glContext : None,
115                                         GL_TRUE );
116     }
117 
118     if ( !m_glContext )
119     {
120         wxFAIL_MSG( _T("Couldn't create OpenGl context") );
121     }
122 }
123 
~wxGLContext()124 wxGLContext::~wxGLContext()
125 {
126     if (!m_glContext) return;
127 
128     if (m_glContext == glXGetCurrentContext())
129     {
130         if (wxGLCanvas::GetGLXVersion() >= 13)
131             // GLX >= 1.3
132             glXMakeContextCurrent( GDK_DISPLAY(), None, None, NULL);
133         else
134             // GLX <= 1.2
135             glXMakeCurrent( GDK_DISPLAY(), None, NULL);
136     }
137 
138     glXDestroyContext( GDK_DISPLAY(), m_glContext );
139 }
140 
SwapBuffers()141 void wxGLContext::SwapBuffers()
142 {
143     if (m_glContext)
144     {
145         GdkWindow *window = GTK_PIZZA(m_widget)->bin_window;
146         glXSwapBuffers( GDK_DISPLAY(), GDK_WINDOW_XWINDOW( window ) );
147     }
148 }
149 
SetCurrent()150 void wxGLContext::SetCurrent()
151 {
152     if (m_glContext)
153     {
154         GdkWindow *window = GTK_PIZZA(m_widget)->bin_window;
155 
156         if (wxGLCanvas::GetGLXVersion() >= 13)
157             // GLX >= 1.3
158             glXMakeContextCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window),
159                                    GDK_WINDOW_XWINDOW(window), m_glContext );
160         else
161             // GLX <= 1.2
162             glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window), m_glContext );
163     }
164 }
165 
SetColour(const wxChar * colour)166 void wxGLContext::SetColour(const wxChar *colour)
167 {
168     wxColour col = wxTheColourDatabase->Find(colour);
169     if (col.Ok())
170     {
171         float r = (float)(col.Red()/256.0);
172         float g = (float)(col.Green()/256.0);
173         float b = (float)(col.Blue()/256.0);
174         glColor3f( r, g, b);
175     }
176 }
177 
SetupPixelFormat()178 void wxGLContext::SetupPixelFormat()
179 {
180 }
181 
SetupPalette(const wxPalette & WXUNUSED (palette))182 void wxGLContext::SetupPalette( const wxPalette& WXUNUSED(palette) )
183 {
184 }
185 
CreateDefaultPalette()186 wxPalette wxGLContext::CreateDefaultPalette()
187 {
188     return wxNullPalette;
189 }
190 
191 //-----------------------------------------------------------------------------
192 // "realize" from m_wxwindow
193 //-----------------------------------------------------------------------------
194 
195 extern "C" {
196 static gint
gtk_glwindow_realized_callback(GtkWidget * WXUNUSED (widget),wxGLCanvas * win)197 gtk_glwindow_realized_callback( GtkWidget *WXUNUSED(widget), wxGLCanvas *win )
198 {
199     if ( !win->m_glContext )
200     {
201         wxGLContext *share = win->m_sharedContext;
202         if ( !share && win->m_sharedContextOf )
203             share = win->m_sharedContextOf->GetContext();
204 
205         win->m_glContext = new wxGLContext( TRUE, win, wxNullPalette, share );
206     }
207 
208     return FALSE;
209 }
210 }
211 
212 //-----------------------------------------------------------------------------
213 // "map" from m_wxwindow
214 //-----------------------------------------------------------------------------
215 
216 extern "C" {
217 static gint
gtk_glwindow_map_callback(GtkWidget * WXUNUSED (widget),wxGLCanvas * win)218 gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
219 {
220     if (win->m_glContext/* && win->m_exposed*/)
221     {
222         wxPaintEvent event( win->GetId() );
223         event.SetEventObject( win );
224         win->GetEventHandler()->ProcessEvent( event );
225 
226         win->m_exposed = false;
227         win->GetUpdateRegion().Clear();
228     }
229 
230     return FALSE;
231 }
232 }
233 
234 //-----------------------------------------------------------------------------
235 // "expose_event" of m_wxwindow
236 //-----------------------------------------------------------------------------
237 
238 extern "C" {
239 static void
gtk_glwindow_expose_callback(GtkWidget * WXUNUSED (widget),GdkEventExpose * gdk_event,wxGLCanvas * win)240 gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
241 {
242     if (g_isIdle)
243         wxapp_install_idle_handler();
244 
245     win->m_exposed = true;
246 
247     win->GetUpdateRegion().Union( gdk_event->area.x,
248                                   gdk_event->area.y,
249                                   gdk_event->area.width,
250                                   gdk_event->area.height );
251 }
252 }
253 
254 //-----------------------------------------------------------------------------
255 // "draw" of m_wxwindow
256 //-----------------------------------------------------------------------------
257 
258 extern "C" {
259 static void
gtk_glwindow_draw_callback(GtkWidget * WXUNUSED (widget),GdkRectangle * rect,wxGLCanvas * win)260 gtk_glwindow_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxGLCanvas *win )
261 {
262     if (g_isIdle)
263         wxapp_install_idle_handler();
264 
265     win->m_exposed = true;
266 
267     win->GetUpdateRegion().Union( rect->x, rect->y,
268                                   rect->width, rect->height );
269 }
270 }
271 
272 //-----------------------------------------------------------------------------
273 // "size_allocate" of m_wxwindow
274 //-----------------------------------------------------------------------------
275 
276 extern "C" {
277 static void
gtk_glcanvas_size_callback(GtkWidget * WXUNUSED (widget),GtkAllocation * alloc,wxGLCanvas * win)278 gtk_glcanvas_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxGLCanvas *win )
279 {
280     if (g_isIdle)
281         wxapp_install_idle_handler();
282 
283     if (!win->m_hasVMT)
284         return;
285 
286     wxSizeEvent event( wxSize(win->m_width,win->m_height), win->GetId() );
287     event.SetEventObject( win );
288     win->GetEventHandler()->ProcessEvent( event );
289 }
290 }
291 
292 //---------------------------------------------------------------------------
293 // wxGlCanvas
294 //---------------------------------------------------------------------------
295 
IMPLEMENT_CLASS(wxGLCanvas,wxWindow)296 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
297 
298 BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
299     EVT_SIZE(wxGLCanvas::OnSize)
300 END_EVENT_TABLE()
301 
302 wxGLCanvas::wxGLCanvas( wxWindow *parent, wxWindowID id,
303                         const wxPoint& pos, const wxSize& size,
304                         long style, const wxString& name,
305                         int *attribList,
306                         const wxPalette& palette )
307 {
308     Create( parent, NULL, NULL, id, pos, size, style, name, attribList, palette );
309 }
310 
wxGLCanvas(wxWindow * parent,const wxGLContext * shared,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name,int * attribList,const wxPalette & palette)311 wxGLCanvas::wxGLCanvas( wxWindow *parent,
312                         const wxGLContext *shared,
313                         wxWindowID id,
314                         const wxPoint& pos, const wxSize& size,
315                         long style, const wxString& name,
316                         int *attribList,
317                         const wxPalette& palette )
318 {
319     Create( parent, shared, NULL, id, pos, size, style, name, attribList, palette );
320 }
321 
wxGLCanvas(wxWindow * parent,const wxGLCanvas * shared,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name,int * attribList,const wxPalette & palette)322 wxGLCanvas::wxGLCanvas( wxWindow *parent,
323                         const wxGLCanvas *shared,
324                         wxWindowID id,
325                         const wxPoint& pos, const wxSize& size,
326                         long style, const wxString& name,
327                         int *attribList,
328                         const wxPalette& palette )
329 {
330     Create( parent, NULL, shared, id, pos, size, style, name, attribList, palette );
331 }
332 
Create(wxWindow * parent,const wxGLContext * shared,const wxGLCanvas * shared_context_of,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name,int * attribList,const wxPalette & palette)333 bool wxGLCanvas::Create( wxWindow *parent,
334                          const wxGLContext *shared,
335                          const wxGLCanvas *shared_context_of,
336                          wxWindowID id,
337                          const wxPoint& pos, const wxSize& size,
338                          long style, const wxString& name,
339                          int *attribList,
340                          const wxPalette& palette)
341 {
342     m_sharedContext = (wxGLContext*)shared;  // const_cast
343     m_sharedContextOf = (wxGLCanvas*)shared_context_of;  // const_cast
344     m_glContext = (wxGLContext*) NULL;
345 
346     m_exposed = false;
347     m_noExpose = true;
348     m_nativeSizeEvent = true;
349     m_fbc = NULL;
350     m_vi = NULL;
351 
352     // to be sure the glx version is known
353     wxGLCanvas::QueryGLXVersion();
354 
355     if (wxGLCanvas::GetGLXVersion() >= 13)
356     {
357         // GLX >= 1.3 uses a GLXFBConfig
358         GLXFBConfig * fbc = NULL;
359         if (wxTheApp->m_glFBCInfo != NULL)
360         {
361             fbc = (GLXFBConfig *) wxTheApp->m_glFBCInfo;
362             m_canFreeFBC = false; // owned by wxTheApp - don't free upon destruction
363         }
364         else
365         {
366             fbc = (GLXFBConfig *) wxGLCanvas::ChooseGLFBC(attribList);
367             m_canFreeFBC = true;
368         }
369         m_fbc = fbc;  // save for later use
370         wxCHECK_MSG( m_fbc, false, _T("required FBConfig couldn't be found") );
371     }
372 
373     XVisualInfo *vi = NULL;
374     if (wxTheApp->m_glVisualInfo != NULL)
375     {
376         vi = (XVisualInfo *)wxTheApp->m_glVisualInfo;
377         m_canFreeVi = false; // owned by wxTheApp - don't free upon destruction
378     }
379     else
380     {
381         if (wxGLCanvas::GetGLXVersion() >= 13)
382         // GLX >= 1.3
383             vi = glXGetVisualFromFBConfig(GDK_DISPLAY(), m_fbc[0]);
384         else
385             // GLX <= 1.2
386             vi = (XVisualInfo *) ChooseGLVisual(attribList);
387 
388         m_canFreeVi = true;
389     }
390 
391     m_vi = vi;  // save for later use
392 
393     wxCHECK_MSG( m_vi, false, _T("required visual couldn't be found") );
394     GdkVisual *visual;
395     GdkColormap *colormap;
396 
397     // MR: This needs a fix for lower gtk+ versions too. Might need to rethink logic (FIXME)
398 #if 0
399     if (!gtk_check_version(2,2,0))
400     {
401         wxWindow::Create( parent, id, pos, size, style, name );
402 
403         m_glWidget = m_wxwindow;
404 
405         GdkScreen *screen = gtk_widget_get_screen( m_glWidget );
406         colormap = gdk_screen_get_default_colormap(screen);
407         visual = gdk_colormap_get_visual(colormap);
408 
409         if (GDK_VISUAL_XVISUAL(visual)->visualid != vi->visualid)
410         {
411             visual = gdk_x11_screen_lookup_visual( screen, vi->visualid );
412             colormap = gdk_colormap_new(visual, FALSE);
413         }
414 
415         gtk_widget_set_colormap( m_glWidget, colormap );
416     }
417     else
418 #endif
419     {
420         visual = gdkx_visual_get( vi->visualid );
421         colormap = gdk_colormap_new( visual, TRUE );
422 
423         gtk_widget_push_colormap( colormap );
424         gtk_widget_push_visual( visual );
425 
426         wxWindow::Create( parent, id, pos, size, style, name );
427         m_glWidget = m_wxwindow;
428     }
429 
430     gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow), FALSE );
431 
432     gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
433                             GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback), (gpointer) this );
434 
435     gtk_signal_connect( GTK_OBJECT(m_wxwindow), "map",
436                             GTK_SIGNAL_FUNC(gtk_glwindow_map_callback), (gpointer) this );
437 
438     gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
439         GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback), (gpointer)this );
440 
441     gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
442         GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback), (gpointer)this );
443 
444     gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
445         GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback), (gpointer)this );
446 
447     gtk_widget_pop_visual();
448     gtk_widget_pop_colormap();
449 
450     // if our parent window is already visible, we had been realized before we
451     // connected to the "realize" signal and hence our m_glContext hasn't been
452     // initialized yet and we have to do it now
453     if (GTK_WIDGET_REALIZED(m_wxwindow))
454         gtk_glwindow_realized_callback( m_wxwindow, this );
455 
456     if (GTK_WIDGET_MAPPED(m_wxwindow))
457         gtk_glwindow_map_callback( m_wxwindow, this );
458 
459     return true;
460 }
461 
~wxGLCanvas()462 wxGLCanvas::~wxGLCanvas()
463 {
464     GLXFBConfig * fbc = (GLXFBConfig *) m_fbc;
465     if (fbc && m_canFreeFBC)
466         XFree( fbc );
467 
468     XVisualInfo *vi = (XVisualInfo *) m_vi;
469     if (vi && m_canFreeVi)
470         XFree( vi );
471 
472     delete m_glContext;
473 }
474 
ChooseGLVisual(int * attribList)475 void* wxGLCanvas::ChooseGLVisual(int *attribList)
476 {
477     int data[512];
478     GetGLAttribListFromWX( attribList, data );
479     attribList = (int*) data;
480 
481     Display *dpy = GDK_DISPLAY();
482 
483     return glXChooseVisual( dpy, DefaultScreen(dpy), attribList );
484 }
485 
ChooseGLFBC(int * attribList)486 void* wxGLCanvas::ChooseGLFBC(int *attribList)
487 {
488     int data[512];
489     GetGLAttribListFromWX( attribList, data );
490     attribList = (int*) data;
491 
492     int returned;
493     return glXChooseFBConfig( GDK_DISPLAY(), DefaultScreen(GDK_DISPLAY()),
494                               attribList, &returned );
495 }
496 
497 
GetGLAttribListFromWX(int * wx_attribList,int * gl_attribList)498 void wxGLCanvas::GetGLAttribListFromWX(int *wx_attribList, int *gl_attribList )
499 {
500     if (!wx_attribList)
501     {
502         if (wxGLCanvas::GetGLXVersion() >= 13)
503         // leave GLX >= 1.3 choose the default attributes
504             gl_attribList[0] = 0;
505         else
506         {
507             int i = 0;
508             // default settings if attriblist = 0
509             gl_attribList[i++] = GLX_RGBA;
510             gl_attribList[i++] = GLX_DOUBLEBUFFER;
511             gl_attribList[i++] = GLX_DEPTH_SIZE;   gl_attribList[i++] = 1;
512             gl_attribList[i++] = GLX_RED_SIZE;     gl_attribList[i++] = 1;
513             gl_attribList[i++] = GLX_GREEN_SIZE;   gl_attribList[i++] = 1;
514             gl_attribList[i++] = GLX_BLUE_SIZE;    gl_attribList[i++] = 1;
515             gl_attribList[i++] = GLX_ALPHA_SIZE;   gl_attribList[i++] = 0;
516             gl_attribList[i++] = None;
517         }
518     }
519     else
520     {
521         int arg=0, p=0;
522         while( (wx_attribList[arg]!=0) && (p<510) )
523         {
524             switch( wx_attribList[arg++] )
525             {
526                 case WX_GL_RGBA:
527                     if (wxGLCanvas::GetGLXVersion() <= 12)
528                         // for GLX >= 1.3, GLX_RGBA is useless (setting this flags will crash on most opengl implm)
529                         gl_attribList[p++] = GLX_RGBA;
530                     break;
531                 case WX_GL_BUFFER_SIZE:
532                     gl_attribList[p++] = GLX_BUFFER_SIZE;
533                     gl_attribList[p++] = wx_attribList[arg++];
534                     break;
535                 case WX_GL_LEVEL:
536                     gl_attribList[p++] = GLX_LEVEL;
537                     gl_attribList[p++] = wx_attribList[arg++];
538                     break;
539                 case WX_GL_DOUBLEBUFFER:
540                     if (wxGLCanvas::GetGLXVersion() <= 12)
541                         gl_attribList[p++] = GLX_DOUBLEBUFFER;
542                     else
543                         // for GLX >= 1.3, GLX_DOUBLEBUFFER format is different (1 <=> True)
544                         // it seems this flag is useless for some hardware opengl implementation.
545                         // but for Mesa 6.2.1, this flag is used so don't ignore it.
546                         gl_attribList[p++] = GLX_DOUBLEBUFFER;
547                     gl_attribList[p++] = 1;
548                     break;
549                 case WX_GL_STEREO:
550                     gl_attribList[p++] = GLX_STEREO;
551                     gl_attribList[p++] = 1;
552                     break;
553                 case WX_GL_AUX_BUFFERS:
554                     gl_attribList[p++] = GLX_AUX_BUFFERS;
555                     gl_attribList[p++] = wx_attribList[arg++];
556                     break;
557                 case WX_GL_MIN_RED:
558                     gl_attribList[p++] = GLX_RED_SIZE;
559                     gl_attribList[p++] = wx_attribList[arg++];
560                     break;
561                 case WX_GL_MIN_GREEN:
562                     gl_attribList[p++] = GLX_GREEN_SIZE;
563                     gl_attribList[p++] = wx_attribList[arg++];
564                     break;
565                 case WX_GL_MIN_BLUE:
566                     gl_attribList[p++] = GLX_BLUE_SIZE;
567                     gl_attribList[p++] = wx_attribList[arg++];
568                     break;
569                 case WX_GL_MIN_ALPHA:
570                     gl_attribList[p++] = GLX_ALPHA_SIZE;
571                     gl_attribList[p++] = wx_attribList[arg++];
572                     break;
573                 case WX_GL_DEPTH_SIZE:
574                     gl_attribList[p++] = GLX_DEPTH_SIZE;
575                     gl_attribList[p++] = wx_attribList[arg++];
576                     break;
577                 case WX_GL_STENCIL_SIZE:
578                     gl_attribList[p++] = GLX_STENCIL_SIZE;
579                     gl_attribList[p++] = wx_attribList[arg++];
580                     break;
581                 case WX_GL_MIN_ACCUM_RED:
582                     gl_attribList[p++] = GLX_ACCUM_RED_SIZE;
583                     gl_attribList[p++] = wx_attribList[arg++];
584                     break;
585                 case WX_GL_MIN_ACCUM_GREEN:
586                     gl_attribList[p++] = GLX_ACCUM_GREEN_SIZE;
587                     gl_attribList[p++] = wx_attribList[arg++];
588                     break;
589                 case WX_GL_MIN_ACCUM_BLUE:
590                     gl_attribList[p++] = GLX_ACCUM_BLUE_SIZE;
591                     gl_attribList[p++] = wx_attribList[arg++];
592                     break;
593                 case WX_GL_MIN_ACCUM_ALPHA:
594                     gl_attribList[p++] = GLX_ACCUM_ALPHA_SIZE;
595                     gl_attribList[p++] = wx_attribList[arg++];
596                     break;
597                 default:
598                     break;
599             }
600         }
601 
602         gl_attribList[p] = 0;
603     }
604 }
605 
QueryGLXVersion()606 void wxGLCanvas::QueryGLXVersion()
607 {
608     if (m_glxVersion == 0)
609     {
610         // check the GLX version
611         int glxMajorVer, glxMinorVer;
612         bool ok = glXQueryVersion(GDK_DISPLAY(), &glxMajorVer, &glxMinorVer);
613         wxASSERT_MSG( ok, _T("GLX version not found") );
614         if (!ok)
615             m_glxVersion = 10; // 1.0 by default
616         else
617             m_glxVersion = glxMajorVer*10 + glxMinorVer;
618     }
619 }
620 
GetGLXVersion()621 int wxGLCanvas::GetGLXVersion()
622 {
623     wxASSERT_MSG( m_glxVersion>0, _T("GLX version has not been initialized with wxGLCanvas::QueryGLXVersion()") );
624     return m_glxVersion;
625 }
626 
627 
SwapBuffers()628 void wxGLCanvas::SwapBuffers()
629 {
630     if (m_glContext)
631         m_glContext->SwapBuffers();
632 }
633 
OnSize(wxSizeEvent & WXUNUSED (event))634 void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
635 {
636 }
637 
SetCurrent()638 void wxGLCanvas::SetCurrent()
639 {
640     if (m_glContext)
641         m_glContext->SetCurrent();
642 }
643 
SetColour(const wxChar * colour)644 void wxGLCanvas::SetColour( const wxChar *colour )
645 {
646     if (m_glContext)
647         m_glContext->SetColour( colour );
648 }
649 
OnInternalIdle()650 void wxGLCanvas::OnInternalIdle()
651 {
652     if (m_glContext && m_exposed)
653     {
654         wxPaintEvent event( GetId() );
655         event.SetEventObject( this );
656         GetEventHandler()->ProcessEvent( event );
657 
658         m_exposed = false;
659         GetUpdateRegion().Clear();
660     }
661 
662     wxWindow::OnInternalIdle();
663 }
664 
665 
666 
667 //---------------------------------------------------------------------------
668 // wxGLApp
669 //---------------------------------------------------------------------------
670 
IMPLEMENT_CLASS(wxGLApp,wxApp)671 IMPLEMENT_CLASS(wxGLApp, wxApp)
672 
673 wxGLApp::~wxGLApp()
674 {
675     if (m_glFBCInfo)
676         XFree(m_glFBCInfo);
677     if (m_glVisualInfo)
678         XFree(m_glVisualInfo);
679 }
680 
InitGLVisual(int * attribList)681 bool wxGLApp::InitGLVisual(int *attribList)
682 {
683     wxGLCanvas::QueryGLXVersion();
684 
685     if (wxGLCanvas::GetGLXVersion() >= 13)
686     {
687         // GLX >= 1.3
688         if (m_glFBCInfo)
689             XFree(m_glFBCInfo);
690         m_glFBCInfo = wxGLCanvas::ChooseGLFBC(attribList);
691 
692         if (m_glFBCInfo)
693         {
694             if (m_glVisualInfo)
695                 XFree(m_glVisualInfo);
696             m_glVisualInfo = glXGetVisualFromFBConfig(GDK_DISPLAY(), ((GLXFBConfig *)m_glFBCInfo)[0]);
697         }
698         return (m_glFBCInfo != NULL) && (m_glVisualInfo != NULL);
699     }
700     else
701     {
702         // GLX <= 1.2
703         if (m_glVisualInfo)
704             XFree(m_glVisualInfo);
705         m_glVisualInfo = wxGLCanvas::ChooseGLVisual(attribList);
706         return m_glVisualInfo != NULL;
707     }
708 }
709 
710 #endif
711     // wxUSE_GLCANVAS
712