From b7ea712cc26f4289211f4a24e308f40ff6445991 Mon Sep 17 00:00:00 2001
From: Robert Roebling <robert@roebling.de>
Date: Wed, 6 Sep 2006 13:31:20 +0000
Subject: [PATCH]   Commit Carsten Fuchs' patch for separating wxGLCanvas    
 and wxGLContext on GTK and MSW.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41031 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/glcanvas.tex  |  69 ++++++++--
 docs/latex/wx/glcontext.tex |  53 ++++----
 include/wx/gtk/glcanvas.h   |  53 ++++----
 include/wx/msw/glcanvas.h   |  42 +++---
 src/gtk/glcanvas.cpp        | 133 ++++++-------------
 src/msw/glcanvas.cpp        | 251 +++++++-----------------------------
 6 files changed, 213 insertions(+), 388 deletions(-)

diff --git a/docs/latex/wx/glcanvas.tex b/docs/latex/wx/glcanvas.tex
index af29c1f49e..6850918ac1 100644
--- a/docs/latex/wx/glcanvas.tex
+++ b/docs/latex/wx/glcanvas.tex
@@ -3,15 +3,25 @@
 wxGLCanvas is a class for displaying OpenGL graphics. There are
 wrappers for OpenGL on Windows, and GTK+ and Motif.
 
-To use this class, create a wxGLCanvas window, call \helpref{wxGLCanvas::SetCurrent}{wxglcanvassetcurrent} 
+There are two ways to use this class:
+
+For the older (before wx 2.7.x) and simpler method, create a wxGLCanvas window using one of the three
+constructors that implicitly create a rendering context, call \helpref{wxGLCanvas::SetCurrent}{wxglcanvassetcurrent} 
 to direct normal OpenGL commands to the window, and then call \helpref{wxGLCanvas::SwapBuffers}{wxglcanvasswapbuffers} 
 to show the OpenGL buffer on the window.
 
-To set up the attributes for the rendering context (number of bits for the depth buffer,
+For the newer (wx 2.7.x+) method, create a wxGLCanvas window using the constructor that does \emph{not} create an implicit rendering context,
+create an explicit instance of a \helpref{wxGLContext}{wxglcontext} that is initialized with the wxGLCanvas yourself,
+then use either \helpref{wxGLCanvas::SetCurrent}{wxglcanvassetcurrent_rc} with the instance of the \helpref{wxGLContext}{wxglcontext}
+or \helpref{wxGLContext::SetCurrent}{wxglcontextsetcurrent} with the instance of the \helpref{wxGLCanvas}{wxglcanvas}
+to bind the OpenGL state that is represented by the rendering context to the canvas, and then call
+\helpref{wxGLCanvas::SwapBuffers}{wxglcanvasswapbuffers} to swap the buffers of the OpenGL canvas and thus show your current output.
+
+To set up the attributes for the canvas (number of bits for the depth buffer,
 number of bits for the stencil buffer and so on) you should set up the correct values of
 the {\it attribList} parameter. The values that should be set up and their meanings will be described below.
 
-To switch wxGLCanvas support on under Windows, edit setup.h and set
+To switch on wxGLCanvas support on under Windows, edit setup.h and set
 {\tt wxUSE\_GLCANVAS} to $1$. You may also need to have to add
 {\tt opengl32.lib} to the list of libraries your program is linked with. On
 Unix, pass {\tt --with-opengl} to configure to compile using OpenGL or Mesa.
@@ -81,7 +91,24 @@ alpha channel, and accum buffer. Other implementations may support them.
  \param{long}{ style=0}, \param{const wxString\& }{name="GLCanvas"},
  \param{int*}{ attribList = 0}, \param{const wxPalette\&}{ palette = wxNullPalette}}
 
-Constructor.
+\func{void}{wxGLCanvas}{\param{wxWindow* }{parent}, \param{wxWindowID}{ id = wxID_ANY},
+ \param{int*}{ attribList = 0},
+ \param{const wxPoint\&}{ pos = wxDefaultPosition}, \param{const wxSize\&}{ size = wxDefaultSize},
+ \param{long}{ style=0}, \param{const wxString\& }{name="GLCanvas"},
+ \param{const wxPalette\&}{ palette = wxNullPalette}}
+
+Constructors.
+The first three constructors implicitly create an instance of \helpref{wxGLContext}{wxglcontext}.
+The fourth constructur is identical to the first, except for the fact that it does \emph{not}
+create such an implicit rendering context, which means that you have to create an explicit instance
+of \helpref{wxGLContext}{wxglcontext} yourself (highly recommended for future compatibility with wxWidgets
+and the flexibility of your own program!).
+
+Note that if you used one of the first three constructors, \helpref{wxGLCanvas::GetContext}{wxglcanvasgetcontext}
+returns the pointer to the implicitly created instance, and the \helpref{wxGLCanvas::SetCurrent}{wxglcanvassetcurrent}
+method \emph{without} the parameter should be used.
+If however you used the fourth constructor, \helpref{wxGLCanvas::GetContext}{wxglcanvasgetcontext} always returns NULL
+and the \helpref{wxGLCanvas::SetCurrent}{wxglcanvassetcurrent_rc} method \emph{with} the parameter must be used!
 
 \docparam{parent}{Pointer to a parent window.}
 
