]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/glcanvas.cpp
Test using wxString::ToCDouble() in wxAny.
[wxWidgets.git] / src / msw / glcanvas.cpp
index b7035b4cd9386a3aa5fd03f2a6e4a0414b19ed9a..a16f03e7b82b6f72e46c1ad4307fba21348219bd 100644 (file)
@@ -29,7 +29,6 @@
     #include "wx/intl.h"
     #include "wx/log.h"
     #include "wx/app.h"
-    #include "wx/module.h"
 #endif
 
 #include "wx/msw/private.h"
@@ -51,40 +50,18 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
 // ----------------------------------------------------------------------------
 
 #ifndef WGL_ARB_pixel_format
-#define WGL_NUMBER_PIXEL_FORMATS_ARB      0x2000
 #define WGL_DRAW_TO_WINDOW_ARB            0x2001
-#define WGL_DRAW_TO_BITMAP_ARB            0x2002
 #define WGL_ACCELERATION_ARB              0x2003
-#define WGL_NEED_PALETTE_ARB              0x2004
-#define WGL_NEED_SYSTEM_PALETTE_ARB       0x2005
-#define WGL_SWAP_LAYER_BUFFERS_ARB        0x2006
-#define WGL_SWAP_METHOD_ARB               0x2007
 #define WGL_NUMBER_OVERLAYS_ARB           0x2008
 #define WGL_NUMBER_UNDERLAYS_ARB          0x2009
-#define WGL_TRANSPARENT_ARB               0x200A
-#define WGL_TRANSPARENT_RED_VALUE_ARB     0x2037
-#define WGL_TRANSPARENT_GREEN_VALUE_ARB   0x2038
-#define WGL_TRANSPARENT_BLUE_VALUE_ARB    0x2039
-#define WGL_TRANSPARENT_ALPHA_VALUE_ARB   0x203A
-#define WGL_TRANSPARENT_INDEX_VALUE_ARB   0x203B
-#define WGL_SHARE_DEPTH_ARB               0x200C
-#define WGL_SHARE_STENCIL_ARB             0x200D
-#define WGL_SHARE_ACCUM_ARB               0x200E
-#define WGL_SUPPORT_GDI_ARB               0x200F
 #define WGL_SUPPORT_OPENGL_ARB            0x2010
 #define WGL_DOUBLE_BUFFER_ARB             0x2011
 #define WGL_STEREO_ARB                    0x2012
-#define WGL_PIXEL_TYPE_ARB                0x2013
 #define WGL_COLOR_BITS_ARB                0x2014
 #define WGL_RED_BITS_ARB                  0x2015
-#define WGL_RED_SHIFT_ARB                 0x2016
 #define WGL_GREEN_BITS_ARB                0x2017
-#define WGL_GREEN_SHIFT_ARB               0x2018
 #define WGL_BLUE_BITS_ARB                 0x2019
-#define WGL_BLUE_SHIFT_ARB                0x201A
 #define WGL_ALPHA_BITS_ARB                0x201B
-#define WGL_ALPHA_SHIFT_ARB               0x201C
-#define WGL_ACCUM_BITS_ARB                0x201D
 #define WGL_ACCUM_RED_BITS_ARB            0x201E
 #define WGL_ACCUM_GREEN_BITS_ARB          0x201F
 #define WGL_ACCUM_BLUE_BITS_ARB           0x2020
@@ -92,14 +69,7 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
 #define WGL_DEPTH_BITS_ARB                0x2022
 #define WGL_STENCIL_BITS_ARB              0x2023
 #define WGL_AUX_BUFFERS_ARB               0x2024
-#define WGL_NO_ACCELERATION_ARB           0x2025
-#define WGL_GENERIC_ACCELERATION_ARB      0x2026
 #define WGL_FULL_ACCELERATION_ARB         0x2027
