[Xfce4-commits] [xfce/xfwm4] 03/03: compositor: Improve GLX support

noreply at xfce.org noreply at xfce.org
Mon Jun 15 21:39:17 CEST 2015


This is an automated email from the git hooks/post-receive script.

olivier pushed a commit to branch master
in repository xfce/xfwm4.

commit 8a67212860898ef02fee79f64fc774bc14ed769c
Author: Olivier Fourdan <fourdan at xfce.org>
Date:   Mon Jun 15 21:27:42 2015 +0200

    compositor: Improve GLX support
    
    Bug: 10439
    
    - Check for GL errors,
    - Add detailed logs,
    - Disable Y inverted support (needs clarification, for NVidia
      proprietary driver support)),
    - Do not enforce ARGB FB config (for NVidia proprietary driver support)
    - Make sure to call glXWaitX() between each frame draw (for NVidia
      proprietary driver support)
    
    Signed-off-by: Olivier Fourdan <fourdan at xfce.org>
---
 src/compositor.c |  341 +++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 246 insertions(+), 95 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index c43d2a0..a0ff4fd 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -179,6 +179,30 @@ find_cwindow_in_display (DisplayInfo *display_info, Window id)
 }
 
 static gboolean
+is_output (DisplayInfo *display_info, Window id)
+{
+    GSList *list;
+
+    g_return_val_if_fail (id != None, FALSE);
+    g_return_val_if_fail (display_info != NULL, FALSE);
+    TRACE ("entering is_output");
+
+    for (list = display_info->screens; list; list = g_slist_next (list))
+    {
+        ScreenInfo *screen_info = (ScreenInfo *) list->data;
+#if HAVE_OVERLAYS
+        if (id == screen_info->output || id == screen_info->overlay)
+#else
+        if (id == screen_info->output)
+#endif
+        {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static gboolean
 is_shaped (DisplayInfo *display_info, Window id)
 {
     int xws, yws, xbs, ybs;
@@ -891,18 +915,11 @@ root_tile (ScreenInfo *screen_info)
 static Pixmap
 create_root_pixmap (ScreenInfo *screen_info)
 {
-    Pixmap pixmap;
-    gint depth;
-
-    depth = DefaultDepth (myScreenGetXDisplay (screen_info),
-                          screen_info->screen);
-
-    pixmap = XCreatePixmap (myScreenGetXDisplay (screen_info),
-                            screen_info->xroot,
-                            screen_info->width,
-                            screen_info->height, depth);
-
-    return pixmap;
+    return XCreatePixmap (myScreenGetXDisplay (screen_info),
+                          screen_info->xroot,
+                          screen_info->width,
+                          screen_info->height,
+                          screen_info->depth);
 }
 
 static Picture
@@ -987,6 +1004,42 @@ cursor_to_picture (ScreenInfo *screen_info, XFixesCursorImage *cursor)
 
 #ifdef HAVE_EPOXY
 static gboolean
+check_gl_error (void)
+{
+    GLenum error;
+    gboolean clean = TRUE;
+
+     error = glGetError();
+     while (error != GL_NO_ERROR);
+     {
+        clean = FALSE;
+        switch (error)
+        {
+            case GL_INVALID_ENUM:
+                g_warning ("GL error: Invalid enum");
+                break;
+            case GL_INVALID_VALUE:
+                g_warning ("GL error: Invalid value");
+                break;
+            case GL_INVALID_OPERATION:
+                g_warning ("GL error: Invalid operation");
+                break;
+            case GL_INVALID_FRAMEBUFFER_OPERATION:
+                g_warning ("GL error: Invalid frame buffer operation");
+                break;
+            case GL_OUT_OF_MEMORY:
+                g_warning ("GL error: Out of memory");
+                break;
+            default:
+                break;
+        }
+        error = glGetError();
+    }
+
+    return clean;
+}
+
+static gboolean
 vblank_enabled (ScreenInfo *screen_info)
 {
     return (screen_info->params->sync_to_vblank &&
@@ -1068,9 +1121,8 @@ choose_glx_settings (ScreenInfo *screen_info)
         GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT,
         GLX_X_RENDERABLE,  True,
         GLX_DOUBLEBUFFER,  True,
-        GLX_CONFIG_CAVEAT, GLX_NONE,
+        GLX_CONFIG_CAVEAT, GLX_DONT_CARE,
         GLX_DEPTH_SIZE,    1,
-        GLX_ALPHA_SIZE,    1,
         GLX_RED_SIZE,      1,
         GLX_GREEN_SIZE,    1,
         GLX_BLUE_SIZE,     1,
@@ -1080,8 +1132,8 @@ choose_glx_settings (ScreenInfo *screen_info)
     GLint texture_target = 0;
     GLint texture_format = 0;
     gboolean texture_inverted = FALSE;
-    int n_configs;
-    int i, value;
+    int n_configs, i;
+    int value, status;
     GLXFBConfig *configs, fb_config;
     XVisualInfo *visual_info;
     gboolean fb_match;
@@ -1103,10 +1155,12 @@ choose_glx_settings (ScreenInfo *screen_info)
 
     if (screen_info->has_texture_rectangle)
     {
+        DBG ("Using texture type GL_TEXTURE_RECTANGLE_ARB");
         screen_info->texture_type = GL_TEXTURE_RECTANGLE_ARB;
     }
     else
     {
+        DBG ("Using texture type GL_TEXTURE_2D");
         screen_info->texture_type = GL_TEXTURE_2D;
     }
 
@@ -1118,38 +1172,48 @@ choose_glx_settings (ScreenInfo *screen_info)
                                                 configs[i]);
         if (!visual_info)
         {
+            DBG ("%i/%i: no visual info, skipped", i + 1, n_configs);
             continue;
         }
 
         if (visual_info->visualid != xvisual_id)
         {
+            DBG ("%i/%i: xvisual id 0x%lx != 0x%lx, skipped", i + 1, n_configs, visual_info->visualid, xvisual_id);
             XFree (visual_info);
             continue;
         }
         XFree (visual_info);
 
-        glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
-                              configs[i],
-                              GLX_DRAWABLE_TYPE, &value);
+        status = glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
+                                       configs[i],
+                                       GLX_DRAWABLE_TYPE, &value);
 
-        if (!(value & GLX_PIXMAP_BIT))
+        if (status != Success || !(value & GLX_PIXMAP_BIT))
         {
+            DBG ("%i/%i: No GLX_PIXMAP_BIT, skipped", i + 1, n_configs);
             continue;
         }
 
-        glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
-                              configs[i],
-                              GLX_BIND_TO_TEXTURE_TARGETS_EXT,
-                              &value);
+        status = glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
+                                       configs[i],
+                                       GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+                                       &value);
+        if (status != Success)
+        {
+            DBG ("%i/%i: No GLX_BIND_TO_TEXTURE_TARGETS_EXT, skipped", i + 1, n_configs);
+            continue;
+        }
 
         if (screen_info->texture_type == GL_TEXTURE_RECTANGLE_ARB)
         {
             if (value & GLX_TEXTURE_RECTANGLE_BIT_EXT)
             {
                 texture_target = GLX_TEXTURE_RECTANGLE_EXT;
+                DBG ("Using texture target GLX_TEXTURE_RECTANGLE_EXT");
             }
             else
             {
+                DBG ("%i/%i: No GLX_TEXTURE_RECTANGLE_BIT_EXT, skipped", i + 1, n_configs);
                 continue;
             }
         }
@@ -1158,37 +1222,57 @@ choose_glx_settings (ScreenInfo *screen_info)
             if (value & GLX_TEXTURE_2D_BIT_EXT)
             {
                 texture_target = GLX_TEXTURE_2D_EXT;
+                DBG ("Using texture target GLX_TEXTURE_2D_EXT");
             }
             else
             {
+                DBG ("%i/%i: No GLX_TEXTURE_2D_BIT_EXT, skipped", i + 1, n_configs);
                 continue;
             }
         }
         else
         {
+            DBG ("%i/%i: No GLX_TEXTURE_*_BIT_EXT, skipped", i + 1, n_configs);
             continue;
         }
 