@@ -121,19 +148,37 @@ Note: palette and WX\_GL\_RGBA are mutually exclusive.}
 
 \func{wxGLContext*}{GetContext}{\void}
 
-Obtains the context that is associated with this canvas.
+Obtains the context that is associated with this canvas if one was implicitly created (by use of one of the first three constructors).
+Always returns NULL if the canvas was constructed with the fourth constructor.
 
 
 \membersection{wxGLCanvas::SetCurrent}\label{wxglcanvassetcurrent}
 
 \func{void}{SetCurrent}{\void}
 
-Sets this canvas as the current recipient of OpenGL calls.
-Each canvas contains an OpenGL device context that has been created during
-the creation of this window. So this call sets the current device context
-as the target device context for OpenGL operations.
+If this canvas was created with one of the first three constructors,
+a call to this method makes the implicit rendering context of this canvas current with this canvas,
+so that subsequent OpenGL calls modify the OpenGL state of the implicit rendering context.
+
+If this canvas was created with the fourth constructor, this method should not be called
+(use the SetCurrent method below with the parameter instead)!
 
-Note that this function may only be called after the window has been shown.
+Note that this function may only be called \emph{after} the window has been shown.
+
+
+\membersection{wxGLCanvas::SetCurrent}\label{wxglcanvassetcurrent_rc}
+
+\func{void}{SetCurrent}{ \param{const wxGLContext&}{ RC} }
+
+If this canvas was created with one of the first three constructors,
+this method should not be called (use the SetCurrent above without the parameter instead)!
+
+If this canvas was created with the fourth constructor, a call to this method
+makes the OpenGL state that is represented by the OpenGL rendering context { \it RC } current with this canvas,
+and if { \it win } is an object of type wxGLCanvas, the statements { \it win.SetCurrent(RC); } and { \it RC.SetCurrent(win); } are equivalent,
+see \helpref{wxGLContext::SetCurrent}{wxglcontextsetcurrent}.
+
+Note that this function may only be called \emph{after} the window has been shown.
 
 
 \membersection{wxGLCanvas::SetColour}\label{wxglcanvassetcolour}
@@ -147,5 +192,5 @@ Sets the current colour for this window, using the wxWidgets colour database to
 
 \func{void}{SwapBuffers}{\void}
 
-Displays the previous OpenGL commands on the window.
-
+Swaps the double-buffer of this window, making the back-buffer the front-buffer and vice versa,
+so that the output of the previous OpenGL commands is displayed on the window.
diff --git a/docs/latex/wx/glcontext.tex b/docs/latex/wx/glcontext.tex
index f2c4b1c33f..692288e9ac 100644
--- a/docs/latex/wx/glcontext.tex
+++ b/docs/latex/wx/glcontext.tex
@@ -1,10 +1,17 @@
 \section{\class{wxGLContext}}\label{wxglcontext}
 
-wxGLContext is a class for sharing OpenGL data resources, such as display lists, with another \helpref{wxGLCanvas}{wxglcanvas}.
+An instance of a wxGLContext represents the state of an OpenGL state machine and the connection between OpenGL and the system.
 
-By sharing data resources, you can prevent code duplication, save memory, and ultimately help optimize your application.
+The OpenGL state includes everything that can be set with the OpenGL API: colors, rendering variables, display lists, texture objects, etc.
+Although it is possible to have multiple rendering contexts share display lists in order to save resources,
+this method is hardly used today any more, because display lists are only a tiny fraction of the overall state.
 
-As an example, let's say you want to draw a ball on two different windows that is identical on each one, but the dimensions of one is slightly different than the other one.  What you would do is create your display lists in the shared context, and then translate each ball on the individual canvas's context.  This way the actual data for the ball is only created once (in the shared context), and you won't have to duplicate your development efforts on the second ball.
+Therefore, one rendering context is usually used with or bound to multiple output windows in turn,
+so that the application has access to the \emph{complete and identical} state while rendering into each window.
+
+Binding (making current) a rendering context with another instance of a wxGLCanvas however works only
+if the other wxGLCanvas was created with the same attributes as the wxGLCanvas from which the wxGLContext
+was initialized. (This applies to sharing display lists among contexts analogously.)
 
 Note that some wxGLContext features are extremely platform-specific - its best to check your native platform's glcanvas header (on windows include/wx/msw/glcanvas.h) to see what features your native platform provides.
 
@@ -22,41 +29,27 @@ Note that some wxGLContext features are extremely platform-specific - its best t
 
 \latexignore{\rtfignore{\wxheading{Members}}}
 
-\membersection{wxGLContext::wxGLContext}\label{wxglcontextconstr}
 
-\func{void}{wxGLContext}{\param{bool }{isRGB}, \param{wxGLCanvas*}{ win}, \param{const wxPalette\&}{ palette = wxNullPalette}}
+\membersection{wxGLContext::wxGLContext}\label{wxglcontextconstr}
 
