From 8b089c5e8c8a2140258d150ca1ce42afd3b79e1b Mon Sep 17 00:00:00 2001
From: Julian Smart <julian@anthemion.co.uk>
Date: Mon, 28 Feb 2000 08:22:57 +0000
Subject: [PATCH] Moved wxGLCanvas to more normal positions

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6326 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 distrib/msw/glcanvas.rsp              |  69 ++-
 distrib/msw/tmake/filelist.txt        |   7 +
 docs/latex/wx/classes.tex             |   1 +
 docs/latex/wx/glcanvas.tex            |  67 +++
 docs/latex/wx/grid.tex                |   1 -
 include/wx/glcanvas.h                 |  21 +
 include/wx/gtk/glcanvas.h             | 169 +++++++
 include/wx/gtk1/glcanvas.h            | 169 +++++++
 include/wx/motif/glcanvas.h           |  52 +++
 include/wx/msw/glcanvas.h             | 174 +++++++
 include/wx/msw/setup0.h               |   3 +
 samples/opengl/cube/Makefile          |  31 ++
 samples/opengl/cube/cube.cpp          | 508 +++++++++++++++++++++
 samples/opengl/cube/cube.h            |  93 ++++
 samples/opengl/cube/cube.rc           |   3 +
 samples/opengl/cube/makefile.b32      |  18 +
 samples/opengl/cube/makefile.bcc      |  21 +
 samples/opengl/cube/makefile.g95      |  18 +
 samples/opengl/cube/makefile.unx      |  23 +
 samples/opengl/cube/makefile.vc       |  26 ++
 samples/opengl/cube/makefile.wat      |  17 +
 samples/opengl/cube/mondrian.ico      | Bin 0 -> 766 bytes
 samples/opengl/isosurf/Makefile       |  32 ++
 samples/opengl/isosurf/isosurf.cpp    | 412 +++++++++++++++++
 samples/opengl/isosurf/isosurf.dat.gz | Bin 0 -> 65537 bytes
 samples/opengl/isosurf/isosurf.h      |  52 +++
 samples/opengl/isosurf/isosurf.rc     |   3 +
 samples/opengl/isosurf/makefile.b32   |  22 +
 samples/opengl/isosurf/makefile.bcc   |  25 ++
 samples/opengl/isosurf/makefile.g95   |  20 +
 samples/opengl/isosurf/makefile.unx   |  27 ++
 samples/opengl/isosurf/makefile.vc    |  30 ++
 samples/opengl/isosurf/makefile.wat   |  20 +
 samples/opengl/isosurf/mondrian.ico   | Bin 0 -> 766 bytes
 samples/opengl/penguin/Makefile       |  37 ++
 samples/opengl/penguin/lw.cpp         | 427 ++++++++++++++++++
 samples/opengl/penguin/lw.h           |  69 +++
 samples/opengl/penguin/makefile.b32   |  18 +
 samples/opengl/penguin/makefile.bcc   |  21 +
 samples/opengl/penguin/makefile.g95   |  18 +
 samples/opengl/penguin/makefile.unx   |  21 +
 samples/opengl/penguin/makefile.vc    |  30 ++
 samples/opengl/penguin/makefile.wat   |  17 +
 samples/opengl/penguin/penguin.cpp    | 236 ++++++++++
 samples/opengl/penguin/penguin.h      |  84 ++++
 samples/opengl/penguin/penguin.lwo    | Bin 0 -> 10028 bytes
 samples/opengl/penguin/penguin.rc     |   3 +
 samples/opengl/penguin/trackball.h    |  78 ++++
 src/generic/scrolwin.cpp              |   4 +
 src/gtk/glcanvas.cpp                  | 432 ++++++++++++++++++
 src/gtk1/glcanvas.cpp                 | 432 ++++++++++++++++++
 src/motif/glcanvas.cpp                | 168 +++++++
 src/msw/glcanvas.cpp                  | 624 ++++++++++++++++++++++++++
 src/msw/makefile.b32                  |   5 +-
 src/msw/makefile.bcc                  |   5 +-
 src/msw/makefile.g95                  |   1 +
 src/msw/makefile.vc                   |   3 +-
 src/msw/makefile.wat                  |   6 +-
 src/wxvc.dsp                          |   4 +
 src/wxvc_dll.dsp                      |   4 +
 utils/projgen/makeproj.cpp            |  75 +---
 61 files changed, 4848 insertions(+), 108 deletions(-)
 create mode 100644 docs/latex/wx/glcanvas.tex
 create mode 100644 include/wx/glcanvas.h
 create mode 100644 include/wx/gtk/glcanvas.h
 create mode 100644 include/wx/gtk1/glcanvas.h
 create mode 100644 include/wx/motif/glcanvas.h
 create mode 100644 include/wx/msw/glcanvas.h
 create mode 100644 samples/opengl/cube/Makefile
 create mode 100644 samples/opengl/cube/cube.cpp
 create mode 100644 samples/opengl/cube/cube.h
 create mode 100644 samples/opengl/cube/cube.rc
 create mode 100644 samples/opengl/cube/makefile.b32
 create mode 100644 samples/opengl/cube/makefile.bcc
 create mode 100644 samples/opengl/cube/makefile.g95
 create mode 100644 samples/opengl/cube/makefile.unx
 create mode 100644 samples/opengl/cube/makefile.vc
 create mode 100644 samples/opengl/cube/makefile.wat
 create mode 100644 samples/opengl/cube/mondrian.ico
 create mode 100644 samples/opengl/isosurf/Makefile
 create mode 100644 samples/opengl/isosurf/isosurf.cpp
 create mode 100644 samples/opengl/isosurf/isosurf.dat.gz
 create mode 100644 samples/opengl/isosurf/isosurf.h
 create mode 100644 samples/opengl/isosurf/isosurf.rc
 create mode 100644 samples/opengl/isosurf/makefile.b32
 create mode 100644 samples/opengl/isosurf/makefile.bcc
 create mode 100644 samples/opengl/isosurf/makefile.g95
 create mode 100644 samples/opengl/isosurf/makefile.unx
 create mode 100644 samples/opengl/isosurf/makefile.vc
 create mode 100644 samples/opengl/isosurf/makefile.wat
 create mode 100644 samples/opengl/isosurf/mondrian.ico
 create mode 100644 samples/opengl/penguin/Makefile
 create mode 100644 samples/opengl/penguin/lw.cpp
 create mode 100644 samples/opengl/penguin/lw.h
 create mode 100644 samples/opengl/penguin/makefile.b32
 create mode 100644 samples/opengl/penguin/makefile.bcc
 create mode 100644 samples/opengl/penguin/makefile.g95
 create mode 100644 samples/opengl/penguin/makefile.unx
 create mode 100644 samples/opengl/penguin/makefile.vc
 create mode 100644 samples/opengl/penguin/makefile.wat
 create mode 100644 samples/opengl/penguin/penguin.cpp
 create mode 100644 samples/opengl/penguin/penguin.h
 create mode 100644 samples/opengl/penguin/penguin.lwo
 create mode 100644 samples/opengl/penguin/penguin.rc
 create mode 100644 samples/opengl/penguin/trackball.h
 create mode 100644 src/gtk/glcanvas.cpp
 create mode 100644 src/gtk1/glcanvas.cpp
 create mode 100644 src/motif/glcanvas.cpp
 create mode 100644 src/msw/glcanvas.cpp

