X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/213ceb3f0e7b88a09d756dd181f14ecb5bd44d57..b9efe021b554fa3967d1442cf758435c5cd5ae8f:/src/msw/glcanvas.cpp?ds=sidebyside diff --git a/src/msw/glcanvas.cpp b/src/msw/glcanvas.cpp index eacc888687..d0867503fa 100644 --- a/src/msw/glcanvas.cpp +++ b/src/msw/glcanvas.cpp @@ -29,6 +29,8 @@ #include "wx/app.h" #endif +#include "wx/module.h" + #include "wx/msw/private.h" // DLL options compatibility check: @@ -37,6 +39,12 @@ 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 @@ -66,6 +74,116 @@ static const wxChar *wxGLCanvasClassNameNoRedraw = wxT("wxGLCanvasClassNR"); LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +// ---------------------------------------------------------------------------- +// wxGLModule is responsible for unregistering wxGLCanvasClass Windows class +// ---------------------------------------------------------------------------- + +class wxGLModule : public wxModule +{ +public: + bool OnInit() { return true; } + void OnExit() { UnregisterClasses(); } + + // register the GL classes if not done yet, return true if ok, false if + // registration failed + static bool RegisterClasses(); + + // unregister the classes, done automatically on program termination + static void UnregisterClasses(); + +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; + +/* static */ +bool wxGLModule::RegisterClasses() +{ + if (ms_registeredGLClasses) + return true; + + // 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." + */ + + 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; + + 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; +} + +/* static */ +void wxGLModule::UnregisterClasses() +{ + // 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; + } +} + /* * GLContext implementation */ @@ -125,11 +243,6 @@ void wxGLContext::SetCurrent() { wglMakeCurrent((HDC) m_hDC, m_glContext); } - - /* - setupPixelFormat(hDC); - setupPalette(hDC); - */ } void wxGLContext::SetColour(const wxChar *colour) @@ -229,8 +342,7 @@ wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID i wxGLCanvas::~wxGLCanvas() { - if (m_glContext) - delete m_glContext; + delete m_glContext; ::ReleaseDC((HWND) GetHWND(), (HDC) m_hDC); } @@ -244,90 +356,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; - - // 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) ) - { - wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)")); - return false; - } + wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") ); - // 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) ) + if ( !wxGLModule::RegisterClasses() ) { - wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)")); - - ::UnregisterClass(wxGLCanvasClassName, wxhInstance); + wxLogError(_("Failed to register OpenGL window class.")); 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; + if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) ) + return false; - parent->AddChild(this); + parent->AddChild(this); - DWORD msflags = 0; + DWORD msflags = 0; - /* - 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. - */ + /* + 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. + */ - WXDWORD exStyle = 0; - msflags |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - msflags |= MSWGetStyle(style, & exStyle) ; + 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,7 +402,7 @@ 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 @@ -366,38 +422,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; @@ -415,7 +471,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) */ @@ -484,7 +540,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 */ { @@ -495,11 +551,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; } } @@ -525,6 +581,12 @@ void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event)) 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(); @@ -578,7 +640,9 @@ void glColorPointerEXT(GLint WXUNUSED(size), GLenum WXUNUSED(type), GLsizei WXUN { } -void glDrawArraysEXT(GLenum mode, GLint first, GLsizei count) +void glDrawArraysEXT(GLenum WXUNUSED_WITHOUT_GL_EXT_vertex_array(mode), + GLint WXUNUSED_WITHOUT_GL_EXT_vertex_array(first), + GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(count)) { #ifdef GL_EXT_vertex_array static PFNGLDRAWARRAYSEXTPROC proc = 0; @@ -605,7 +669,10 @@ void glIndexPointerEXT(GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei { } -void glNormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +void glNormalPointerEXT(GLenum WXUNUSED_WITHOUT_GL_EXT_vertex_array(type), + GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(stride), + GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(count), + const GLvoid *WXUNUSED_WITHOUT_GL_EXT_vertex_array(pointer)) { #ifdef GL_EXT_vertex_array static PFNGLNORMALPOINTEREXTPROC proc = 0; @@ -624,7 +691,11 @@ void glTexCoordPointerEXT(GLint WXUNUSED(size), GLenum WXUNUSED(type), GLsizei W { } -void glVertexPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +void glVertexPointerEXT(GLint WXUNUSED_WITHOUT_GL_EXT_vertex_array(size), + GLenum WXUNUSED_WITHOUT_GL_EXT_vertex_array(type), + GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(stride), + GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(count), + const GLvoid *WXUNUSED_WITHOUT_GL_EXT_vertex_array(pointer)) { #ifdef GL_EXT_vertex_array static PFNGLVERTEXPOINTEREXTPROC proc = 0; @@ -715,7 +786,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) */