-\func{void}{wxGLContext}{\param{bool }{isRGB}, \param{wxGLCanvas*}{ win}, \param{const wxPalette\&}{ palette = wxNullPalette},
- \param{const wxGLContext*}{ other}}
+\func{ }{wxGLContext}{ \param{wxGLCanvas*}{ win}, \param{const wxGLContext*}{ other=NULL} }
 
-\docparam{win}{Canvas to associate this shared context with.}
+Constructor.
 
-\docparam{other}{Context to share data resources with.}
+\docparam{win}{The canvas that is used to initialize this context. This parameter is needed only temporarily,
+and the caller may do anything with it (e.g. destroy the window) after the constructor returned.
 
-\membersection{wxGLContext::GetWindow}\label{wxglcontextgetwindow}
+It will be possible to bind (make current) this context to any other wxGLCanvas that has been created
+with equivalent attributes as {\it win}.}
 
-\func{const wxWindow*}{GetWindow}{\void}
+\docparam{other}{Context to share display lists with or NULL (the default) for no sharing.}
 
-Obtains the window that is associated with this context.
 
 \membersection{wxGLContext::SetCurrent}\label{wxglcontextsetcurrent}
 
-\func{void}{SetCurrent}{\void}
-
-Sets this context as the current recipient of OpenGL calls.
-Each context contains an OpenGL device context that has been created during
-the creation of this window. So this call sets the current device context
-as the target device context for OpenGL operations.
-
-\membersection{wxGLContext::SetColour}\label{wxglcontextsetcolour}
-
-\func{void}{SetColour}{\param{const char*}{ colour}}
-
-Sets the current colour for this context, using the wxWidgets colour database to find a named colour.
-
-\membersection{wxGLContext::SwapBuffers}\label{wxglcontextswapbuffers}
-
-\func{void}{SwapBuffers}{\void}
-
-Displays the previous OpenGL commands on the associated window.
+\func{void}{SetCurrent}{\param{const wxGLCanvas&}{ win}}
 
+Makes the OpenGL state that is represented by this rendering context current with the wxGLCanvas {\it win}.
+Note that {\it win} can be a different wxGLCanvas window than the one that was passed to the constructor of this rendering context.
+If { \it RC } is an object of type wxGLContext, the statements { \it RC.SetCurrent(win); } and { \it win.SetCurrent(RC); } are equivalent,
+see \helpref{wxGLCanvas::SetCurrent}{wxglcanvassetcurrent_rc}.
diff --git a/include/wx/gtk/glcanvas.h b/include/wx/gtk/glcanvas.h
index 1dd9dd5d6f..31dd8b6749 100644
--- a/include/wx/gtk/glcanvas.h
+++ b/include/wx/gtk/glcanvas.h
@@ -60,36 +60,19 @@ class WXDLLEXPORT wxGLCanvas;
 class WXDLLEXPORT wxGLContext: public wxObject
 {
 public:
-    wxGLContext( bool isRGB, wxWindow *win, const wxPalette& palette = wxNullPalette );
-    wxGLContext(
-               bool WXUNUSED(isRGB), wxWindow *win,
-               const wxPalette& WXUNUSED(palette),
-               const wxGLContext *other        /* for sharing display lists */
-    );
+    wxGLContext(wxWindow* win, const wxGLContext* other=NULL /* for sharing display lists */);
     virtual ~wxGLContext();
 
-    void SetCurrent();
-    void SetColour(const wxChar *colour);
-    void SwapBuffers();
-
-    void SetupPixelFormat();
-    void SetupPalette(const wxPalette& palette);
-    wxPalette CreateDefaultPalette();
-
-    inline wxPalette* GetPalette() const { return (wxPalette*) & m_palette; }
-    inline wxWindow* GetWindow() const { return m_window; }
-    inline GtkWidget* GetWidget() const { return m_widget; }
-    inline GLXContext GetContext() const { return m_glContext; }
-
 public:
-   GLXContext       m_glContext;
+    // The win wxGLCanvas needs not necessarily be the same as the wxGLCanvas with which this context was created!
+    void SetCurrent(const wxGLCanvas& win) const;
 
-   GtkWidget       *m_widget;
-   wxPalette        m_palette;
-   wxWindow*        m_window;
 
 private:
-  DECLARE_CLASS(wxGLContext)
+    GLXContext m_glContext;
+
+private:
+    DECLARE_CLASS(wxGLContext)
 };
 
 //---------------------------------------------------------------------------