diff --git a/distrib/msw/glcanvas.rsp b/distrib/msw/glcanvas.rsp
index 923fc507bd..d23618a158 100644
--- a/distrib/msw/glcanvas.rsp
+++ b/distrib/msw/glcanvas.rsp
@@ -1,42 +1,37 @@
-utils/glcanvas/Makefile.in
-utils/glcanvas/docs/*.*
-utils/glcanvas/win/*.cpp
-utils/glcanvas/win/*.h
-utils/glcanvas/win/make*.*
-utils/glcanvas/gtk/*.cpp
-utils/glcanvas/gtk/*.h
-utils/glcanvas/gtk/make*.*
-utils/glcanvas/motif/*.cpp
-utils/glcanvas/motif/*.h
-utils/glcanvas/motif/make*.*
-utils/glcanvas/motif/*.txt
-utils/glcanvas/samples/cube/*.cpp
-utils/glcanvas/samples/cube/*.h
-utils/glcanvas/samples/cube/*.rc
-utils/glcanvas/samples/cube/*.ico
-utils/glcanvas/samples/cube/*.xbm
-utils/glcanvas/samples/cube/make*.*
-utils/glcanvas/samples/cube/Makefile
+include/wx/glcanvas.h
+include/wx/motif/glcanvas.h
+include/wx/gtk/glcanvas.h
+include/wx/msw/glcanvas.h
 
-utils/glcanvas/samples/isosurf/*.cpp
-utils/glcanvas/samples/isosurf/*.h
-utils/glcanvas/samples/isosurf/*.rc
-utils/glcanvas/samples/isosurf/*.ico
-utils/glcanvas/samples/isosurf/*.xbm
-utils/glcanvas/samples/isosurf/*.dat.gz
-utils/glcanvas/samples/isosurf/make*.*
-utils/glcanvas/samples/isosurf/Makefile
+src/motif/glcanvas.cpp
+src/gtk/glcanvas.cpp
+src/msw/glcanvas.cpp
 
-utils/glcanvas/samples/penguin/*.cpp
-utils/glcanvas/samples/penguin/*.c
-utils/glcanvas/samples/penguin/*.h
-utils/glcanvas/samples/penguin/*.rc
-utils/glcanvas/samples/penguin/*.ico
-utils/glcanvas/samples/penguin/*.xbm
-utils/glcanvas/samples/penguin/*.xpm
-utils/glcanvas/samples/penguin/make*.*
-utils/glcanvas/samples/penguin/Makefile
-utils/glcanvas/samples/penguin/penguin.lwo
+samples/opengl/cube/*.cpp
+samples/opengl/cube/*.h
+samples/opengl/cube/*.rc
+samples/opengl/cube/*.ico
+samples/opengl/cube/*.xbm
+samples/opengl/cube/make*.*
+samples/opengl/cube/Makefile
 
+samples/opengl/isosurf/*.cpp
+samples/opengl/isosurf/*.h
+samples/opengl/isosurf/*.rc
+samples/opengl/isosurf/*.ico
+samples/opengl/isosurf/*.xbm
+samples/opengl/isosurf/*.dat.gz
+samples/opengl/isosurf/make*.*
+samples/opengl/isosurf/Makefile
 
+samples/opengl/penguin/*.cpp
+samples/opengl/penguin/*.c
+samples/opengl/penguin/*.h
+samples/opengl/penguin/*.rc
+samples/opengl/penguin/*.ico
+samples/opengl/penguin/*.xbm
+samples/opengl/penguin/*.xpm
+samples/opengl/penguin/make*.*
+samples/opengl/penguin/Makefile
+samples/opengl/penguin/penguin.lwo
 
diff --git a/distrib/msw/tmake/filelist.txt b/distrib/msw/tmake/filelist.txt
index e483bf786b..e5f716ff6c 100644
--- a/distrib/msw/tmake/filelist.txt
+++ b/distrib/msw/tmake/filelist.txt
@@ -247,6 +247,7 @@ gauge95.cpp	M	32
 gaugemsw.cpp	M	16
 gdiimage.cpp	M
 gdiobj.cpp	M
+glcanvas.cpp	M
 helpwin.cpp	M
 icon.cpp	M
 imaglist.cpp	M	32
@@ -343,6 +344,7 @@ fontdlg.cpp	R
 frame.cpp	R
 gauge.cpp	R
 gdiobj.cpp	R
+glcanvas.cpp	R
 icon.cpp	R
 listbox.cpp	R
 main.cpp	R
@@ -400,6 +402,7 @@ font.cpp	X
 frame.cpp	X
 gauge.cpp	X
 gdiobj.cpp	X
+glcanvas.cpp	X
 icon.cpp	X
 listbox.cpp	X
 main.cpp	X
@@ -603,6 +606,7 @@ gdicmn.h	W
 gdiobj.h	W
 geometry.h	W
 gifdecod.h	W
+glcanvas.h	W
 grid.h	W
 gsocket.h	W
 hash.h	W	B
@@ -761,6 +765,7 @@ fontdlg.h	K
 frame.h	K
 gauge.h	K
 gdiobj.h	K
+glcanvas.h	K
 icon.h	K
 joystick.h	K
 listbox.h	K
@@ -823,6 +828,7 @@ fontdlg.h	F
 frame.h	F
 gauge.h	F
 gdiobj.h	F
+glcanvas.h	F
 icon.h	F
 joystick.h	F
 listbox.h	F
@@ -891,6 +897,7 @@ gauge95.h	9
 gaugemsw.h	9
 gdiimage.h	9
 gdiobj.h	9
+glcanvas.h	9
 helpwin.h	9
 icon.h	9
 imaglist.h	9
diff --git a/docs/latex/wx/classes.tex b/docs/latex/wx/classes.tex
index fb000358a0..a6adbfd61c 100644
--- a/docs/latex/wx/classes.tex
+++ b/docs/latex/wx/classes.tex
@@ -94,6 +94,7 @@
 \input ftp.tex
 \input gauge.tex
 \input gdiobj.tex
+\input glcanvas.tex
 \input valgen.tex
 \input grid.tex
 \input hash.tex
diff --git a/docs/latex/wx/glcanvas.tex b/docs/latex/wx/glcanvas.tex
new file mode 100644
index 0000000000..fddb1541ee
--- /dev/null
+++ b/docs/latex/wx/glcanvas.tex
@@ -0,0 +1,67 @@
+\section{\class{wxGLCanvas}}\label{wxglcanvas}
+
+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} 
+to direct normal OpenGL commands to the window, and then call \helpref{wxGLCanvas::SwapBuffers}{wxglcanvasswapbuffers} 
+to show the OpenGL buffer on the window.
+
+Please note that despite deriving from wxScrolledWindow, scrolling is not enabled for this class under
+Windows.
+
+To switch wxGLCanvas support on under Windows, edit setup.h and set wxUSE\_GLCANVAS to 1.
+
+\wxheading{Derived from}
+
+\helpref{wxScrolledWindow}{wxscrolledwindow}\\
+\helpref{wxWindow}{wxwindow}\\
+\helpref{wxEvtHandler}{wxevthandler}\\
+\helpref{wxObject}{wxobject}
+
+\wxheading{Include files}
+
+<wx/glcanvas.h>
+
+\wxheading{Window styles}
+
+There are no specific window styles for this class.
+
+See also \helpref{window styles overview}{windowstyles}.
+
+\latexignore{\rtfignore{\wxheading{Members}}}
+
+\membersection{wxGLCanvas::wxGLCanvas}\label{wxglcanvasconstr}
+
+\func{void}{wxGLCanvas}{\param{wxWindow* }{parent}, \param{wxWindowID}{ id = -1}, \param{const wxPoint\&}{ pos},
+ \param{const wxSize\&}{ size}, \param{long}{ style=0}, \param{const wxString\& }{name="GLCanvas"},
+ \param{int*}{ attribList = 0}, \param{const wxPalette\&}{ palette = wxNullPalette}}
+
+\func{void}{wxGLCanvas}{\param{wxWindow* }{parent}, \param{wxGLCanvas* }{ sharedCanvas = NULL}, \param{wxWindowID}{ id = -1}, \param{const wxPoint\&}{ pos},
+ \param{const wxSize\&}{ size}, \param{long}{ style=0}, \param{const wxString\& }{name="GLCanvas"},
+ \param{int*}{ attribList = 0}, \param{const wxPalette\&}{ palette = wxNullPalette}}
+
+\func{void}{wxGLCanvas}{\param{wxWindow* }{parent}, \param{wxGLContext* }{ sharedContext = NULL}, \param{wxWindowID}{ id = -1}, \param{const wxPoint\&}{ pos},
+ \param{const wxSize\&}{ size}, \param{long}{ style=0}, \param{const wxString\& }{name="GLCanvas"},
+ \param{int*}{ attribList = 0}, \param{const wxPalette\&}{ palette = wxNullPalette}}
+
+Constructor.
+
+\membersection{wxGLCanvas::SetCurrent}\label{wxglcanvassetcurrent}
+
+\func{void}{SetCurrent}{\void}
+
+Sets this canvas as the current recipient of OpenGL calls.
+
+\membersection{wxGLCanvas::SetColour}\label{wxglcanvassetcolour}
+
+\func{void}{SetColour}{\param{const char*}{ colour}}
+
+Sets the current colour for this window, using the wxWindows colour database to find a named colour.
+
+\membersection{wxGLCanvas::SwapBuffers}\label{wxglcanvasswapbuffers}
+
+\func{void}{SwapBuffers}{\void}
+
+Displays the previous OpenGL commands on the window.
+
diff --git a/docs/latex/wx/grid.tex b/docs/latex/wx/grid.tex
index 384d32438c..540ed2fed1 100644
--- a/docs/latex/wx/grid.tex
+++ b/docs/latex/wx/grid.tex
@@ -608,4 +608,3 @@ Call this function whenever a change has been made via the API that
 might alter size characteristics. You may also need to follow it with
 a call to AdjustScrollbars.
 
-
diff --git a/include/wx/glcanvas.h b/include/wx/glcanvas.h
new file mode 100644
index 0000000000..2385447aab
--- /dev/null
+++ b/include/wx/glcanvas.h
@@ -0,0 +1,21 @@
+#ifndef _WX_GLCANVAS_H_BASE_
+#define _WX_GLCANVAS_H_BASE_
+
+#if defined(__WXMSW__)
+#include "wx/msw/glcanvas.h"
+#elif defined(__WXMOTIF__)
+#include "wx/motif/glcanvas.h"
+#elif defined(__WXGTK__)
+#include "wx/gtk/glcanvas.h"
+#elif defined(__WXQT__)
+#include "wx/qt/glcanvas.h"
+#elif defined(__WXMAC__)
+#include "wx/mac/glcanvas.h"
+#elif defined(__WXPM__)
+#include "wx/os2/glcanvas.h"
+#elif defined(__WXSTUBS__)
+#include "wx/stubs/glcanvas.h"
+#endif
+
+#endif
+    // _WX_GLCANVAS_H_BASE_
diff --git a/include/wx/gtk/glcanvas.h b/include/wx/gtk/glcanvas.h
new file mode 100644
index 0000000000..14c439691d
--- /dev/null
+++ b/include/wx/gtk/glcanvas.h
@@ -0,0 +1,169 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        glcanvas.h
+// Purpose:     wxGLCanvas, for using OpenGL/Mesa with wxWindows and GTK
+// Author:      Robert Roebling
+// Modified by:
+// Created:     17/8/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Robert Roebling
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma interface "glcanvas.h"
+#endif
+
+#ifndef _WX_GLCANVAS_H_
+#define _WX_GLCANVAS_H_
+
+#include <wx/defs.h>
+
+#if wxUSE_GLCANVAS
+
+#include <wx/scrolwin.h>
+
+extern "C" {
+#include "GL/gl.h"
+#include "GL/glx.h"
+#include "GL/glu.h"
+}
+
+//---------------------------------------------------------------------------
+// Constants for attriblist
+//---------------------------------------------------------------------------
+
+enum
+{
+  WX_GL_RGBA=1,          /* use true color palette */
+  WX_GL_DEPTH_SIZE,      /* bits for Z-buffer (0,16,32) */
+  WX_GL_DOUBLEBUFFER,    /* use doublebuffer */
+  WX_GL_MIN_RED,         /* use red buffer with most bits (> MIN_RED bits) */
+  WX_GL_MIN_GREEN,       /* use green buffer with most bits (> MIN_GREEN bits) */
+  WX_GL_MIN_BLUE         /* use blue buffer with most bits (> MIN_BLUE bits) */
+/* these are enough constants for now, the remaining will be added later */
+};
+
+//---------------------------------------------------------------------------
+// classes
+//---------------------------------------------------------------------------
+
+class WXDLLEXPORT wxGLContext;
+class WXDLLEXPORT wxGLCanvas;
+
+//---------------------------------------------------------------------------
+// wxGLContext
+//---------------------------------------------------------------------------
+
+
+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();
+
+    void SetCurrent();
+    void SetColour(const char *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;
+
+   GtkWidget       *m_widget;
+   wxPalette        m_palette;
+   wxWindow*        m_window;
+   
+private:
+  DECLARE_CLASS(wxGLContext)
+};
+
+//---------------------------------------------------------------------------
+// wxGLContext
+//---------------------------------------------------------------------------
+
+class WXDLLEXPORT wxGLCanvas: public wxScrolledWindow
+{
+public:
+   inline wxGLCanvas() {
+      m_glContext = (wxGLContext*) NULL;
+      m_sharedContext = (wxGLContext*) NULL;
+      m_glWidget = (GtkWidget*) NULL;
+      m_vi = (void*) NULL;
+      m_exposed = FALSE;
+   }
+   wxGLCanvas( wxWindow *parent, wxWindowID id = -1, 
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, 
+        long style = 0, const wxString& name = "GLCanvas", 
+        int *attribList = (int*) NULL, 
+        const wxPalette& palette = wxNullPalette );
+   wxGLCanvas( wxWindow *parent, const wxGLContext *shared = (wxGLContext *)NULL,
+        wxWindowID id = -1, 
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, 
+        long style = 0, const wxString& name = "GLCanvas", 
+        int *attribList = (int*) NULL, 
+        const wxPalette& palette = wxNullPalette );
+   wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared = (wxGLCanvas *)NULL,
+        wxWindowID id = -1, 
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, 
+        long style = 0, const wxString& name = "GLCanvas", 
+        int *attribList = (int*) NULL, 
+        const wxPalette& palette = wxNullPalette );
+
+   bool Create( wxWindow *parent, 
+	const wxGLContext *shared = (wxGLContext*)NULL,
+	const wxGLCanvas *shared_context_of = (wxGLCanvas*)NULL,
+        wxWindowID id = -1, 
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, 
+	long style = 0, const wxString& name = "GLCanvas", 
+	int *attribList = (int*) NULL,
+	const wxPalette& palette = wxNullPalette );
+	
+   ~wxGLCanvas();
+
+   void SetCurrent();
+   void SetColour(const char *colour);
+   void SwapBuffers();
+
+   void OnSize(wxSizeEvent& event);
+   
+   void OnInternalIdle();
+
+   inline wxGLContext* GetContext() const { return m_glContext; } 
+
+ // implementation
+  
+    wxGLContext      *m_glContext,
+                     *m_sharedContext;
+    wxGLCanvas       *m_sharedContextOf;
+    void             *m_vi;
+    GtkWidget        *m_glWidget;
+    bool              m_exposed;
+
+private:
+    DECLARE_EVENT_TABLE()
+    DECLARE_CLASS(wxGLCanvas)
+};
+
+#endif
+    // wxUSE_GLCANVAS
+
+#endif
+    // _WX_GLCANVAS_H_
+
diff --git a/include/wx/gtk1/glcanvas.h b/include/wx/gtk1/glcanvas.h
new file mode 100644
index 0000000000..14c439691d
--- /dev/null
+++ b/include/wx/gtk1/glcanvas.h
@@ -0,0 +1,169 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        glcanvas.h
+// Purpose:     wxGLCanvas, for using OpenGL/Mesa with wxWindows and GTK
+// Author:      Robert Roebling
+// Modified by:
+// Created:     17/8/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Robert Roebling
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma interface "glcanvas.h"
+#endif
+
+#ifndef _WX_GLCANVAS_H_
+#define _WX_GLCANVAS_H_
+
+#include <wx/defs.h>
+
+#if wxUSE_GLCANVAS
+
+#include <wx/scrolwin.h>
+
+extern "C" {
+#include "GL/gl.h"
+#include "GL/glx.h"
+#include "GL/glu.h"
+}
+
+//---------------------------------------------------------------------------
+// Constants for attriblist
+//---------------------------------------------------------------------------
+
+enum
+{
+  WX_GL_RGBA=1,          /* use true color palette */
+  WX_GL_DEPTH_SIZE,      /* bits for Z-buffer (0,16,32) */
+  WX_GL_DOUBLEBUFFER,    /* use doublebuffer */
+  WX_GL_MIN_RED,         /* use red buffer with most bits (> MIN_RED bits) */
+  WX_GL_MIN_GREEN,       /* use green buffer with most bits (> MIN_GREEN bits) */
+  WX_GL_MIN_BLUE         /* use blue buffer with most bits (> MIN_BLUE bits) */
+/* these are enough constants for now, the remaining will be added later */
+};
+
+//---------------------------------------------------------------------------
+// classes
+//---------------------------------------------------------------------------
+
+class WXDLLEXPORT wxGLContext;
+class WXDLLEXPORT wxGLCanvas;
+
+//---------------------------------------------------------------------------
+// wxGLContext
+//---------------------------------------------------------------------------
+
+
+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();
+
+    void SetCurrent();
+    void SetColour(const char *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;
+
+   GtkWidget       *m_widget;
+   wxPalette        m_palette;
+   wxWindow*        m_window;
+   
+private:
+  DECLARE_CLASS(wxGLContext)
+};
+
+//---------------------------------------------------------------------------
+// wxGLContext
+//---------------------------------------------------------------------------
+
+class WXDLLEXPORT wxGLCanvas: public wxScrolledWindow
+{
+public:
+   inline wxGLCanvas() {
+      m_glContext = (wxGLContext*) NULL;
+      m_sharedContext = (wxGLContext*) NULL;
+      m_glWidget = (GtkWidget*) NULL;
+      m_vi = (void*) NULL;
+      m_exposed = FALSE;
+   }
+   wxGLCanvas( wxWindow *parent, wxWindowID id = -1, 
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, 
+        long style = 0, const wxString& name = "GLCanvas", 
+        int *attribList = (int*) NULL, 
+        const wxPalette& palette = wxNullPalette );
+   wxGLCanvas( wxWindow *parent, const wxGLContext *shared = (wxGLContext *)NULL,
+        wxWindowID id = -1, 
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, 
+        long style = 0, const wxString& name = "GLCanvas", 
+        int *attribList = (int*) NULL, 
+        const wxPalette& palette = wxNullPalette );
+   wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared = (wxGLCanvas *)NULL,
+        wxWindowID id = -1, 
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, 
+        long style = 0, const wxString& name = "GLCanvas", 
+        int *attribList = (int*) NULL, 
+        const wxPalette& palette = wxNullPalette );
+
+   bool Create( wxWindow *parent, 
+	const wxGLContext *shared = (wxGLContext*)NULL,
+	const wxGLCanvas *shared_context_of = (wxGLCanvas*)NULL,
+        wxWindowID id = -1, 
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, 
+	long style = 0, const wxString& name = "GLCanvas", 
+	int *attribList = (int*) NULL,
+	const wxPalette& palette = wxNullPalette );
+	
+   ~wxGLCanvas();
+
+   void SetCurrent();
+   void SetColour(const char *colour);
+   void SwapBuffers();
+
+   void OnSize(wxSizeEvent& event);
+   
+   void OnInternalIdle();
+
+   inline wxGLContext* GetContext() const { return m_glContext; } 
+
+ // implementation
+  
+    wxGLContext      *m_glContext,
+                     *m_sharedContext;
+    wxGLCanvas       *m_sharedContextOf;
+    void             *m_vi;
+    GtkWidget        *m_glWidget;
+    bool              m_exposed;
+
+private:
+    DECLARE_EVENT_TABLE()
+    DECLARE_CLASS(wxGLCanvas)
+};
+
+#endif
+    // wxUSE_GLCANVAS
+
+#endif
+    // _WX_GLCANVAS_H_
+
diff --git a/include/wx/motif/glcanvas.h b/include/wx/motif/glcanvas.h
new file mode 100644
index 0000000000..b3a9ab8016
--- /dev/null
+++ b/include/wx/motif/glcanvas.h
@@ -0,0 +1,52 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        glcanvas.h
+// Purpose:     wxGLCanvas, for using OpenGL with wxWindows 2.0 for Motif.
+//              Uses the GLX extension.
+// Author:      Julian Smart and Wolfram Gloger
+// Modified by:
+// Created:     1995, 1999
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart, Wolfram Gloger
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma interface "glcanvas.h"
+#endif
+
+#ifndef _WX_GLCANVAS_H_
+#define _WX_GLCANVAS_H_
+
+#include <wx/setup.h>
+
+#if wxUSE_GLCANVAS
+
+#include <wx/gdicmn.h>
+#include <wx/palette.h>
+#include <wx/scrolwin.h>
+
+#include <GL/glx.h>
+
+class WXDLLEXPORT wxGLCanvas: public wxScrolledWindow
+{
+DECLARE_CLASS(wxGLCanvas)
+public:
+    GLXContext glx_cx;
+
+    inline wxGLCanvas() { glx_cx = 0; }
+
+    wxGLCanvas(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, long style = 0,
+        const wxString& name = "GLCanvas", int *attribList = 0, const wxPalette& palette = wxNullPalette);
+    ~wxGLCanvas(void);
+
+    void SetCurrent();
+    void SwapBuffers();
+    void SetColour(const char *col);
+};
+
+#endif
+  //  wxUSE_GLCANVAS
+
+#endif
+  // _WX_GLCANVAS_H_
diff --git a/include/wx/msw/glcanvas.h b/include/wx/msw/glcanvas.h
new file mode 100644
index 0000000000..f743c5430a
--- /dev/null
+++ b/include/wx/msw/glcanvas.h
@@ -0,0 +1,174 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        glcanvas.h
+// Purpose:     wxGLCanvas, for using OpenGL with wxWindows under Windows
+// Author:      Julian Smart
+// Modified by:
+// Created:     04/01/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma interface "glcanvas.h"
+#endif
+
+#ifndef _WX_GLCANVAS_H_
+#define _WX_GLCANVAS_H_
+
+#include <wx/setup.h>
+
+#if wxUSE_GLCANVAS
+
+#include <wx/scrolwin.h>
+
+#include <windows.h>
+
+#include "gl/gl.h"
+
+//---------------------------------------------------------------------------
+// Constants for attriblist
+//---------------------------------------------------------------------------
+
+enum
+{
+  WX_GL_RGBA=1,          /* use true color palette */
+  WX_GL_DEPTH_SIZE,      /* bits for Z-buffer (0,16,32) */
+  WX_GL_DOUBLEBUFFER,    /* use doublebuffer */
+  WX_GL_MIN_RED,         /* use red buffer with most bits (> MIN_RED bits) */
+  WX_GL_MIN_GREEN,       /* use green buffer with most bits (> MIN_GREEN bits) */
+  WX_GL_MIN_BLUE         /* use blue buffer with most bits (> MIN_BLUE bits) */
+/* these are enough constants for now, the remaining will be added later */
+};
+
+class WXDLLEXPORT wxGLCanvas;     /* forward reference */
+
+class WXDLLEXPORT 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();
+
+   void SetCurrent();
+   void SetColour(const char *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;
+};
+
+class WXDLLEXPORT wxGLCanvas: public wxScrolledWindow
+{
+   DECLARE_CLASS(wxGLCanvas)
+ public:
+   wxGLCanvas(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, long style = 0,
+        const wxString& name = "GLCanvas", int *attribList = 0, const wxPalette& palette = wxNullPalette);
+   wxGLCanvas( wxWindow *parent, const wxGLContext *shared = (wxGLContext *)NULL,
+        wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = "GLCanvas", 
+	      int *attribList = (int*) NULL, const wxPalette& palette = wxNullPalette );
+
+   wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared = (wxGLCanvas *)NULL, wxWindowID id = -1,
+        const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, 
+		const wxString& name = "GLCanvas", int *attribList = 0, const wxPalette& palette = wxNullPalette );
+
+   ~wxGLCanvas();
+
+   // Replaces wxWindow::Create functionality, since we need to use a different window class
+   bool Create(wxWindow *parent, wxWindowID id,
+              const wxPoint& pos, const wxSize& size, long style, const wxString& name);
+
+   void SetCurrent();
+   void SetColour(const char *colour);
+   void SwapBuffers();
+
+   void OnSize(wxSizeEvent& event);
+
+   void OnQueryNewPalette(wxQueryNewPaletteEvent& event);
+   void OnPaletteChanged(wxPaletteChangedEvent& event);
+
+   inline wxGLContext* GetContext() const { return m_glContext; }
+
+   inline WXHDC GetHDC() const { return m_hDC; }
+   void SetupPixelFormat();
+   void SetupPalette(const wxPalette& palette);
+   wxPalette CreateDefaultPalette();
+
+   inline wxPalette* GetPalette() const { return (wxPalette*) & m_palette; }
+
+protected:
+    wxGLContext*   m_glContext;  // this is typedef-ed ptr, in fact
+    wxPalette      m_palette;
+    WXHDC          m_hDC;
+
+DECLARE_EVENT_TABLE()
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Give extensions proper function names. */
+
+/* N.B. - this is not completely implemented as yet */
+
+/* EXT_vertex_array */
+void glArrayElementEXT(GLint i);
+void glColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+void glDrawArraysEXT(GLenum mode, GLint first, GLsizei count);
+void glEdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *pointer);
+void glGetPointervEXT(GLenum pname, GLvoid* *params);
+void glIndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+void glNormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+void glTexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+void glVertexPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+
+/* EXT_color_subtable */
+void glColorSubtableEXT(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *table);
+
+/* EXT_color_table */
+void glColorTableEXT(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+void glCopyColorTableEXT(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+void glGetColorTableEXT(GLenum target, GLenum format, GLenum type, GLvoid *table);
+void glGetColorTableParamaterfvEXT(GLenum target, GLenum pname, GLfloat *params);
+void glGetColorTavleParameterivEXT(GLenum target, GLenum pname, GLint *params);
+
+/* SGI_compiled_vertex_array */
+void glLockArraysSGI(GLint first, GLsizei count);
+void glUnlockArraysSGI();
+
+/* SGI_cull_vertex */
+void glCullParameterdvSGI(GLenum pname, GLdouble* params);
+void glCullParameterfvSGI(GLenum pname, GLfloat* params);
+
+/* SGI_index_func */
+void glIndexFuncSGI(GLenum func, GLclampf ref);
+
+/* SGI_index_material */
+void glIndexMaterialSGI(GLenum face, GLenum mode);
+
+/* WIN_swap_hint */
+void glAddSwapHintRectWin(GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+    // wxUSE_GLCANVAS
+#endif
+    // _WX_GLCANVAS_H_
+
diff --git a/include/wx/msw/setup0.h b/include/wx/msw/setup0.h
index d8e736f282..f86739919a 100644
--- a/include/wx/msw/setup0.h
+++ b/include/wx/msw/setup0.h
@@ -217,6 +217,9 @@
 // Recommended setting: 1
 #define wxUSE_PLOT           1
 
+// OpenGL canvas
+#define wxUSE_GLCANVAS       0
+
 // ----------------------------------------------------------------------------
 // Postscript support settings
 // ----------------------------------------------------------------------------
diff --git a/samples/opengl/cube/Makefile b/samples/opengl/cube/Makefile
new file mode 100644
index 0000000000..56fac3db98
--- /dev/null
+++ b/samples/opengl/cube/Makefile
@@ -0,0 +1,31 @@
+#
+# File:		Makefile
+# Author:	Robert Roebling
+# Created:	1999
+# Updated:	
+# Copyright:	(c) 1998 Robert Roebling
+#
+# Makefile for OpenGl demo (GTK version)
+#
+# This makefile requires wxWindows/GTK to be 
+# installed (possibly using "make install")
+# on your system.
+#
+
+CC = gcc
+WXCONFIG=../../../wx-config
+WXINCLUDE=-I../../../include
+WXLIB=-L../../../lib
+
+cube: cube.o # glcanvas.o
+	$(CC) -o cube cube.o `$(WXCONFIG) --libs` $(WXLIB) -lMesaGL -lMesaGLU
+
+cube.o: cube.cpp
+	$(CC) `$(WXCONFIG) --cflags` -I../../gtk $(WXINCLUDE) -c cube.cpp
+
+glcanvas.o: ../../gtk/glcanvas.cpp
+	$(CC) `$(WXCONFIG) --cflags` `gtk-config --cflags` -I../../gtk $(WXINCLUDE) -c ../../gtk/glcanvas.cpp
+
+clean: 
+	rm -f *.o cube
+
diff --git a/samples/opengl/cube/cube.cpp b/samples/opengl/cube/cube.cpp
new file mode 100644
index 0000000000..2f145970d2
--- /dev/null
+++ b/samples/opengl/cube/cube.cpp
@@ -0,0 +1,508 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        cube.cpp
+// Purpose:     wxGLCanvas demo program
+// Author:      Julian Smart
+// Modified by:
+// Created:     04/01/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#pragma interface
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "wx/log.h"
+
+#include "cube.h"
+
+#ifndef __WXMSW__     // for wxStopWatch, see remark below 
+#include <sys/time.h>
+#include <sys/unistd.h>
+#else
+#include <sys/timeb.h>
+#endif
+
+#define ID_NEW_WINDOW 10000
+#define ID_DEF_ROTATE_LEFT_KEY 10001
+#define ID_DEF_ROTATE_RIGHT_KEY 10002
+
+/*----------------------------------------------------------
+  Control to get a keycode
+  ----------------------------------------------------------*/
+class ScanCodeCtrl : public wxTextCtrl
+{
+public:
+  ScanCodeCtrl( wxWindow* parent, wxWindowID id, int code,
+                const wxPoint& pos, const wxSize& size );
+  void OnChar( wxKeyEvent& event ) { } /* do nothing */
+  void OnKeyDown(wxKeyEvent& event);
+private:
+// any class wishing to process wxWindows events must use this macro
+  DECLARE_EVENT_TABLE()
+};
+BEGIN_EVENT_TABLE( ScanCodeCtrl, wxTextCtrl )
+  EVT_CHAR( ScanCodeCtrl::OnChar )
+  EVT_KEY_DOWN( ScanCodeCtrl::OnKeyDown )
+END_EVENT_TABLE()
+
+ScanCodeCtrl::ScanCodeCtrl( wxWindow* parent, wxWindowID id, int code,
+                             const wxPoint& pos, const wxSize& size )
+                  : wxTextCtrl( parent, id, "", pos, size )
+{ wxString buf;
+  buf.Printf( "0x%04x", code );
+  SetValue( buf );
+}
+
+void ScanCodeCtrl::OnKeyDown( wxKeyEvent& event )
+{ wxString buf;
+  buf.Printf( "0x%04x", event.KeyCode() );
+  SetValue( buf );
+}
+
+/*------------------------------------------------------------------
+ Dialog for defining a keypress
+-------------------------------------------------------------------*/
+
+class ScanCodeDialog : public wxDialog
+{
+public:
+  ScanCodeDialog( wxWindow* parent, wxWindowID id, const int code,
+                  const wxString &descr, const wxString& title );
+  int GetValue(); 
+private:
+  ScanCodeCtrl       *m_ScanCode;
+  wxTextCtrl         *m_Description;
+};
+
+ScanCodeDialog::ScanCodeDialog( wxWindow* parent, wxWindowID id, 
+               const int code, const wxString &descr, const wxString& title )
+          : wxDialog( parent, id, title, wxPoint(-1, -1), wxSize(96*2,76*2) )
+{
+  new wxStaticText( this, -1, "Scancode", wxPoint(4*2,3*2), 
+                    wxSize(31*2,12*2) );
+  m_ScanCode = new ScanCodeCtrl( this, -1, code, wxPoint(37*2,6*2), 
+                                 wxSize(53*2,14*2) );
+
+  new wxStaticText( this, -1, "Description", wxPoint(4*2,24*2),
+                    wxSize(32*2,12*2) );
+  m_Description = new wxTextCtrl( this, -1, descr, wxPoint(37*2,27*2),
+                                  wxSize(53*2,14*2) );
+
+  new wxButton( this, wxID_OK, "Ok", wxPoint(20*2,50*2), wxSize(20*2,13*2) );
+  new wxButton( this, wxID_CANCEL, "Cancel", wxPoint(44*2,50*2),
+                wxSize(25*2,13*2) );
+}
+
+int ScanCodeDialog::GetValue()
+{
+  int code;
+  wxString buf = m_ScanCode->GetValue();
+  sscanf( buf.c_str(), "%i", &code );
+  return( code );
+}
+
+/*----------------------------------------------------------------------
+  Utility function to get the elapsed time (in msec) since a given point
+  in time (in sec)  (because current version of wxGetElapsedTime doesn´t 
+  works right with glibc-2.1 and linux, at least for me) 
+-----------------------------------------------------------------------*/
+unsigned long wxStopWatch( unsigned long *sec_base )
+{
+  unsigned long secs,msec;
+
+#ifndef __WXMSW__        // think every unice has gettimeofday
+  struct timeval tv;
+  gettimeofday( &tv, (struct timezone *)NULL );
+  secs = tv.tv_sec;
+  msec = tv.tv_usec/1000;
+#else
+  struct timeb tb;
+
+  ftime( &tb );
+
+  secs = tb.time;
+
+  msec = tb.millitm;
+
+#endif
+
+  if( *sec_base == 0 )
+    *sec_base = secs;
+    
+  return( (secs-*sec_base)*1000 + msec );
+}
+
+/*----------------------------------------------------------------
+  Implementation of Test-GLCanvas
+-----------------------------------------------------------------*/
+
+BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
+  EVT_SIZE(TestGLCanvas::OnSize)
+  EVT_PAINT(TestGLCanvas::OnPaint)
+  EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground)
+  EVT_KEY_DOWN( TestGLCanvas::OnKeyDown )
+  EVT_KEY_UP( TestGLCanvas::OnKeyUp )
+  EVT_ENTER_WINDOW( TestGLCanvas::OnEnterWindow )
+END_EVENT_TABLE()
+
+unsigned long  TestGLCanvas::m_secbase = 0;
+int            TestGLCanvas::m_TimeInitialized = 0;
+unsigned long  TestGLCanvas::m_xsynct;
+unsigned long  TestGLCanvas::m_gsynct;
+
+TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id,
+    const wxPoint& pos, const wxSize& size, long style, const wxString& name):
+  wxGLCanvas(parent, (wxGLCanvas*) NULL, id, pos, size, style, name )
+{
+    m_init = FALSE;
+    m_gllist = 0;
+    m_rleft = WXK_LEFT;
+    m_rright = WXK_RIGHT;
+}
+
+TestGLCanvas::TestGLCanvas(wxWindow *parent, const TestGLCanvas &other, 
+    wxWindowID id, const wxPoint& pos, const wxSize& size, long style,
+    const wxString& name ) :
+      wxGLCanvas(parent, other.GetContext(), id, pos, size, style, name  )
+{
+    m_init = FALSE;
+    m_gllist = other.m_gllist;    /* share display list */
+    m_rleft = WXK_LEFT;
+    m_rright = WXK_RIGHT;
+}
+
+TestGLCanvas::~TestGLCanvas()
+{
+}
+
+void TestGLCanvas::Render()
+{
+    wxPaintDC dc(this);
+
+#ifndef __WXMOTIF__
+    if (!GetContext()) return;
+#endif
+
+    SetCurrent();
+    /* init OpenGL once, but after SetCurrent */
+    if (!m_init)
+    {
+        InitGL();
+        m_init = TRUE;
+    }
+    
+    /* clear color and depth buffers */
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  if( m_gllist == 0 )
+  {
+    m_gllist = glGenLists( 1 );
+    glNewList( m_gllist, GL_COMPILE_AND_EXECUTE );        
+    /* draw six faces of a cube */
+    glBegin(GL_QUADS);
+    glNormal3f( 0.0F, 0.0F, 1.0F);
+    glVertex3f( 0.5F, 0.5F, 0.5F); glVertex3f(-0.5F, 0.5F, 0.5F);
+    glVertex3f(-0.5F,-0.5F, 0.5F); glVertex3f( 0.5F,-0.5F, 0.5F);
+
+    glNormal3f( 0.0F, 0.0F,-1.0F);
+    glVertex3f(-0.5F,-0.5F,-0.5F); glVertex3f(-0.5F, 0.5F,-0.5F);
+    glVertex3f( 0.5F, 0.5F,-0.5F); glVertex3f( 0.5F,-0.5F,-0.5F);
+
+    glNormal3f( 0.0F, 1.0F, 0.0F);
+    glVertex3f( 0.5F, 0.5F, 0.5F); glVertex3f( 0.5F, 0.5F,-0.5F);
+    glVertex3f(-0.5F, 0.5F,-0.5F); glVertex3f(-0.5F, 0.5F, 0.5F);
+
+    glNormal3f( 0.0F,-1.0F, 0.0F);
+    glVertex3f(-0.5F,-0.5F,-0.5F); glVertex3f( 0.5F,-0.5F,-0.5F);
+    glVertex3f( 0.5F,-0.5F, 0.5F); glVertex3f(-0.5F,-0.5F, 0.5F);
+
+    glNormal3f( 1.0F, 0.0F, 0.0F);
+    glVertex3f( 0.5F, 0.5F, 0.5F); glVertex3f( 0.5F,-0.5F, 0.5F);
+    glVertex3f( 0.5F,-0.5F,-0.5F); glVertex3f( 0.5F, 0.5F,-0.5F);
+
+    glNormal3f(-1.0F, 0.0F, 0.0F);
+    glVertex3f(-0.5F,-0.5F,-0.5F); glVertex3f(-0.5F,-0.5F, 0.5F);
+    glVertex3f(-0.5F, 0.5F, 0.5F); glVertex3f(-0.5F, 0.5F,-0.5F);
+    glEnd();
+
+    glEndList();
+  }
+  else
+    glCallList( m_gllist );    
+
+  glFlush();
+  SwapBuffers();
+}
+
+void TestGLCanvas::OnEnterWindow( wxMouseEvent& event )
+{
+    SetFocus();
+}
+
+void TestGLCanvas::OnPaint( wxPaintEvent& event )
+{
+    Render();
+}
+
+void TestGLCanvas::OnSize(wxSizeEvent& event)
+{
+    int width, height;
+    GetClientSize(& width, & height);
+
+#ifndef __WXMOTIF__
+    if (GetContext())
+#endif
+    {
+        SetCurrent();
+        glViewport(0, 0, width, height);
+    }
+}
+
+void TestGLCanvas::OnEraseBackground(wxEraseEvent& event)
+{
+  // Do nothing, to avoid flashing.
+}
+
+void TestGLCanvas::InitGL()
+{
+    SetCurrent();
+    
+    /* set viewing projection */
+    glMatrixMode(GL_PROJECTION);
+    glFrustum(-0.5F, 0.5F, -0.5F, 0.5F, 1.0F, 3.0F);
+
+    /* position viewer */
+    glMatrixMode(GL_MODELVIEW);
+    glTranslatef(0.0F, 0.0F, -2.0F);
+
+    /* position object */
+    glRotatef(30.0F, 1.0F, 0.0F, 0.0F);
+    glRotatef(30.0F, 0.0F, 1.0F, 0.0F);
+
+    glEnable(GL_DEPTH_TEST);
+    glEnable(GL_LIGHTING);
+    glEnable(GL_LIGHT0);
+}
+
+GLfloat TestGLCanvas::CalcRotateSpeed( unsigned long acceltime )
+{
+  GLfloat t,v;
+
+  t = ((GLfloat)acceltime) / 1000.0f;
+
+  if( t < 0.5f )
+    v = t;
+  else if( t < 1.0f )
+    v = t * (2.0f - t);
+  else
+    v = 0.75f;
+
+  return(v);
+}
+
+GLfloat TestGLCanvas::CalcRotateAngle( unsigned long lasttime,
+                                  unsigned long acceltime )
+{
+    GLfloat t,s1,s2;
+
+    t = ((GLfloat)(acceltime - lasttime)) / 1000.0f;
+    s1 = CalcRotateSpeed( lasttime );
+    s2 = CalcRotateSpeed( acceltime );
+    
+    return( t * (s1 + s2) * 135.0f );
+}
+
+void TestGLCanvas::Action( long code, unsigned long lasttime,
+                           unsigned long acceltime )
+{
+    GLfloat angle = CalcRotateAngle( lasttime, acceltime );
+
+    if (code == m_rleft) 
+        Rotate( angle );
+    else if (code == m_rright) 
+            Rotate( -angle );
+}
+
+void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
+{
+    long evkey = event.KeyCode();
+    if (evkey == 0) return;
+
+    if (!m_TimeInitialized)
+    {
+        m_TimeInitialized = 1;
+        m_xsynct = event.m_timeStamp;
+        m_gsynct = wxStopWatch(&m_secbase);
+
+        m_Key = evkey;
+        m_StartTime = 0;
+        m_LastTime = 0;
+        m_LastRedraw = 0;
+    }
+
+    unsigned long currTime = event.m_timeStamp - m_xsynct;
+  
+    if (evkey != m_Key)
+    {
+        m_Key = evkey;
+        m_LastRedraw = m_StartTime = m_LastTime = currTime;
+    }
+
+    if (currTime >= m_LastRedraw)      // Redraw:
+    {
+        Action( m_Key, m_LastTime-m_StartTime, currTime-m_StartTime );
+                  
+        m_LastRedraw = wxStopWatch(&m_secbase) - m_gsynct;
+        m_LastTime = currTime;
+    }
+    
+    event.Skip();
+}
+
+void TestGLCanvas::OnKeyUp( wxKeyEvent& event )
+{
+    m_Key = 0;
+    m_StartTime = 0;
+    m_LastTime = 0;
+    m_LastRedraw = 0;
+    
+    event.Skip();
+}
+
+void TestGLCanvas::Rotate( GLfloat deg )
+{
+    SetCurrent();
+
+    glMatrixMode(GL_MODELVIEW);
+    glRotatef((GLfloat)deg, 0.0F, 0.0F, 1.0F);
+    Refresh(FALSE);
+}
+
+
+/* -----------------------------------------------------------------------
+  Main Window
+-------------------------------------------------------------------------*/
+
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+    EVT_MENU(wxID_EXIT, MyFrame::OnExit)
+    EVT_MENU( ID_NEW_WINDOW, MyFrame::OnNewWindow)
+    EVT_MENU( ID_DEF_ROTATE_LEFT_KEY, MyFrame::OnDefRotateLeftKey)
+    EVT_MENU( ID_DEF_ROTATE_RIGHT_KEY, MyFrame::OnDefRotateRightKey)
+END_EVENT_TABLE()
+
+// My frame constructor
+MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
+                 const wxSize& size, long style) 
+         : wxFrame(frame, -1, title, pos, size, style)
+{
+    m_canvas = NULL;
+}
+
+// Intercept menu commands
+void MyFrame::OnExit(wxCommandEvent& event)
+{
+    Destroy();
+}
+
+void MyFrame::OnNewWindow()
+{
+  MyFrame *frame = new MyFrame(NULL, "Cube OpenGL Demo Clone",
+                               wxPoint(50, 50), wxSize(400, 300));
+  // Give it an icon
+#ifdef wx_msw
+  frame->SetIcon(wxIcon("mondrian"));
+#endif
+
+  // Make a menubar
+  wxMenu *winMenu = new wxMenu;
+
+  winMenu->Append(wxID_EXIT, "&Close");
+  winMenu->Append(ID_NEW_WINDOW, "&New" );
+  wxMenuBar *menuBar = new wxMenuBar;
+  menuBar->Append(winMenu, "&Window");
+
+  winMenu = new wxMenu;
+  winMenu->Append(ID_DEF_ROTATE_LEFT_KEY, "Rotate &left");
+  winMenu->Append(ID_DEF_ROTATE_RIGHT_KEY, "Rotate &right");
+  menuBar->Append(winMenu, "&Key");
+
+  frame->SetMenuBar(menuBar);
+
+  frame->m_canvas = new TestGLCanvas( frame, *m_canvas, -1, 
+               wxPoint(0, 0), wxSize(200, 200) );
+  
+  // Show the frame
+  frame->Show(TRUE);
+}
+
+void MyFrame::OnDefRotateLeftKey()
+{
+  ScanCodeDialog dial( this, -1, m_canvas->m_rleft, 
+                       wxString("Left"), "Define key" );
+  int result = dial.ShowModal();
+  if( result == wxID_OK )
+    m_canvas->m_rleft = dial.GetValue();
+}
+void MyFrame::OnDefRotateRightKey()
+{
+  ScanCodeDialog dial( this, -1, m_canvas->m_rright, 
+                       wxString("Right"), "Define key" );
+  int result = dial.ShowModal();
+  if( result == wxID_OK )
+    m_canvas->m_rright = dial.GetValue();
+}
+
+/*------------------------------------------------------------------
+  Application object ( equivalent to main() )
+------------------------------------------------------------------ */
+
+IMPLEMENT_APP(MyApp)
+
+bool MyApp::OnInit(void)
+{
+  wxLog::SetTraceMask(wxTraceMessages);
+
+  // Create the main frame window
+  MyFrame *frame = new MyFrame(NULL, "Cube OpenGL Demo", wxPoint(50, 50),
+                               wxSize(400, 300));
+  // Give it an icon
+#ifdef wx_msw
+  frame->SetIcon(wxIcon("mondrian"));
+#endif
+
+  // Make a menubar
+  wxMenu *winMenu = new wxMenu;
+
+  winMenu->Append(wxID_EXIT, "&Close");
+  winMenu->Append(ID_NEW_WINDOW, "&New" );
+  wxMenuBar *menuBar = new wxMenuBar;
+  menuBar->Append(winMenu, "&Window");
+
+  winMenu = new wxMenu;
+  winMenu->Append(ID_DEF_ROTATE_LEFT_KEY, "Rotate &left");
+  winMenu->Append(ID_DEF_ROTATE_RIGHT_KEY, "Rotate &right");
+  menuBar->Append(winMenu, "&Key");
+
+  frame->SetMenuBar(menuBar);
+
+  frame->m_canvas = new TestGLCanvas(frame, -1, wxPoint(0, 0), wxSize(200, 200));
+
+  // Show the frame
+  frame->Show(TRUE);
+  
+  return TRUE;
+}
diff --git a/samples/opengl/cube/cube.h b/samples/opengl/cube/cube.h
new file mode 100644
index 0000000000..66732f2453
--- /dev/null
+++ b/samples/opengl/cube/cube.h
@@ -0,0 +1,93 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        cube.h
+// Purpose:     wxGLCanvas demo program
+// Author:      Julian Smart
+// Modified by:
+// Created:     04/01/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_CUBE_H_
+#define _WX_CUBE_H_
+
+#include <wx/glcanvas.h>
+
+// Define a new application type
+class MyApp: public wxApp
+{
+public:
+    bool OnInit(void);
+};
+
+// Define a new frame type
+class TestGLCanvas;
+class MyFrame: public wxFrame
+{
+public:
+    MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
+            const wxSize& size, long style = wxDEFAULT_FRAME_STYLE);
+
+    void OnExit(wxCommandEvent& event);
+    void OnNewWindow();
+    void OnDefRotateLeftKey();
+    void OnDefRotateRightKey();
+    
+public:
+    TestGLCanvas*    m_canvas;
+
+DECLARE_EVENT_TABLE()
+};
+
+class TestGLCanvas: public wxGLCanvas
+{
+  friend class MyFrame;
+public:
+ TestGLCanvas(wxWindow *parent, const wxWindowID id = -1, 
+    const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
+    long style = 0, const wxString& name = "TestGLCanvas");
+ TestGLCanvas(wxWindow *parent, const TestGLCanvas &other,
+          const wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
+          const wxSize& size = wxDefaultSize, long style = 0,
+          const wxString& name = "TestGLCanvas" );
+   
+ ~TestGLCanvas(void);
+
+ void OnPaint(wxPaintEvent& event);
+ void OnSize(wxSizeEvent& event);
+ void OnEraseBackground(wxEraseEvent& event);
+ void OnKeyDown(wxKeyEvent& event);
+ void OnKeyUp(wxKeyEvent& event);
+ void OnEnterWindow( wxMouseEvent& event );
+ 
+ void Render( void );
+ void InitGL(void);
+ void Rotate( GLfloat deg );
+ static GLfloat CalcRotateSpeed( unsigned long acceltime );
+ static GLfloat CalcRotateAngle( unsigned long lasttime,
+                                 unsigned long acceltime );
+ void Action( long code, unsigned long lasttime,
+              unsigned long acceltime );
+   
+private:
+  bool   m_init;
+  GLuint m_gllist;
+  long   m_rleft;
+  long   m_rright;
+
+  static unsigned long  m_secbase;
+  static int            m_TimeInitialized;
+  static unsigned long  m_xsynct;
+  static unsigned long  m_gsynct;
+ 
+  long           m_Key;
+  unsigned long  m_StartTime;
+  unsigned long  m_LastTime;
+  unsigned long  m_LastRedraw;
+
+DECLARE_EVENT_TABLE()
+};
+
+#endif
+
diff --git a/samples/opengl/cube/cube.rc b/samples/opengl/cube/cube.rc
new file mode 100644
index 0000000000..7655c62a4c
--- /dev/null
+++ b/samples/opengl/cube/cube.rc
@@ -0,0 +1,3 @@
+mondrian ICON "mondrian.ico"
+#include "wx/msw/wx.rc"
+
diff --git a/samples/opengl/cube/makefile.b32 b/samples/opengl/cube/makefile.b32
new file mode 100644
index 0000000000..7bc170c87a
--- /dev/null
+++ b/samples/opengl/cube/makefile.b32
@@ -0,0 +1,18 @@
+#
+# File:		makefile.b32
+# Author:	Julian Smart
+# Created:	1999
+# Updated:	
+# Copyright:
+#
+# Makefile : Builds sample for 32-bit BC++
+
+WXDIR = $(WXWIN)
+
+TARGET=cube
+#EXTRALIBS=$(WXDIR)\lib\glcanvas.lib
+#EXTRACPPFLAGS=-I$(WXDIR)\utils\glcanvas\win
+OBJECTS = $(TARGET).obj
+
+!include $(WXDIR)\src\makeprog.b32
+
diff --git a/samples/opengl/cube/makefile.bcc b/samples/opengl/cube/makefile.bcc
new file mode 100644
index 0000000000..b46274d17e
--- /dev/null
+++ b/samples/opengl/cube/makefile.bcc
@@ -0,0 +1,21 @@
+#
+# File:		makefile.bcc
+# Author:	Julian Smart
+# Created:	1998
+# Updated:	
+#
+# Builds a BC++ 16-bit sample
+
+!if "$(WXWIN)" == ""
+!error You must define the WXWIN variable in autoexec.bat, e.g. WXWIN=c:\wx
+!endif
+
+WXDIR = $(WXWIN)
+
+TARGET=cube
+#EXTRALIBS=$(WXDIR)\lib\glcanvas.lib
+#EXTRACPPFLAGS=-I$(WXDIR)\utils\glcanvas\win
+OBJECTS = $(TARGET).obj
+
+!include $(WXDIR)\src\makeprog.bcc
+
diff --git a/samples/opengl/cube/makefile.g95 b/samples/opengl/cube/makefile.g95
new file mode 100644
index 0000000000..60381560ed
--- /dev/null
+++ b/samples/opengl/cube/makefile.g95
@@ -0,0 +1,18 @@
+#
+# File:         makefile.g95
+# Author:       Julian Smart
+# Created:      1999
+# Updated:
+# Copyright:    (c) Julian Smart, 1999
+#
+# Makefile for wxWindows sample (Cygwin/Mingw32).
+
+WXDIR = ../../..
+
+TARGET=cube
+#EXTRACPPFLAGS=-I../../win
+EXTRALIBS=-lopengl32 -lglu32
+OBJECTS = $(TARGET).o
+
+include $(WXDIR)/src/makeprog.g95
+
diff --git a/samples/opengl/cube/makefile.unx b/samples/opengl/cube/makefile.unx
new file mode 100644
index 0000000000..ecf313ff33
--- /dev/null
+++ b/samples/opengl/cube/makefile.unx
@@ -0,0 +1,23 @@
+#
+# File:		makefile.unx
+# Author:	Julian Smart
+# Created:	1998
+# Updated:	
+# Copyright:	(c) 1998 Julian Smart
+#
+# "%W% %G%"
+#
+# Makefile for cube example (UNIX).
+
+PROGRAM=cube
+
+OPENGLHOME=/home/jacs/mesa/Mesa-2.3
+
+EXTRACPPFLAGS=-I$(OPENGLHOME)/include
+EXTRALDFLAGS=-L$(OPENGLHOME)/lib
+EXTRALDLIBS=-lMesaGL -lMesaGLU
+
+OBJECTS=$(PROGRAM).o
+
+include ../../../src/makeprog.env
+
diff --git a/samples/opengl/cube/makefile.vc b/samples/opengl/cube/makefile.vc
new file mode 100644
index 0000000000..c761a91325
--- /dev/null
+++ b/samples/opengl/cube/makefile.vc
@@ -0,0 +1,26 @@
+#
+# File:		makefile.vc
+# Author:	Julian Smart
+# Created:	1999
+# Updated:	
+# Copyright:	(c) Julian Smart
+#
+# Makefile : Builds sample (VC++, WIN32)
+# Use FINAL=1 argument to nmake to build final version with no debug info.
+
+# Set WXDIR for your system
+WXDIR = $(WXWIN)
+
+!if "$(FINAL)" == "1"
+!else
+LIBEXT=_d
+!endif
+
+PROGRAM=cube
+OBJECTS = $(PROGRAM).obj
+#EXTRAINC=-I..\..\win
+#EXTRALIBS=$(WXDIR)\lib\glcanvas$(LIBEXT).lib glu32.lib opengl32.lib
+EXTRALIBS=glu32.lib opengl32.lib
+
+!include $(WXDIR)\src\makeprog.vc
+
diff --git a/samples/opengl/cube/makefile.wat b/samples/opengl/cube/makefile.wat
new file mode 100644
index 0000000000..66cb0511c1
--- /dev/null
+++ b/samples/opengl/cube/makefile.wat
@@ -0,0 +1,17 @@
+#
+# Makefile for WATCOM
+#
+# Created by Julian Smart, January 1999
+# 
+#
+
+WXDIR = $(%WXWIN)
+
+PROGRAM = cube
+OBJECTS = $(PROGRAM).obj
+#EXTRALIBS=$(WXDIR)\lib\glcanvas.lib
+#EXTRACPPFLAGS=-I$(WXDIR)\utils\glcanvas\win
+
+!include $(WXDIR)\src\makeprog.wat
+
+
diff --git a/samples/opengl/cube/mondrian.ico b/samples/opengl/cube/mondrian.ico
new file mode 100644
index 0000000000000000000000000000000000000000..2310c5d275a87af295d5ea8dc79ea417a5e74c53
GIT binary patch
literal 766
zcmZQzU<5)11px*Sc)`TLAO@s0fLH;D9e|jTfdxnc0Z<M**w4TKL=5})Lnt5#WHKB$
zaDbtqp#doIAB-6O{|B*v7zjZ^AOa2W|NsACHyAJ}De?dRKnp(HN~rljcR;{k;{zQE
i@;}UZ|9Q?Fpp*~yJCwmWbLIrN`9Qm9%}2L?p!oo$cZ4ed