-        glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
-                              configs[i],
-                              GLX_BIND_TO_TEXTURE_RGB_EXT,
-                              &value);
-        if (!value)
+        status = glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
+                                       configs[i],
+                                       GLX_BIND_TO_TEXTURE_RGBA_EXT,
+                                       &value);
+        if (status == Success && value == TRUE)
         {
-            continue;
+            texture_format = GLX_TEXTURE_FORMAT_RGBA_EXT;
+            DBG ("Using texture format GLX_TEXTURE_FORMAT_RGBA_EXT");
         }
-
-        texture_format = GLX_TEXTURE_FORMAT_RGB_EXT;
-
-        glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
-                              configs[i],
-                              GLX_Y_INVERTED_EXT,
-                              &value);
-        if (value == TRUE)
+        else
         {
-            texture_inverted = TRUE;
+            status = glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
+                                           configs[i],
+                                           GLX_BIND_TO_TEXTURE_RGB_EXT,
+                                           &value);
+            if (status == Success && value == TRUE)
+            {
+                DBG ("Using texture format GLX_TEXTURE_FORMAT_RGB_EXT");
+                texture_format = GLX_TEXTURE_FORMAT_RGB_EXT;
+            }
+            else
+            {
+                DBG ("%i/%i: No GLX_BIND_TO_TEXTURE_RGB/RGBA_EXT, skipped", i + 1, n_configs);
+                continue;
+            }
         }