@@ -99,19 +82,23 @@ private:
 class WXDLLEXPORT wxGLCanvas: public wxWindow
 {
 public:
-   inline wxGLCanvas() {
-      m_glContext = (wxGLContext*) NULL;
-      m_sharedContext = (wxGLContext*) NULL;
-      m_glWidget = (GtkWidget*) NULL;
-      m_vi = (void*) NULL;
-      m_exposed = FALSE;
-   }
+    // This ctor is identical to the next, except for the fact that it
+    // doesn't create an implicit wxGLContext.
+    // The attribList parameter has been moved to avoid overload clashes.
+    wxGLCanvas( wxWindow *parent, wxWindowID id = -1,
+        int *attribList = (int*) NULL,
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize,
+        long style = 0, const wxString& name = wxGLCanvasName,
+        const wxPalette& palette = wxNullPalette );
+
    wxGLCanvas( wxWindow *parent, wxWindowID id = -1,
         const wxPoint& pos = wxDefaultPosition,
         const wxSize& size = wxDefaultSize,
         long style = 0, const wxString& name = wxGLCanvasName,
         int *attribList = (int*) NULL,
         const wxPalette& palette = wxNullPalette );
+
    wxGLCanvas( wxWindow *parent, const wxGLContext *shared,
         wxWindowID id = -1,
         const wxPoint& pos = wxDefaultPosition,
@@ -119,6 +106,7 @@ public:
         long style = 0, const wxString& name = wxGLCanvasName,
         int *attribList = (int*) NULL,
         const wxPalette& palette = wxNullPalette );
+
    wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared,
         wxWindowID id = -1,
         const wxPoint& pos = wxDefaultPosition,
@@ -140,6 +128,7 @@ public:
 
    virtual ~wxGLCanvas();
 
+   void SetCurrent(const wxGLContext& RC) const;
    void SetCurrent();
    void SetColour(const wxChar *colour);
    void SwapBuffers();
@@ -155,6 +144,7 @@ public:
     wxGLContext      *m_glContext,
                      *m_sharedContext;
     wxGLCanvas       *m_sharedContextOf;
+    const bool        m_createImplicitContext;
     void             *m_vi; // actually an XVisualInfo*
     GLXFBConfig      *m_fbc;
     bool              m_canFreeVi;
@@ -173,6 +163,7 @@ public:
     static void QueryGLXVersion();
     static int GetGLXVersion();
     static int m_glxVersion;
+    
 private:
     DECLARE_EVENT_TABLE()
     DECLARE_CLASS(wxGLCanvas)
diff --git a/include/wx/msw/glcanvas.h b/include/wx/msw/glcanvas.h
index 6cfa954599..c25634410e 100644
--- a/include/wx/msw/glcanvas.h
+++ b/include/wx/msw/glcanvas.h
@@ -53,38 +53,31 @@ class WXDLLIMPEXP_GL wxGLCanvas;     /* forward reference */
 class WXDLLIMPEXP_GL wxGLContext: public wxObject
 {
 public:
-    wxGLContext(bool isRGB, wxGLCanvas *win, const wxPalette& palette = wxNullPalette);
-
-    wxGLContext( bool isRGB, wxGLCanvas *win,
-        const wxPalette& WXUNUSED(palette),
-        const wxGLContext *other /* for sharing display lists */ );
-
+    wxGLContext(wxGLCanvas *win, const wxGLContext* other=NULL /* for sharing display lists */ );
     virtual ~wxGLContext();
 
-
-    void SetCurrent();
-
-    void SetColour(const wxChar *colour);
-
-    void SwapBuffers();
-
-
-    inline wxWindow* GetWindow() const { return m_window; }
-
-    inline WXHDC GetHDC() const { return m_hDC; }
-
     inline HGLRC GetGLRC() const { return m_glContext; }
 
-public:
-    HGLRC            m_glContext;
-    WXHDC            m_hDC;
-    wxWindow*        m_window;
+protected:
+    HGLRC m_glContext;
+
+private:
+    DECLARE_CLASS(wxGLContext)
 };
 
 class WXDLLIMPEXP_GL wxGLCanvas: public wxWindow
 {
-    DECLARE_CLASS(wxGLCanvas)
 public:
+    // This ctor is identical to the next, except for the fact that it
+    // doesn't create an implicit wxGLContext.
+    // The attribList parameter has been moved to avoid overload clashes.
+    wxGLCanvas(wxWindow *parent, wxWindowID id = wxID_ANY,
+        int* attribList = 0,
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, long style = 0,
+        const wxString& name = wxGLCanvasName,
+        const wxPalette& palette = wxNullPalette);
+
     wxGLCanvas(wxWindow *parent, wxWindowID id = wxID_ANY,
         const wxPoint& pos = wxDefaultPosition,
         const wxSize& size = wxDefaultSize, long style = 0,
@@ -119,6 +112,7 @@ public:
         const wxPoint& pos, const wxSize& size,
         long style, const wxString& name);
 
+    void SetCurrent(const wxGLContext& RC) const;
     void SetCurrent();
 
 #ifdef __WXUNIVERSAL__
@@ -152,7 +146,9 @@ protected:
     wxPalette      m_palette;
     WXHDC          m_hDC;
 
+private:
     DECLARE_EVENT_TABLE()
+    DECLARE_CLASS(wxGLCanvas)
 };
 
 #endif
diff --git a/src/gtk/glcanvas.cpp b/src/gtk/glcanvas.cpp
index 85d0451334..a373cb8bdf 100644
--- a/src/gtk/glcanvas.cpp
+++ b/src/gtk/glcanvas.cpp
@@ -55,40 +55,8 @@ XVisualInfo *g_vi = (XVisualInfo*) NULL;
 
 IMPLEMENT_CLASS(wxGLContext,wxObject)
 
-wxGLContext::wxGLContext( bool WXUNUSED(isRGB), wxWindow *win, const wxPalette& WXUNUSED(palette) )
+wxGLContext::wxGLContext(wxWindow* win, const wxGLContext* other)
 {
-    m_window = win;
-    m_widget = win->m_wxwindow;
-
-    wxGLCanvas *gc = (wxGLCanvas*) win;
-
-    if (wxGLCanvas::GetGLXVersion() >= 13)
-    {
-        // GLX >= 1.3
-        GLXFBConfig *fbc = gc->m_fbc;
-        wxCHECK_RET( fbc, _T("invalid GLXFBConfig for OpenGl") );
-        m_glContext = glXCreateNewContext( GDK_DISPLAY(), fbc[0], GLX_RGBA_TYPE, None, GL_TRUE );
-    }
-    else
-    {
-        // GLX <= 1.2
-        XVisualInfo *vi = (XVisualInfo *) gc->m_vi;
-        wxCHECK_RET( vi, _T("invalid visual for OpenGl") );
-        m_glContext = glXCreateContext( GDK_DISPLAY(), vi, None, GL_TRUE );
-    }
-
-    wxCHECK_RET( m_glContext, _T("Couldn't create OpenGl context") );
-}
-
-wxGLContext::wxGLContext(
-               bool WXUNUSED(isRGB), wxWindow *win,
-               const wxPalette& WXUNUSED(palette),
-               const wxGLContext *other        /* for sharing display lists */
-)
-{
-    m_window = win;
-    m_widget = win->m_wxwindow;
-
     wxGLCanvas *gc = (wxGLCanvas*) win;
 
     if (wxGLCanvas::GetGLXVersion() >= 13)
@@ -133,55 +101,21 @@ wxGLContext::~wxGLContext()
     glXDestroyContext( GDK_DISPLAY(), m_glContext );
 }
 
-void wxGLContext::SwapBuffers()
-{
-    if (m_glContext)
-    {
-        GdkWindow *window = GTK_PIZZA(m_widget)->bin_window;
-        glXSwapBuffers( GDK_DISPLAY(), GDK_WINDOW_XWINDOW( window ) );
-    }
-}
-
-void wxGLContext::SetCurrent()
+void wxGLContext::SetCurrent(const wxGLCanvas& win) const
 {
     if (m_glContext)
     {
-        GdkWindow *window = GTK_PIZZA(m_widget)->bin_window;
+        GdkWindow *window = GTK_PIZZA(win.m_wxwindow)->bin_window;
 
         if (wxGLCanvas::GetGLXVersion() >= 13)
             // GLX >= 1.3
-            glXMakeContextCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window),
-                                   GDK_WINDOW_XWINDOW(window), m_glContext );
+            glXMakeContextCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window), GDK_WINDOW_XWINDOW(window), m_glContext );
         else
             // GLX <= 1.2
             glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window), m_glContext );
     }
 }
 