literal 0
HcmV?d00001

diff --git a/samples/opengl/isosurf/Makefile b/samples/opengl/isosurf/Makefile
new file mode 100644
index 0000000000..b11b16b7b6
--- /dev/null
+++ b/samples/opengl/isosurf/Makefile
@@ -0,0 +1,32 @@
+#
+# File:		Makefile
+# Author:	Robert Roebling
+# Created:	1999
+# Updated:	
+# Copyright:	(c) 1998 Robert Roebling
+#
+# Makefile for OpenGl demo (GTK version)
+#
+# This makefile requires wxWindows/GTK to be 
+# installed (possibly using "make install")
+# on your system.
+#
+
+CC = g++
+WXCONFIG=../../../wx-config
+WXINCLUDE=-I../../../include
+WXLIB=-L../../../lib
+
+isosurf: isosurf.o # glcanvas.o
+	$(CC) -o isosurf \
+	isosurf.o \
+	`$(WXCONFIG) --libs` $(WXLIB) -lMesaGL -lMesaGLU
+
+isosurf.o: isosurf.cpp
+	$(CC) `$(WXCONFIG) --cflags` -I../../gtk $(WXINCLUDE) -c isosurf.cpp
+
+glcanvas.o: ../../gtk/glcanvas.cpp
+	$(CC) `$(WXCONFIG) --cflags` `gtk-config --cflags` -I../../gtk -c $(WXINCLUDE) ../../gtk/glcanvas.cpp
+
+clean: 
+	rm -f *.o isosurf
diff --git a/samples/opengl/isosurf/isosurf.cpp b/samples/opengl/isosurf/isosurf.cpp
new file mode 100644
index 0000000000..6ba560cff1
--- /dev/null
+++ b/samples/opengl/isosurf/isosurf.cpp
@@ -0,0 +1,412 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        isosurf.cpp
+// Purpose:     wxGLCanvas demo program
+// Author:      Brian Paul (original gltk version), Wolfram Gloger
+// Modified by: Julian Smart
+// Created:     04/01/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#pragma interface
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "wx/timer.h"
+#include "wx/glcanvas.h"
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#include "isosurf.h"
+
+// The following part is taken largely unchanged from the original C Version
+
+#include <math.h>
+
+GLboolean speed_test = GL_FALSE;
+GLboolean use_vertex_arrays = GL_FALSE;
+
+GLboolean doubleBuffer = GL_TRUE;
+
+GLboolean smooth = GL_TRUE;
+GLboolean lighting = GL_TRUE;
+
+
+#define MAXVERTS 10000
+
+static GLfloat verts[MAXVERTS][3];
+static GLfloat norms[MAXVERTS][3];
+static GLint numverts;
+
+static GLfloat xrot;
+static GLfloat yrot;
+
+
+static void read_surface( char *filename )
+{
+   FILE *f;
+
+   f = fopen(filename,"r");
+   if (!f) {
+      wxString msg("Couldn't read ");
+      msg += filename;
+      wxMessageBox(msg);
+      return;
+   }
+
+   numverts = 0;
+   while (!feof(f) && numverts<MAXVERTS) {
+      fscanf( f, "%f %f %f  %f %f %f",
+	      &verts[numverts][0], &verts[numverts][1], &verts[numverts][2],
+	      &norms[numverts][0], &norms[numverts][1], &norms[numverts][2] );
+      numverts++;
+   }
+   numverts--;
+
+   printf("%d vertices, %d triangles\n", numverts, numverts-2);
+   fclose(f);
+}
+
+
+static void draw_surface( void )
+{
+   GLint i;
+
+#ifdef GL_EXT_vertex_array
+   if (use_vertex_arrays) {
+      glDrawArraysEXT( GL_TRIANGLE_STRIP, 0, numverts );
+   }
+   else {
+#endif
+      glBegin( GL_TRIANGLE_STRIP );
+      for (i=0;i<numverts;i++) {
+         glNormal3fv( norms[i] );
+         glVertex3fv( verts[i] );
+      }
+      glEnd();
+#ifdef GL_EXT_vertex_array
+   }
+#endif
+}
+
+
+static void draw1(void)
+{
+    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+    glPushMatrix();
+    glRotatef( yrot, 0.0, 1.0, 0.0 );
+    glRotatef( xrot, 1.0, 0.0, 0.0 );
+
+    draw_surface();
+
+    glPopMatrix();
+
+    glFlush();
+}
+
+
+static void InitMaterials(void)
+{
+    static float ambient[] = {0.1, 0.1, 0.1, 1.0};
+    static float diffuse[] = {0.5, 1.0, 1.0, 1.0};
+    static float position0[] = {0.0, 0.0, 20.0, 0.0};
+    static float position1[] = {0.0, 0.0, -20.0, 0.0};
+    static float front_mat_shininess[] = {60.0};
+    static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0};
+    static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0};
+    /*
+    static float back_mat_shininess[] = {60.0};
+    static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0};
+    static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0};
+    */
+    static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
+    static float lmodel_twoside[] = {GL_FALSE};
+
+    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
+    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
+    glLightfv(GL_LIGHT0, GL_POSITION, position0);
+    glEnable(GL_LIGHT0);
+    
+    glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
+    glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
+    glLightfv(GL_LIGHT1, GL_POSITION, position1);
+    glEnable(GL_LIGHT1);
+    
+    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
+    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
+    glEnable(GL_LIGHTING);
+
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse);
+}
+
+
+static void Init(void)
+{
+   glClearColor(0.0, 0.0, 0.0, 0.0);
+
+   glShadeModel(GL_SMOOTH);
+   glEnable(GL_DEPTH_TEST);
+
+   InitMaterials();
+
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 );
+
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef( 0.0, 0.0, -6.0 );
+
+#ifdef GL_EXT_vertex_array
+   if (use_vertex_arrays) {
+      glVertexPointerEXT( 3, GL_FLOAT, 0, numverts, verts );
+      glNormalPointerEXT( GL_FLOAT, 0, numverts, norms );
+      glEnable( GL_VERTEX_ARRAY_EXT );
+      glEnable( GL_NORMAL_ARRAY_EXT );
+   }
+#endif
+}
+
+
+static void Reshape(int width, int height)
+{
+  glViewport(0, 0, (GLint)width, (GLint)height);
+}
+
+
+static GLenum Args(int argc, char **argv)
+{
+   GLint i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-sb") == 0) {
+         doubleBuffer = GL_FALSE;
+      }
+      else if (strcmp(argv[i], "-db") == 0) {
+         doubleBuffer = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-speed") == 0) {
+         speed_test = GL_TRUE;
+         doubleBuffer = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-va") == 0) {
+         use_vertex_arrays = GL_TRUE;
+      }
+      else {
+         wxString msg("Bad option: ");
+         msg += argv[i];
+         wxMessageBox(msg);
+         return GL_FALSE;
+      }
+   }
+
+   return GL_TRUE;
+}
+
+// The following part was written for wxWindows 1.66
+MyFrame *frame = NULL;
+
+IMPLEMENT_APP(MyApp)
+
+// `Main program' equivalent, creating windows and returning main app frame
+bool MyApp::OnInit(void)
+{
+  Args(argc, argv);
+
+  // Create the main frame window
+  frame = new MyFrame(NULL, "Isosurf GL Sample", wxPoint(50, 50), wxSize(200, 200));
+
+  // Give it an icon
+  frame->SetIcon(wxIcon("mondrian"));
+
+  // Make a menubar
+  wxMenu *fileMenu = new wxMenu;
+
+  fileMenu->Append(wxID_EXIT, "E&xit");
+  wxMenuBar *menuBar = new wxMenuBar;
+  menuBar->Append(fileMenu, "&File");
+  frame->SetMenuBar(menuBar);
+
+  // Make a TestGLCanvas
+
+  // JACS
+#ifdef __WXMSW__
+  int *gl_attrib = NULL;
+#else
+  int gl_attrib[20] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
+			GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1,
+			GLX_DOUBLEBUFFER, None };
+#endif
+
+  if(!doubleBuffer)
+   {
+      printf("don't have double buffer, disabling\n");
+#ifdef __WXGTK__
+      gl_attrib[9] = None;
+#endif
+      doubleBuffer = GL_FALSE;
+  }
+  frame->m_canvas = new TestGLCanvas(frame, -1, wxPoint(0, 0), wxSize(200, 200), 0, "TestGLCanvas",
+				   gl_attrib);
+
+  // Show the frame
+  frame->Show(TRUE);
+
+  frame->m_canvas->SetCurrent();
+  read_surface( "isosurf.dat" );
+
+  Init();
+
+  return TRUE;
+}
+
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+    EVT_MENU(wxID_EXIT, MyFrame::OnExit)
+END_EVENT_TABLE()
+
+// My frame constructor
+MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
+    const wxSize& size, long style):
+  wxFrame(frame, -1, title, pos, size, style)
+{
+    m_canvas = NULL;
+}
+
+// Intercept menu commands
+void MyFrame::OnExit(wxCommandEvent& event)
+{
+    Destroy();
+}
+
+/*
+ * TestGLCanvas implementation
+ */
+
+BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
+    EVT_SIZE(TestGLCanvas::OnSize)
+    EVT_PAINT(TestGLCanvas::OnPaint)
+    EVT_CHAR(TestGLCanvas::OnChar)
+    EVT_MOUSE_EVENTS(TestGLCanvas::OnMouseEvent)
+    EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground)
+END_EVENT_TABLE()
+
+TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id,
+    const wxPoint& pos, const wxSize& size, long style, const wxString& name, int* gl_attrib):
+  wxGLCanvas(parent, id, pos, size, style, name, gl_attrib)
+{
+   parent->Show(TRUE);
+   SetCurrent();
+   /* Make sure server supports the vertex array extension */
+   char* extensions = (char *) glGetString( GL_EXTENSIONS );
+   if (!extensions || !strstr( extensions, "GL_EXT_vertex_array" )) {
+      use_vertex_arrays = GL_FALSE;
+   }
+}
+
+
+TestGLCanvas::~TestGLCanvas(void)
+{
+}
+
+void TestGLCanvas::OnPaint( wxPaintEvent& event )
+{
+    // This is a dummy, to avoid an endless succession of paint messages.
+    // OnPaint handlers must always create a wxPaintDC.
+    wxPaintDC dc(this);
+
+    draw1();
+    SwapBuffers();
+}
+
+void TestGLCanvas::OnSize(wxSizeEvent& event)
+{
+    SetCurrent();
+    int width, height;
+    GetClientSize(& width, & height);
+    Reshape(width, height);
+}
+
+void TestGLCanvas::OnChar(wxKeyEvent& event)
+{
+    switch(event.KeyCode()) {
+    case WXK_ESCAPE:
+	exit(0);
+    case WXK_LEFT:
+	yrot -= 15.0;
+	break;
+    case WXK_RIGHT:
+	yrot += 15.0;
+	break;
+    case WXK_UP:
+	xrot += 15.0;
+	break;
+    case WXK_DOWN:
+	xrot -= 15.0;
+	break;
+    case 's': case 'S':
+	smooth = !smooth;
+	if (smooth) {
+	    glShadeModel(GL_SMOOTH);
+	} else {
+	    glShadeModel(GL_FLAT);
+	}
+	break;
+    case 'l': case 'L':
+	lighting = !lighting;
+	if (lighting) {
+	    glEnable(GL_LIGHTING);
+	} else {
+	    glDisable(GL_LIGHTING);
+	}
+	break;
+     default:
+      {
+        event.Skip();
+	return;
+      }
+    }
+
+    Refresh(FALSE);
+}
+
+void TestGLCanvas::OnMouseEvent(wxMouseEvent& event)
+{
+    static int dragging = 0;
+    static float last_x, last_y;
+
+    //printf("%f %f %d\n", event.GetX(), event.GetY(), (int)event.LeftIsDown());
+    if(event.LeftIsDown()) {
+	if(!dragging) {
+	    dragging = 1;
+	} else {
+	    yrot += (event.GetX() - last_x)*1.0;
+	    xrot += (event.GetY() - last_y)*1.0;
+	    Refresh(FALSE);
+	}
+	last_x = event.GetX();
+	last_y = event.GetY();
+    } else
+	dragging = 0;
+}
+
+void TestGLCanvas::OnEraseBackground(wxEraseEvent& event)
+{
+    // Do nothing, to avoid flashing.
+}
+
diff --git a/samples/opengl/isosurf/isosurf.dat.gz b/samples/opengl/isosurf/isosurf.dat.gz
new file mode 100644
index 0000000000000000000000000000000000000000..c07dc570d26c504f21d610df90b7363ba6027a2f
GIT binary patch
literal 65537
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