-
+#if 0
+        status = glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
+                                       configs[i],
+                                       GLX_Y_INVERTED_EXT,
+                                       &value);
+        texture_inverted = (status == Success && value == True);
+        if (texture_inverted)
+        {
+            DBG ("Using texture attribute GLX_Y_INVERTED_EXT");
+        }
+#endif
         fb_config = configs[i];
         fb_match = TRUE;
         break;
@@ -1200,7 +1284,8 @@ choose_glx_settings (ScreenInfo *screen_info)
         g_warning ("Cannot find a matching visual for the frame buffer config.");
         return FALSE;
     }
-
+    DBG ("Selected texture target 0x%x format 0x%x (%s)", texture_target,
+         texture_format, texture_inverted ? "inverted" : "non inverted");
     screen_info->texture_target = texture_target;
     screen_info->texture_format = texture_format;
     screen_info->texture_inverted = texture_inverted;
@@ -1219,6 +1304,7 @@ init_glx (ScreenInfo *screen_info)
     TRACE ("entering init_glx");
 
     version = epoxy_glx_version (myScreenGetXDisplay (screen_info), screen_info->screen);
+    DBG ("Using GLX version %d", version);
     if (version < 13)
     {
         g_warning ("GLX version %d is too old, GLX support disabled.", version);
@@ -1247,14 +1333,29 @@ init_glx (ScreenInfo *screen_info)
                                                     GLX_RGBA_TYPE,
                                                     0,
                                                     TRUE);
+    if (!screen_info->glx_context)
+    {
+        g_warning ("Could not create GLX context.");
+        return FALSE;
+    }
 
     screen_info->glx_window = glXCreateWindow (myScreenGetXDisplay (screen_info),
                                                screen_info->glx_fbconfig,
                                                screen_info->output,
                                                NULL);