-#define WGL_SWAP_EXCHANGE_ARB             0x2028
-#define WGL_SWAP_COPY_ARB                 0x2029
-#define WGL_SWAP_UNDEFINED_ARB            0x202A
-#define WGL_TYPE_RGBA_ARB                 0x202B
-#define WGL_TYPE_COLORINDEX_ARB           0x202C
 #endif
 
 #ifndef WGL_ARB_multisample
@@ -133,110 +103,6 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
 #  pragma comment( lib, "glu32" )
 #endif
 
-// ----------------------------------------------------------------------------
-// constants
-// ----------------------------------------------------------------------------
-
-static const wxChar *wxGLCanvasClassName = wxT("wxGLCanvasClass");
-static const wxChar *wxGLCanvasClassNameNoRedraw = wxT("wxGLCanvasClassNR");
-
-// ============================================================================
-// implementation
-// ============================================================================
-
-// ----------------------------------------------------------------------------
-// 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: some OpenGL drivers are buggy and don't work with
-    // windows without this style
-    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;
-    }
-}
-
 // ----------------------------------------------------------------------------
 // wxGLContext
 // ----------------------------------------------------------------------------
@@ -251,7 +117,9 @@ wxGLContext::wxGLContext(wxGLCanvas *win, const wxGLContext* other)
     if ( other )
     {
         if ( !wglShareLists(other->m_glContext, m_glContext) )
-            wxLogLastError(_T("wglShareLists"));
+        {
+            wxLogLastError(wxT("wglShareLists"));
+        }
     }
 }
 