literal 0
HcmV?d00001

diff --git a/samples/opengl/isosurf/isosurf.h b/samples/opengl/isosurf/isosurf.h
new file mode 100644
index 0000000000..e84098c56b
--- /dev/null
+++ b/samples/opengl/isosurf/isosurf.h
@@ -0,0 +1,52 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        isosurf.h
+// Purpose:     wxGLCanvas demo program
+// Author:      Brian Paul (original gltk version), Wolfram Gloger
+// Modified by: Julian Smart
+// Created:     04/01/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_ISOSURF_H_
+#define _WX_ISOSURF_H_
+
+// Define a new application type
+class MyApp: public wxApp
+{ public:
+    bool OnInit(void);
+};
+
+class TestGLCanvas: public wxGLCanvas
+{
+ public:
+   TestGLCanvas(wxWindow *parent, const wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
+      const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = "TestGLCanvas",
+      int* gl_attrib = NULL);
+   ~TestGLCanvas(void);
+
+   void OnPaint(wxPaintEvent& event);
+   void OnSize(wxSizeEvent& event);
+   void OnEraseBackground(wxEraseEvent& event);
+   void OnChar(wxKeyEvent& event);
+   void OnMouseEvent(wxMouseEvent& event);
+
+DECLARE_EVENT_TABLE()
+};
+
+class MyFrame: public wxFrame
+{
+public:
+    MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size,
+        long style = wxDEFAULT_FRAME_STYLE);
+
+    void OnExit(wxCommandEvent& event);
+public:
+    TestGLCanvas*    m_canvas;
+
+DECLARE_EVENT_TABLE()
+};
+
+#endif
+
diff --git a/samples/opengl/isosurf/isosurf.rc b/samples/opengl/isosurf/isosurf.rc
new file mode 100644
index 0000000000..7655c62a4c
--- /dev/null
+++ b/samples/opengl/isosurf/isosurf.rc
@@ -0,0 +1,3 @@
+mondrian ICON "mondrian.ico"
+#include "wx/msw/wx.rc"
+
diff --git a/samples/opengl/isosurf/makefile.b32 b/samples/opengl/isosurf/makefile.b32
new file mode 100644
index 0000000000..0154a0aac0
--- /dev/null
+++ b/samples/opengl/isosurf/makefile.b32
@@ -0,0 +1,22 @@
+#
+# File:		makefile.b32
+# Author:	Julian Smart
+# Created:	1999
+# Updated:	
+# Copyright:
+#
+# Makefile : Builds sample for 32-bit BC++
+
+WXDIR = $(WXWIN)
+
+TARGET=isosurf
+# EXTRALIBS=$(WXDIR)\lib\glcanvas.lib
+# EXTRACPPFLAGS=-I$(WXDIR)\utils\glcanvas\win
+OBJECTS = $(TARGET).obj
+EXTRATARGETS=isosurf.dat
+
+!include $(WXDIR)\src\makeprog.b32
+
+isosurf.dat:    isosurf.dat.gz
+    gzip -c -d isosurf.dat.gz > isosurf.dat
+
diff --git a/samples/opengl/isosurf/makefile.bcc b/samples/opengl/isosurf/makefile.bcc
new file mode 100644
index 0000000000..680d8c95bf
--- /dev/null
+++ b/samples/opengl/isosurf/makefile.bcc
@@ -0,0 +1,25 @@
+#
+# File:		makefile.bcc
+# Author:	Julian Smart
+# Created:	1998
+# Updated:	
+#
+# Builds a BC++ 16-bit sample
+
+!if "$(WXWIN)" == ""
+!error You must define the WXWIN variable in autoexec.bat, e.g. WXWIN=c:\wx
+!endif
+
+WXDIR = $(WXWIN)
+
+TARGET=isosurf
+# EXTRALIBS=$(WXDIR)\lib\glcanvas.lib
+# EXTRACPPFLAGS=-I$(WXDIR)\utils\glcanvas\win
+OBJECTS = $(TARGET).obj
+EXTRATARGETS=isosurf.dat
+
+!include $(WXDIR)\src\makeprog.bcc
+
+isosurf.dat:    isosurf.dat.gz
+    gzip -c -d isosurf.dat.gz > isosurf.dat
+
diff --git a/samples/opengl/isosurf/makefile.g95 b/samples/opengl/isosurf/makefile.g95
new file mode 100644
index 0000000000..f0396a5d3d
--- /dev/null
+++ b/samples/opengl/isosurf/makefile.g95
@@ -0,0 +1,20 @@
+#
+# File:         makefile.g95
+# Author:       Julian Smart
+# Created:      1999
+# Updated:
+# Copyright:    (c) Julian Smart, 1999
+#
+# Makefile for wxWindows sample (Cygwin/Mingw32).
+
+WXDIR = ../../..
+
+TARGET=isosurf
+# EXTRACPPFLAGS=-I../../win
+EXTRALIBS=-lopengl32 -lglu32
+OBJECTS = $(TARGET).o
+
+include $(WXDIR)/src/makeprog.g95
+
+isosurf.dat: isosurf.dat.gz
+	gzip -c -d isosurf.dat.gz > isosurf.dat
diff --git a/samples/opengl/isosurf/makefile.unx b/samples/opengl/isosurf/makefile.unx
new file mode 100644
index 0000000000..2c0a364808
--- /dev/null
+++ b/samples/opengl/isosurf/makefile.unx
@@ -0,0 +1,27 @@
+#
+# File:		makefile.unx
+# Author:	Julian Smart
+# Created:	1998
+# Updated:	
+# Copyright:	(c) 1998 Julian Smart
+#
+# "%W% %G%"
+#
+# Makefile for isosurf example (UNIX).
+
+PROGRAM=isosurf
+
+OPENGLHOME=/home/jacs/mesa/Mesa-2.3
+
+EXTRACPPFLAGS=-I$(OPENGLHOME)/include
+EXTRALDFLAGS=-L$(OPENGLHOME)/lib
+EXTRALDLIBS=-lMesaGL -lMesaGLU
+
+OBJECTS=$(PROGRAM).o
+EXTRATARGETS=isosurf.dat
+
+include ../../../src/makeprog.env
+
+isosurf.dat:	isosurf.dat.gz
+	gzip -c -d isosurf.dat.gz > isosurf.dat
+
diff --git a/samples/opengl/isosurf/makefile.vc b/samples/opengl/isosurf/makefile.vc
new file mode 100644
index 0000000000..9c787154f2
--- /dev/null
+++ b/samples/opengl/isosurf/makefile.vc
@@ -0,0 +1,30 @@
+#
+# File:		makefile.vc
+# Author:	Julian Smart
+# Created:	1999
+# Updated:	
+# Copyright:	(c) Julian Smart
+#
+# Makefile : Builds sample (VC++, WIN32)
+# Use FINAL=1 argument to nmake to build final version with no debug info.
+
+# Set WXDIR for your system
+WXDIR = $(WXWIN)
+
+!if "$(FINAL)" == "1"
+!else
+LIBEXT=_d
+!endif
+
+PROGRAM=isosurf
+OBJECTS = $(PROGRAM).obj
+#EXTRAINC=-I..\..\win
+EXTRALIBS=glu32.lib opengl32.lib
+EXTRATARGETS=isosurf.dat
+
+!include $(WXDIR)\src\makeprog.vc
+
+isosurf.dat: isosurf.dat.gz
+    gzip -c -d isosurf.dat.gz > isosurf.dat
+
+
diff --git a/samples/opengl/isosurf/makefile.wat b/samples/opengl/isosurf/makefile.wat
new file mode 100644
index 0000000000..ba3a87cef8
--- /dev/null
+++ b/samples/opengl/isosurf/makefile.wat
@@ -0,0 +1,20 @@
+#
+# Makefile for WATCOM
+#
+# Created by Julian Smart, January 1999
+# 
+#
+
+WXDIR = $(%WXWIN)
+
+PROGRAM = isosurf
+OBJECTS = $(PROGRAM).obj
+#EXTRALIBS=$(WXDIR)\lib\glcanvas.lib
+#EXTRACPPFLAGS=-I$(WXDIR)\utils\glcanvas\win
+EXTRATARGETS=isosurf.dat
+
+!include $(WXDIR)\src\makeprog.wat
+
+isosurf.dat:    isosurf.dat.gz
+    gzip -c -d isosurf.dat.gz > isosurf.dat
+
diff --git a/samples/opengl/isosurf/mondrian.ico b/samples/opengl/isosurf/mondrian.ico
new file mode 100644
index 0000000000000000000000000000000000000000..2310c5d275a87af295d5ea8dc79ea417a5e74c53
GIT binary patch
literal 766
zcmZQzU<5)11px*Sc)`TLAO@s0fLH;D9e|jTfdxnc0Z<M**w4TKL=5})Lnt5#WHKB$
zaDbtqp#doIAB-6O{|B*v7zjZ^AOa2W|NsACHyAJ}De?dRKnp(HN~rljcR;{k;{zQE
i@;}UZ|9Q?Fpp*~yJCwmWbLIrN`9Qm9%}2L?p!oo$cZ4ed

literal 0
HcmV?d00001