-    glXMakeCurrent (myScreenGetXDisplay (screen_info),
-                    screen_info->glx_window,
-                    screen_info->glx_context);
+    if (!screen_info->glx_window)
+    {
+        g_warning ("Could not create GLX window.");
+        return FALSE;
+    }
+
+    if (!glXMakeCurrent (myScreenGetXDisplay (screen_info),
+                         screen_info->glx_window,
+                         screen_info->glx_context))
+    {
+        g_warning ("Could not make OpenGL context current.");
+        return FALSE;
+    }
 
     if (!check_glx_renderer (screen_info))
     {
@@ -1262,14 +1363,21 @@ init_glx (ScreenInfo *screen_info)
 
         glXDestroyContext (myScreenGetXDisplay (screen_info), screen_info->glx_context);
         screen_info->glx_context = None;
-
-        glXDestroyWindow (myScreenGetXDisplay (screen_info), screen_info->glx_window);
-        screen_info->glx_window = None;
-
+        if (screen_info->glx_window)
+        {
+            glXDestroyWindow (myScreenGetXDisplay (screen_info), screen_info->glx_window);
+            screen_info->glx_window = None;
+        }
         return FALSE;
     }
 
+    glDisable(GL_DEPTH_TEST);
+    glDepthMask(GL_FALSE);
+    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    glDisable(GL_BLEND);
+
     glLoadIdentity();
+    check_gl_error();
 
     return TRUE;
 }
@@ -1324,11 +1432,36 @@ create_glx_drawable (ScreenInfo *screen_info, Pixmap pixmap)
     glx_drawable = glXCreatePixmap (myScreenGetXDisplay (screen_info),
                                     screen_info->glx_fbconfig,
                                     pixmap, pixmap_attribs);
+    check_gl_error();
+    TRACE ("Created GLX pixmap 0x%lx from Pixmap 0x%lx", glx_drawable, pixmap);
 
     return glx_drawable;
 }
 
 static void