-void wxGLContext::SetColour(const wxChar *colour)
-{
-    wxColour col = wxTheColourDatabase->Find(colour);
-    if (col.Ok())
-    {
-        float r = (float)(col.Red()/256.0);
-        float g = (float)(col.Green()/256.0);
-        float b = (float)(col.Blue()/256.0);
-        glColor3f( r, g, b);
-    }
-}
-
-void wxGLContext::SetupPixelFormat()
-{
-}
-
-void wxGLContext::SetupPalette( const wxPalette& WXUNUSED(palette) )
-{
-}
-
-wxPalette wxGLContext::CreateDefaultPalette()
-{
-    return wxNullPalette;
-}
 
 //-----------------------------------------------------------------------------
 // "realize" from m_wxwindow
@@ -191,13 +125,13 @@ extern "C" {
 static gint
 gtk_glwindow_realized_callback( GtkWidget *WXUNUSED(widget), wxGLCanvas *win )
 {
-    if ( !win->m_glContext )
+    if (!win->m_glContext && win->m_createImplicitContext)
     {
         wxGLContext *share = win->m_sharedContext;
         if ( !share && win->m_sharedContextOf )
             share = win->m_sharedContextOf->GetContext();
 
-        win->m_glContext = new wxGLContext( TRUE, win, wxNullPalette, share );
+        win->m_glContext = new wxGLContext(win, share);
     }
 
     return FALSE;
@@ -212,7 +146,8 @@ extern "C" {
 static gint
 gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
 {
-    if (win->m_glContext/* && win->m_exposed*/)
+    // CF: Can the "if" line be removed, and the code unconditionally (always) be run?
+    if (win->m_glContext || !win->m_createImplicitContext)
     {
         wxPaintEvent event( win->GetId() );
         event.SetEventObject( win );
@@ -275,11 +210,22 @@ BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
     EVT_SIZE(wxGLCanvas::OnSize)
 END_EVENT_TABLE()
 
+wxGLCanvas::wxGLCanvas( wxWindow *parent, wxWindowID id,
+                        int *attribList,
+                        const wxPoint& pos, const wxSize& size,
+                        long style, const wxString& name,
+                        const wxPalette& palette )
+    : m_createImplicitContext(false)
+{
+    Create( parent, NULL, NULL, id, pos, size, style, name, attribList, palette );
+}
+
 wxGLCanvas::wxGLCanvas( wxWindow *parent, wxWindowID id,
                         const wxPoint& pos, const wxSize& size,
                         long style, const wxString& name,
                         int *attribList,
                         const wxPalette& palette )
+    : m_createImplicitContext(true)
 {
     Create( parent, NULL, NULL, id, pos, size, style, name, attribList, palette );
 }
@@ -291,6 +237,7 @@ wxGLCanvas::wxGLCanvas( wxWindow *parent,
                         long style, const wxString& name,
                         int *attribList,
                         const wxPalette& palette )
+    : m_createImplicitContext(true)
 {
     Create( parent, shared, NULL, id, pos, size, style, name, attribList, palette );
 }
@@ -302,6 +249,7 @@ wxGLCanvas::wxGLCanvas( wxWindow *parent,
                         long style, const wxString& name,
                         int *attribList,
                         const wxPalette& palette )
+    : m_createImplicitContext(true)
 {
     Create( parent, NULL, shared, id, pos, size, style, name, attribList, palette );
 }
@@ -404,18 +352,10 @@ bool wxGLCanvas::Create( wxWindow *parent,
 
     gtk_widget_set_double_buffered( m_glWidget, FALSE );
 
-    g_signal_connect (m_wxwindow, "realize",
-                      G_CALLBACK (gtk_glwindow_realized_callback),
-                      this);
-    g_signal_connect (m_wxwindow, "map",
-                      G_CALLBACK (gtk_glwindow_map_callback),
-                      this);
-    g_signal_connect (m_wxwindow, "expose_event",
-                      G_CALLBACK (gtk_glwindow_expose_callback),
-                      this);
-    g_signal_connect (m_widget, "size_allocate",
-                      G_CALLBACK (gtk_glcanvas_size_callback),
-                      this);
+    g_signal_connect(m_wxwindow, "realize",       G_CALLBACK(gtk_glwindow_realized_callback), this);
+    g_signal_connect(m_wxwindow, "map",           G_CALLBACK(gtk_glwindow_map_callback),      this);
+    g_signal_connect(m_wxwindow, "expose_event",  G_CALLBACK(gtk_glwindow_expose_callback),   this);
+    g_signal_connect(m_widget,   "size_allocate", G_CALLBACK(gtk_glcanvas_size_callback),     this);
 
     if (gtk_check_version(2,2,0) != NULL)
     {
@@ -601,29 +541,40 @@ int wxGLCanvas::GetGLXVersion()
 
 void wxGLCanvas::SwapBuffers()
 {
-    if (m_glContext)
-        m_glContext->SwapBuffers();
+    GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
+    glXSwapBuffers( GDK_DISPLAY(), GDK_WINDOW_XWINDOW( window ) );
 }
 
 void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
 {
 }
 
+void wxGLCanvas::SetCurrent(const wxGLContext& RC) const
+{
+    RC.SetCurrent(*this);
+}
+
 void wxGLCanvas::SetCurrent()
 {
     if (m_glContext)
-        m_glContext->SetCurrent();
+        m_glContext->SetCurrent(*this);
 }
 
 void wxGLCanvas::SetColour( const wxChar *colour )
 {
-    if (m_glContext)
-        m_glContext->SetColour( colour );
+    wxColour col = wxTheColourDatabase->Find(colour);
+    if (col.Ok())
+    {
+        float r = (float)(col.Red()/256.0);
+        float g = (float)(col.Green()/256.0);
+        float b = (float)(col.Blue()/256.0);
+        glColor3f( r, g, b);
+    }
 }
 
 void wxGLCanvas::OnInternalIdle()
 {
-    if (m_glContext && m_exposed)
+    if (/*m_glContext &&*/ m_exposed)
     {
         wxPaintEvent event( GetId() );
         event.SetEventObject( this );
diff --git a/src/msw/glcanvas.cpp b/src/msw/glcanvas.cpp
index 0f4ee4b78b..64f90c4ef2 100644
--- a/src/msw/glcanvas.cpp
+++ b/src/msw/glcanvas.cpp
@@ -183,73 +183,26 @@ void wxGLModule::UnregisterClasses()
  * GLContext implementation
  */
 
-wxGLContext::wxGLContext(bool WXUNUSED(isRGB), wxGLCanvas *win, const wxPalette& WXUNUSED(palette))
-{
-  m_window = win;
-
-  m_hDC = win->GetHDC();
+IMPLEMENT_CLASS(wxGLContext, wxObject)
 
-  m_glContext = wglCreateContext((HDC) m_hDC);
-  wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGL context") );
-
-  wglMakeCurrent((HDC) m_hDC, m_glContext);
-}
-
-wxGLContext::wxGLContext(
-               bool WXUNUSED(isRGB), wxGLCanvas *win,
-               const wxPalette& WXUNUSED(palette),
-               const wxGLContext *other  /* for sharing display lists */
-             )
+wxGLContext::wxGLContext(wxGLCanvas* win, const wxGLContext* other /* for sharing display lists */)
 {
-  m_window = win;
-
-  m_hDC = win->GetHDC();
-
-  m_glContext = wglCreateContext((HDC) m_hDC);
+  m_glContext = wglCreateContext((HDC) win->GetHDC());
   wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGL context") );
 
   if( other != 0 )
     wglShareLists( other->m_glContext, m_glContext );
-
-  wglMakeCurrent((HDC) m_hDC, m_glContext);
 }
 
 wxGLContext::~wxGLContext()
 {
-  if (m_glContext)
-  {
-    wglMakeCurrent(NULL, NULL);
+    // If this context happens to be the current context, wglDeleteContext() makes it un-current first.
     wglDeleteContext(m_glContext);
-  }
 }
 
-void wxGLContext::SwapBuffers()
+void wxGLContext::SetCurrent(const wxGLCanvas& win) const
 {
-  if (m_glContext)
-  {
-    wglMakeCurrent((HDC) m_hDC, m_glContext);
-    ::SwapBuffers((HDC) m_hDC);    //blits the backbuffer into DC
-  }
-}
-
-void wxGLContext::SetCurrent()
-{
-  if (m_glContext)
-  {
-    wglMakeCurrent((HDC) m_hDC, m_glContext);
-  }
-}
-
-void wxGLContext::SetColour(const wxChar *colour)
-{
-    wxColour col = wxTheColourDatabase->Find(colour);
-    if (col.Ok())
-    {
-        float r = (float)(col.Red()/256.0);
-        float g = (float)(col.Green()/256.0);
-        float b = (float)(col.Blue()/256.0);
-        glColor3f( r, g, b);
-    }
+    wglMakeCurrent((HDC) win.GetHDC(), m_glContext);
 }
 
 
@@ -265,6 +218,26 @@ BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
     EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
 END_EVENT_TABLE()
 
+wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id, int *attribList,
+    const wxPoint& pos, const wxSize& size, long style,
+    const wxString& name, const wxPalette& palette) : wxWindow()
+{
+    m_glContext = NULL;
+
+    if (Create(parent, id, pos, size, style, name))
+    {
+        SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
+    }
+
+    m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
+
+    SetupPixelFormat(attribList);
+    SetupPalette(palette);
+
+    // This ctor does *not* create an instance of wxGLContext,
+    // m_glContext intentionally remains NULL.
+}
+
 wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
     const wxPoint& pos, const wxSize& size, long style, const wxString& name,
     int *attribList, const wxPalette& palette) : wxWindow()
@@ -283,7 +256,7 @@ wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
   SetupPixelFormat(attribList);
   SetupPalette(palette);
 
-  m_glContext = new wxGLContext(true, this, palette);
+  m_glContext = new wxGLContext(this);
 }
 
 wxGLCanvas::wxGLCanvas( wxWindow *parent,
@@ -306,7 +279,7 @@ wxGLCanvas::wxGLCanvas( wxWindow *parent,
   SetupPixelFormat(attribList);
   SetupPalette(palette);
 
-  m_glContext = new wxGLContext(true, this, palette, shared );
+  m_glContext = new wxGLContext(this, shared);
 }
 
 // Not very useful for wxMSW, but this is to be wxGTK compliant
@@ -332,7 +305,7 @@ wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID i
 
   wxGLContext *sharedContext=0;
   if (shared) sharedContext=shared->GetContext();
-  m_glContext = new wxGLContext(true, this, palette, sharedContext );
+  m_glContext = new wxGLContext(this, sharedContext);
 }
 
 wxGLCanvas::~wxGLCanvas()
@@ -566,14 +539,23 @@ wxPalette wxGLCanvas::CreateDefaultPalette()
 
 void wxGLCanvas::SwapBuffers()
 {
-  if (m_glContext)
-    m_glContext->SwapBuffers();
+    ::SwapBuffers((HDC) m_hDC);
 }
 
 void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
 {
 }
 
+void wxGLCanvas::SetCurrent(const wxGLContext& RC) const
+{
+    // although on MSW it works even if the window is still hidden, it doesn't
+  	// under wxGTK and documentation mentions that SetCurrent() can only be
+  	// called for a shown window, so check it
+  	wxASSERT_MSG( GetParent()->IsShown(), _T("can't make hidden GL canvas current") );
+
+    RC.SetCurrent(*this);
+}
+
 void wxGLCanvas::SetCurrent()
 {
   // although on MSW it works even if the window is still hidden, it doesn't
@@ -584,14 +566,21 @@ void wxGLCanvas::SetCurrent()
 
   if (m_glContext)
   {
-    m_glContext->SetCurrent();
+    m_glContext->SetCurrent(*this);
   }
 }
 
 void wxGLCanvas::SetColour(const wxChar *colour)
 {
-  if (m_glContext)
-    m_glContext->SetColour(colour);
+    wxColour col = wxTheColourDatabase->Find(colour);
+
+    if (col.Ok())
+    {
+        float r = (float)(col.Red()/256.0);
+        float g = (float)(col.Green()/256.0);
+        float b = (float)(col.Blue()/256.0);
+        glColor3f( r, g, b);
+    }
 }
 
 // TODO: Have to have this called by parent frame (?)
@@ -624,146 +613,6 @@ void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
   }
 }
 
-/* Give extensions proper function names. */
-
-/* EXT_vertex_array */
-void glArrayElementEXT(GLint WXUNUSED(i))
-{
-}
-
-void glColorPointerEXT(GLint WXUNUSED(size), GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
-{
-}
-
-void glDrawArraysEXT(GLenum  WXUNUSED_WITHOUT_GL_EXT_vertex_array(mode),
-                     GLint   WXUNUSED_WITHOUT_GL_EXT_vertex_array(first),
-                     GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(count))
-{
-#ifdef GL_EXT_vertex_array
-    static PFNGLDRAWARRAYSEXTPROC proc = 0;
-
-    if ( !proc )
-    {
-        proc = (PFNGLDRAWARRAYSEXTPROC) wglGetProcAddress("glDrawArraysEXT");
-    }
-
-    if ( proc )
-        (* proc) (mode, first, count);
-#endif
-}
-
-void glEdgeFlagPointerEXT(GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLboolean *WXUNUSED(pointer))
-{
-}
-
-void glGetPointervEXT(GLenum WXUNUSED(pname), GLvoid* *WXUNUSED(params))
-{
-}
-
-void glIndexPointerEXT(GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
-{
-}
-
-void glNormalPointerEXT(GLenum        WXUNUSED_WITHOUT_GL_EXT_vertex_array(type),
-                        GLsizei       WXUNUSED_WITHOUT_GL_EXT_vertex_array(stride),
-                        GLsizei       WXUNUSED_WITHOUT_GL_EXT_vertex_array(count),
-                        const GLvoid *WXUNUSED_WITHOUT_GL_EXT_vertex_array(pointer))
-{
-#ifdef GL_EXT_vertex_array
-  static PFNGLNORMALPOINTEREXTPROC proc = 0;
-
-  if ( !proc )
-  {
-    proc = (PFNGLNORMALPOINTEREXTPROC) wglGetProcAddress("glNormalPointerEXT");
-  }
-
-  if ( proc )
-    (* proc) (type, stride, count, pointer);
-#endif
-}
-
-void glTexCoordPointerEXT(GLint WXUNUSED(size), GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
-{
-}
-
-void glVertexPointerEXT(GLint         WXUNUSED_WITHOUT_GL_EXT_vertex_array(size),
-                        GLenum        WXUNUSED_WITHOUT_GL_EXT_vertex_array(type),
-                        GLsizei       WXUNUSED_WITHOUT_GL_EXT_vertex_array(stride),
-                        GLsizei       WXUNUSED_WITHOUT_GL_EXT_vertex_array(count),
-                        const GLvoid *WXUNUSED_WITHOUT_GL_EXT_vertex_array(pointer))
-{
-#ifdef GL_EXT_vertex_array
-  static PFNGLVERTEXPOINTEREXTPROC proc = 0;
-
-  if ( !proc )
-  {
-    proc = (PFNGLVERTEXPOINTEREXTPROC) wglGetProcAddress("glVertexPointerEXT");
-  }
-  if ( proc )
-    (* proc) (size, type, stride, count, pointer);
-#endif
-}
-
-/* EXT_color_subtable */
-void glColorSubtableEXT(GLenum WXUNUSED(target), GLsizei WXUNUSED(start), GLsizei WXUNUSED(count), GLenum WXUNUSED(format), GLenum WXUNUSED(type), const GLvoid *WXUNUSED(table))
-{
-}
-
-/* EXT_color_table */
-void glColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(internalformat), GLsizei WXUNUSED(width), GLenum WXUNUSED(format), GLenum WXUNUSED(type), const GLvoid *WXUNUSED(table))
-{
-}
-
-void glCopyColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(internalformat), GLint WXUNUSED(x), GLint WXUNUSED(y), GLsizei WXUNUSED(width))
-{
-}
-
-void glGetColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(format), GLenum WXUNUSED(type), GLvoid *WXUNUSED(table))
-{
-}
-
-void glGetColorTableParamaterfvEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(pname), GLfloat *WXUNUSED(params))
-{
-}
-
-void glGetColorTavleParameterivEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(pname), GLint *WXUNUSED(params))
-{
-}
-
-/* SGI_compiled_vertex_array */
-void glLockArraysSGI(GLint WXUNUSED(first), GLsizei WXUNUSED(count))
-{
-}
-
-void glUnlockArraysSGI()
-{
-}
-
-
-/* SGI_cull_vertex */
-void glCullParameterdvSGI(GLenum WXUNUSED(pname), GLdouble* WXUNUSED(params))
-{
-}
-
-void glCullParameterfvSGI(GLenum WXUNUSED(pname), GLfloat* WXUNUSED(params))
-{
-}
-
-/* SGI_index_func */
-void glIndexFuncSGI(GLenum WXUNUSED(func), GLclampf WXUNUSED(ref))
-{
-}
-
-/* SGI_index_material */
-void glIndexMaterialSGI(GLenum WXUNUSED(face), GLenum WXUNUSED(mode))
-{
-}
-
-/* WIN_swap_hint */
-void glAddSwapHintRectWin(GLint WXUNUSED(x), GLint WXUNUSED(y), GLsizei WXUNUSED(width), GLsizei WXUNUSED(height))
-{
-}
-
 
 //---------------------------------------------------------------------------
 // wxGLApp
-- 
2.50.0