diff --git a/samples/opengl/penguin/Makefile b/samples/opengl/penguin/Makefile
new file mode 100644
index 0000000000..7a3ef78bbe
--- /dev/null
+++ b/samples/opengl/penguin/Makefile
@@ -0,0 +1,37 @@
+#
+# File:		Makefile
+# Author:	Robert Roebling
+# Created:	1999
+# Updated:	
+# Copyright:	(c) 1998 Robert Roebling
+#
+# Makefile for OpenGL demo (GTK version)
+#
+# This makefile requires wxWindows/GTK to be 
+# installed (possibly using "make install")
+# on your system.
+#
+
+CPP = gcc
+CC = gcc
+WXCONFIG=../../../wx-config
+WXINCLUDE=-I../../../include
+WXLIB=-L../../../lib
+
+Penguin: penguin.o trackball.o lw.o # glcanvas.o
+	$(CPP) -o Penguin penguin.o trackball.o lw.o `$(WXCONFIG) --libs` $(WXLIB) -lMesaGL -lMesaGLU
+
+penguin.o: penguin.cpp
+	$(CPP) `$(WXCONFIG) --cflags` -I../../gtk $(WXINCLUDE) -c penguin.cpp
+
+lw.o: lw.cpp
+	$(CPP) `$(WXCONFIG) --cflags` -I../../gtk $(WXINCLUDE) -c lw.cpp
+
+trackball.o: trackball.c
+	$(CC) `$(WXCONFIG) --cflags` -I../../gtk $(WXINCLUDE) -c trackball.c
+
+glcanvas.o: ../../gtk/glcanvas.cpp
+	$(CPP) `$(WXCONFIG) --cflags` `gtk-config --cflags` -g -I../../gtk $(WXINCLUDE) -c ../../gtk/glcanvas.cpp
+
+clean: 
+	rm -f *.o Penguin
diff --git a/samples/opengl/penguin/lw.cpp b/samples/opengl/penguin/lw.cpp
new file mode 100644
index 0000000000..e7bfe17843
--- /dev/null
+++ b/samples/opengl/penguin/lw.cpp
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 1998 Janne Löf <jlof@mail.student.oulu.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __WXMSW__
+#include <windows.h>
+#endif
+
+#include "lw.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#define wxInt32 int
+#define wxUint32 unsigned int
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#define MK_ID(a,b,c,d) ((((wxUint32)(a))<<24)| \
+			(((wxUint32)(b))<<16)| \
+			(((wxUint32)(c))<< 8)| \
+			(((wxUint32)(d))    ))
+
+#define ID_FORM MK_ID('F','O','R','M')
+#define ID_LWOB MK_ID('L','W','O','B')
+#define ID_PNTS MK_ID('P','N','T','S')
+#define ID_SRFS MK_ID('S','R','F','S')
+#define ID_SURF MK_ID('S','U','R','F')
+#define ID_POLS MK_ID('P','O','L','S')
+#define ID_COLR MK_ID('C','O','L','R')
+
+static wxInt32 read_char(FILE *f)
+{
+  int c = fgetc(f);
+  return c;
+}
+
+static wxInt32 read_short(FILE *f)
+{
+  return (read_char(f)<<8) | read_char(f);
+}
+
+static wxInt32 read_long(FILE *f)
+{
+  return (read_char(f)<<24) | (read_char(f)<<16) | (read_char(f)<<8) | read_char(f);
+}
+
+static GLfloat read_float(FILE *f)
+{
+  wxInt32 x = read_long(f);
+  return *(GLfloat*)&x;
+}
+
+static int read_string(FILE *f, char *s)
+{
+  int c;
+  int cnt = 0;
+  do {
+    c = read_char(f);
+    if (cnt < LW_MAX_NAME_LEN)
+      s[cnt] = c;
+    else
+      s[LW_MAX_NAME_LEN-1] = 0;
+    cnt++;
+  } while (c != 0);
+  /* if length of string (including \0) is odd skip another byte */
+  if (cnt%2) {
+    read_char(f);
+    cnt++;
+  }
+  return cnt;
+}
+
+static void read_srfs(FILE *f, int nbytes, lwObject *lwo)
+{
+  int guess_cnt = lwo->material_cnt;
+
+  while (nbytes > 0) {
+    lwMaterial *material;
+
+    /* allocate more memory for materials if needed */
+    if (guess_cnt <= lwo->material_cnt) {
+      guess_cnt += guess_cnt/2 + 4;
+      lwo->material = (lwMaterial*) realloc(lwo->material, sizeof(lwMaterial)*guess_cnt);
+    }
+    material = lwo->material + lwo->material_cnt++;
+
+    /* read name */
+    nbytes -= read_string(f,material->name);
+
+    /* defaults */
+    material->r = 0.7;
+    material->g = 0.7;
+    material->b = 0.7;
+  }
+  lwo->material = (lwMaterial*) realloc(lwo->material, sizeof(lwMaterial)*lwo->material_cnt);
+}
+
+
+static void read_surf(FILE *f, int nbytes, lwObject *lwo)
+{
+  int i;
+  char name[LW_MAX_NAME_LEN];
+  lwMaterial *material = NULL;
+
+  /* read surface name */
+  nbytes -= read_string(f,name);
+
+  /* find material */
+  for (i=0; i< lwo->material_cnt; i++) {
+    if (strcmp(lwo->material[i].name,name) == 0) {
+      material = &lwo->material[i];
+      break;
+    }
+  }
+
+  /* read values */
+  while (nbytes > 0) {
+    int id = read_long(f);
+    int len = read_short(f);
+    nbytes -= 6 + len + (len%2);
+
+    switch (id) {
+    case ID_COLR:
+      material->r = read_char(f) / 255.0;
+      material->g = read_char(f) / 255.0;
+      material->b = read_char(f) / 255.0;
+      read_char(f); /* dummy */
+      break;
+    default:
+      fseek(f, len+(len%2), SEEK_CUR);
+    }
+  }
+}
+
+
+static void read_pols(FILE *f, int nbytes, lwObject *lwo)
+{
+  int guess_cnt = lwo->face_cnt;
+  
+  while (nbytes > 0) {
+    lwFace *face;
+    int i;
+
+    /* allocate more memory for polygons if necessary */
+    if (guess_cnt <= lwo->face_cnt) {
+      guess_cnt += guess_cnt + 4;
+      lwo->face = (lwFace*) realloc((void*) lwo->face, sizeof(lwFace)*guess_cnt);
+    }
+    face = lwo->face + lwo->face_cnt++;
+
+    /* number of points in this face */
+    face->index_cnt = read_short(f);
+    nbytes -= 2;
+
+    /* allocate space for points */
+    face->index = (int*) calloc(sizeof(int)*face->index_cnt,1);
+    
+    /* read points in */
+    for (i=0; i<face->index_cnt; i++) {
+      face->index[i] = read_short(f);
+      nbytes -= 2;
+    }
+    
+    /* read surface material */
+    face->material = read_short(f);
+    nbytes -= 2;
+    
+    /* skip over detail  polygons */
+    if (face->material < 0) {
+      int det_cnt;
+      face->material = -face->material;
+      det_cnt = read_short(f);
+      nbytes -= 2;
+      while (det_cnt-- > 0) {
+	int cnt = read_short(f);
+	fseek(f, cnt*2+2, SEEK_CUR);
+	nbytes -= cnt*2+2;
+      }
+    }
+    face->material -= 1;
+  }
+  /* readjust to true size */
+  lwo->face = (lwFace*) realloc(lwo->face, sizeof(lwFace)*lwo->face_cnt);
+}
+
+
+
+static void read_pnts(FILE *f, int nbytes, lwObject *lwo)
+{
+  int i;
+  lwo->vertex_cnt = nbytes / 12;
+  lwo->vertex = (float*) calloc(sizeof(GLfloat)*lwo->vertex_cnt*3, 1);
+  for (i=0; i<lwo->vertex_cnt; i++) {
+    lwo->vertex[i*3+0] = read_float(f);
+    lwo->vertex[i*3+1] = read_float(f);
+    lwo->vertex[i*3+2] = read_float(f);
+  }
+}
+
+
+
+
+
+
+int lw_is_lwobject(const char *lw_file)
+{
+  FILE *f = fopen(lw_file, "rb");
+  if (f) {
+    wxInt32 form = read_long(f);
+    wxInt32 nlen = read_long(f);
+    wxInt32 lwob = read_long(f);
+    fclose(f);
+    if (form == ID_FORM && nlen != 0 && lwob == ID_LWOB)
+      return TRUE;
+  }
+  return FALSE;
+}
+
+
+lwObject *lw_object_read(const char *lw_file)
+{
+  FILE *f = NULL;
+  lwObject *lw_object = NULL;
+
+  wxInt32 form_bytes = 0;
+  wxInt32 read_bytes = 0;
+
+  /* open file */
+  f = fopen(lw_file, "rb");
+  if (f == NULL) {
+    return NULL;
+  }
+
+  /* check for headers */
+  if (read_long(f) != ID_FORM) {
+    fclose(f);
+    return NULL;
+  }
+  form_bytes = read_long(f);
+  read_bytes += 4;
+
+  if (read_long(f) != ID_LWOB) {
+    fclose(f);
+    return NULL;
+  }
+
+  /* create new lwObject */
+  lw_object = (lwObject*) calloc(sizeof(lwObject),1);
+
+  /* read chunks */
+  while (read_bytes < form_bytes) {
+    wxInt32  id     = read_long(f);
+    wxInt32  nbytes = read_long(f);
+    read_bytes += 8 + nbytes + (nbytes%2);
+
+    switch (id) {
+    case ID_PNTS:
+      read_pnts(f, nbytes, lw_object);
+      break;
+    case ID_POLS:
+      read_pols(f, nbytes, lw_object);
+      break;
+    case ID_SRFS:
+      read_srfs(f, nbytes, lw_object);
+      break;
+    case ID_SURF:
+      read_surf(f, nbytes, lw_object);
+      break;
+    default:
+      fseek(f, nbytes + (nbytes%2), SEEK_CUR);
+    }
+  }
+
+  fclose(f);
+  return lw_object;
+}
+
+
+
+void lw_object_free(lwObject *lw_object)
+{
+  if (lw_object->face) {
+    int i;
+    for (i=0; i<lw_object->face_cnt; i++)
+      free(lw_object->face[i].index);
+    free(lw_object->face);
+  }
+  free(lw_object->material);
+  free(lw_object->vertex);
+  free(lw_object);
+}
+
+
+
+
+
+#define PX(i) (lw_object->vertex[face->index[i]*3+0])
+#define PY(i) (lw_object->vertex[face->index[i]*3+1])
+#define PZ(i) (lw_object->vertex[face->index[i]*3+2])
+void lw_object_show(const lwObject *lw_object)
+{
+  int i,j;
+  int prev_index_cnt = -1;
+  int prev_material  = -1;
+  GLfloat prev_nx = 0;
+  GLfloat prev_ny = 0;
+  GLfloat prev_nz = 0;
+
+  for (i=0; i<lw_object->face_cnt; i++) {
+    GLfloat ax,ay,az,bx,by,bz,nx,ny,nz,r;
+    const lwFace *face = lw_object->face+i;
+
+    /* ignore faces with less than 3 points */
+    if (face->index_cnt < 3)
+      continue;
+
+    /* calculate normal */
+    ax = PX(1) - PX(0);
+    ay = PY(1) - PY(0);
+    az = PZ(1) - PZ(0);
+
+    bx = PX(face->index_cnt-1) - PX(0);
+    by = PY(face->index_cnt-1) - PY(0);
+    bz = PZ(face->index_cnt-1) - PZ(0);
+
+    nx = ay * bz - az * by;
+    ny = az * bx - ax * bz;
+    nz = ax * by - ay * bx;
+
+    r = sqrt(nx*nx + ny*ny + nz*nz);
+    if (r < 0.000001) /* avoid division by zero */
+      continue;
+    nx /= r;
+    ny /= r;
+    nz /= r;
+
+    /* glBegin/glEnd */
+    if (prev_index_cnt != face->index_cnt || prev_index_cnt > 4) {
+      if (prev_index_cnt > 0) glEnd();
+      prev_index_cnt = face->index_cnt;
+      switch (face->index_cnt) {
+      case 3:
+	glBegin(GL_TRIANGLES);
+	break;
+      case 4:
+	glBegin(GL_QUADS);
+	break;
+      default:
+	glBegin(GL_POLYGON);
+      }
+    }
+
+    /* update material if necessary */
+    if (prev_material != face->material) {
+      prev_material = face->material;
+      glColor3f(lw_object->material[face->material].r,
+		lw_object->material[face->material].g,
+		lw_object->material[face->material].b);
+    }
+
+    /* update normal if necessary */
+    if (nx != prev_nx || ny != prev_ny || nz != prev_nz) {
+      prev_nx = nx;
+      prev_ny = ny;
+      prev_nz = nz;
+      glNormal3f(nx,ny,nz);
+    }
+
+    /* draw polygon/triangle/quad */
+    for (j=0; j<face->index_cnt; j++)
+      glVertex3f(PX(j),PY(j),PZ(j));
+
+  }
+
+  /* if glBegin was called call glEnd */
+  if (prev_index_cnt > 0)
+    glEnd();
+}
+
+
+GLfloat lw_object_radius(const lwObject *lwo)
+{
+  int i;
+  double max_radius = 0.0;
+
+  for (i=0; i<lwo->vertex_cnt; i++) {
+    GLfloat *v = &lwo->vertex[i*3];
+    double r = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
+    if (r > max_radius)
+      max_radius = r;
+  }
+  return sqrt(max_radius);
+}
+
+void lw_object_scale(lwObject *lwo, GLfloat scale)
+{
+  int i;
+
+  for (i=0; i<lwo->vertex_cnt; i++) {
+    lwo->vertex[i*3+0] *= scale;
+    lwo->vertex[i*3+1] *= scale;
+    lwo->vertex[i*3+2] *= scale;
+  }
+}
+
+
diff --git a/samples/opengl/penguin/lw.h b/samples/opengl/penguin/lw.h
new file mode 100644
index 0000000000..b49e8ffc91
--- /dev/null
+++ b/samples/opengl/penguin/lw.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 1998 Janne Löf <jlof@mail.student.oulu.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef LW_H
+#define LW_H
+
+#include <GL/gl.h>
+
+#define LW_MAX_POINTS   200
+#define LW_MAX_NAME_LEN 500
+
+typedef struct {
+  char name[LW_MAX_NAME_LEN];
+  GLfloat r,g,b;
+} lwMaterial;
+
+typedef struct {
+  int material;         /* material of this face */
+  int index_cnt;        /* number of vertices */
+  int *index;           /* index to vertex */
+  float *texcoord;      /* u,v texture coordinates */
+} lwFace;
+
+typedef struct {
+  int face_cnt;
+  lwFace *face;
+
+  int material_cnt;
+  lwMaterial *material;
+
+  int vertex_cnt;
+  GLfloat *vertex;
+
+} lwObject;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int       lw_is_lwobject(const char     *lw_file);
+lwObject *lw_object_read(const char     *lw_file);
+void      lw_object_free(      lwObject *lw_object);
+void      lw_object_show(const lwObject *lw_object);
+
+GLfloat   lw_object_radius(const lwObject *lw_object);
+void      lw_object_scale (lwObject *lw_object, GLfloat scale);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LW_H */
+
diff --git a/samples/opengl/penguin/makefile.b32 b/samples/opengl/penguin/makefile.b32
new file mode 100644
index 0000000000..0f8d581ddc
--- /dev/null
+++ b/samples/opengl/penguin/makefile.b32
@@ -0,0 +1,18 @@
+#
+# File:		makefile.b32
+# Author:	Julian Smart
+# Created:	1999
+# Updated:	
+# Copyright:
+#
+# Makefile : Builds sample for 32-bit BC++
+
+WXDIR = $(WXWIN)
+
+TARGET=penguin
+#EXTRALIBS=$(WXDIR)\lib\glcanvas.lib
+#EXTRACPPFLAGS=-I$(WXDIR)\utils\glcanvas\win
+OBJECTS = $(TARGET).obj lw.obj trackball.obj
+
+!include $(WXDIR)\src\makeprog.b32
+
diff --git a/samples/opengl/penguin/makefile.bcc b/samples/opengl/penguin/makefile.bcc
new file mode 100644
index 0000000000..c789bde1b0
--- /dev/null
+++ b/samples/opengl/penguin/makefile.bcc
@@ -0,0 +1,21 @@
+#
+# File:		makefile.bcc
+# Author:	Julian Smart
+# Created:	1998
+# Updated:	
+#
+# Builds a BC++ 16-bit sample
+
+!if "$(WXWIN)" == ""
+!error You must define the WXWIN variable in autoexec.bat, e.g. WXWIN=c:\wx
+!endif
+
+WXDIR = $(WXWIN)
+
+TARGET=penguin
+#EXTRALIBS=$(WXDIR)\lib\glcanvas.lib
+#EXTRACPPFLAGS=-I$(WXDIR)\utils\glcanvas\win
+OBJECTS = $(TARGET).obj
+
+!include $(WXDIR)\src\makeprog.bcc
+
diff --git a/samples/opengl/penguin/makefile.g95 b/samples/opengl/penguin/makefile.g95
new file mode 100644
index 0000000000..a15d8d0306
--- /dev/null
+++ b/samples/opengl/penguin/makefile.g95
@@ -0,0 +1,18 @@
+#
+# File:         makefile.g95
+# Author:       Julian Smart
+# Created:      1999
+# Updated:
+# Copyright:    (c) Julian Smart, 1999
+#
+# Makefile for wxWindows sample (Cygwin/Mingw32).
+
+WXDIR = ../../..
+
+TARGET=penguin
+#EXTRACPPFLAGS=-I../../win
+EXTRALIBS=-lopengl32 -lglu32
+OBJECTS = $(TARGET).o lw.o trackball.o
+
+include $(WXDIR)/src/makeprog.g95
+
diff --git a/samples/opengl/penguin/makefile.unx b/samples/opengl/penguin/makefile.unx
new file mode 100644
index 0000000000..c8d335c1bf
--- /dev/null
+++ b/samples/opengl/penguin/makefile.unx
@@ -0,0 +1,21 @@
+#
+# File:		makefile.unx
+# Author:	Julian Smart
+# Created:	1998
+# Updated:	
+# Copyright:	(c) 1998 Julian Smart
+#
+# Makefile for penguin example (UNIX).
+
+PROGRAM=penguin
+
+OPENGLHOME=/home/jacs/mesa/Mesa-2.3
+
+EXTRACPPFLAGS=-I$(OPENGLHOME)/include # -I../../motif
+EXTRALDFLAGS=-L$(OPENGLHOME)/lib
+EXTRALDLIBS=-lMesaGL -lMesaGLU
+
+OBJECTS=$(PROGRAM).o trackball.o lw.o
+
+include ../../../src/makeprog.env
+
diff --git a/samples/opengl/penguin/makefile.vc b/samples/opengl/penguin/makefile.vc
new file mode 100644
index 0000000000..246fea6d3e
--- /dev/null
+++ b/samples/opengl/penguin/makefile.vc
@@ -0,0 +1,30 @@
+#
+# File:		makefile.vc
+# Author:	Julian Smart
+# Created:	1999
+# Updated:	
+# Copyright:	(c) Julian Smart
+#
+# Makefile : Builds sample (VC++, WIN32)
+# Use FINAL=1 argument to nmake to build final version with no debug info.
+
+# Set WXDIR for your system
+WXDIR = $(WXWIN)
+
+!if "$(FINAL)" == "1"
+!else
+LIBEXT=_d
+!endif
+
+PROGRAM=penguin
+OBJECTS = $(PROGRAM).obj trackball.obj lw.obj
+#EXTRAINC=-I..\..\win
+EXTRALIBS=glu32.lib opengl32.lib
+
+!include $(WXDIR)\src\makeprog.vc
+
+lw.obj:      lw.cpp lw.h
+        $(cc) @<<
+$(CPPFLAGS2) /c $*.$(SRCSUFF)
+<<
+
diff --git a/samples/opengl/penguin/makefile.wat b/samples/opengl/penguin/makefile.wat
new file mode 100644
index 0000000000..c8a2f81645
--- /dev/null
+++ b/samples/opengl/penguin/makefile.wat
@@ -0,0 +1,17 @@
+#
+# Makefile for WATCOM
+#
+# Created by Julian Smart, January 1999
+# 
+#
+
+WXDIR = $(%WXWIN)
+
+PROGRAM = penguin
+OBJECTS = $(PROGRAM).obj
+#EXTRALIBS=$(WXDIR)\lib\glcanvas.lib
+#EXTRACPPFLAGS=-I$(WXDIR)\utils\glcanvas\win
+
+!include $(WXDIR)\src\makeprog.wat
+
+
diff --git a/samples/opengl/penguin/penguin.cpp b/samples/opengl/penguin/penguin.cpp
new file mode 100644
index 0000000000..8eaed6a1d9
--- /dev/null
+++ b/samples/opengl/penguin/penguin.cpp
@@ -0,0 +1,236 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        penguin.cpp
+// Purpose:     wxGLCanvas demo program
+// Author:      Robert Roebling
+// Modified by:
+// Created:     04/01/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Robert Roebling
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation
+#pragma interface
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "penguin.h"
+#include <GL/glu.h>
+
+#define VIEW_ASPECT 1.3
+
+/* `Main program' equivalent, creating windows and returning main app frame */
+bool MyApp::OnInit(void)
+{
+
+  /* Create the main frame window */
+  MyFrame *frame = new MyFrame(NULL, "wxWindows OpenGL Demo", wxPoint(50, 50), wxSize(400, 300));
+
+  /* Make a menubar */
+  wxMenu *fileMenu = new wxMenu;
+
+  fileMenu->Append(wxID_EXIT, "E&xit");
+  wxMenuBar *menuBar = new wxMenuBar;
+  menuBar->Append(fileMenu, "&File");
+  frame->SetMenuBar(menuBar);
+
+  frame->m_canvas = new TestGLCanvas(frame, -1, wxPoint(0, 0), wxSize(200, 200));
+
+  /* Load file wiht mesh data */
+  frame->m_canvas->LoadLWO( "penguin.lwo" );
+
+  /* Show the frame */
+  frame->Show(TRUE);
+  
+  return TRUE;
+}
+
+IMPLEMENT_APP(MyApp)
+
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+    EVT_MENU(wxID_EXIT, MyFrame::OnExit)
+END_EVENT_TABLE()
+
+/* My frame constructor */
+MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
+    const wxSize& size, long style):
+  wxFrame(frame, -1, title, pos, size, style)
+{
+    m_canvas = NULL;
+}
+
+/* Intercept menu commands */
+void MyFrame::OnExit(wxCommandEvent& event)
+{
+    Destroy();
+}
+
+BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
+    EVT_SIZE(TestGLCanvas::OnSize)
+    EVT_PAINT(TestGLCanvas::OnPaint)
+    EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground)
+    EVT_MOUSE_EVENTS(TestGLCanvas::OnMouse)
+END_EVENT_TABLE()
+
+TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id,
+    const wxPoint& pos, const wxSize& size, long style, const wxString& name):
+  wxGLCanvas(parent, id, pos, size, style, name)
+{
+   block = FALSE;
+}
+
+TestGLCanvas::~TestGLCanvas(void)
+{
+    /* destroy mesh */
+    lw_object_free(info.lwobject);
+}
+
+void TestGLCanvas::OnPaint( wxPaintEvent& event )
+{
+    /* must always be here */
+    wxPaintDC dc(this);
+
+#ifndef __WXMOTIF__
+    if (!GetContext()) return;
+#endif
+
+    SetCurrent();
+    
+    /* initialize OpenGL */
+    if (info.do_init == TRUE) 
+    {
+        InitGL();
+        info.do_init = FALSE;
+    }
+  
+    /* view */
+    glMatrixMode( GL_PROJECTION );
+    glLoadIdentity();
+    gluPerspective( info.zoom, VIEW_ASPECT, 1, 100 );
+    glMatrixMode( GL_MODELVIEW );
+
+    /* clear */
+    glClearColor( .3, .4, .6, 1 );
+    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+    /* transformations */
+    GLfloat m[4][4];
+    glLoadIdentity();
+    glTranslatef( 0, 0, -30 );
+    build_rotmatrix( m,info.quat );
+    glMultMatrixf( &m[0][0] );
+
+    /* draw object */
+    lw_object_show( info.lwobject );
+    
+    /* flush */
+    glFlush();
+
+    /* swap */
+    SwapBuffers();
+}
+
+void TestGLCanvas::OnSize(wxSizeEvent& event)
+{
+    int width, height;
+    GetClientSize(& width, & height);
+    
+#ifndef __WXMOTIF__
+    if (GetContext())
+#endif
+    {
+        SetCurrent();
+        glViewport(0, 0, width, height);
+    }
+}
+
+void TestGLCanvas::OnEraseBackground(wxEraseEvent& event)
+{
+    /* Do nothing, to avoid flashing on MSW */
+}
+
+void TestGLCanvas::LoadLWO(const wxString &filename)
+{
+    /* test if lightwave object */
+    if (!lw_is_lwobject(filename)) return;
+  
+    /* read lightwave object */
+    lwObject *lwobject = lw_object_read(filename);
+    
+    /* scale */
+    lw_object_scale(lwobject, 10.0 / lw_object_radius(lwobject));
+    
+    /* set up mesh info */
+    info.do_init = TRUE;
+    info.lwobject = lwobject;
+    info.beginx = 0;
+    info.beginy = 0;
+    info.zoom   = 45;
+    trackball( info.quat, 0.0, 0.0, 0.0, 0.0 );
+}
+
+void TestGLCanvas::OnMouse( wxMouseEvent& event )
+{
+    wxSize sz(GetClientSize());
+    if (event.Dragging())
+    {
+        /* drag in progress, simulate trackball */
+        float spin_quat[4];
+        trackball(spin_quat,
+	      (2.0*info.beginx -       sz.x) / sz.x,
+	      (     sz.y - 2.0*info.beginy) / sz.y,
+	      (     2.0*event.GetX() - sz.x) / sz.x,
+	      (    sz.y - 2.0*event.GetY()) / sz.y);
+	      
+        add_quats( spin_quat, info.quat, info.quat );
+	
+        /* orientation has changed, redraw mesh */
+  	Refresh(FALSE);
+    }
+    
+    info.beginx = event.GetX();
+    info.beginy = event.GetY();
+}
+
+void TestGLCanvas::InitGL(void)
+{
+    GLfloat light0_pos[4]   = { -50.0, 50.0, 0.0, 0.0 };
+    GLfloat light0_color[4] = { .6, .6, .6, 1.0 }; /* white light */
+    GLfloat light1_pos[4]   = {  50.0, 50.0, 0.0, 0.0 };
+    GLfloat light1_color[4] = { .4, .4, 1, 1.0 };  /* cold blue light */
+
+    /* remove back faces */
+    glDisable(GL_CULL_FACE);
+    glEnable(GL_DEPTH_TEST);
+  
+    /* speedups */
+    glEnable(GL_DITHER);
+    glShadeModel(GL_SMOOTH);
+    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+    glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
+
+    /* light */
+    glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
+    glLightfv(GL_LIGHT0, GL_DIFFUSE,  light0_color);  
+    glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);
+    glLightfv(GL_LIGHT1, GL_DIFFUSE,  light1_color);
+    glEnable(GL_LIGHT0);
+    glEnable(GL_LIGHT1);
+    glEnable(GL_LIGHTING);
+    
+    glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
+    glEnable(GL_COLOR_MATERIAL);  
+}
+
+
diff --git a/samples/opengl/penguin/penguin.h b/samples/opengl/penguin/penguin.h
new file mode 100644
index 0000000000..1730b2130f
--- /dev/null
+++ b/samples/opengl/penguin/penguin.h
@@ -0,0 +1,84 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        penguin.h
+// Purpose:     wxGLCanvas demo program
+// Author:      Robert Roebling
+// Modified by:
+// Created:     04/01/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Robert Roebling
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_PENGUIN_H_
+#define _WX_PENGUIN_H_
+
+
+#include "wx/defs.h"
+#include "wx/app.h"
+#include "wx/menu.h"
+#include "wx/dcclient.h"
+
+#include "wx/glcanvas.h"
+
+extern "C" {
+#include "lw.h"
+#include "trackball.h"
+}
+
+/* information needed to display lightwave mesh */
+typedef struct 
+{
+//  gint do_init;         /* true if initgl not yet called */
+  int do_init;
+  lwObject *lwobject;   /* lightwave object mesh */
+  float beginx,beginy;  /* position of mouse */
+  float quat[4];        /* orientation of object */
+  float zoom;           /* field of view in degrees */
+} mesh_info;
+
+
+/* Define a new application type */
+class MyApp: public wxApp
+{
+public:
+    bool OnInit(void);
+};
+
+/* Define a new frame type */
+class TestGLCanvas;
+class MyFrame: public wxFrame
+{
+public:
+    MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size,
+        long style = wxDEFAULT_FRAME_STYLE);
+
+    void OnExit(wxCommandEvent& event);
+public:
+    TestGLCanvas*    m_canvas;
+
+DECLARE_EVENT_TABLE()
+};
+
+
+class TestGLCanvas: public wxGLCanvas
+{
+ public:
+   TestGLCanvas(wxWindow *parent, const wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
+      const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = "TestGLCanvas");
+   ~TestGLCanvas(void);
+
+   void OnPaint(wxPaintEvent& event);
+   void OnSize(wxSizeEvent& event);
+   void OnEraseBackground(wxEraseEvent& event);
+   void LoadLWO( const wxString &filename);
+   void OnMouse( wxMouseEvent& event );
+   void InitGL(void);
+   
+   mesh_info  info;
+   bool       block;
+
+DECLARE_EVENT_TABLE()
+};
+
+#endif
+
diff --git a/samples/opengl/penguin/penguin.lwo b/samples/opengl/penguin/penguin.lwo
new file mode 100644
index 0000000000000000000000000000000000000000..3f5122db827e09028d394b682ee6c0a1deec0ddd
GIT binary patch
literal 10028
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
PcWrX~nY%asqw)U-TLDh;