+enable_glx_texture (ScreenInfo *screen_info)
+{
+    g_return_if_fail (screen_info != NULL);
+
+    TRACE ("entering enable_glx_texture");
+
+    glBindTexture(screen_info->texture_type, screen_info->rootTexture);
+    glEnable(screen_info->texture_type);
+}
+
+
+static void
+disable_glx_texture (ScreenInfo *screen_info)
+{
+    g_return_if_fail (screen_info != NULL);
+
+    TRACE ("entering disable_glx_texture");
+
+    glBindTexture(screen_info->texture_type, None);
+    glDisable(screen_info->texture_type);
+}
+
+static void
 unbind_glx_texture (ScreenInfo *screen_info)
 {
     g_return_if_fail (screen_info != NULL);
@@ -1337,6 +1470,7 @@ unbind_glx_texture (ScreenInfo *screen_info)
 
     if (screen_info->glx_drawable)
     {
+        TRACE ("Unbinding GLX drawable 0x%lx", screen_info->glx_drawable);
         glXReleaseTexImageEXT (myScreenGetXDisplay (screen_info),
                                screen_info->glx_drawable, GLX_FRONT_EXT);
         glXDestroyPixmap(myScreenGetXDisplay (screen_info), screen_info->glx_drawable);
@@ -1345,10 +1479,11 @@ unbind_glx_texture (ScreenInfo *screen_info)
 
     if (screen_info->rootTexture)
     {
-        glBindTexture (screen_info->texture_type, None);
+        disable_glx_texture (screen_info);
         glDeleteTextures (1, &screen_info->rootTexture);
         screen_info->rootTexture = None;
     }
+    check_gl_error();
 }
 
 static void
@@ -1362,30 +1497,26 @@ bind_glx_texture (ScreenInfo *screen_info, Pixmap pixmap)
     if (screen_info->rootTexture == None)
     {
         glGenTextures(1, &screen_info->rootTexture);
+        TRACE ("Generated texture 0x%x", screen_info->rootTexture);
     }
-
-    glBindTexture (screen_info->texture_type, screen_info->rootTexture);
-
     if (screen_info->glx_drawable == None)
     {
         screen_info->glx_drawable = create_glx_drawable (screen_info, pixmap);
-        glEnable(screen_info->texture_type);
-    }
-    else
-    {
-        glXReleaseTexImageEXT (myScreenGetXDisplay (screen_info),
-                               screen_info->glx_drawable, GLX_FRONT_EXT);
     }
 
+    TRACE ("(Re)Binding GLX pixmap 0x%lx to texture 0x%x",
+           screen_info->glx_drawable, screen_info->rootTexture);
+    enable_glx_texture (screen_info);
     glXBindTexImageEXT (myScreenGetXDisplay (screen_info),
                         screen_info->glx_drawable, GLX_FRONT_EXT, NULL);
-
-    glTexParameterf(screen_info->texture_type,
+    glTexParameteri(screen_info->texture_type,
                     GL_TEXTURE_MIN_FILTER,
                     screen_info->texture_filter);
-    glTexParameterf(screen_info->texture_type,
+    glTexParameteri(screen_info->texture_type,
                     GL_TEXTURE_MAG_FILTER,
                     screen_info->texture_filter);
+
+    check_gl_error();
 }
 
 static void
@@ -1394,7 +1525,8 @@ redraw_glx_texture (ScreenInfo *screen_info)
     g_return_if_fail (screen_info != NULL);
 
     TRACE ("entering redraw_glx_texture");
-
+    TRACE ("(Re)Drawing GLX pixmap 0x%lx/texture 0x%x",
+           screen_info->glx_drawable, screen_info->rootTexture);
     glPushMatrix();
 
     if (screen_info->zoomed)
@@ -1434,6 +1566,15 @@ redraw_glx_texture (ScreenInfo *screen_info)
 
     glXSwapBuffers (myScreenGetXDisplay (screen_info),
                     screen_info->glx_window);
+
+    disable_glx_texture (screen_info);
+
+    TRACE ("Releasing bind GLX pixmap 0x%lx to texture 0x%x",
+           screen_info->glx_drawable, screen_info->rootTexture);
+    glXReleaseTexImageEXT (myScreenGetXDisplay (screen_info),
+                           screen_info->glx_drawable, GLX_FRONT_EXT);
+
+    check_gl_error();
 }
 #endif /* HAVE_EPOXY */
 
@@ -2019,7 +2160,7 @@ paint_all (ScreenInfo *screen_info, XserverRegion region, gushort buffer)
 #ifdef HAVE_EPOXY
     if (screen_info->use_glx) /* glx first if available */
     {
-        XFlush (dpy);
+        glXWaitX ();
         if (vblank_enabled (screen_info))
         {
             wait_glx_vblank (screen_info);
@@ -2597,6 +2738,12 @@ add_win (DisplayInfo *display_info, Window id, Client *c)
 
     TRACE ("entering add_win: 0x%lx", id);
 
+    if (is_output (display_info, id))
+    {
+        TRACE ("Not adding output window 0x%lx", id);
+        return;
+    }
+
     new = find_cwindow_in_display (display_info, id);
     if (new)
     {
@@ -2660,11 +2807,7 @@ add_win (DisplayInfo *display_info, Window id, Client *c)
     new->shaped = is_shaped (display_info, id);
     new->viewable = (new->attr.map_state == IsViewable);
 
-    if ((new->attr.class != InputOnly)
-#if HAVE_OVERLAYS
-         && ((!display_info->have_overlays) || (id != screen_info->overlay))
-#endif
-         && (id != screen_info->output))
+    if (new->attr.class != InputOnly)
     {
         new->damage = XDamageCreate (display_info->dpy, id, XDamageReportNonEmpty);
     }
@@ -4058,25 +4201,6 @@ compositorManageScreen (ScreenInfo *screen_info)
 
     compositorSetCMSelection (screen_info, screen_info->xfwm4_win);
     display_info = screen_info->display_info;
-    XCompositeRedirectSubwindows (display_info->dpy, screen_info->xroot, display_info->composite_mode);
-    screen_info->compositor_active = TRUE;
-
-    if (display_info->composite_mode == CompositeRedirectAutomatic)
-    {
-        /* That's enough for automatic compositing */
-        TRACE ("Automatic compositing enabled");
-        return TRUE;
-    }
-
-    visual_format = XRenderFindVisualFormat (display_info->dpy,
-                                             DefaultVisual (display_info->dpy,
-                                                            screen_info->screen));
-    if (!visual_format)
-    {
-        g_warning ("Cannot find visual format on screen %i", screen_info->screen);
-        compositorUnmanageScreen (screen_info);
-        return FALSE;
-    }
 
     screen_info->output = screen_info->xroot;
 #if HAVE_OVERLAYS
@@ -4085,28 +4209,55 @@ compositorManageScreen (ScreenInfo *screen_info)
         screen_info->overlay = XCompositeGetOverlayWindow (display_info->dpy, screen_info->xroot);
         if (screen_info->overlay != None)
         {
+            XserverRegion region;
             XSetWindowAttributes attributes;
 
+            XMapRaised (display_info->dpy, screen_info->overlay);
+
+            region = XFixesCreateRegion (display_info->dpy, NULL, 0);
+            XFixesSetWindowShapeRegion (display_info->dpy, screen_info->overlay,
+                                        ShapeBounding, 0, 0, 0);
+            XFixesSetWindowShapeRegion (display_info->dpy, screen_info->overlay,
+                                        ShapeInput, 0, 0, region);
+            XFixesDestroyRegion (display_info->dpy, region);
+
             screen_info->root_overlay = XCreateWindow (display_info->dpy, screen_info->overlay,
                                                        0, 0, screen_info->width, screen_info->height, 0, screen_info->depth,
                                                        InputOutput, screen_info->visual, 0, &attributes);
-            XMapWindow (display_info->dpy, screen_info->root_overlay);
-            XRaiseWindow (display_info->dpy, screen_info->overlay);
-            XShapeCombineRectangles (display_info->dpy, screen_info->overlay,
-                                     ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
-            XShapeCombineRectangles (display_info->dpy, screen_info->root_overlay,
-                                     ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
+            XMapRaised (display_info->dpy, screen_info->root_overlay);
+
             screen_info->output = screen_info->root_overlay;
-            TRACE ("Overlay enabled");
+            DBG ("Overlay enabled (0x%lx -> 0x%lx)", screen_info->overlay, screen_info->root_overlay);
         }
         else
         {
             /* Something is wrong with overlay support */
-            TRACE ("Cannot get root window overlay, overlay support disabled");
+            DBG ("Cannot get root window overlay, overlay support disabled");
             display_info->have_overlays = FALSE;
         }
     }
 #endif /* HAVE_OVERLAYS */
+    DBG ("Window used for output: 0x%lx (%s)", screen_info->output, display_info->have_overlays ? "overlay" : "root");
+
+    XCompositeRedirectSubwindows (display_info->dpy, screen_info->xroot, display_info->composite_mode);
+    screen_info->compositor_active = TRUE;
+
+    if (display_info->composite_mode == CompositeRedirectAutomatic)
+    {
+        /* That's enough for automatic compositing */
+        TRACE ("Automatic compositing enabled");
+        return TRUE;
+    }
+
+    visual_format = XRenderFindVisualFormat (display_info->dpy,
+                                             DefaultVisual (display_info->dpy,
+                                                            screen_info->screen));
+    if (!visual_format)
+    {
+        g_warning ("Cannot find visual format on screen %i", screen_info->screen);
+        compositorUnmanageScreen (screen_info);
+        return FALSE;
+    }
 
     pa.subwindow_mode = IncludeInferiors;
     screen_info->rootPicture = XRenderCreatePicture (display_info->dpy, screen_info->output,

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list