X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a8d20c57aec929ec861194892784143fe2e74125..cb3a0d420a58658bffb26e9d7430f292c2d639d6:/src/msw/glcanvas.cpp diff --git a/src/msw/glcanvas.cpp b/src/msw/glcanvas.cpp index 0f24a7cff6..64f90c4ef2 100644 --- a/src/msw/glcanvas.cpp +++ b/src/msw/glcanvas.cpp @@ -1,37 +1,67 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: glcanvas.cpp -// Purpose: wxGLCanvas, for using OpenGL with wxWindows under MS Windows +// Name: src/msw/glcanvas.cpp +// Purpose: wxGLCanvas, for using OpenGL with wxWidgets under MS Windows // Author: Julian Smart // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart -// Licence: wxWindows licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "glcanvas.h" -#endif - #include "wx/wxprec.h" #if defined(__BORLANDC__) -#pragma hdrstop + #pragma hdrstop #endif -#include - #if wxUSE_GLCANVAS #ifndef WX_PRECOMP -#include + #include "wx/frame.h" + #include "wx/settings.h" + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/app.h" + #include "wx/module.h" #endif -#include -#include -#include +#include "wx/msw/private.h" + +// DLL options compatibility check: +#include "wx/build.h" +WX_CHECK_BUILD_OPTIONS("wxGL") + +#include "wx/glcanvas.h" + +#if GL_EXT_vertex_array + #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) name +#else + #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) WXUNUSED(name) +#endif + +/* + The following two compiler directives are specific to the Microsoft Visual + C++ family of compilers + + Fundementally what they do is instruct the linker to use these two libraries + for the resolution of symbols. In essence, this is the equivalent of adding + these two libraries to either the Makefile or project file. + + This is NOT a recommended technique, and certainly is unlikely to be used + anywhere else in wxWidgets given it is so specific to not only wxMSW, but + also the VC compiler. However, in the case of opengl support, it's an + applicable technique as opengl is optional in setup.h This code (wrapped by + wxUSE_GLCANVAS), now allows opengl support to be added purely by modifying + setup.h rather than by having to modify either the project or DSP fle. + + See MSDN for further information on the exact usage of these commands. +*/ +#ifdef _MSC_VER +# pragma comment( lib, "opengl32" ) +# pragma comment( lib, "glu32" ) +#endif -#include static const wxChar *wxGLCanvasClassName = wxT("wxGLCanvasClass"); static const wxChar *wxGLCanvasClassNameNoRedraw = wxT("wxGLCanvasClassNR"); @@ -39,85 +69,140 @@ static const wxChar *wxGLCanvasClassNameNoRedraw = wxT("wxGLCanvasClassNR"); LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -/* - * GLContext implementation - */ +// ---------------------------------------------------------------------------- +// wxGLModule is responsible for unregistering wxGLCanvasClass Windows class +// ---------------------------------------------------------------------------- -wxGLContext::wxGLContext(bool isRGB, wxGLCanvas *win, const wxPalette& palette) +class wxGLModule : public wxModule { - m_window = win; +public: + bool OnInit() { return true; } + void OnExit() { UnregisterClasses(); } - m_hDC = win->GetHDC(); + // register the GL classes if not done yet, return true if ok, false if + // registration failed + static bool RegisterClasses(); - m_glContext = wglCreateContext((HDC) m_hDC); - wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") ); + // unregister the classes, done automatically on program termination + static void UnregisterClasses(); - wglMakeCurrent((HDC) m_hDC, m_glContext); -} +private: + // wxGLCanvas is only used from the main thread so this is MT-ok + static bool ms_registeredGLClasses; + + DECLARE_DYNAMIC_CLASS(wxGLModule) +}; + +IMPLEMENT_DYNAMIC_CLASS(wxGLModule, wxModule) + +bool wxGLModule::ms_registeredGLClasses = false; -wxGLContext::wxGLContext( - bool isRGB, wxGLCanvas *win, - const wxPalette& palette, - const wxGLContext *other /* for sharing display lists */ - ) +/* static */ +bool wxGLModule::RegisterClasses() { - m_window = win; + if (ms_registeredGLClasses) + return true; - m_hDC = win->GetHDC(); + // We have to register a special window class because we need the CS_OWNDC + // style for GLCanvas. - m_glContext = wglCreateContext((HDC) m_hDC); - wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") ); + /* + From Angel Popov - if( other != 0 ) - wglShareLists( other->m_glContext, m_glContext ); + 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." + */ + + WNDCLASS wndclass; + + // 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 = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC; - wglMakeCurrent((HDC) m_hDC, m_glContext); + if ( !::RegisterClass(&wndclass) ) + { + wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)")); + return false; + } + + // Register the GLCanvas class name for windows which don't do full repaint + // on resize + wndclass.lpszClassName = wxGLCanvasClassNameNoRedraw; + wndclass.style &= ~(CS_HREDRAW | CS_VREDRAW); + + if ( !::RegisterClass(&wndclass) ) + { + wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)")); + + ::UnregisterClass(wxGLCanvasClassName, wxhInstance); + + return false; + } + + ms_registeredGLClasses = true; + + return true; } -wxGLContext::~wxGLContext() +/* static */ +void wxGLModule::UnregisterClasses() { - if (m_glContext) - { - wglMakeCurrent(NULL, NULL); - wglDeleteContext(m_glContext); - } + // we need to unregister the classes in case we're in a DLL which is + // unloaded and then loaded again because if we don't, the registration is + // going to fail in wxGLCanvas::Create() the next time we're loaded + if ( ms_registeredGLClasses ) + { + ::UnregisterClass(wxGLCanvasClassName, wxhInstance); + ::UnregisterClass(wxGLCanvasClassNameNoRedraw, wxhInstance); + + ms_registeredGLClasses = false; + } } -void wxGLContext::SwapBuffers() +/* + * GLContext implementation + */ + +IMPLEMENT_CLASS(wxGLContext, wxObject) + +wxGLContext::wxGLContext(wxGLCanvas* win, const wxGLContext* other /* for sharing display lists */) { - if (m_glContext) - { - wglMakeCurrent((HDC) m_hDC, m_glContext); - ::SwapBuffers((HDC) m_hDC); //blits the backbuffer into DC - } + m_glContext = wglCreateContext((HDC) win->GetHDC()); + wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGL context") ); + + if( other != 0 ) + wglShareLists( other->m_glContext, m_glContext ); } -void wxGLContext::SetCurrent() +wxGLContext::~wxGLContext() { - if (m_glContext) - { - wglMakeCurrent((HDC) m_hDC, m_glContext); - } - - /* - setupPixelFormat(hDC); - setupPalette(hDC); - */ + // If this context happens to be the current context, wglDeleteContext() makes it un-current first. + wglDeleteContext(m_glContext); } -void wxGLContext::SetColour(const char *colour) +void wxGLContext::SetCurrent(const wxGLCanvas& win) const { - 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); - } + wglMakeCurrent((HDC) win.GetHDC(), m_glContext); } @@ -125,17 +210,37 @@ void wxGLContext::SetColour(const char *colour) * wxGLCanvas implementation */ -IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow) +IMPLEMENT_CLASS(wxGLCanvas, wxWindow) -BEGIN_EVENT_TABLE(wxGLCanvas, wxScrolledWindow) +BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow) EVT_SIZE(wxGLCanvas::OnSize) EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged) EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette) END_EVENT_TABLE() +wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id, int *attribList, + const wxPoint& pos, const wxSize& size, long style, + const wxString& name, const wxPalette& palette) : wxWindow() +{ + m_glContext = NULL; + + if (Create(parent, id, pos, size, style, name)) + { + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); + } + + m_hDC = (WXHDC) ::GetDC((HWND) GetHWND()); + + SetupPixelFormat(attribList); + SetupPalette(palette); + + // This ctor does *not* create an instance of wxGLContext, + // m_glContext intentionally remains NULL. +} + wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name, - int *attribList, const wxPalette& palette) : wxScrolledWindow() + int *attribList, const wxPalette& palette) : wxWindow() { m_glContext = (wxGLContext*) NULL; @@ -143,8 +248,7 @@ wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id, if ( ret ) { - SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE)); - SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT)); + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); } m_hDC = (WXHDC) ::GetDC((HWND) GetHWND()); @@ -152,14 +256,14 @@ wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id, SetupPixelFormat(attribList); SetupPalette(palette); - m_glContext = new wxGLContext(TRUE, this, palette); + m_glContext = new wxGLContext(this); } wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLContext *shared, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name, int *attribList, const wxPalette& palette ) - : wxScrolledWindow() + : wxWindow() { m_glContext = (wxGLContext*) NULL; @@ -167,8 +271,7 @@ wxGLCanvas::wxGLCanvas( wxWindow *parent, if ( ret ) { - SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE)); - SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT)); + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); } m_hDC = (WXHDC) ::GetDC((HWND) GetHWND()); @@ -176,7 +279,7 @@ wxGLCanvas::wxGLCanvas( wxWindow *parent, SetupPixelFormat(attribList); SetupPalette(palette); - m_glContext = new wxGLContext(TRUE, this, palette, shared ); + m_glContext = new wxGLContext(this, shared); } // Not very useful for wxMSW, but this is to be wxGTK compliant @@ -184,7 +287,7 @@ wxGLCanvas::wxGLCanvas( wxWindow *parent, 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() + wxWindow() { m_glContext = (wxGLContext*) NULL; @@ -192,8 +295,7 @@ wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID i if ( ret ) { - SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE)); - SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT)); + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); } m_hDC = (WXHDC) ::GetDC((HWND) GetHWND()); @@ -203,13 +305,12 @@ wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID i wxGLContext *sharedContext=0; if (shared) sharedContext=shared->GetContext(); - m_glContext = new wxGLContext(TRUE, this, palette, sharedContext ); + m_glContext = new wxGLContext(this, sharedContext); } wxGLCanvas::~wxGLCanvas() { - if (m_glContext) - delete m_glContext; + delete m_glContext; ::ReleaseDC((HWND) GetHWND(), (HDC) m_hDC); } @@ -223,111 +324,34 @@ bool wxGLCanvas::Create(wxWindow *parent, long style, const wxString& name) { - static bool s_registeredGLCanvasClass = FALSE; - - // We have to register a special window class because we need - // the CS_OWNDC style for GLCanvas. - - /* - From Angel Popov - - 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 (!s_registeredGLCanvasClass) - { - WNDCLASS wndclass; - - // 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; + wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") ); - // Register the GLCanvas class name - wndclass.hbrBackground = (HBRUSH)NULL; - wndclass.lpszClassName = wxGLCanvasClassName; - wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC; - - if ( !::RegisterClass(&wndclass) ) + if ( !wxGLModule::RegisterClasses() ) { - wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)")); - return FALSE; - } + wxLogError(_("Failed to register OpenGL window class.")); - // Register the GLCanvas class name for windows which don't do full repaint - // on resize - wndclass.lpszClassName = wxGLCanvasClassNameNoRedraw; - wndclass.style &= ~(CS_HREDRAW | CS_VREDRAW); - - if ( !::RegisterClass(&wndclass) ) - { - wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)")); - - ::UnregisterClass(wxGLCanvasClassName, wxhInstance); - - return FALSE; + return false; } - s_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; - - /* - A general rule with OpenGL and Win32 is that any window that will have a - HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS. - You can find references about this within the knowledge base and most OpenGL - books that contain the wgl function descriptions. - */ + if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) ) + return false; - msflags |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + parent->AddChild(this); - bool want3D; - WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D); + DWORD msflags = 0; - // 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; - } + /* + A general rule with OpenGL and Win32 is that any window that will have a + HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS. + You can find references about this within the knowledge base and most OpenGL + books that contain the wgl function descriptions. + */ - // 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; - } + WXDWORD exStyle = 0; + msflags |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + msflags |= MSWGetStyle(style, & exStyle) ; - return MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle); + return MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle); } static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, int *attribList) @@ -346,16 +370,16 @@ static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, int *attribList) pfd.iPixelType = PFD_TYPE_RGBA; break; case WX_GL_BUFFER_SIZE: - pfd.cColorBits = attribList[arg++]; + pfd.cColorBits = (BYTE)attribList[arg++]; break; case WX_GL_LEVEL: // this member looks like it may be obsolete if (attribList[arg] > 0) { - pfd.iLayerType = PFD_OVERLAY_PLANE; + pfd.iLayerType = (BYTE)PFD_OVERLAY_PLANE; } else if (attribList[arg] < 0) { - pfd.iLayerType = PFD_UNDERLAY_PLANE; + pfd.iLayerType = (BYTE)PFD_UNDERLAY_PLANE; } else { - pfd.iLayerType = PFD_MAIN_PLANE; + pfd.iLayerType = (BYTE)PFD_MAIN_PLANE; } arg++; break; @@ -366,38 +390,38 @@ static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, int *attribList) pfd.dwFlags |= PFD_STEREO; break; case WX_GL_AUX_BUFFERS: - pfd.cAuxBuffers = attribList[arg++]; + pfd.cAuxBuffers = (BYTE)attribList[arg++]; break; case WX_GL_MIN_RED: - pfd.cColorBits += (pfd.cRedBits = attribList[arg++]); + pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cRedBits = (BYTE)attribList[arg++])); break; case WX_GL_MIN_GREEN: - pfd.cColorBits += (pfd.cGreenBits = attribList[arg++]); + pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cGreenBits = (BYTE)attribList[arg++])); break; case WX_GL_MIN_BLUE: - pfd.cColorBits += (pfd.cBlueBits = attribList[arg++]); + pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cBlueBits = (BYTE)attribList[arg++])); break; case WX_GL_MIN_ALPHA: // doesn't count in cColorBits - pfd.cAlphaBits = attribList[arg++]; + pfd.cAlphaBits = (BYTE)attribList[arg++]; break; case WX_GL_DEPTH_SIZE: - pfd.cDepthBits = attribList[arg++]; + pfd.cDepthBits = (BYTE)attribList[arg++]; break; case WX_GL_STENCIL_SIZE: - pfd.cStencilBits = attribList[arg++]; + pfd.cStencilBits = (BYTE)attribList[arg++]; break; case WX_GL_MIN_ACCUM_RED: - pfd.cAccumBits += (pfd.cAccumRedBits = attribList[arg++]); + pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumRedBits = (BYTE)attribList[arg++])); break; case WX_GL_MIN_ACCUM_GREEN: - pfd.cAccumBits += (pfd.cAccumGreenBits = attribList[arg++]); + pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumGreenBits = (BYTE)attribList[arg++])); break; case WX_GL_MIN_ACCUM_BLUE: - pfd.cAccumBits += (pfd.cAccumBlueBits = attribList[arg++]); + pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumBlueBits = (BYTE)attribList[arg++])); break; case WX_GL_MIN_ACCUM_ALPHA: - pfd.cAccumBits += (pfd.cAccumAlphaBits = attribList[arg++]); + pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumAlphaBits = (BYTE)attribList[arg++])); break; default: break; @@ -408,7 +432,6 @@ static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, int *attribList) void wxGLCanvas::SetupPixelFormat(int *attribList) // (HDC hDC) { - int pixelFormat; PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), /* size */ 1, /* version */ @@ -416,7 +439,7 @@ void wxGLCanvas::SetupPixelFormat(int *attribList) // (HDC hDC) PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER, /* support double-buffering */ PFD_TYPE_RGBA, /* color type */ - 16, /* prefered color depth */ + 16, /* preferred color depth */ 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ 0, /* no alpha buffer */ 0, /* alpha bits (ignored) */ @@ -432,13 +455,13 @@ void wxGLCanvas::SetupPixelFormat(int *attribList) // (HDC hDC) AdjustPFDForAttributes(pfd, attribList); - pixelFormat = ChoosePixelFormat((HDC) m_hDC, &pfd); + int pixelFormat = ChoosePixelFormat((HDC) m_hDC, &pfd); if (pixelFormat == 0) { - wxLogWarning(_("ChoosePixelFormat failed.")); + wxLogLastError(_T("ChoosePixelFormat")); } else { - if (SetPixelFormat((HDC) m_hDC, pixelFormat, &pfd) != TRUE) { - wxLogWarning(_("SetPixelFormat failed.")); + if ( !::SetPixelFormat((HDC) m_hDC, pixelFormat, &pfd) ) { + wxLogLastError(_T("SetPixelFormat")); } } } @@ -467,8 +490,8 @@ void wxGLCanvas::SetupPalette(const wxPalette& palette) if (m_palette.Ok()) { - SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), FALSE); - RealizePalette((HDC) m_hDC); + ::SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), FALSE); + ::RealizePalette((HDC) m_hDC); } } @@ -485,7 +508,7 @@ wxPalette wxGLCanvas::CreateDefaultPalette() LOGPALETTE* pPal = (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY)); pPal->palVersion = 0x300; - pPal->palNumEntries = paletteSize; + pPal->palNumEntries = (WORD)paletteSize; /* build a simple RGB color palette */ { @@ -496,11 +519,11 @@ wxPalette wxGLCanvas::CreateDefaultPalette() for (i=0; ipalPalEntry[i].peRed = - (((i >> pfd.cRedShift) & redMask) * 255) / redMask; + (BYTE)((((i >> pfd.cRedShift) & redMask) * 255) / redMask); pPal->palPalEntry[i].peGreen = - (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask; + (BYTE)((((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask); pPal->palPalEntry[i].peBlue = - (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask; + (BYTE)((((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask); pPal->palPalEntry[i].peFlags = 0; } } @@ -516,39 +539,48 @@ wxPalette wxGLCanvas::CreateDefaultPalette() void wxGLCanvas::SwapBuffers() { - if (m_glContext) - m_glContext->SwapBuffers(); + ::SwapBuffers((HDC) m_hDC); } -void wxGLCanvas::OnSize(wxSizeEvent& event) +void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event)) { - int width, height; - GetClientSize(& width, & height); +} - if (m_glContext) - { - m_glContext->SetCurrent(); +void wxGLCanvas::SetCurrent(const wxGLContext& RC) const +{ + // although on MSW it works even if the window is still hidden, it doesn't + // under wxGTK and documentation mentions that SetCurrent() can only be + // called for a shown window, so check it + wxASSERT_MSG( GetParent()->IsShown(), _T("can't make hidden GL canvas current") ); - 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); - } + RC.SetCurrent(*this); } void wxGLCanvas::SetCurrent() { + // although on MSW it works even if the window is still hidden, it doesn't + // under wxGTK and documentation mentions that SetCurrent() can only be + // called for a shown window, so check it + wxASSERT_MSG( GetParent()->IsShown(), + _T("can't make hidden GL canvas current") ); + if (m_glContext) { - m_glContext->SetCurrent(); + m_glContext->SetCurrent(*this); } } -void wxGLCanvas::SetColour(const char *colour) +void wxGLCanvas::SetColour(const wxChar *colour) { - if (m_glContext) - m_glContext->SetColour(colour); + wxColour col = wxTheColourDatabase->Find(colour); + + if (col.Ok()) + { + float r = (float)(col.Red()/256.0); + float g = (float)(col.Green()/256.0); + float b = (float)(col.Blue()/256.0); + glColor3f( r, g, b); + } } // TODO: Have to have this called by parent frame (?) @@ -561,10 +593,10 @@ void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event) ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE); ::RealizePalette((HDC) GetHDC()); Refresh(); - event.SetPaletteRealized(TRUE); + event.SetPaletteRealized(true); } else - event.SetPaletteRealized(FALSE); + event.SetPaletteRealized(false); } // I think this doesn't have to be propagated to child windows. @@ -581,137 +613,6 @@ void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event) } } -/* 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) -{ -} - //--------------------------------------------------------------------------- // wxGLApp @@ -729,7 +630,7 @@ bool wxGLApp::InitGLVisual(int *attribList) PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER, /* support double-buffering */ PFD_TYPE_RGBA, /* color type */ - 16, /* prefered color depth */ + 16, /* preferred color depth */ 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ 0, /* no alpha buffer */ 0, /* alpha bits (ignored) */ @@ -746,14 +647,14 @@ bool wxGLApp::InitGLVisual(int *attribList) AdjustPFDForAttributes(pfd, attribList); // use DC for whole (root) screen, since no windows have yet been created - pixelFormat = ChoosePixelFormat((HDC) ::GetDC(NULL), &pfd); + pixelFormat = ChoosePixelFormat(ScreenHDC(), &pfd); if (pixelFormat == 0) { wxLogError(_("Failed to initialize OpenGL")); - return FALSE; + return false; } - return TRUE; + return true; } wxGLApp::~wxGLApp()