literal 0
HcmV?d00001

diff --git a/samples/opengl/penguin/penguin.rc b/samples/opengl/penguin/penguin.rc
new file mode 100644
index 0000000000..626b82f58a
--- /dev/null
+++ b/samples/opengl/penguin/penguin.rc
@@ -0,0 +1,3 @@
+/* mondrian ICON "mondrian.ico" */
+#include "wx/msw/wx.rc"
+
diff --git a/samples/opengl/penguin/trackball.h b/samples/opengl/penguin/trackball.h
new file mode 100644
index 0000000000..b676fb4e54
--- /dev/null
+++ b/samples/opengl/penguin/trackball.h
@@ -0,0 +1,78 @@
+/*
+ * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
+ * ALL RIGHTS RESERVED
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose and without fee is hereby granted, provided that the above
+ * copyright notice appear in all copies and that both the copyright notice
+ * and this permission notice appear in supporting documentation, and that
+ * the name of Silicon Graphics, Inc. not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission.
+ *
+ * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
+ * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
+ * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
+ * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
+ * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
+ * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
+ * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
+ * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
+ * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * US Government Users Restricted Rights
+ * Use, duplication, or disclosure by the Government is subject to
+ * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+ * (c)(1)(ii) of the Rights in Technical Data and Computer Software
+ * clause at DFARS 252.227-7013 and/or in similar or successor
+ * clauses in the FAR or the DOD or NASA FAR Supplement.
+ * Unpublished-- rights reserved under the copyright laws of the
+ * United States.  Contractor/manufacturer is Silicon Graphics,
+ * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
+ *
+ * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
+ */
+/*
+ * trackball.h
+ * A virtual trackball implementation
+ * Written by Gavin Bell for Silicon Graphics, November 1988.
+ */
+
+/*
+ * Pass the x and y coordinates of the last and current positions of
+ * the mouse, scaled so they are from (-1.0 ... 1.0).
+ *
+ * The resulting rotation is returned as a quaternion rotation in the
+ * first paramater.
+ */
+void
+trackball(float q[4], float p1x, float p1y, float p2x, float p2y);
+
+/*
+ * Given two quaternions, add them together to get a third quaternion.
+ * Adding quaternions to get a compound rotation is analagous to adding
+ * translations to get a compound translation.  When incrementally
+ * adding rotations, the first argument here should be the new
+ * rotation, the second and third the total rotation (which will be
+ * over-written with the resulting new total rotation).
+ */
+void
+add_quats(float *q1, float *q2, float *dest);
+
+/*
+ * A useful function, builds a rotation matrix in Matrix based on
+ * given quaternion.
+ */
+void
+build_rotmatrix(float m[4][4], float q[4]);
+
+/*
+ * This function computes a quaternion based on an axis (defined by
+ * the given vector) and an angle about which to rotate.  The angle is
+ * expressed in radians.  The result is put into the third argument.
+ */
+void
+axis_to_quat(float a[3], float phi, float q[4]);
+
diff --git a/src/generic/scrolwin.cpp b/src/generic/scrolwin.cpp
index 1c28693778..ada5b1c236 100644
--- a/src/generic/scrolwin.cpp
+++ b/src/generic/scrolwin.cpp
@@ -85,6 +85,7 @@ wxScrolledWindow::wxScrolledWindow()
     m_yScrollLinesPerPage = 0;
     m_scaleX = 1.0;
     m_scaleY = 1.0;
