[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kwin
Subject:    GetFBConfigs
From:       Philip Falkner <philip.falkner () gmail ! com>
Date:       2007-01-27 0:25:27
Message-ID: 200701261925.27890.philip.falkner () gmail ! com
[Download RAW message or body]

Largely lifted from compiz, here's some code which should select decent 
configs for both the buffer and the drawables.  It works here with all three 
modes, even though it chooses different configs than does current svn.  From 
what I've gathered about nvidia/fglrx, this should work there too (fingers 
crossed).

It tries to get minimal stencil/depth buffers for the drawables, and maximal 
for the main buffer.  I'm not convinced about sorting by caveat; it works 
around a problem in fallback mode for me, but otherwise provides little/no 
benefit or disadvantage.

Please test; I'm hoping this might get tfp working for you, Rivo.

-- 
Philip Falkner

["configs.patch" (text/x-diff)]

Index: scene_opengl.h
===================================================================
--- scene_opengl.h	(revision 627547)
+++ scene_opengl.h	(working copy)
@@ -39,6 +39,7 @@ class SceneOpenGL
         virtual void paintBackground( QRegion region );
     private:
         void selectMode();
+        bool initFBConfigs();
         bool initTfp();
         bool initShm();
         void cleanupShm();
@@ -53,13 +54,16 @@ class SceneOpenGL
         Drawable buffer;
         GLXFBConfig fbcbuffer;
         static bool db;
-        static GLXFBConfig fbcdrawable;
+        static GLXFBConfig fbcbuffer_db;
+        static GLXFBConfig fbcbuffer_nondb;
+        static GLXFBConfig fbcdrawable[ 32 + 1 ];
         static GLXDrawable glxbuffer;
         static GLXContext ctxbuffer;
         static GLXContext ctxdrawable;
         static GLXDrawable last_pixmap; // for a workaround in bindTexture()
         static bool tfp_mode;
         static bool shm_mode;
+        static bool tfp_bind_to_rgba;
         static bool strict_binding;
         static bool copy_buffer_hack;
         static bool supports_npot_textures;
Index: scene_opengl.cpp
===================================================================
--- scene_opengl.cpp	(revision 627547)
+++ scene_opengl.cpp	(working copy)
@@ -74,8 +74,11 @@ namespace KWinInternal
 // SceneOpenGL
 //****************************************
 
-// the config used for windows
-GLXFBConfig SceneOpenGL::fbcdrawable;
+// the configs used for the destination
+GLXFBConfig SceneOpenGL::fbcbuffer_db;
+GLXFBConfig SceneOpenGL::fbcbuffer_nondb;
+// the configs used for windows
+GLXFBConfig SceneOpenGL::fbcdrawable[ 32 + 1 ];
 // GLX content
 GLXContext SceneOpenGL::ctxbuffer;
 GLXContext SceneOpenGL::ctxdrawable;
@@ -83,6 +86,7 @@ GLXContext SceneOpenGL::ctxdrawable;
 GLXDrawable SceneOpenGL::glxbuffer;
 GLXDrawable SceneOpenGL::last_pixmap;
 bool SceneOpenGL::tfp_mode; // using glXBindTexImageEXT (texture_from_pixmap)
+bool SceneOpenGL::tfp_bind_to_rgba; // can use GLX_TEXTURE_FORMAT_RGBA_EXT
 bool SceneOpenGL::strict_binding; // intended for AIGLX
 bool SceneOpenGL::db; // destination drawable is double-buffered
 bool SceneOpenGL::copy_buffer_hack; // workaround for nvidia < 1.0-9xxx drivers
@@ -169,9 +173,14 @@ SceneOpenGL::SceneOpenGL( Workspace* ws 
     initBuffer(); // create destination buffer
     int vis_buffer, vis_drawable;
     glXGetFBConfigAttrib( display(), fbcbuffer, GLX_VISUAL_ID, &vis_buffer );
-    glXGetFBConfigAttrib( display(), fbcdrawable, GLX_VISUAL_ID, &vis_drawable );
-    kDebug( 1212 ) << "Buffer visual: 0x" << QString::number( vis_buffer, 16 ) << ", \
                drawable visual: 0x"
-        << QString::number( vis_drawable, 16 ) << endl;
+    kDebug( 1212 ) << "Buffer visual (depth " << QX11Info::appDepth() << "): 0x" << \
QString::number( vis_buffer, 16 ) << endl; +    for( int i = 0; i <= 32; i++ )
+        {
+        if( fbcdrawable[ i ] == NULL )
+            continue;
+        glXGetFBConfigAttrib( display(), fbcdrawable[ i ], GLX_VISUAL_ID, \
&vis_drawable ); +        kDebug( 1212 ) << "Drawable visual (depth " << i << "): 0x" \
<< QString::number( vis_drawable, 16 ) << endl; +        }
     initRenderingContext();
 
     // Initialize OpenGL
@@ -250,7 +259,7 @@ void SceneOpenGL::selectMode()
         else if( initTfp())
             tfp_mode = true;
         }
