]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/glx11.cpp
first stab at supporting custom renderers
[wxWidgets.git] / src / unix / glx11.cpp
index ffa31f4eb4b1261e7ad4841c852f5bf950fa8d62..05f9625a8c360bb928322df20bfad2259738ada0 100644 (file)
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
-// 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
 // Purpose:     code common to all X11-based wxGLCanvas implementations
 // Author:      Vadim Zeitlin
 // Created:     2007-04-15
 
 #include "wx/glcanvas.h"
 
 
 #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
 // ============================================================================
 // ============================================================================
 // wxGLContext implementation
 // ============================================================================
@@ -38,7 +48,7 @@ wxGLContext::wxGLContext(wxGLCanvas *gc, const wxGLContext *other)
     if ( wxGLCanvas::GetGLXVersion() >= 13 )
     {
         GLXFBConfig *fbc = gc->GetGLXFBConfig();
     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,
 
         m_glContext = glXCreateNewContext( wxGetX11Display(), fbc[0], GLX_RGBA_TYPE,
                                            other ? other->m_glContext : None,
@@ -47,14 +57,14 @@ wxGLContext::wxGLContext(wxGLCanvas *gc, const wxGLContext *other)
     else // GLX <= 1.2
     {
         XVisualInfo *vi = gc->GetXVisualInfo();
     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 );
     }
 
 
         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()
 }
 
 wxGLContext::~wxGLContext()
@@ -68,26 +78,26 @@ wxGLContext::~wxGLContext()
     glXDestroyContext( wxGetX11Display(), m_glContext );
 }
 
     glXDestroyContext( wxGetX11Display(), m_glContext );
 }
 
-void wxGLContext::SetCurrent(const wxGLCanvas& win) const
+bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
 {
     if ( !m_glContext )
 {
     if ( !m_glContext )
-        return;
+        return false;
 
     const Window xid = win.GetXWindow();
 
     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 */
 }
 
 // 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)
 {
     if (wxGLCanvas::GetGLXVersion() >= 13)
-        glXMakeContextCurrent( wxGetX11Display(), drawable, drawable, context);
+        return glXMakeContextCurrent( wxGetX11Display(), drawable, drawable, context);
     else // GLX <= 1.2 doesn't have glXMakeContextCurrent()
     else // GLX <= 1.2 doesn't have glXMakeContextCurrent()
-        glXMakeCurrent( wxGetX11Display(), drawable, context);
+        return glXMakeCurrent( wxGetX11Display(), drawable, context);
 }
 
 // ============================================================================
 }
 
 // ============================================================================
@@ -122,33 +132,71 @@ wxGLCanvasX11::~wxGLCanvasX11()
 // working with GL attributes
 // ----------------------------------------------------------------------------
 
 // 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)
 {
 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 ( !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
         {
             // default settings if attriblist = 0
-            size_t i = 0;
             glattrs[i++] = GLX_RGBA;
             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++] = 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
     {
     }
     else // have non-default attributes
     {
@@ -158,25 +206,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)
             // 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;
 
                 return false;
 
+            // indicates whether we have a boolean attribute
+            bool isBoolAttr = false;
+
             switch ( wxattrs[arg++] )
             {
             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;
                 case WX_GL_BUFFER_SIZE:
                     glattrs[p++] = GLX_BUFFER_SIZE;
                     break;
@@ -185,16 +222,25 @@ wxGLCanvasX11::ConvertWXAttrsToGL(const int *wxattrs, int *glattrs, size_t n)
                     glattrs[p++] = GLX_LEVEL;
                     break;
 
                     glattrs[p++] = GLX_LEVEL;
                     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;
                 case WX_GL_DOUBLEBUFFER:
                     glattrs[p++] = GLX_DOUBLEBUFFER;
-                    glattrs[p++] = True;
-
-                    // again, we don't have value for this one in wx list (even
-                    // though OpenGL does use it)
-                    continue;
+                    isBoolAttr = true;
+                    break;
 
                 case WX_GL_STEREO:
                     glattrs[p++] = GLX_STEREO;
 
                 case WX_GL_STEREO:
                     glattrs[p++] = GLX_STEREO;
+                    isBoolAttr = true;
                     break;
 
                 case WX_GL_AUX_BUFFERS:
                     break;
 
                 case WX_GL_AUX_BUFFERS:
@@ -241,14 +287,53 @@ wxGLCanvasX11::ConvertWXAttrsToGL(const int *wxattrs, int *glattrs, size_t n)
                     glattrs[p++] = GLX_ACCUM_ALPHA_SIZE;
                     break;
 
                     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:
                 default:
-                    wxLogDebug(_T("Unsupported OpenGL attribute %d"),
+                    wxLogDebug(wxT("Unsupported OpenGL attribute %d"),
                                wxattrs[arg - 1]);
                     continue;
             }
 
                                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;
         }
 
         glattrs[p] = None;
@@ -293,6 +378,24 @@ wxGLCanvasX11::InitXVisualInfo(const int *attribList,
     return *pXVisual != NULL;
 }
 
     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
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // default visual management
 // ----------------------------------------------------------------------------
@@ -337,7 +440,7 @@ int wxGLCanvasX11::GetGLXVersion()
         // check the GLX version
         int glxMajorVer, glxMinorVer;
         bool ok = glXQueryVersion(wxGetX11Display(), &glxMajorVer, &glxMinorVer);
         // 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
         if (!ok)
             s_glxVersion = 10; // 1.0 by default
         else
@@ -347,12 +450,13 @@ int wxGLCanvasX11::GetGLXVersion()
     return s_glxVersion;
 }
 
     return s_glxVersion;
 }
 
-void wxGLCanvasX11::SwapBuffers()
+bool wxGLCanvasX11::SwapBuffers()
 {
     const Window xid = GetXWindow();
 {
     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);
 
     glXSwapBuffers(wxGetX11Display(), xid);
+    return true;
 }
 
 bool wxGLCanvasX11::IsShownOnScreen() const
 }
 
 bool wxGLCanvasX11::IsShownOnScreen() const