+    m_targetWindow = (wxWindow*) NULL;
 }
 
 bool wxScrolledWindow::Create(wxWindow *parent,
@@ -503,6 +504,9 @@ void wxScrolledWindow::SetScrollPageSize(int orient, int pageSize)
  */
 void wxScrolledWindow::Scroll( int x_pos, int y_pos )
 {
+    if (!m_targetWindow)
+        return;
+
     if (((x_pos == -1) || (x_pos == m_xScrollPosition)) &&
         ((y_pos == -1) || (y_pos == m_yScrollPosition))) return;
 
diff --git a/src/gtk/glcanvas.cpp b/src/gtk/glcanvas.cpp
new file mode 100644
index 0000000000..16c1cabe06
--- /dev/null
+++ b/src/gtk/glcanvas.cpp
@@ -0,0 +1,432 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        glcanvas.cpp
+// Purpose:     wxGLCanvas, for using OpenGL/Mesa with wxWindows and GTK
+// Author:      Robert Roebling
+// Modified by:
+// Created:     17/08/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Robert Roebling
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "glcanvas.h"
+#endif
+
+#include "wx/setup.h"
+
+#if wxUSE_GLCANVAS
+
+#include "wx/glcanvas.h"
+
+#include "wx/frame.h"
+#include "wx/colour.h"
+#include "wx/module.h"
+#include "wx/app.h"
+
+extern "C" {
+#include "gtk/gtk.h"
+#include "gdk/gdk.h"
+#include "gdk/gdkx.h"
+}
+
+#include "wx/gtk/win_gtk.h"
+
+//---------------------------------------------------------------------------
+// global data
+//---------------------------------------------------------------------------
+
+XVisualInfo *g_vi = (XVisualInfo*) NULL;
+
+//-----------------------------------------------------------------------------
+// idle system
+//-----------------------------------------------------------------------------
+
+extern void wxapp_install_idle_handler();
+extern bool g_isIdle;
+
+//---------------------------------------------------------------------------
+// wxGLContext
+//---------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGLContext,wxObject)
+
+wxGLContext::wxGLContext( bool WXUNUSED(isRGB), wxWindow *win, const wxPalette& WXUNUSED(palette) )
+{
+    m_window = win;
+    m_widget = win->m_wxwindow;
+
+    wxGLCanvas *gc = (wxGLCanvas*) win;
+    XVisualInfo *vi = (XVisualInfo *) gc->m_vi;
+    
+    wxCHECK_RET( vi, "invalid visual for OpenGl" );
+    
+    m_glContext = glXCreateContext( GDK_DISPLAY(), vi, None, GL_TRUE );
+  
+    wxCHECK_RET( m_glContext, "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;
+    XVisualInfo *vi = (XVisualInfo *) gc->m_vi;
+    
+    wxCHECK_RET( vi, "invalid visual for OpenGl" );
+    
+    if( other != 0 )
+        m_glContext = glXCreateContext( GDK_DISPLAY(), vi, other->m_glContext, GL_TRUE );
+    else
+        m_glContext = glXCreateContext( GDK_DISPLAY(), vi, None, GL_TRUE );
+    
+    wxCHECK_RET( m_glContext, "Couldn't create OpenGl context" );
+}
+
+wxGLContext::~wxGLContext()
+{
+    if (!m_glContext) return;
+    
+    if (m_glContext == glXGetCurrentContext())
+    {
+        glXMakeCurrent( GDK_DISPLAY(), None, NULL);
+    }
+	
+    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()
+{
+    if (m_glContext) 
+    { 
+        GdkWindow *window = GTK_PIZZA(m_widget)->bin_window;
+        glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window), m_glContext );
+    }
+}
+
+void wxGLContext::SetColour(const char *colour)
+{
+    float r = 0.0;
+    float g = 0.0;
+    float b = 0.0;
+    wxColour *col = wxTheColourDatabase->FindColour(colour);
+    if (col)
+    {
+        r = (float)(col->Red()/256.0);
+        g = (float)(col->Green()/256.0);
+        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
+//-----------------------------------------------------------------------------
+
+static gint
+gtk_glwindow_realized_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
+{
+    wxGLContext *share= win->m_sharedContext;
+    if (share==NULL && win->m_sharedContextOf) share=win->m_sharedContextOf->GetContext();
+
+    win->m_glContext = new wxGLContext( TRUE, win, wxNullPalette, share );
+
+    return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "map" from m_wxwindow
+//-----------------------------------------------------------------------------
+
+static gint
+gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
+{
+    if (win->m_glContext/* && win->m_exposed*/)
+    {
+        wxPaintEvent event( win->GetId() );
+        event.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent( event );
+
+        win->m_exposed = FALSE;
+        win->GetUpdateRegion().Clear();
+    }
+
+    return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "expose_event" of m_wxwindow
+//-----------------------------------------------------------------------------
+
+static void 
+gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
+{
+    if (g_isIdle) 
+        wxapp_install_idle_handler();
+
+    win->m_exposed = TRUE;
+
+    win->GetUpdateRegion().Union( gdk_event->area.x,
+                                  gdk_event->area.y,
+                                  gdk_event->area.width,
+                                  gdk_event->area.height );
+}
+
+//-----------------------------------------------------------------------------
+// "draw" of m_wxwindow
+//-----------------------------------------------------------------------------
+
+static void 
+gtk_glwindow_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxGLCanvas *win )
+{
+    if (g_isIdle) 
+        wxapp_install_idle_handler();
+
+    win->m_exposed = TRUE;
+
+    win->GetUpdateRegion().Union( rect->x, rect->y,
+                                  rect->width, rect->height );
+}
+
+//-----------------------------------------------------------------------------
+// "size_allocate" of m_wxwindow
+//-----------------------------------------------------------------------------
+
+static void 
+gtk_glcanvas_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxGLCanvas *win )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    if (!win->m_hasVMT)
+        return;
+
+    wxSizeEvent event( wxSize(win->m_width,win->m_height), win->GetId() );
+    event.SetEventObject( win );
+    win->GetEventHandler()->ProcessEvent( event );
+}
+
+//---------------------------------------------------------------------------
+// wxGlCanvas
+//---------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
+
+BEGIN_EVENT_TABLE(wxGLCanvas, wxScrolledWindow)
+    EVT_SIZE(wxGLCanvas::OnSize)
+END_EVENT_TABLE()
+
+wxGLCanvas::wxGLCanvas( wxWindow *parent, wxWindowID id,
+                        const wxPoint& pos, const wxSize& size, 
+			long style, const wxString& name,
+                        int *attribList, 
+			const wxPalette& palette )
+{
+    Create( parent, NULL, NULL, id, pos, size, style, name, attribList, palette );
+}
+
+wxGLCanvas::wxGLCanvas( wxWindow *parent, 
+                        const wxGLContext *shared,
+                        wxWindowID id,
+                        const wxPoint& pos, const wxSize& size, 
+			long style, const wxString& name,
+                        int *attribList, 
+			const wxPalette& palette )
+{			
+    Create( parent, shared, NULL, id, pos, size, style, name, attribList, palette );
+}
+
+wxGLCanvas::wxGLCanvas( wxWindow *parent, 
+                        const wxGLCanvas *shared,
+                        wxWindowID id,
+                        const wxPoint& pos, const wxSize& size, 
+			long style, const wxString& name,
+                        int *attribList, 
+			const wxPalette& palette )
+{			
+    Create( parent, NULL, shared, id, pos, size, style, name, attribList, palette );
+}
+
+bool wxGLCanvas::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)
+{
+    m_sharedContext = (wxGLContext*)shared;  // const_cast
+    m_sharedContextOf = (wxGLCanvas*)shared_context_of;  // const_cast
+    m_glContext = (wxGLContext*) NULL;
+    
+    m_exposed = FALSE;
+    m_noExpose = TRUE;
+    m_nativeSizeEvent = TRUE;
+    
+    if (!attribList)
+    {
+        int data[] = { GLX_RGBA, 
+	               GLX_DOUBLEBUFFER, 
+		       GLX_DEPTH_SIZE, 1,  // use largest available depth buffer
+		       GLX_RED_SIZE, 1, 
+		       GLX_GREEN_SIZE, 1, 
+		       GLX_BLUE_SIZE, 1, 
+		       GLX_ALPHA_SIZE, 0, 
+		       None };
+	attribList = (int*) data;
+    }
+    else
+    {
+      int data[512], arg=0, p=0;
+       
+      while( (attribList[arg]!=0) && (p<512) )
+      {
+        switch( attribList[arg++] )
+        {
+          case WX_GL_RGBA: data[p++] = GLX_RGBA; break;
+          case WX_GL_DOUBLEBUFFER: data[p++] = GLX_DOUBLEBUFFER; break;
+          case WX_GL_DEPTH_SIZE: 
+            data[p++]=GLX_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
+          case WX_GL_MIN_RED:
+            data[p++]=GLX_RED_SIZE; data[p++]=attribList[arg++]; break;
+          case WX_GL_MIN_GREEN:
+            data[p++]=GLX_GREEN_SIZE; data[p++]=attribList[arg++]; break;
+          case WX_GL_MIN_BLUE:
+            data[p++]=GLX_BLUE_SIZE; data[p++]=attribList[arg++]; break;
+          default:
+            break;
+        }
+      }       
+      data[p] = 0; 
+
+      attribList = (int*) data;
+    }
+    
+    
+    Display *dpy = GDK_DISPLAY();
+    
+    XVisualInfo *vi = glXChooseVisual( dpy, DefaultScreen(dpy), attribList );
+    
+    m_vi = vi;  // safe for later use
+    
+    wxCHECK_MSG( m_vi, FALSE, "required visual couldn't be found" );
+
+    GdkVisual *visual = gdkx_visual_get( vi->visualid );
+    GdkColormap *colormap = gdk_colormap_new( gdkx_visual_get(vi->visualid), TRUE );
+    
+    gtk_widget_push_colormap( colormap );
+    gtk_widget_push_visual( visual );
+
+    wxScrolledWindow::Create( parent, id, pos, size, style, name );
+
+    m_glWidget = m_wxwindow;
+    
+    gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow), FALSE );
+    
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
+                            GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback), (gpointer) this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "map",
+                            GTK_SIGNAL_FUNC(gtk_glwindow_map_callback), (gpointer) this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
+        GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback), (gpointer)this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
+        GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback), (gpointer)this );
+	
+    gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
+        GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback), (gpointer)this );
+
+    gtk_widget_pop_visual();
+    gtk_widget_pop_colormap();
+    
+    return TRUE;
+}
+
+wxGLCanvas::~wxGLCanvas()
+{
+    XVisualInfo *vi = (XVisualInfo *) m_vi;
+    
+    if (vi) XFree( vi );
+    if (m_glContext) delete m_glContext;
+}
+
+void wxGLCanvas::SwapBuffers()
+{
+    if (m_glContext) m_glContext->SwapBuffers();
+}
+
+void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
+{
+    int width, height;
+    GetClientSize( &width, &height );
+    
+    if (m_glContext && GTK_WIDGET_REALIZED(m_glWidget) )
+    {
+        SetCurrent(); 
+	
+        glViewport(0, 0, (GLint)width, (GLint)height );
+        glMatrixMode(GL_PROJECTION);
+        glLoadIdentity();
+        glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
+        glMatrixMode(GL_MODELVIEW);
+    }
+}
+
+void wxGLCanvas::SetCurrent()
+{
+    if (m_glContext) m_glContext->SetCurrent();
+}
+
+void wxGLCanvas::SetColour( const char *colour )
+{
+    if (m_glContext) m_glContext->SetColour( colour );
+}
+
+void wxGLCanvas::OnInternalIdle()
+{
+    if (m_glContext && m_exposed)
+    {
+        wxPaintEvent event( GetId() );
+        event.SetEventObject( this );
+        GetEventHandler()->ProcessEvent( event );
+
+        m_exposed = FALSE;
+        GetUpdateRegion().Clear();
+    }
+    
+    wxWindow::OnInternalIdle();
+}
+
+#endif
+    // wxUSE_GLCANVAS
+
diff --git a/src/gtk1/glcanvas.cpp b/src/gtk1/glcanvas.cpp
new file mode 100644
index 0000000000..16c1cabe06
--- /dev/null
+++ b/src/gtk1/glcanvas.cpp
@@ -0,0 +1,432 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        glcanvas.cpp
+// Purpose:     wxGLCanvas, for using OpenGL/Mesa with wxWindows and GTK
+// Author:      Robert Roebling
+// Modified by:
+// Created:     17/08/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Robert Roebling
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "glcanvas.h"
+#endif
+
+#include "wx/setup.h"
+
+#if wxUSE_GLCANVAS
+
+#include "wx/glcanvas.h"
+
+#include "wx/frame.h"
+#include "wx/colour.h"
+#include "wx/module.h"
+#include "wx/app.h"
+
+extern "C" {
+#include "gtk/gtk.h"
+#include "gdk/gdk.h"
+#include "gdk/gdkx.h"
+}
+
+#include "wx/gtk/win_gtk.h"
+
+//---------------------------------------------------------------------------
+// global data
+//---------------------------------------------------------------------------
+
+XVisualInfo *g_vi = (XVisualInfo*) NULL;
+
+//-----------------------------------------------------------------------------
+// idle system
+//-----------------------------------------------------------------------------
+
+extern void wxapp_install_idle_handler();
+extern bool g_isIdle;
+
+//---------------------------------------------------------------------------
+// wxGLContext
+//---------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGLContext,wxObject)
+
+wxGLContext::wxGLContext( bool WXUNUSED(isRGB), wxWindow *win, const wxPalette& WXUNUSED(palette) )
+{
+    m_window = win;
+    m_widget = win->m_wxwindow;
+
+    wxGLCanvas *gc = (wxGLCanvas*) win;
+    XVisualInfo *vi = (XVisualInfo *) gc->m_vi;
+    
+    wxCHECK_RET( vi, "invalid visual for OpenGl" );
+    
+    m_glContext = glXCreateContext( GDK_DISPLAY(), vi, None, GL_TRUE );
+  
+    wxCHECK_RET( m_glContext, "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;
+    XVisualInfo *vi = (XVisualInfo *) gc->m_vi;
+    
+    wxCHECK_RET( vi, "invalid visual for OpenGl" );
+    
+    if( other != 0 )
+        m_glContext = glXCreateContext( GDK_DISPLAY(), vi, other->m_glContext, GL_TRUE );
+    else
+        m_glContext = glXCreateContext( GDK_DISPLAY(), vi, None, GL_TRUE );
+    
+    wxCHECK_RET( m_glContext, "Couldn't create OpenGl context" );
+}
+
+wxGLContext::~wxGLContext()
+{
+    if (!m_glContext) return;
+    
+    if (m_glContext == glXGetCurrentContext())
+    {
+        glXMakeCurrent( GDK_DISPLAY(), None, NULL);
+    }
+	
+    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()
+{
+    if (m_glContext) 
+    { 
+        GdkWindow *window = GTK_PIZZA(m_widget)->bin_window;
+        glXMakeCurrent( GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window), m_glContext );
+    }
+}
+
+void wxGLContext::SetColour(const char *colour)
+{
+    float r = 0.0;
+    float g = 0.0;
+    float b = 0.0;
+    wxColour *col = wxTheColourDatabase->FindColour(colour);
+    if (col)
+    {
+        r = (float)(col->Red()/256.0);
+        g = (float)(col->Green()/256.0);
+        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
+//-----------------------------------------------------------------------------
+
+static gint
+gtk_glwindow_realized_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
+{
+    wxGLContext *share= win->m_sharedContext;
+    if (share==NULL && win->m_sharedContextOf) share=win->m_sharedContextOf->GetContext();
+
+    win->m_glContext = new wxGLContext( TRUE, win, wxNullPalette, share );
+
+    return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "map" from m_wxwindow
+//-----------------------------------------------------------------------------
+
+static gint
+gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
+{
+    if (win->m_glContext/* && win->m_exposed*/)
+    {
+        wxPaintEvent event( win->GetId() );
+        event.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent( event );
+
+        win->m_exposed = FALSE;
+        win->GetUpdateRegion().Clear();
+    }
+
+    return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "expose_event" of m_wxwindow
+//-----------------------------------------------------------------------------
+
+static void 
+gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
+{
+    if (g_isIdle) 
+        wxapp_install_idle_handler();
+
+    win->m_exposed = TRUE;
+
+    win->GetUpdateRegion().Union( gdk_event->area.x,
+                                  gdk_event->area.y,
+                                  gdk_event->area.width,
+                                  gdk_event->area.height );
+}
+
+//-----------------------------------------------------------------------------
+// "draw" of m_wxwindow
+//-----------------------------------------------------------------------------
+
+static void 
+gtk_glwindow_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxGLCanvas *win )
+{
+    if (g_isIdle) 
+        wxapp_install_idle_handler();
+
+    win->m_exposed = TRUE;
+
+    win->GetUpdateRegion().Union( rect->x, rect->y,
+                                  rect->width, rect->height );
+}
+
+//-----------------------------------------------------------------------------
+// "size_allocate" of m_wxwindow
+//-----------------------------------------------------------------------------
+
+static void 
+gtk_glcanvas_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxGLCanvas *win )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    if (!win->m_hasVMT)
+        return;
+
+    wxSizeEvent event( wxSize(win->m_width,win->m_height), win->GetId() );
+    event.SetEventObject( win );
+    win->GetEventHandler()->ProcessEvent( event );
+}
+
+//---------------------------------------------------------------------------
+// wxGlCanvas
+//---------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
+
+BEGIN_EVENT_TABLE(wxGLCanvas, wxScrolledWindow)
+    EVT_SIZE(wxGLCanvas::OnSize)
+END_EVENT_TABLE()
+
+wxGLCanvas::wxGLCanvas( wxWindow *parent, wxWindowID id,
+                        const wxPoint& pos, const wxSize& size, 
+			long style, const wxString& name,
+                        int *attribList, 
+			const wxPalette& palette )
+{
+    Create( parent, NULL, NULL, id, pos, size, style, name, attribList, palette );
+}
+
+wxGLCanvas::wxGLCanvas( wxWindow *parent, 
+                        const wxGLContext *shared,
+                        wxWindowID id,
+                        const wxPoint& pos, const wxSize& size, 
+			long style, const wxString& name,
+                        int *attribList, 
+			const wxPalette& palette )
+{			
+    Create( parent, shared, NULL, id, pos, size, style, name, attribList, palette );
+}
+
+wxGLCanvas::wxGLCanvas( wxWindow *parent, 
+                        const wxGLCanvas *shared,
+                        wxWindowID id,
+                        const wxPoint& pos, const wxSize& size, 
+			long style, const wxString& name,
+                        int *attribList, 
+			const wxPalette& palette )
+{			
+    Create( parent, NULL, shared, id, pos, size, style, name, attribList, palette );
+}
+
+bool wxGLCanvas::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)
+{
+    m_sharedContext = (wxGLContext*)shared;  // const_cast
+    m_sharedContextOf = (wxGLCanvas*)shared_context_of;  // const_cast
+    m_glContext = (wxGLContext*) NULL;
+    
+    m_exposed = FALSE;
+    m_noExpose = TRUE;
+    m_nativeSizeEvent = TRUE;
+    
+    if (!attribList)
+    {
+        int data[] = { GLX_RGBA, 
+	               GLX_DOUBLEBUFFER, 
+		       GLX_DEPTH_SIZE, 1,  // use largest available depth buffer
+		       GLX_RED_SIZE, 1, 
+		       GLX_GREEN_SIZE, 1, 
+		       GLX_BLUE_SIZE, 1, 
+		       GLX_ALPHA_SIZE, 0, 
+		       None };
+	attribList = (int*) data;
+    }
+    else
+    {
+      int data[512], arg=0, p=0;
+       
+      while( (attribList[arg]!=0) && (p<512) )
+      {
+        switch( attribList[arg++] )
+        {
+          case WX_GL_RGBA: data[p++] = GLX_RGBA; break;
+          case WX_GL_DOUBLEBUFFER: data[p++] = GLX_DOUBLEBUFFER; break;
+          case WX_GL_DEPTH_SIZE: 
+            data[p++]=GLX_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
+          case WX_GL_MIN_RED:
+            data[p++]=GLX_RED_SIZE; data[p++]=attribList[arg++]; break;
+          case WX_GL_MIN_GREEN:
+            data[p++]=GLX_GREEN_SIZE; data[p++]=attribList[arg++]; break;
+          case WX_GL_MIN_BLUE:
+            data[p++]=GLX_BLUE_SIZE; data[p++]=attribList[arg++]; break;
+          default:
+            break;
+        }
+      }       
+      data[p] = 0; 
+
+      attribList = (int*) data;
+    }
+    
+    
+    Display *dpy = GDK_DISPLAY();
+    
+    XVisualInfo *vi = glXChooseVisual( dpy, DefaultScreen(dpy), attribList );
+    
+    m_vi = vi;  // safe for later use
+    
+    wxCHECK_MSG( m_vi, FALSE, "required visual couldn't be found" );
+
+    GdkVisual *visual = gdkx_visual_get( vi->visualid );
+    GdkColormap *colormap = gdk_colormap_new( gdkx_visual_get(vi->visualid), TRUE );
+    
+    gtk_widget_push_colormap( colormap );
+    gtk_widget_push_visual( visual );
+
+    wxScrolledWindow::Create( parent, id, pos, size, style, name );
+
+    m_glWidget = m_wxwindow;
+    
+    gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow), FALSE );
+    
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
+                            GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback), (gpointer) this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "map",
+                            GTK_SIGNAL_FUNC(gtk_glwindow_map_callback), (gpointer) this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
+        GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback), (gpointer)this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
+        GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback), (gpointer)this );
+	
+    gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
+        GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback), (gpointer)this );
+
+    gtk_widget_pop_visual();
+    gtk_widget_pop_colormap();
+    
+    return TRUE;
+}
+
+wxGLCanvas::~wxGLCanvas()
+{
+    XVisualInfo *vi = (XVisualInfo *) m_vi;
+    
+    if (vi) XFree( vi );
+    if (m_glContext) delete m_glContext;
+}
+
+void wxGLCanvas::SwapBuffers()
+{
+    if (m_glContext) m_glContext->SwapBuffers();
+}
+
+void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
+{
+    int width, height;
+    GetClientSize( &width, &height );
+    
+    if (m_glContext && GTK_WIDGET_REALIZED(m_glWidget) )
+    {
+        SetCurrent(); 
+	
+        glViewport(0, 0, (GLint)width, (GLint)height );
+        glMatrixMode(GL_PROJECTION);
+        glLoadIdentity();
+        glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
+        glMatrixMode(GL_MODELVIEW);
+    }
+}
+
+void wxGLCanvas::SetCurrent()
+{
+    if (m_glContext) m_glContext->SetCurrent();
+}
+
+void wxGLCanvas::SetColour( const char *colour )
+{
+    if (m_glContext) m_glContext->SetColour( colour );
+}
+
+void wxGLCanvas::OnInternalIdle()
+{
+    if (m_glContext && m_exposed)
+    {
+        wxPaintEvent event( GetId() );
+        event.SetEventObject( this );
+        GetEventHandler()->ProcessEvent( event );
+
+        m_exposed = FALSE;
+        GetUpdateRegion().Clear();
+    }
+    
+    wxWindow::OnInternalIdle();
+}
+
+#endif
+    // wxUSE_GLCANVAS
+
diff --git a/src/motif/glcanvas.cpp b/src/motif/glcanvas.cpp
new file mode 100644
index 0000000000..1d5e2936a3
--- /dev/null
+++ b/src/motif/glcanvas.cpp
@@ -0,0 +1,168 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        glcanvas.cpp
+// Purpose:     wxGLCanvas, for using OpenGL with wxWindows 2.0 for Motif.
+//              Uses the GLX extension.
+// Author:      Julian Smart and Wolfram Gloger
+// Modified by:
+// Created:     1995, 1999
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart, Wolfram Gloger
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "glcanvas.h"
+#endif
+
+#include "wx/setup.h"
+
+#if wxUSE_GLCANVAS
+
+#include "wx/glcanvas.h"
+#include "wx/utils.h"
+#include "wx/app.h"
+
+#include <Xm/Xm.h>
+#include "wx/motif/private.h"
+
+#ifdef OLD_MESA
+// workaround for bug in Mesa's glx.c
+static int bitcount( unsigned long n )
+{
+    int bits;
+    for (bits=0; n>0;) {
+	if(n & 1) bits++;
+	n = n >> 1;
+    }
+    return bits;
+}
+#endif
+
+/*
+ * GLCanvas implementation
+ */
+
+IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
+
+wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos,
+  const wxSize& size, long style, 
+  const wxString& name, int *attrib_list, const wxPalette& palette):
+    wxScrolledWindow(parent, id, pos, size, style, name)
+{
+    XVisualInfo *vi, vi_templ;
+    XWindowAttributes xwa;
+    int val, n;
+
+    Display* display = (Display*) GetXDisplay();
+
+    glx_cx = 0;
+    // Check for the presence of the GLX extension
+    if(!glXQueryExtension(display, NULL, NULL)) {
+	wxDebugMsg("wxGLCanvas: GLX extension is missing\n");
+	return;
+    }
+
+    if(attrib_list) {
+	// Get an appropriate visual
+	vi = glXChooseVisual(display, DefaultScreen(display), attrib_list);
+	if(!vi) return;
+
+	// Here we should make sure that vi is the same visual as the
+	// one used by the xwindow drawable in wxCanvas.  However,
+	// there is currently no mechanism for this in wx_canvs.cc.
+    } else {
+	// By default, we use the visual of xwindow
+	XGetWindowAttributes(display, (Window) GetXWindow(), &xwa);
+	vi_templ.visualid = XVisualIDFromVisual(xwa.visual);
+	vi = XGetVisualInfo(display, VisualIDMask, &vi_templ, &n);
+	if(!vi) return;
+	glXGetConfig(display, vi, GLX_USE_GL, &val);
+	if(!val) return;
+	// Basically, this is it.  It should be possible to use vi
+	// in glXCreateContext() below.  But this fails with Mesa.
+	// I notified the Mesa author about it; there may be a fix.
+#ifdef OLD_MESA
+	// Construct an attribute list matching the visual
+	int a_list[32];
+	n = 0;
+	if(vi->c_class==TrueColor || vi->c_class==DirectColor) { // RGBA visual
+	    a_list[n++] = GLX_RGBA;
+	    a_list[n++] = GLX_RED_SIZE;
+	    a_list[n++] = bitcount(vi->red_mask);
+	    a_list[n++] = GLX_GREEN_SIZE;
+	    a_list[n++] = bitcount(vi->green_mask);
+	    a_list[n++] = GLX_BLUE_SIZE;
+	    a_list[n++] = bitcount(vi->blue_mask);
+	    glXGetConfig(display, vi, GLX_ALPHA_SIZE, &val);
+	    a_list[n++] = GLX_ALPHA_SIZE;
+	    a_list[n++] = val;
+	} else { // Color index visual
+	    glXGetConfig(display, vi, GLX_BUFFER_SIZE, &val);
+	    a_list[n++] = GLX_BUFFER_SIZE;
+	    a_list[n++] = val;
+	}
+	a_list[n] = None;
+	XFree(vi);
+	vi = glXChooseVisual(display, DefaultScreen(display), a_list);
+	if(!vi) return;
+#endif /* OLD_MESA */
+    }
+
+    // Create the GLX context and make it current
+    glx_cx = glXCreateContext(display, vi, 0, GL_TRUE);
+#ifndef OLD_MESA
+    XFree(vi);
+#endif
+    SetCurrent();
+}
+
+wxGLCanvas::~wxGLCanvas(void)
+{
+    Display* display = (Display*) GetXDisplay();
+    if(glx_cx) glXDestroyContext(display, glx_cx);
+}
+
+void wxGLCanvas::SwapBuffers()
+{
+    Display* display = (Display*) GetXDisplay();
+    if(glx_cx) glXSwapBuffers(display, (Window) GetXWindow());
+}
+
+void wxGLCanvas::SetCurrent()
+{
+    Display* display = (Display*) GetXDisplay();
+    if(glx_cx) glXMakeCurrent(display, (Window) GetXWindow(), glx_cx);
+}
+
+void wxGLCanvas::SetColour(const char *col)
+{
+    wxColour *the_colour = wxTheColourDatabase->FindColour(col);
+    if(the_colour) {
+	GLboolean b;
+	glGetBooleanv(GL_RGBA_MODE, &b);
+	if(b) {
+	    glColor3ub(the_colour->Red(),
+		       the_colour->Green(),
+		       the_colour->Blue());
+	} else {
+	    GLint pix = (GLint)the_colour->m_pixel;
+	    if(pix == -1) {
+		XColor exact_def;
+		exact_def.red = (unsigned short)the_colour->Red() << 8;
+		exact_def.green = (unsigned short)the_colour->Green() << 8;
+		exact_def.blue = (unsigned short)the_colour->Blue() << 8;
+		exact_def.flags = DoRed | DoGreen | DoBlue;
+		if(!XAllocColor((Display*) GetXDisplay(), (Colormap) wxTheApp->GetMainColormap(GetXDisplay()), &exact_def)) {
+		    wxDebugMsg("wxGLCanvas: cannot allocate color\n");
+		    return;
+		}
+		pix = the_colour->m_pixel = exact_def.pixel;
+	    }
+	    glIndexi(pix);
+	}
+    }
+}
+
+#endif
+    // wxUSE_GLCANVAS
+
diff --git a/src/msw/glcanvas.cpp b/src/msw/glcanvas.cpp
new file mode 100644
index 0000000000..dd49c13117
--- /dev/null
+++ b/src/msw/glcanvas.cpp
@@ -0,0 +1,624 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        glcanvas.cpp
+// Purpose:     wxGLCanvas, for using OpenGL with wxWindows under MS Windows
+// Author:      Julian Smart
+// Modified by:
+// Created:     04/01/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:   	wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "glcanvas.h"
+#endif
+
+#include "wx/wxprec.h"
+
+#if defined(__BORLANDC__)
+#pragma hdrstop
+#endif
+
+#include <wx/setup.h>
+
+#if wxUSE_GLCANVAS
+
+#ifndef WX_PRECOMP
+#include <wx/frame.h>
+#endif
+
+#include <wx/msw/private.h>
+
+#include <wx/glcanvas.h>
+
+wxChar wxGLCanvasClassName[]        = wxT("wxGLCanvasClass");
+
+LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
+                                   WPARAM wParam, LPARAM lParam);
+
+/*
+ * GLContext implementation
+ */
+
+wxGLContext::wxGLContext(bool isRGB, wxGLCanvas *win, const wxPalette& palette)
+{
+  m_window = win;
+
+  m_hDC = win->GetHDC();
+
+  m_glContext = wglCreateContext((HDC) m_hDC);
+  wxCHECK_RET( m_glContext, "Couldn't create OpenGl context" );
+
+  wglMakeCurrent((HDC) m_hDC, m_glContext);
+}
+
+wxGLContext::wxGLContext(
+               bool isRGB, wxGLCanvas *win,
+               const wxPalette& palette,
+               const wxGLContext *other        /* for sharing display lists */
+)
+{
+    m_window = win;
+
+    m_hDC = win->GetHDC();
+
+    m_glContext = wglCreateContext((HDC) m_hDC);
+    wxCHECK_RET( m_glContext, "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);
+  	wglDeleteContext(m_glContext);
+  }
+}
+
+void wxGLContext::SwapBuffers()
+{
+  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);
+  }
+
+/*
+	setupPixelFormat(hDC);
+	setupPalette(hDC);
+*/
+}
+
+void wxGLContext::SetColour(const char *colour)
+{
+  float r = 0.0;
+  float g = 0.0;
+  float b = 0.0;
+  wxColour *col = wxTheColourDatabase->FindColour(colour);
+  if (col)
+  {
+    r = (float)(col->Red()/256.0);
+    g = (float)(col->Green()/256.0);
+    b = (float)(col->Blue()/256.0);
+    glColor3f( r, g, b);
+  }
+}
+
+
+/*
+ * wxGLCanvas implementation
+ */
+
+IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
+
+BEGIN_EVENT_TABLE(wxGLCanvas, wxScrolledWindow)
+    EVT_SIZE(wxGLCanvas::OnSize)
+    EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
+    EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
+END_EVENT_TABLE()
+
+wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
+    const wxPoint& pos, const wxSize& size, long style, const wxString& name,
+    int *attribList /* not used yet! */, const wxPalette& palette):
+  wxScrolledWindow()
+{
+    m_glContext = (wxGLContext*) NULL;
+
+    bool ret = Create(parent, id, pos, size, style, name);
+
+    if ( ret )
+    {
+        SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
+        SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
+    }
+
+	m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
+
+    SetupPixelFormat();
+    SetupPalette(palette);
+
+    m_glContext = new wxGLContext(TRUE, this, palette);
+}
+
+wxGLCanvas::wxGLCanvas( wxWindow *parent,
+              const wxGLContext *shared, wxWindowID id,
+              const wxPoint& pos, const wxSize& size, long style, const wxString& name,
+              int *attribList, const wxPalette& palette )
+  : wxScrolledWindow()
+{
+   m_glContext = (wxGLContext*) NULL;
+
+   bool ret = Create(parent, id, pos, size, style, name);
+
+    if ( ret )
+    {
+        SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
+        SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
+    }
+
+    m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
+
+    SetupPixelFormat();
+    SetupPalette(palette);
+
+    m_glContext = new wxGLContext(TRUE, this, palette, shared );
+}
+
+// Not very usefull for wxMSW, but this is to be wxGTK compliant
+
+wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
+                        const wxPoint& pos, const wxSize& size, long style, const wxString& name,
+                        int *attribList, const wxPalette& palette ):
+  wxScrolledWindow()
+{
+    m_glContext = (wxGLContext*) NULL;
+
+    bool ret = Create(parent, id, pos, size, style, name);
+
+    if ( ret )
+    {
+        SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
+        SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
+    }
+
+	m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
+
+    SetupPixelFormat();
+    SetupPalette(palette);
+
+    wxGLContext *sharedContext=0;
+    if (shared) sharedContext=shared->GetContext();
+    m_glContext = new wxGLContext(TRUE, this, palette, sharedContext );
+}
+
+wxGLCanvas::~wxGLCanvas()
+{
+  if (m_glContext)
+    delete m_glContext;
+
+  ::ReleaseDC((HWND) GetHWND(), (HDC) m_hDC);
+}
+
+// Replaces wxWindow::Create functionality, since we need to use a different window class
+bool wxGLCanvas::Create(wxWindow *parent, wxWindowID id,
+              const wxPoint& pos, const wxSize& size, long style, const wxString& name)
+{
+    static bool registeredGLCanvasClass = FALSE;
+
+    // We have to register a special window class because we need
+    // the CS_OWNDC style for GLCanvas.
+
+/*
+    From Angel Popov <jumpo@bitex.com>
+
+    Here are two snips from a dicussion in the OpenGL Gamedev list that explains
+    how this problem can be fixed:
+
+    "There are 5 common DCs available in Win95. These are aquired when you call
+    GetDC or GetDCEx from a window that does _not_ have the OWNDC flag.
+    OWNDC flagged windows do not get their DC from the common DC pool, the issue
+    is they require 800 bytes each from the limited 64Kb local heap for GDI."
+
+    "The deal is, if you hold onto one of the 5 shared DC's too long (as GL apps
+    do), Win95 will actually "steal" it from you.  MakeCurrent fails,
+    apparently, because Windows re-assigns the HDC to a different window.  The
+    only way to prevent this, the only reliable means, is to set CS_OWNDC."
+*/
+
+    if (!registeredGLCanvasClass)
+    {
+        WNDCLASS wndclass;
+
+        static const long styleNormal = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC;
+
+        // the fields which are common to all classes
+        wndclass.lpfnWndProc   = (WNDPROC)wxWndProc;
+        wndclass.cbClsExtra    = 0;
+        wndclass.cbWndExtra    = sizeof( DWORD ); // VZ: what is this DWORD used for?
+        wndclass.hInstance     = wxhInstance;
+        wndclass.hIcon         = (HICON) NULL;
+        wndclass.hCursor       = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
+        wndclass.lpszMenuName  = NULL;
+
+        // Register the GLCanvas class name
+        wndclass.hbrBackground = (HBRUSH)NULL;
+        wndclass.lpszClassName = wxGLCanvasClassName;
+        wndclass.style         = styleNormal;
+
+        if ( !RegisterClass(&wndclass) )
+        {
+            wxLogLastError("RegisterClass(wxGLCanvasClass)");
+
+            return FALSE;
+        }
+        registeredGLCanvasClass = TRUE;
+    }
+
+    wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
+
+    if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
+        return FALSE;
+
+    parent->AddChild(this);
+
+    DWORD msflags = 0;
+    if ( style & wxBORDER )
+        msflags |= WS_BORDER;
+    if ( style & wxTHICK_FRAME )
+        msflags |= WS_THICKFRAME;
+
+    msflags |= WS_CHILD | WS_VISIBLE;
+    if ( style & wxCLIP_CHILDREN )
+        msflags |= WS_CLIPCHILDREN;
+
+    bool want3D;
+    WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D);
+
+    // Even with extended styles, need to combine with WS_BORDER
+    // for them to look right.
+    if ( want3D || (m_windowStyle & wxSIMPLE_BORDER) || (m_windowStyle & wxRAISED_BORDER ) ||
+        (m_windowStyle & wxSUNKEN_BORDER) || (m_windowStyle & wxDOUBLE_BORDER))
+    {
+        msflags |= WS_BORDER;
+    }
+
+    // calculate the value to return from WM_GETDLGCODE handler
+    if ( GetWindowStyleFlag() & wxWANTS_CHARS )
+    {
+        // want everything: i.e. all keys and WM_CHAR message
+        m_lDlgCode = DLGC_WANTARROWS | DLGC_WANTCHARS |
+                     DLGC_WANTTAB | DLGC_WANTMESSAGE;
+    }
+
+    MSWCreate(m_windowId, parent, wxGLCanvasClassName, this, NULL,
+              pos.x, pos.y,
+              WidthDefault(size.x), HeightDefault(size.y),
+              msflags, NULL, exStyle);
+
+    return TRUE;
+
+}
+
+void wxGLCanvas::SetupPixelFormat() // (HDC hDC)
+{
+    PIXELFORMATDESCRIPTOR pfd = {
+	sizeof(PIXELFORMATDESCRIPTOR),	/* size */
+	1,				/* version */
+	PFD_SUPPORT_OPENGL |
+	PFD_DRAW_TO_WINDOW |
+	PFD_DOUBLEBUFFER,		/* support double-buffering */
+	PFD_TYPE_RGBA,			/* color type */
+	16,				/* prefered color depth */
+	0, 0, 0, 0, 0, 0,		/* color bits (ignored) */
+	0,				/* no alpha buffer */
+	0,				/* alpha bits (ignored) */
+	0,				/* no accumulation buffer */
+	0, 0, 0, 0,			/* accum bits (ignored) */
+	16,				/* depth buffer */
+	0,				/* no stencil buffer */
+	0,				/* no auxiliary buffers */
+	PFD_MAIN_PLANE,			/* main layer */
+	0,				/* reserved */
+	0, 0, 0,			/* no layer, visible, damage masks */
+    };
+    int pixelFormat;
+
+    pixelFormat = ChoosePixelFormat((HDC) m_hDC, &pfd);
+    if (pixelFormat == 0) {
+	MessageBox(WindowFromDC((HDC) m_hDC), "ChoosePixelFormat failed.", "Error",
+		MB_ICONERROR | MB_OK);
+	exit(1);
+    }
+
+    if (SetPixelFormat((HDC) m_hDC, pixelFormat, &pfd) != TRUE) {
+	MessageBox(WindowFromDC((HDC) m_hDC), "SetPixelFormat failed.", "Error",
+		MB_ICONERROR | MB_OK);
+	exit(1);
+    }
+}
+
+void wxGLCanvas::SetupPalette(const wxPalette& palette)
+{
+    int pixelFormat = GetPixelFormat((HDC) m_hDC);
+    PIXELFORMATDESCRIPTOR pfd;
+
+    DescribePixelFormat((HDC) m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+
+    if (pfd.dwFlags & PFD_NEED_PALETTE)
+    {
+    }
+    else
+    {
+	  return;
+    }
+
+    m_palette = palette;
+
+    if ( !m_palette.Ok() )
+    {
+        m_palette = CreateDefaultPalette();
+    }
+
+    if (m_palette.Ok())
+    {
+        SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), FALSE);
+        RealizePalette((HDC) m_hDC);
+    }
+}
+
+wxPalette wxGLCanvas::CreateDefaultPalette()
+{
+    PIXELFORMATDESCRIPTOR pfd;
+    int paletteSize;
+    int pixelFormat = GetPixelFormat((HDC) m_hDC);
+
+    DescribePixelFormat((HDC) m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+
+	paletteSize = 1 << pfd.cColorBits;
+
+    LOGPALETTE* pPal =
+     (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
+    pPal->palVersion = 0x300;
+    pPal->palNumEntries = paletteSize;
+
+    /* build a simple RGB color palette */
+    {
+	int redMask = (1 << pfd.cRedBits) - 1;
+	int greenMask = (1 << pfd.cGreenBits) - 1;
+	int blueMask = (1 << pfd.cBlueBits) - 1;
+	int i;
+
+	for (i=0; i<paletteSize; ++i) {
+	    pPal->palPalEntry[i].peRed =
+		    (((i >> pfd.cRedShift) & redMask) * 255) / redMask;
+	    pPal->palPalEntry[i].peGreen =
+		    (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
+	    pPal->palPalEntry[i].peBlue =
+		    (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
+	    pPal->palPalEntry[i].peFlags = 0;
+	}
+    }
+
+    HPALETTE hPalette = CreatePalette(pPal);
+    free(pPal);
+
+    wxPalette palette;
+    palette.SetHPALETTE((WXHPALETTE) hPalette);
+
+    return palette;
+}
+
+void wxGLCanvas::SwapBuffers()
+{
+  if (m_glContext)
+    m_glContext->SwapBuffers();
+}
+
+void wxGLCanvas::OnSize(wxSizeEvent& event)
+{
+  int width, height;
+  GetClientSize(& width, & height);
+
+  if (m_glContext)
+  {
+    m_glContext->SetCurrent();
+
+    glViewport(0, 0, (GLint)width, (GLint)height);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
+    glMatrixMode(GL_MODELVIEW);
+  }
+}
+
+void wxGLCanvas::SetCurrent()
+{
+  if (m_glContext)
+  {
+    m_glContext->SetCurrent();
+  }
+}
+
+void wxGLCanvas::SetColour(const char *colour)
+{
+  if (m_glContext)
+    m_glContext->SetColour(colour);
+}
+
+// TODO: Have to have this called by parent frame (?)
+// So we need wxFrame to call OnQueryNewPalette for all children...
+void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
+{
+	/* realize palette if this is the current window */
+	if ( GetPalette()->Ok() ) {
+	    ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
+	    ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
+	    ::RealizePalette((HDC) GetHDC());
+	    Refresh();
+	    event.SetPaletteRealized(TRUE);
+    }
+    else
+	    event.SetPaletteRealized(FALSE);
+}
+
+// I think this doesn't have to be propagated to child windows.
+void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
+{
+	/* realize palette if this is *not* the current window */
+	if ( GetPalette() &&
+       GetPalette()->Ok() && (this != event.GetChangedWindow()) )
+    {
+	    ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
+	    ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
+	    ::RealizePalette((HDC) GetHDC());
+	    Refresh();
+	}
+}
+
+/* Give extensions proper function names. */
+
+/* EXT_vertex_array */
+void glArrayElementEXT(GLint i)
+{
+}
+
+void glColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
+{
+}
+
+void glDrawArraysEXT(GLenum mode, GLint first, GLsizei 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 stride, GLsizei count, const GLboolean *pointer)
+{
+}
+
+void glGetPointervEXT(GLenum pname, GLvoid* *params)
+{
+}
+
+void glIndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
+{
+}
+
+void glNormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid *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 size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
+{
+}
+
+void glVertexPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *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 target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *table)
+{
+}
+
+/* EXT_color_table */
+void glColorTableEXT(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table)
+{
+}
+
+void glCopyColorTableEXT(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width)
+{
+}
+
+void glGetColorTableEXT(GLenum target, GLenum format, GLenum type, GLvoid *table)
+{
+}
+
+void glGetColorTableParamaterfvEXT(GLenum target, GLenum pname, GLfloat *params)
+{
+}
+
+void glGetColorTavleParameterivEXT(GLenum target, GLenum pname, GLint *params)
+{
+}
+
+/* SGI_compiled_vertex_array */
+void glLockArraysSGI(GLint first, GLsizei count)
+{
+}
+
+void glUnlockArraysSGI()
+{
+}
+
+
+/* SGI_cull_vertex */
+void glCullParameterdvSGI(GLenum pname, GLdouble* params)
+{
+}
+
+void glCullParameterfvSGI(GLenum pname, GLfloat* params)
+{
+}
+
+/* SGI_index_func */
+void glIndexFuncSGI(GLenum func, GLclampf ref)
+{
+}
+
+/* SGI_index_material */
+void glIndexMaterialSGI(GLenum face, GLenum mode)
+{
+}
+
+/* WIN_swap_hint */
+void glAddSwapHintRectWin(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+}
+
+#endif
+    // wxUSE_GLCANVAS
diff --git a/src/msw/makefile.b32 b/src/msw/makefile.b32
index 908733e039..5259b6be0a 100644
--- a/src/msw/makefile.b32
+++ b/src/msw/makefile.b32
@@ -1,6 +1,6 @@
 
 
-# This file was automatically generated by tmake at 18:32, 2000/02/17
+# This file was automatically generated by tmake at 15:17, 2000/02/27
 # DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE B32.T!
 
 #
@@ -257,6 +257,7 @@ MSWOBJS = $(MSWDIR)\accel.obj \
 		$(MSWDIR)\gauge95.obj \
 		$(MSWDIR)\gdiimage.obj \
 		$(MSWDIR)\gdiobj.obj \
+		$(MSWDIR)\glcanvas.obj \
 		$(MSWDIR)\gsocket.obj \
 		$(MSWDIR)\helpwin.obj \
 		$(MSWDIR)\icon.obj \
@@ -469,6 +470,8 @@ $(MSWDIR)\gdiimage.obj: $(MSWDIR)\gdiimage.$(SRCSUFF)
 
 $(MSWDIR)\gdiobj.obj: $(MSWDIR)\gdiobj.$(SRCSUFF)
 
+$(MSWDIR)\glcanvas.obj: $(MSWDIR)\glcanvas.$(SRCSUFF)
+
 $(MSWDIR)\gsocket.obj: $(MSWDIR)\gsocket.c
 
 $(MSWDIR)\helpwin.obj: $(MSWDIR)\helpwin.$(SRCSUFF)
diff --git a/src/msw/makefile.bcc b/src/msw/makefile.bcc
index c60cbc60b8..161d261176 100644
--- a/src/msw/makefile.bcc
+++ b/src/msw/makefile.bcc
@@ -1,6 +1,6 @@
 
 
-# This file was automatically generated by tmake at 18:32, 2000/02/17
+# This file was automatically generated by tmake at 15:18, 2000/02/27
 # DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE BCC.T!
 
 #
@@ -226,6 +226,7 @@ MSWOBJS = $(MSWDIR)\accel.obj \
 		$(MSWDIR)\gaugemsw.obj \
 		$(MSWDIR)\gdiimage.obj \
 		$(MSWDIR)\gdiobj.obj \
+		$(MSWDIR)\glcanvas.obj \
 		$(MSWDIR)\gsocket.obj \
 		$(MSWDIR)\helpwin.obj \
 		$(MSWDIR)\icon.obj \
@@ -378,6 +379,8 @@ $(MSWDIR)\gdiimage.obj: $(MSWDIR)\gdiimage.$(SRCSUFF)
 
 $(MSWDIR)\gdiobj.obj: $(MSWDIR)\gdiobj.$(SRCSUFF)
 
+$(MSWDIR)\glcanvas.obj: $(MSWDIR)\glcanvas.$(SRCSUFF)
+
 $(MSWDIR)\gsocket.obj: $(MSWDIR)\gsocket.c
 
 $(MSWDIR)\helpwin.obj: $(MSWDIR)\helpwin.$(SRCSUFF)
diff --git a/src/msw/makefile.g95 b/src/msw/makefile.g95
index a8e77fbb68..0762df0d7c 100644
--- a/src/msw/makefile.g95
+++ b/src/msw/makefile.g95
@@ -255,6 +255,7 @@ MSWOBJS     = \
 		$(MSWDIR)/gauge95.$(OBJSUFF) \
 		$(MSWDIR)/gdiimage.$(OBJSUFF) \
 		$(MSWDIR)/gdiobj.$(OBJSUFF) \
+		$(MSWDIR)/glcanvas.$(OBJSUFF) \
 		$(MSWDIR)/gsocket.$(OBJSUFF) \
 		$(MSWDIR)/helpwin.$(OBJSUFF) \
 		$(MSWDIR)/icon.$(OBJSUFF) \
diff --git a/src/msw/makefile.vc b/src/msw/makefile.vc
index e555f8b83c..3ceaa58c47 100644
--- a/src/msw/makefile.vc
+++ b/src/msw/makefile.vc
@@ -1,4 +1,4 @@
-# This file was automatically generated by tmake at 18:32, 2000/02/17
+# This file was automatically generated by tmake at 15:17, 2000/02/27
 # DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE VC.T!
 
 # File:     makefile.vc
@@ -274,6 +274,7 @@ MSWOBJS = ..\msw\$D\accel.obj \
 		..\msw\$D\gauge95.obj \
 		..\msw\$D\gdiimage.obj \
 		..\msw\$D\gdiobj.obj \
+		..\msw\$D\glcanvas.obj \
 		..\msw\$D\gsocket.obj \
 		..\msw\$D\helpwin.obj \
 		..\msw\$D\icon.obj \
diff --git a/src/msw/makefile.wat b/src/msw/makefile.wat
index e13fc89232..c2a5bc5448 100644
--- a/src/msw/makefile.wat
+++ b/src/msw/makefile.wat
@@ -1,6 +1,6 @@
 #!/binb/wmake.exe
 
-# This file was automatically generated by tmake at 18:32, 2000/02/17
+# This file was automatically generated by tmake at 15:18, 2000/02/27
 # DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE WAT.T!
 
 #
@@ -230,6 +230,7 @@ MSWOBJS = accel.obj &
 	gaugemsw.obj &
 	gdiimage.obj &
 	gdiobj.obj &
+	glcanvas.obj &
 	gsocket.obj &
 	helpwin.obj &
 	icon.obj &
@@ -450,6 +451,9 @@ gdiimage.obj:     $(MSWDIR)\gdiimage.cpp
 gdiobj.obj:     $(MSWDIR)\gdiobj.cpp
   *$(CCC) $(CPPFLAGS) $(IFLAGS) $<
 
+glcanvas.obj:     $(MSWDIR)\glcanvas.cpp
+  *$(CCC) $(CPPFLAGS) $(IFLAGS) $<
+
 gsocket.obj:     $(MSWDIR)\gsocket.c
   *$(CC) $(CPPFLAGS) $(IFLAGS) $<
 
diff --git a/src/wxvc.dsp b/src/wxvc.dsp
index 6c87170f6c..b95508cacb 100644
--- a/src/wxvc.dsp
+++ b/src/wxvc.dsp
@@ -853,6 +853,10 @@ SOURCE=.\msw\gdiobj.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\msw\glcanvas.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\msw\gsocket.c
 # SUBTRACT CPP /YX /Yc /Yu
 # End Source File
diff --git a/src/wxvc_dll.dsp b/src/wxvc_dll.dsp
index edacc9f9f9..ee66692879 100644
--- a/src/wxvc_dll.dsp
+++ b/src/wxvc_dll.dsp
@@ -851,6 +851,10 @@ SOURCE=.\msw\gdiobj.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\msw\glcanvas.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\msw\gsocket.c
 # SUBTRACT CPP /YX /Yc /Yu
 # End Source File
diff --git a/utils/projgen/makeproj.cpp b/utils/projgen/makeproj.cpp
index fa66425fe4..c8a377f17b 100644
--- a/utils/projgen/makeproj.cpp
+++ b/utils/projgen/makeproj.cpp
@@ -183,6 +183,7 @@ bool MyApp::GenerateSample(const wxString& projectName, const wxString& targetNa
     project.SetLibDirs(wxStringList((const char*) relativeLibPath, 0));
     project.SetDebugLibDirs(wxStringList((const char*) relativeDebugPath, (const char*) relativeDebugPathJPEG, (const char*) relativeDebugPathTIFF, 0));
     project.SetReleaseLibDirs(wxStringList((const char*) relativeReleasePath, (const char*) relativeReleasePathJPEG, (const char*) relativeReleasePathTIFF, 0));
+    project.SetExtraLibs(wxStringList("opengl32.lib", "glu32.lib", 0));
 
     project.SetProjectName(projectName);
     project.SetTargetName(targetName);
@@ -228,6 +229,14 @@ void MyApp::GenerateSamples(const wxString& dir)
     GenerateSample("NewGridVC", "griddemo", dir + wxString("/samples/newgrid"), wxStringList("griddemo.cpp", 0));
     GenerateSample("HelpVC", "demo", dir + wxString("/samples/help"), wxStringList("demo.cpp", 0));
 
+    // OpenGL samples
+    GenerateSample("CubeVC", "cube", dir + wxString("/samples/opengl/cube"), wxStringList("cube.cpp", "cube.h", 0),
+        "../../..");
+    GenerateSample("IsosurfVC", "isosurf", dir + wxString("/samples/opengl/isosurf"), wxStringList("isosurf.cpp", "isousrf.h", 0),
+        "../../..");
+    GenerateSample("PenguinVC", "penguin", dir + wxString("/samples/opengl/penguin"), wxStringList("penguin.cpp", "penguin.h",
+        "lw.cpp", "lw.h", "trackball.c", "trackball.h", 0), "../../..");
+
     // wxHTML samples
     GenerateSample("AboutVC", "about", dir + wxString("/samples/html/about"), wxStringList("about.cpp", 0),
         "../../..");
@@ -488,72 +497,6 @@ void MyApp::GenerateSamples(const wxString& dir)
         wxString msg("Could not generate OGL Studio project");
         wxMessageBox(msg);
     }
-
-    // GLCanvas cube sample
-
-    project.SetIncludeDirs(wxStringList("../../../../include", "../../win", 0));
-    project.SetResourceIncludeDirs(wxStringList("../../../../include", 0));
-    project.SetLibDirs(wxStringList("../../../../lib", 0));
-    project.SetDebugLibDirs(wxStringList("../../../../src/Debug", "../../win/Debug", "../../../../src/jpeg/Debug", "../../../../src/tiff/Debug", 0));
-    project.SetReleaseLibDirs(wxStringList("../../../../src/Release", "../../win/Release", "../../../../src/jpeg/Release", "../../../../src/tiff/Release", 0));
-
-    project.SetExtraLibs(wxStringList("glcanvas.lib", "opengl32.lib", "glu32.lib", 0));
-
-    project.SetProjectName("CubeVC");
-    project.SetTargetName("cube");
-    project.SetProjectPath(dir + wxString("/utils/glcanvas/samples/cube"));
-    project.SetSourceFiles(wxStringList("cube.cpp", "cube.h",
-        0));
-
-    if (!project.GenerateVCProject())
-    {
-        wxString msg("Could not generate GLCanvas Cube project");
-        wxMessageBox(msg);
-    }
-
-    // GLCanvas isosurf sample
-
-    project.SetIncludeDirs(wxStringList("../../../../include", "../../win", 0));
-    project.SetResourceIncludeDirs(wxStringList("../../../../include", 0));
-    project.SetLibDirs(wxStringList("../../../../lib", 0));
-    project.SetDebugLibDirs(wxStringList("../../../../src/Debug", "../../win/Debug", "../../../../src/jpeg/Debug", "../../../../src/tiff/Debug", 0));
-    project.SetReleaseLibDirs(wxStringList("../../../../src/Release", "../../win/Release", "../../../../src/jpeg/Release", "../../../../src/tiff/Release", 0));
-    project.SetExtraLibs(wxStringList("glcanvas.lib", "opengl32.lib", "glu32.lib", 0));
-
-    project.SetProjectName("IsoSurfVC");
-    project.SetTargetName("isosurf");
-    project.SetProjectPath(dir + wxString("/utils/glcanvas/samples/isosurf"));
-    project.SetSourceFiles(wxStringList("isosurf.cpp", "isosurf.h",
-        0));
-
-    if (!project.GenerateVCProject())
-    {
-        wxString msg("Could not generate GLCanvas IsoSurf project");
-        wxMessageBox(msg);
-    }
-
-    // GLCanvas penguin sample
-
-    project.SetIncludeDirs(wxStringList("../../../../include", "../../win", 0));
-    project.SetResourceIncludeDirs(wxStringList("../../../../include", 0));
-    project.SetLibDirs(wxStringList("../../../../lib", 0));
-    project.SetDebugLibDirs(wxStringList("../../../../src/Debug", "../../win/Debug", "../../../../src/jpeg/Debug", "../../../../src/tiff/Debug", 0));
-    project.SetReleaseLibDirs(wxStringList("../../../../src/Release", "../../win/Release", "../../../../src/jpeg/Release", "../../../../src/tiff/Release", 0));
-    project.SetExtraLibs(wxStringList("glcanvas.lib", "opengl32.lib", "glu32.lib", 0));
-
-    project.SetProjectName("PenguinVC");
-    project.SetTargetName("penguin");
-    project.SetProjectPath(dir + wxString("/utils/glcanvas/samples/penguin"));
-    project.SetSourceFiles(wxStringList("penguin.cpp", "penguin.h",
-        "lw.cpp", "lw.h",
-        "trackball.c", "trackball.h",
-        0));
-
-    if (!project.GenerateVCProject())
-    {
-        wxString msg("Could not generate GLCanvas Penguin project");
-        wxMessageBox(msg);
-    }
 }
 
 // ----------------------------------------------------------------------------
-- 
2.50.0

