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