@@ -265,7 +133,7 @@ bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
 {
     if ( !wglMakeCurrent(win.GetHDC(), m_glContext) )
     {
-        wxLogLastError(_T("wglMakeCurrent"));
+        wxLogLastError(wxT("wglMakeCurrent"));
         return false;
     }
     return true;
@@ -278,14 +146,18 @@ bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
 
 BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
+#if wxUSE_PALETTE
     EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
     EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
+#endif
 END_EVENT_TABLE()
 
 // ----------------------------------------------------------------------------
 // wxGLCanvas construction
 // ----------------------------------------------------------------------------
 
+static int ChoosePixelFormatARB(HDC hdc, const int *attribList);
+
 void wxGLCanvas::Init()
 {
 #if WXWIN_COMPATIBILITY_2_8
@@ -315,24 +187,15 @@ wxGLCanvas::~wxGLCanvas()
 
 // 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,
-                        const int *attribList,
-                        const wxPalette& palette)
+bool wxGLCanvas::CreateWindow(wxWindow *parent,
+                              wxWindowID id,
+                              const wxPoint& pos,
+                              const wxSize& size,
+                              long style,
+                              const wxString& name)
 {
     wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
 
-    if ( !wxGLModule::RegisterClasses() )
-    {
-        wxLogError(_("Failed to register OpenGL window class."));
-
-        return false;
-    }
-
     if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
         return false;
 
@@ -348,16 +211,80 @@ bool wxGLCanvas::Create(wxWindow *parent,
     DWORD msflags = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
     msflags |= MSWGetStyle(style, &exStyle);
 
-    if ( !MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle) )
+    if ( !MSWCreate(wxApp::GetRegisteredClassName(wxT("wxGLCanvas"), -1, CS_OWNDC),
+                    NULL, pos, size, msflags, exStyle) )
         return false;
 
     m_hDC = ::GetDC(GetHwnd());
     if ( !m_hDC )
         return false;
 
-    if ( !DoSetup(attribList) )
+    return true;
+}
+
+bool wxGLCanvas::Create(wxWindow *parent,
+                        wxWindowID id,
+                        const wxPoint& pos,
+                        const wxSize& size,
+                        long style,
+                        const wxString& name,
+                        const int *attribList,
+                        const wxPalette& palette)
+{
+    // Create the window first: we will either use it as is or use it to query
+    // for multisampling support and recreate it later with another pixel format
+    if ( !CreateWindow(parent, id, pos, size, style, name) )
         return false;
 
+    PIXELFORMATDESCRIPTOR pfd;
+    const int setupVal = DoSetup(pfd, attribList);
+    if ( setupVal == 0 ) // PixelFormat error
+        return false;
+
+    if ( setupVal == -1 ) // FSAA requested
+    {
+        // now that we have a valid OpenGL window, query it for FSAA support
+        int pixelFormat;
+        {
+            wxGLContext ctx(this);
+            ctx.SetCurrent(*this);
+            pixelFormat = ::ChoosePixelFormatARB(m_hDC, attribList);
+        }
+
+        if ( pixelFormat > 0 )
+        {
+            // from http://msdn.microsoft.com/en-us/library/ms537559(VS.85).aspx:
+            //
+            //      Setting the pixel format of a window more than once can
+            //      lead to significant complications for the Window Manager
+            //      and for multithread applications, so it is not allowed. An
+            //      application can only set the pixel format of a window one
+            //      time. Once a window's pixel format is set, it cannot be
+            //      changed.
+            //
+            // so we need to delete the old window and create the new one
+
+            // destroy Window
+            ::ReleaseDC(GetHwnd(), m_hDC);
+            m_hDC = 0;
+
+            parent->RemoveChild(this);
+            const HWND hwnd = GetHwnd();
+            DissociateHandle(); // will do SetHWND(0);
+            ::DestroyWindow(hwnd);
+
+            // now recreate with FSAA pixelFormat
+            if ( !CreateWindow(parent, id, pos, size, style, name) )
+                return false;
+
+            if ( !::SetPixelFormat(m_hDC, pixelFormat, &pfd) )
+            {
+                wxLogLastError(wxT("SetPixelFormat"));
+                return false;
+            }
+        }
+    }
+
 #if wxUSE_PALETTE
     if ( !SetupPalette(palette) )
         return false;
@@ -376,7 +303,7 @@ bool wxGLCanvas::SwapBuffers()
 {
     if ( !::SwapBuffers(m_hDC) )
     {
-        wxLogLastError(_T("SwapBuffers"));
+        wxLogLastError(wxT("SwapBuffers"));
         return false;
     }
 
@@ -568,12 +495,21 @@ static int ChoosePixelFormatARB(HDC hdc, const int *attribList)
 
     int pf;
     UINT numFormats = 0;
+
     if ( !wglChoosePixelFormatARB(hdc, iAttributes, NULL, 1, &pf, &numFormats) )
     {
-        wxLogLastError(_T("wglChoosePixelFormatARB"));
+        wxLogLastError(wxT("wglChoosePixelFormatARB"));
         return 0;
     }
 
+    // Although TRUE is returned if no matching formats are found (see
+    // http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt), pf is
+    // not initialized in this case so we need to check for numFormats being
+    // not 0 explicitly (however this is not an error so don't call
+    // wxLogLastError() here).
+    if ( !numFormats )
+        pf = 0;
+
     return pf;
 }
 
@@ -595,6 +531,7 @@ AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, const int *attribList)
     pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
     pfd.iPixelType = PFD_TYPE_COLORINDEX;
 
+    bool requestFSAA = false;
     for ( int arg = 0; attribList[arg]; )
     {
         switch ( attribList[arg++] )
@@ -673,11 +610,14 @@ AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, const int *attribList)
 
             case WX_GL_SAMPLE_BUFFERS:
             case WX_GL_SAMPLES:
-                return -1;
+                // There is no support for multisample when using PIXELFORMATDESCRIPTOR
+                requestFSAA = true; // Remember that multi sample is requested.
+                arg++;              // will call ChoosePixelFormatARB() later
+                break;
         }
     }
 
-    return 1;
+    return requestFSAA ? -1 : 1;
 }
 
 /* static */
