X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5ec69e9666e300c9ba210812a11ca5dc9111b5f9..cb40fa312eee41ba47999a83743a697760ba5bb0:/src/msw/glcanvas.cpp?ds=sidebyside diff --git a/src/msw/glcanvas.cpp b/src/msw/glcanvas.cpp index 2c5406e2fd..b7035b4cd9 100644 --- a/src/msw/glcanvas.cpp +++ b/src/msw/glcanvas.cpp @@ -46,6 +46,67 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) WXUNUSED(name) #endif +// ---------------------------------------------------------------------------- +// define possibly missing WGL constants +// ---------------------------------------------------------------------------- + +#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 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#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 +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif + // ---------------------------------------------------------------------------- // libraries // ---------------------------------------------------------------------------- @@ -249,10 +310,6 @@ wxGLCanvas::wxGLCanvas(wxWindow *parent, wxGLCanvas::~wxGLCanvas() { -#if WXWIN_COMPATIBILITY_2_8 - delete m_glContext; -#endif - ::ReleaseDC(GetHwnd(), m_hDC); } @@ -319,37 +376,237 @@ bool wxGLCanvas::SwapBuffers() { if ( !::SwapBuffers(m_hDC) ) { - return false; 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; + } + + return pf; +} + // ---------------------------------------------------------------------------- // pixel format stuff // ---------------------------------------------------------------------------- -static void +// returns true if pfd was adjusted accordingly to attributes provided, false +// if there is an error with attributes or -1 if the attributes indicate +// features not supported by ChoosePixelFormat() at all (currently only multi +// sampling) +static int AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, const int *attribList) { if ( !attribList ) - return; + return 1; + // remove default attributes pfd.dwFlags &= ~PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_COLORINDEX; - pfd.cColorBits = 0; - int arg=0; - while ( attribList[arg] ) + for ( int arg = 0; attribList[arg]; ) { switch ( attribList[arg++] ) { case WX_GL_RGBA: pfd.iPixelType = PFD_TYPE_RGBA; break; + case WX_GL_BUFFER_SIZE: pfd.cColorBits = attribList[arg++]; break; + case WX_GL_LEVEL: // this member looks like it may be obsolete if ( attribList[arg] > 0 ) @@ -360,55 +617,67 @@ AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, const int *attribList) pfd.iLayerType = PFD_MAIN_PLANE; arg++; break; + case WX_GL_DOUBLEBUFFER: pfd.dwFlags |= PFD_DOUBLEBUFFER; break; + case WX_GL_STEREO: pfd.dwFlags |= PFD_STEREO; break; + case WX_GL_AUX_BUFFERS: pfd.cAuxBuffers = attribList[arg++]; break; + case WX_GL_MIN_RED: - pfd.cColorBits = (pfd.cColorBits + - (pfd.cRedBits = attribList[arg++])); + pfd.cColorBits += (pfd.cRedBits = attribList[arg++]); break; + case WX_GL_MIN_GREEN: - pfd.cColorBits = (pfd.cColorBits + - (pfd.cGreenBits = attribList[arg++])); + pfd.cColorBits += (pfd.cGreenBits = attribList[arg++]); break; + case WX_GL_MIN_BLUE: - pfd.cColorBits = (pfd.cColorBits + - (pfd.cBlueBits = attribList[arg++])); + pfd.cColorBits += (pfd.cBlueBits = attribList[arg++]); break; + case WX_GL_MIN_ALPHA: // doesn't count in cColorBits pfd.cAlphaBits = attribList[arg++]; break; + case WX_GL_DEPTH_SIZE: pfd.cDepthBits = attribList[arg++]; break; + case WX_GL_STENCIL_SIZE: pfd.cStencilBits = attribList[arg++]; break; + case WX_GL_MIN_ACCUM_RED: - pfd.cAccumBits = (pfd.cAccumBits + - (pfd.cAccumRedBits = attribList[arg++])); + pfd.cAccumBits += (pfd.cAccumRedBits = attribList[arg++]); break; + case WX_GL_MIN_ACCUM_GREEN: - pfd.cAccumBits = (pfd.cAccumBits + - (pfd.cAccumGreenBits = attribList[arg++])); + pfd.cAccumBits += (pfd.cAccumGreenBits = attribList[arg++]); break; + case WX_GL_MIN_ACCUM_BLUE: - pfd.cAccumBits = (pfd.cAccumBits + - (pfd.cAccumBlueBits = attribList[arg++])); + pfd.cAccumBits += (pfd.cAccumBlueBits = attribList[arg++]); break; + case WX_GL_MIN_ACCUM_ALPHA: - pfd.cAccumBits = (pfd.cAccumBits + - (pfd.cAccumAlphaBits = attribList[arg++])); + pfd.cAccumBits += (pfd.cAccumAlphaBits = attribList[arg++]); break; + + case WX_GL_SAMPLE_BUFFERS: + case WX_GL_SAMPLES: + return -1; } } + + return 1; } /* static */ @@ -424,14 +693,13 @@ wxGLCanvas::ChooseMatchingPixelFormat(HDC hdc, 1, // version PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | - PFD_DOUBLEBUFFER, // support double-buffering - PFD_TYPE_RGBA, // color type - 16, // preferred 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, // accumulator bits (ignored) + PFD_DOUBLEBUFFER, // use double-buffering by default + PFD_TYPE_RGBA, // default pixel type + 0, // preferred color depth (don't care) + 0, 0, 0, 0, 0, 0, // color bits and shift bits (ignored) + 0, 0, // alpha bits and shift (ignored) + 0, // accumulation total bits + 0, 0, 0, 0, // accumulator RGBA bits (not used) 16, // depth buffer 0, // no stencil buffer 0, // no auxiliary buffers @@ -445,9 +713,33 @@ wxGLCanvas::ChooseMatchingPixelFormat(HDC hdc, else *ppfd = pfd; - AdjustPFDForAttributes(*ppfd, attribList); + // adjust the PFD using the provided attributes and also check if we can + // use PIXELFORMATDESCRIPTOR at all: if multisampling is requested, we + // can't as it's not supported by ChoosePixelFormat() + switch ( AdjustPFDForAttributes(*ppfd, attribList) ) + { + case 1: + return ::ChoosePixelFormat(hdc, ppfd); + + default: + wxFAIL_MSG( "unexpected AdjustPFDForAttributes() return value" ); + // fall through + + case 0: + // error in attributes + return 0; + + case -1: + return ::ChoosePixelFormatARB(hdc, attribList); + } +} - return ::ChoosePixelFormat(hdc, ppfd); +/* static */ +bool wxGLCanvasBase::IsDisplaySupported(const int *attribList) +{ + // We need a device context to test the pixel format, so get one + // for the root window. + return wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList) > 0; } bool wxGLCanvas::DoSetup(const int *attribList) @@ -534,13 +826,12 @@ wxPalette wxGLCanvas::CreateDefaultPalette() pPal->palNumEntries = (WORD)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; ipalPalEntry[i].peRed = (BYTE)((((i >> pfd.cRedShift) & redMask) * 255) / redMask); pPal->palPalEntry[i].peGreen = @@ -549,7 +840,6 @@ wxPalette wxGLCanvas::CreateDefaultPalette() (BYTE)((((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask); pPal->palPalEntry[i].peFlags = 0; } - } HPALETTE hPalette = CreatePalette(pPal); free(pPal);