-    if( !tfp_mode && !findConfig( drawable_attrs, &fbcdrawable ))
+    if( !initFBConfigs())
         assert( false );
     // use copy buffer hack from glcompmgr (called COPY_BUFFER there) - nvidia \
drivers older than  // 1.0-9xxx don't update pixmaps properly, so do a copy first
@@ -261,7 +270,7 @@ bool SceneOpenGL::initTfp()
     {
     if( glXBindTexImageEXT == NULL || glXReleaseTexImageEXT == NULL )
         return false;
-    if( !findConfig( drawable_tfp_attrs, &fbcdrawable ))
+    if( !initFBConfigs())
         return false;
     return true;
     }
@@ -333,7 +342,7 @@ void SceneOpenGL::initRenderingContext()
         }
     if( !tfp_mode && !shm_mode )
         {
-        ctxdrawable = glXCreateNewContext( display(), fbcdrawable, GLX_RGBA_TYPE, \
ctxbuffer, +        ctxdrawable = glXCreateNewContext( display(), fbcdrawable[ \
QX11Info::appDepth() ], GLX_RGBA_TYPE, ctxbuffer,  direct_rendering ? GL_TRUE : \
GL_FALSE );  }
     }
@@ -341,8 +350,9 @@ void SceneOpenGL::initRenderingContext()
 // create destination buffer
 void SceneOpenGL::initBuffer()
     {
-    if( findConfig( buffer_db_attrs, &fbcbuffer ) && wspace->createOverlay())
+    if( fbcbuffer_db != NULL && wspace->createOverlay())
         { // we have overlay, try to create double-buffered window in it
+        fbcbuffer = fbcbuffer_db;
         XVisualInfo* visual = glXGetVisualFromFBConfig( display(), fbcbuffer );
         XSetWindowAttributes attrs;
         attrs.colormap = XCreateColormap( display(), rootWindow(), visual->visual, \
AllocNone ); @@ -356,8 +366,9 @@ void SceneOpenGL::initBuffer()
         db = true;
         XFree( visual );
         }
-    else if( findConfig( buffer_nondb_attrs, &fbcbuffer ))
+    else if( fbcbuffer_nondb != NULL )
         { // cannot get any double-buffered drawable, will double-buffer using a \
pixmap +        fbcbuffer = fbcbuffer_nondb;
         db = false;
         XGCValues gcattr;
         gcattr.subwindow_mode = IncludeInferiors;
@@ -388,6 +399,165 @@ static void debugFBConfig( GLXFBConfig* 
         }
     }
 
+// choose the best configs for the destination, make a list of the best configs
+// for windows by depth
+bool SceneOpenGL::initFBConfigs()
+    {
+    int cnt, i;
+    GLXFBConfig *fbconfigs = glXGetFBConfigs( display(), DefaultScreen( display() ), \
&cnt ); +
+    // Find the best destination configs (double- and single-buffered)
+    fbcbuffer_db = NULL;
+    fbcbuffer_nondb = NULL;
+    for( i = 0; i < 2; i++ )
+        {
+        int back, stencil, depth, caveat, alpha;
+        if( i > 0 )
+            back = INT_MAX;
+        else
+            back = 1;
+        stencil = 0;
+        depth = 0;
+        caveat = INT_MAX;
+        alpha = 0;
+        for( int j = 0; j < cnt; j++ )
+            {
+            XVisualInfo *vi;
+            int visual_depth;
+            vi = glXGetVisualFromFBConfig( display(), fbconfigs[ j ] );
+            if( vi == NULL )
+                continue;
+            visual_depth = vi->depth;
+            XFree( vi );
+            if( visual_depth != QX11Info::appDepth() )
+                continue;
+            int value;
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_ALPHA_SIZE, &alpha );
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_BUFFER_SIZE, &value );
+            if( value != QX11Info::appDepth() && ( value - alpha ) != \
QX11Info::appDepth() ) +                continue;
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_DOUBLEBUFFER, &value );
+            if( i > 0 )
+                {
+                if( value > back )
+                    continue;
+                }
+            else
+                {
+                if( value < back )
+                    continue;
+                }
+            back = value;
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_STENCIL_SIZE, &value );
+            if( value < stencil )
+                continue;
+            stencil = value;
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_DEPTH_SIZE, &value );
+            if( value < depth )
+                continue;
+            depth = value;
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_CONFIG_CAVEAT, &value );
+            if( value > caveat )
+                continue;
+            caveat = value;
+            if( i > 0 )
+                fbcbuffer_nondb = fbconfigs[ j ];
+            else
+                fbcbuffer_db = fbconfigs[ j ];
+            }
+        }
+    // Find the best drawable configs (one for each bit depth)
+    tfp_bind_to_rgba = false;
+    for( i = 0; i <= 32; i++ )
+        {
+        int back, stencil, depth, caveat, alpha;
+        back = INT_MAX;
+        stencil = INT_MAX;
+        depth = INT_MAX;
+        caveat = INT_MAX;
+        fbcdrawable[ i ] = NULL;
+        for( int j = 0; j < cnt; j++ )
+            {
+            XVisualInfo *vi;
+            int visual_depth;
+            vi = glXGetVisualFromFBConfig( display(), fbconfigs[ j ] );
+            if( vi == NULL )
+                continue;
+            visual_depth = vi->depth;
+            XFree( vi );
+            if( visual_depth != i )
+                continue;
+            int value;
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_ALPHA_SIZE, &alpha );
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_BUFFER_SIZE, &value );
+            if( value != i && ( value - alpha ) != i )
+                continue;
+            if( tfp_mode )
+                {
+                value = 0;
+                if( i == 32 )
+                    {
+                    glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                          GLX_BIND_TO_TEXTURE_RGBA_EXT, &value );
+                    if( value )
+                        tfp_bind_to_rgba = true;
+                    }
+                if( !value )
+                    {
+                    if( tfp_bind_to_rgba )
+                        continue;
+                    glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                          GLX_BIND_TO_TEXTURE_RGB_EXT, &value );
+                    if( !value )
+                        continue;
+                    }
+                }
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_DOUBLEBUFFER, &value );
+            if( value > back )
+                continue;
+            back = value;
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_STENCIL_SIZE, &value );
+            if( value > stencil )
+                continue;
+            stencil = value;
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_DEPTH_SIZE, &value );
+            if( value > depth )
+                continue;
+            depth = value;
+            glXGetFBConfigAttrib( display(), fbconfigs[ j ],
+                                  GLX_CONFIG_CAVEAT, &value );
+            if( value > caveat )
+                continue;
+            caveat = value;
+            fbcdrawable[ i ] = fbconfigs[ j ];
+            }
+        }
+    if( cnt )
+        XFree( fbconfigs );
+    if( fbcbuffer_db == NULL && fbcbuffer_nondb == NULL )
+        {
+        kDebug( 1212 ) << "Couldn't find framebuffer configuration for buffer!" << \
endl; +        return false;
+        }
+    if( fbcdrawable[ QX11Info::appDepth() ] == NULL )
+        {
+        kDebug( 1212 ) << "Couldn't find framebuffer configuration for default \
depth!" << endl; +        return false;
+        }
+    return true;
+    }
+
 // find config matching the given attributes and possibly the given X visual
 bool SceneOpenGL::findConfig( const int* attrs, GLXFBConfig* config, VisualID visual \
)  {
@@ -862,16 +1032,16 @@ void SceneOpenGL::Window::bindTexture()
             tfp_target = GLX_TEXTURE_RECTANGLE_EXT;
         static const int attrs[] =
             {
-            GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
+            GLX_TEXTURE_FORMAT_EXT, toplevel->hasAlpha() && tfp_bind_to_rgba ? \
GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT,  GLX_TEXTURE_TARGET_EXT, \
tfp_target,  None
             };
         // the GLXPixmap will reference the X pixmap, so it will be freed \
automatically  // when no longer needed
-        bound_glxpixmap = glXCreatePixmap( display(), fbcdrawable, pix, attrs );
+        bound_glxpixmap = glXCreatePixmap( display(), fbcdrawable[ toplevel->depth() \
], pix, attrs );  findTextureTarget();
         int value;
-        glXGetFBConfigAttrib( display(), fbcdrawable, GLX_Y_INVERTED_EXT, &value );
+        glXGetFBConfigAttrib( display(), fbcdrawable[ toplevel->depth() ], \
GLX_Y_INVERTED_EXT, &value );  texture_y_inverted = value ? true : false;
         glBindTexture( texture_target, texture );
         if( !strict_binding )
@@ -880,8 +1050,10 @@ void SceneOpenGL::Window::bindTexture()
         }
     else
         { // non-tfp case, copy pixmap contents to a texture
+        if( toplevel->depth() != QX11Info::appDepth())
+            kDebug( 1212 ) << "Window depth " << toplevel->depth() << " is not the \
default depth; this may not work" << endl;  findTextureTarget();
-        GLXDrawable pixmap = glXCreatePixmap( display(), fbcdrawable, pix, NULL );
+        GLXDrawable pixmap = glXCreatePixmap( display(), fbcdrawable[ \
QX11Info::appDepth() ], pix, NULL );  glXMakeContextCurrent( display(), pixmap, \
pixmap, ctxdrawable );  if( last_pixmap != None )
             glXDestroyPixmap( display(), last_pixmap );



_______________________________________________
Kwin mailing list
Kwin@kde.org
https://mail.kde.org/mailman/listinfo/kwin


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic