+ DWORD msflags = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+ msflags |= MSWGetStyle(style, &exStyle);
+
+ if ( !MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle) )
+ return false;
+
+ m_hDC = ::GetDC(GetHwnd());
+ if ( !m_hDC )
+ return false;
+
+ 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(_T("SetPixelFormat"));
+ return false;
+ }
+ }
+ }
+
+#if wxUSE_PALETTE
+ if ( !SetupPalette(palette) )
+ return false;
+#else // !wxUSE_PALETTE
+ wxUnusedVar(palette);
+#endif // wxUSE_PALETTE/!wxUSE_PALETTE
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+// operations
+// ----------------------------------------------------------------------------
+
+bool wxGLCanvas::SwapBuffers()
+{
+ if ( !::SwapBuffers(m_hDC) )
+ {
+ wxLogLastError(_T("SwapBuffers"));
+ return false;
+ }
+
+ return true;
+}
+
+
+// ----------------------------------------------------------------------------
+// multi sample support
+// ----------------------------------------------------------------------------
+
+// this macro defines a variable of type "name_t" called "name" and initializes
+// it with the pointer to WGL function "name" (which may be NULL)
+#define wxDEFINE_WGL_FUNC(name) \
+ name##_t name = (name##_t)wglGetProcAddress(#name)
+
+/* static */
+bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
+{
+ static const char *s_extensionsList = (char *)wxUIntPtr(-1);
+ if ( s_extensionsList == (char *)wxUIntPtr(-1) )
+ {
+ typedef const char * (WINAPI *wglGetExtensionsStringARB_t)(HDC hdc);
+
+ wxDEFINE_WGL_FUNC(wglGetExtensionsStringARB);
+ if ( wglGetExtensionsStringARB )
+ {
+ s_extensionsList = wglGetExtensionsStringARB(wglGetCurrentDC());
+ }
+ else
+ {
+ typedef const char * (WINAPI * wglGetExtensionsStringEXT_t)();
+
+ wxDEFINE_WGL_FUNC(wglGetExtensionsStringEXT);
+ if ( wglGetExtensionsStringEXT )
+ {
+ s_extensionsList = wglGetExtensionsStringEXT();
+ }
+ else
+ {
+ s_extensionsList = NULL;
+ }
+ }
+ }
+
+ return s_extensionsList && IsExtensionInList(s_extensionsList, extension);
+}
+
+// this is a wrapper around wglChoosePixelFormatARB(): returns the pixel format
+// index matching the given attributes on success or 0 on failure
+static int ChoosePixelFormatARB(HDC hdc, const int *attribList)
+{
+ if ( !wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample") )
+ return 0;
+
+ typedef BOOL (WINAPI * wglChoosePixelFormatARB_t)
+ (HDC hdc,
+ const int *piAttribIList,
+ const FLOAT *pfAttribFList,
+ UINT nMaxFormats,
+ int *piFormats,
+ UINT *nNumFormats
+ );
+
+ wxDEFINE_WGL_FUNC(wglChoosePixelFormatARB);
+ if ( !wglChoosePixelFormatARB )
+ return 0; // should not occur if extension is supported
+
+ int iAttributes[128];
+ int dst = 0; // index in iAttributes array
+
+ #define ADD_ATTR(attr, value) \
+ iAttributes[dst++] = attr; iAttributes[dst++] = value
+
+ ADD_ATTR( WGL_DRAW_TO_WINDOW_ARB, GL_TRUE );
+ ADD_ATTR( WGL_SUPPORT_OPENGL_ARB, GL_TRUE );
+ ADD_ATTR( WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB );
+
+ if ( !attribList )
+ {
+ ADD_ATTR( WGL_COLOR_BITS_ARB, 24 );
+ ADD_ATTR( WGL_ALPHA_BITS_ARB, 8 );
+ ADD_ATTR( WGL_DEPTH_BITS_ARB, 16 );
+ ADD_ATTR( WGL_STENCIL_BITS_ARB, 0 );
+ ADD_ATTR( WGL_DOUBLE_BUFFER_ARB, GL_TRUE );
+ ADD_ATTR( WGL_SAMPLE_BUFFERS_ARB, GL_TRUE );
+ ADD_ATTR( WGL_SAMPLES_ARB, 4 );
+ }
+ else // have custom attributes
+ {
+ #define ADD_ATTR_VALUE(attr) ADD_ATTR(attr, attribList[src++])
+
+ int src = 0;
+ while ( attribList[src] )
+ {
+ switch ( attribList[src++] )
+ {
+ case WX_GL_RGBA:
+ ADD_ATTR( WGL_COLOR_BITS_ARB, 24 );
+ ADD_ATTR( WGL_ALPHA_BITS_ARB, 8 );
+ break;
+
+ case WX_GL_BUFFER_SIZE:
+ ADD_ATTR_VALUE( WGL_COLOR_BITS_ARB);
+ break;
+
+ case WX_GL_LEVEL:
+ if ( attribList[src] > 0 )
+ {
+ ADD_ATTR( WGL_NUMBER_OVERLAYS_ARB, 1 );
+ }
+ else if ( attribList[src] <0 )
+ {
+ ADD_ATTR( WGL_NUMBER_UNDERLAYS_ARB, 1 );
+ }
+ //else: ignore it
+
+ src++; // skip the value in any case
+ break;
+
+ case WX_GL_DOUBLEBUFFER:
+ ADD_ATTR( WGL_DOUBLE_BUFFER_ARB, GL_TRUE );
+ break;
+
+ case WX_GL_STEREO:
+ ADD_ATTR( WGL_STEREO_ARB, GL_TRUE );
+ break;
+
+ case WX_GL_AUX_BUFFERS:
+ ADD_ATTR_VALUE( WGL_AUX_BUFFERS_ARB );
+ break;
+
+ case WX_GL_MIN_RED:
+ ADD_ATTR_VALUE( WGL_RED_BITS_ARB );
+ break;
+
+ case WX_GL_MIN_GREEN:
+ ADD_ATTR_VALUE( WGL_GREEN_BITS_ARB );
+ break;
+
+ case WX_GL_MIN_BLUE:
+ ADD_ATTR_VALUE( WGL_BLUE_BITS_ARB );
+ break;
+
+ case WX_GL_MIN_ALPHA:
+ ADD_ATTR_VALUE( WGL_ALPHA_BITS_ARB );
+ break;
+
+ case WX_GL_DEPTH_SIZE:
+ ADD_ATTR_VALUE( WGL_DEPTH_BITS_ARB );
+ break;
+
+ case WX_GL_STENCIL_SIZE:
+ ADD_ATTR_VALUE( WGL_STENCIL_BITS_ARB );
+ break;
+
+ case WX_GL_MIN_ACCUM_RED:
+ ADD_ATTR_VALUE( WGL_ACCUM_RED_BITS_ARB );
+ break;
+
+ case WX_GL_MIN_ACCUM_GREEN:
+ ADD_ATTR_VALUE( WGL_ACCUM_GREEN_BITS_ARB );
+ break;
+
+ case WX_GL_MIN_ACCUM_BLUE:
+ ADD_ATTR_VALUE( WGL_ACCUM_BLUE_BITS_ARB );
+ break;
+
+ case WX_GL_MIN_ACCUM_ALPHA:
+ ADD_ATTR_VALUE( WGL_ACCUM_ALPHA_BITS_ARB );
+ break;
+
+ case WX_GL_SAMPLE_BUFFERS:
+ ADD_ATTR_VALUE( WGL_SAMPLE_BUFFERS_ARB );
+ break;
+
+ case WX_GL_SAMPLES:
+ ADD_ATTR_VALUE( WGL_SAMPLES_ARB );
+ break;
+ }
+ }
+
+ #undef ADD_ATTR_VALUE
+ }
+
+ #undef ADD_ATTR
+
+ iAttributes[dst++] = 0;
+
+ int pf;
+ UINT numFormats = 0;
+ if ( !wglChoosePixelFormatARB(hdc, iAttributes, NULL, 1, &pf, &numFormats) )
+ {
+ wxLogLastError(_T("wglChoosePixelFormatARB"));
+ return 0;
+ }