@@ -730,7 +670,9 @@ wxGLCanvas::ChooseMatchingPixelFormat(HDC hdc,
             return 0;
 
         case -1:
-            return ::ChoosePixelFormatARB(hdc, attribList);
+            // requestFSAA == true, will continue as normal
+            // in order to query later for a FSAA pixelformat
+            return -1;
     }
 }
 
@@ -742,23 +684,27 @@ bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
     return wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList) > 0;
 }
 
-bool wxGLCanvas::DoSetup(const int *attribList)
+int wxGLCanvas::DoSetup(PIXELFORMATDESCRIPTOR &pfd, const int *attribList)
 {
-    PIXELFORMATDESCRIPTOR pfd;
-    const int pixelFormat = ChooseMatchingPixelFormat(m_hDC, attribList, &pfd);
+    int pixelFormat = ChooseMatchingPixelFormat(m_hDC, attribList, &pfd);
+
+    const bool requestFSAA = pixelFormat == -1;
+    if ( requestFSAA )
+        pixelFormat = ::ChoosePixelFormat(m_hDC, &pfd);
+
     if ( !pixelFormat )
     {
-        wxLogLastError(_T("ChoosePixelFormat"));
-        return false;
+        wxLogLastError(wxT("ChoosePixelFormat"));
+        return 0;
     }
 
     if ( !::SetPixelFormat(m_hDC, pixelFormat, &pfd) )
     {
-        wxLogLastError(_T("SetPixelFormat"));
-        return false;
+        wxLogLastError(wxT("SetPixelFormat"));
+        return 0;
     }
 
-    return true;
+    return requestFSAA ? -1 : 1;
 }
 
 // ----------------------------------------------------------------------------
@@ -772,14 +718,14 @@ bool wxGLCanvas::SetupPalette(const wxPalette& palette)
     const int pixelFormat = ::GetPixelFormat(m_hDC);
     if ( !pixelFormat )
     {
-        wxLogLastError(_T("GetPixelFormat"));
+        wxLogLastError(wxT("GetPixelFormat"));
         return false;
     }
 
     PIXELFORMATDESCRIPTOR pfd;
     if ( !::DescribePixelFormat(m_hDC, pixelFormat, sizeof(pfd), &pfd) )
     {
-        wxLogLastError(_T("DescribePixelFormat"));
+        wxLogLastError(wxT("DescribePixelFormat"));
         return false;
     }
 
@@ -788,22 +734,22 @@ bool wxGLCanvas::SetupPalette(const wxPalette& palette)
 
     m_palette = palette;
 
-    if ( !m_palette.Ok() )
+    if ( !m_palette.IsOk() )
     {
         m_palette = CreateDefaultPalette();
-        if ( !m_palette.Ok() )
+        if ( !m_palette.IsOk() )
             return false;
     }
 
     if ( !::SelectPalette(m_hDC, GetHpaletteOf(m_palette), FALSE) )
     {
-        wxLogLastError(_T("SelectPalette"));
+        wxLogLastError(wxT("SelectPalette"));
         return false;
     }
 
     if ( ::RealizePalette(m_hDC) == GDI_ERROR )
     {
-        wxLogLastError(_T("RealizePalette"));
+        wxLogLastError(wxT("RealizePalette"));
         return false;
     }
 
@@ -853,7 +799,7 @@ wxPalette wxGLCanvas::CreateDefaultPalette()
 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
 {
   /* realize palette if this is the current window */
-  if ( GetPalette()->Ok() ) {
+  if ( GetPalette()->IsOk() ) {
     ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
     ::SelectPalette(GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
     ::RealizePalette(GetHDC());
@@ -868,7 +814,7 @@ void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
 {
   /* realize palette if this is *not* the current window */
   if ( GetPalette() &&
-       GetPalette()->Ok() && (this != event.GetChangedWindow()) )
+       GetPalette()->IsOk() && (this != event.GetChangedWindow()) )
   {
     ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
     ::SelectPalette(GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);