X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/85866f52b3fe2c781e57cf20354306c3dc23f34e..6f026b5b63fe7ccb025e84509886f74772b9df13:/src/unix/glx11.cpp diff --git a/src/unix/glx11.cpp b/src/unix/glx11.cpp index b4a8b2d147..ec2bd5b098 100644 --- a/src/unix/glx11.cpp +++ b/src/unix/glx11.cpp @@ -1,9 +1,8 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: src/univ/glx11.cpp +// Name: src/unix/glx11.cpp // Purpose: code common to all X11-based wxGLCanvas implementations // Author: Vadim Zeitlin // Created: 2007-04-15 -// RCS-ID: $Id$ // Copyright: (c) 2007 Vadim Zeitlin // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -27,6 +26,16 @@ #include "wx/glcanvas.h" +// IRIX headers call this differently +#ifdef __SGI__ + #ifndef GLX_SAMPLE_BUFFERS_ARB + #define GLX_SAMPLE_BUFFERS_ARB GLX_SAMPLE_BUFFERS_SGIS + #endif + #ifndef GLX_SAMPLES_ARB + #define GLX_SAMPLES_ARB GLX_SAMPLES_SGIS + #endif +#endif // __SGI__ + // ============================================================================ // wxGLContext implementation // ============================================================================ @@ -38,7 +47,7 @@ wxGLContext::wxGLContext(wxGLCanvas *gc, const wxGLContext *other) if ( wxGLCanvas::GetGLXVersion() >= 13 ) { GLXFBConfig *fbc = gc->GetGLXFBConfig(); - wxCHECK_RET( fbc, _T("invalid GLXFBConfig for OpenGL") ); + wxCHECK_RET( fbc, wxT("invalid GLXFBConfig for OpenGL") ); m_glContext = glXCreateNewContext( wxGetX11Display(), fbc[0], GLX_RGBA_TYPE, other ? other->m_glContext : None, @@ -47,14 +56,14 @@ wxGLContext::wxGLContext(wxGLCanvas *gc, const wxGLContext *other) else // GLX <= 1.2 { XVisualInfo *vi = gc->GetXVisualInfo(); - wxCHECK_RET( vi, _T("invalid visual for OpenGL") ); + wxCHECK_RET( vi, wxT("invalid visual for OpenGL") ); m_glContext = glXCreateContext( wxGetX11Display(), vi, other ? other->m_glContext : None, GL_TRUE ); } - wxASSERT_MSG( m_glContext, _T("Couldn't create OpenGL context") ); + wxASSERT_MSG( m_glContext, wxT("Couldn't create OpenGL context") ); } wxGLContext::~wxGLContext() @@ -68,26 +77,26 @@ wxGLContext::~wxGLContext() glXDestroyContext( wxGetX11Display(), m_glContext ); } -void wxGLContext::SetCurrent(const wxGLCanvas& win) const +bool wxGLContext::SetCurrent(const wxGLCanvas& win) const { if ( !m_glContext ) - return; + return false; const Window xid = win.GetXWindow(); - wxCHECK_RET( xid, _T("window must be shown") ); + wxCHECK2_MSG( xid, return false, wxT("window must be shown") ); - MakeCurrent(xid, m_glContext); + return MakeCurrent(xid, m_glContext); } // wrapper around glXMakeContextCurrent/glXMakeCurrent depending on GLX // version /* static */ -void wxGLContext::MakeCurrent(GLXDrawable drawable, GLXContext context) +bool wxGLContext::MakeCurrent(GLXDrawable drawable, GLXContext context) { if (wxGLCanvas::GetGLXVersion() >= 13) - glXMakeContextCurrent( wxGetX11Display(), drawable, drawable, context); + return glXMakeContextCurrent( wxGetX11Display(), drawable, drawable, context); else // GLX <= 1.2 doesn't have glXMakeContextCurrent() - glXMakeCurrent( wxGetX11Display(), drawable, context); + return glXMakeCurrent( wxGetX11Display(), drawable, context); } // ============================================================================ @@ -122,33 +131,71 @@ wxGLCanvasX11::~wxGLCanvasX11() // working with GL attributes // ---------------------------------------------------------------------------- +/* static */ +bool wxGLCanvasBase::IsExtensionSupported(const char *extension) +{ + Display * const dpy = wxGetX11Display(); + + return IsExtensionInList(glXQueryExtensionsString(dpy, DefaultScreen(dpy)), + extension); +} + + +/* static */ +bool wxGLCanvasX11::IsGLXMultiSampleAvailable() +{ + static int s_isMultiSampleAvailable = -1; + if ( s_isMultiSampleAvailable == -1 ) + s_isMultiSampleAvailable = IsExtensionSupported("GLX_ARB_multisample"); + + return s_isMultiSampleAvailable != 0; +} + bool wxGLCanvasX11::ConvertWXAttrsToGL(const int *wxattrs, int *glattrs, size_t n) { - wxCHECK_MSG( n >= 16, false, _T("GL attributes buffer too small") ); + wxCHECK_MSG( n >= 16, false, wxT("GL attributes buffer too small") ); + + /* + Different versions of GLX API use rather different attributes lists, see + the following URLs: + + - <= 1.2: http://www.opengl.org/sdk/docs/man/xhtml/glXChooseVisual.xml + - >= 1.3: http://www.opengl.org/sdk/docs/man/xhtml/glXChooseFBConfig.xml + + Notice in particular that + - GLX_RGBA is boolean attribute in the old version of the API but a + value of GLX_RENDER_TYPE in the new one + - Boolean attributes such as GLX_DOUBLEBUFFER don't take values in the + old version but must be followed by True or False in the new one. + */ if ( !wxattrs ) { - if ( GetGLXVersion() >= 13 ) - { - // leave GLX >= 1.3 choose the default attributes - glattrs[0] = None; - } - else // GLX < 1.3 + size_t i = 0; + + // use double-buffered true colour by default + glattrs[i++] = GLX_DOUBLEBUFFER; + + if ( GetGLXVersion() < 13 ) { // default settings if attriblist = 0 - size_t i = 0; glattrs[i++] = GLX_RGBA; - glattrs[i++] = GLX_DOUBLEBUFFER; glattrs[i++] = GLX_DEPTH_SIZE; glattrs[i++] = 1; glattrs[i++] = GLX_RED_SIZE; glattrs[i++] = 1; glattrs[i++] = GLX_GREEN_SIZE; glattrs[i++] = 1; glattrs[i++] = GLX_BLUE_SIZE; glattrs[i++] = 1; glattrs[i++] = GLX_ALPHA_SIZE; glattrs[i++] = 0; - glattrs[i++] = None; - - wxASSERT_MSG( i < n, _T("GL attributes buffer too small") ); } + else // recent GLX can choose the defaults on its own just fine + { + // we just need to have a value after GLX_DOUBLEBUFFER + glattrs[i++] = True; + } + + glattrs[i] = None; + + wxASSERT_MSG( i < n, wxT("GL attributes buffer too small") ); } else // have non-default attributes { @@ -158,25 +205,14 @@ wxGLCanvasX11::ConvertWXAttrsToGL(const int *wxattrs, int *glattrs, size_t n) // check if we have any space left, knowing that we may insert 2 // more elements during this loop iteration and we always need to // terminate the list with None (hence -3) - if ( p >= n - 2 ) + if ( p > n - 3 ) return false; + // indicates whether we have a boolean attribute + bool isBoolAttr = false; + switch ( wxattrs[arg++] ) { - case WX_GL_RGBA: - // for GLX >= 1.3, GLX_RGBA is useless and apparently - // harmful for some implementations - // - // FIXME: is this true? - if ( GetGLXVersion() <= 12 ) - { - glattrs[p++] = GLX_RGBA; - } - - // use "continue" to skip the assignment of the attribute - // value at the end of the loop - continue; - case WX_GL_BUFFER_SIZE: glattrs[p++] = GLX_BUFFER_SIZE; break; @@ -185,21 +221,26 @@ wxGLCanvasX11::ConvertWXAttrsToGL(const int *wxattrs, int *glattrs, size_t n) glattrs[p++] = GLX_LEVEL; break; - // the following boolean attributes don't have values in wx - // API (they're turned on if specified) but do have them in - // OpenGL, so do put them into glattrs and also skip the - // copy of wx value after switch by using "continue" - // instead of "break" + case WX_GL_RGBA: + if ( GetGLXVersion() >= 13 ) + { + // this is the default GLX_RENDER_TYPE anyhow + continue; + } + + glattrs[p++] = GLX_RGBA; + isBoolAttr = true; + break; + case WX_GL_DOUBLEBUFFER: glattrs[p++] = GLX_DOUBLEBUFFER; - glattrs[p++] = True; - continue; + isBoolAttr = true; + break; case WX_GL_STEREO: glattrs[p++] = GLX_STEREO; - glattrs[p++] = True; - continue; - + isBoolAttr = true; + break; case WX_GL_AUX_BUFFERS: glattrs[p++] = GLX_AUX_BUFFERS; @@ -245,14 +286,53 @@ wxGLCanvasX11::ConvertWXAttrsToGL(const int *wxattrs, int *glattrs, size_t n) glattrs[p++] = GLX_ACCUM_ALPHA_SIZE; break; + case WX_GL_SAMPLE_BUFFERS: +#ifdef GLX_SAMPLE_BUFFERS_ARB + if ( IsGLXMultiSampleAvailable() ) + { + glattrs[p++] = GLX_SAMPLE_BUFFERS_ARB; + break; + } +#endif // GLX_SAMPLE_BUFFERS_ARB + // if it was specified just to disable it, no problem + if ( !wxattrs[arg++] ) + continue; + + // otherwise indicate that it's not supported + return false; + + case WX_GL_SAMPLES: +#ifdef GLX_SAMPLES_ARB + if ( IsGLXMultiSampleAvailable() ) + { + glattrs[p++] = GLX_SAMPLES_ARB; + break; + } +#endif // GLX_SAMPLES_ARB + + if ( !wxattrs[arg++] ) + continue; + + return false; + default: - wxLogDebug(_T("Unsupported OpenGL attribute %d"), + wxLogDebug(wxT("Unsupported OpenGL attribute %d"), wxattrs[arg - 1]); continue; } - // copy attribute value as is - glattrs[p++] = wxattrs[arg++]; + if ( isBoolAttr ) + { + // as explained above, for pre 1.3 API the attribute just needs + // to be present so we only add its value when using the new API + if ( GetGLXVersion() >= 13 ) + glattrs[p++] = True; + } + else // attribute with real (non-boolean) value + { + // copy attribute value as is + glattrs[p++] = wxattrs[arg++]; + } } glattrs[p] = None; @@ -297,6 +377,24 @@ wxGLCanvasX11::InitXVisualInfo(const int *attribList, return *pXVisual != NULL; } +/* static */ +bool +wxGLCanvasBase::IsDisplaySupported(const int *attribList) +{ + GLXFBConfig *fbc = NULL; + XVisualInfo *vi = NULL; + + const bool + isSupported = wxGLCanvasX11::InitXVisualInfo(attribList, &fbc, &vi); + + if ( fbc ) + XFree(fbc); + if ( vi ) + XFree(vi); + + return isSupported; +} + // ---------------------------------------------------------------------------- // default visual management // ---------------------------------------------------------------------------- @@ -341,7 +439,7 @@ int wxGLCanvasX11::GetGLXVersion() // check the GLX version int glxMajorVer, glxMinorVer; bool ok = glXQueryVersion(wxGetX11Display(), &glxMajorVer, &glxMinorVer); - wxASSERT_MSG( ok, _T("GLX version not found") ); + wxASSERT_MSG( ok, wxT("GLX version not found") ); if (!ok) s_glxVersion = 10; // 1.0 by default else @@ -351,12 +449,13 @@ int wxGLCanvasX11::GetGLXVersion() return s_glxVersion; } -void wxGLCanvasX11::SwapBuffers() +bool wxGLCanvasX11::SwapBuffers() { const Window xid = GetXWindow(); - wxCHECK_RET( xid, _T("window must be shown") ); + wxCHECK2_MSG( xid, return false, wxT("window must be shown") ); glXSwapBuffers(wxGetX11Display(), xid); + return true; } bool wxGLCanvasX11::IsShownOnScreen() const