[Xfce4-commits] [xfce/xfwm4] 02/02: compositor: Add support for GLX

noreply at xfce.org noreply at xfce.org
Fri Apr 24 22:33:55 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 fee08eafa751a153ff93b04152ea66334141cac5
Author: Olivier Fourdan <fourdan at xfce.org>
Date:   Thu Apr 9 23:06:38 2015 +0200

    compositor: Add support for GLX
    
    Bug: 10439
    
    Using texture-from-pixmap extension.
    
    Signed-off-by: Olivier Fourdan <fourdan at xfce.org>
---
 src/compositor.c |  612 ++++++++++++++++++++++++++++++++++++++++++++----------
 src/screen.h     |   14 ++
 2 files changed, 517 insertions(+), 109 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 75d5ce2..4e1b100 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -26,7 +26,6 @@
 #include "config.h"
 #endif
 
-#include <sys/ioctl.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
@@ -868,7 +867,7 @@ root_tile (ScreenInfo *screen_info)
             memcpy (&pixmap, prop, 4);
             XFree (prop);
             pa.repeat = TRUE;
-            format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen_info->screen));
+            format = XRenderFindVisualFormat (dpy, screen_info->visual);
             g_return_val_if_fail (format != NULL, None);
             picture = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa);
             break;
@@ -912,16 +911,13 @@ create_root_buffer (ScreenInfo *screen_info, Pixmap pixmap)
     DisplayInfo *display_info;
     Picture pict;
     XRenderPictFormat *format;
-    Visual *visual;
 
     g_return_val_if_fail (screen_info != NULL, None);
     g_return_val_if_fail (pixmap != None, None);
     TRACE ("entering create_root_buffer");
 
     display_info = screen_info->display_info;
-    visual = DefaultVisual (display_info->dpy, screen_info->screen);
-
-    format = XRenderFindVisualFormat (display_info->dpy, visual);
+    format = XRenderFindVisualFormat (display_info->dpy, screen_info->visual);
     g_return_val_if_fail (format != NULL, None);
 
     pict = XRenderCreatePicture (display_info->dpy,
@@ -955,7 +951,7 @@ cursor_to_picture (ScreenInfo *screen_info, XFixesCursorImage *cursor)
     }
 
     ximage = XCreateImage (display_info->dpy,
-                           DefaultVisual(display_info->dpy, screen_info->screen),
+                           screen_info->visual,
                            32, ZPixmap, 0, (char *) data,
                            cursor->width, cursor->height, 32,
                            cursor->width * sizeof (guint32));
@@ -989,7 +985,7 @@ cursor_to_picture (ScreenInfo *screen_info, XFixesCursorImage *cursor)
     return picture;
 }
 
-#if HAVE_EPOXY
+#ifdef HAVE_EPOXY
 static gboolean
 vblank_enabled (ScreenInfo *screen_info)
 {
@@ -998,108 +994,296 @@ vblank_enabled (ScreenInfo *screen_info)
 }
 
 static gboolean
-vblank_init(ScreenInfo *screen_info)
+check_glx_renderer (ScreenInfo *screen_info)
 {
-    static int visual_attribs[] = {
+    const char *glRenderer;
+    const char *blacklisted[] = {
+        "Software Rasterizer",
+        "Mesa X11",
+        "llvmpipe",
+        NULL
+    };
+    int i;
+
+    g_return_val_if_fail (screen_info != NULL, FALSE);
+
+    TRACE ("entering check_glx_renderer");
+
+    glRenderer = (const char *) glGetString (GL_RENDERER);
+    if (glRenderer == NULL)
+    {
+        g_warning ("Cannot identify GLX renderer.");
+        return FALSE;
+    }
+
+    i = 0;
+    while (blacklisted[i] && !strcasestr (glRenderer, blacklisted[i]))
+        i++;
+    if (blacklisted[i])
+    {
+        g_warning ("Unsupported OpenGL renderer (%s).", glRenderer);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void
+init_glx_extensions (ScreenInfo *screen_info)
+{
+    g_return_if_fail (screen_info != NULL);
+
+    TRACE ("entering init_glx_extensions");
+
+    screen_info->has_glx_sync_control =
+        epoxy_has_glx_extension (myScreenGetXDisplay (screen_info),
+                                 screen_info->screen,
+                                 "GLX_OML_sync_control");
+
+    screen_info->has_glx_video_sync =
+        epoxy_has_glx_extension (myScreenGetXDisplay (screen_info),
+                                 screen_info->screen,
+                                 "GLX_SGI_video_sync");
+
+    screen_info->has_texture_from_pixmap =
+        epoxy_has_glx_extension (myScreenGetXDisplay (screen_info),
+                                 screen_info->screen,
+                                 "GLX_EXT_texture_from_pixmap");
+
+    screen_info->has_texture_rectangle =
+        epoxy_has_glx_extension (myScreenGetXDisplay (screen_info),
+                                 screen_info->screen,
+                                 "GL_ARB_texture_rectangle");
+
+    screen_info->has_texture_non_power_of_two =
+        epoxy_has_glx_extension (myScreenGetXDisplay (screen_info),
+                                 screen_info->screen,
+                                 "GL_ARB_texture_non_power_of_two");
+}
+
+static gboolean
+choose_glx_settings (ScreenInfo *screen_info)
+{
+    static GLint visual_attribs[] = {
+        GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT,
         GLX_X_RENDERABLE,  True,
-        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+        GLX_DOUBLEBUFFER,  True,
+        GLX_CONFIG_CAVEAT, GLX_NONE,
+        GLX_DEPTH_SIZE,    1,
+        GLX_ALPHA_SIZE,    1,
+        GLX_RED_SIZE,      1,
+        GLX_GREEN_SIZE,    1,
+        GLX_BLUE_SIZE,     1,
+        GLX_RENDER_TYPE,   GLX_RGBA_BIT,
         None
     };
-    int version;
+    GLint texture_target = 0;
+    GLint texture_format = 0;
+    gboolean texture_inverted = FALSE;
     int n_configs;
-    int i;
-    GLXFBConfig* configs, fb_config;
+    int i, value;
+    GLXFBConfig *configs, fb_config;
+    XVisualInfo *visual_info;
     gboolean fb_match;
     VisualID xvisual_id;
 
-    version = epoxy_glx_version (myScreenGetXDisplay (screen_info), screen_info->screen);
-    if (version < 13)
+    g_return_val_if_fail (screen_info != NULL, FALSE);
+
+    TRACE ("entering choose_glx_settings");
+
+    configs = glXChooseFBConfig (myScreenGetXDisplay (screen_info),
+                                 screen_info->screen,
+                                 visual_attribs,
+                                 &n_configs);
+    if (configs == NULL)
     {
-        g_warning ("GLX version %d is too old, vsync disabled.", version);
+        g_warning ("Cannot retrieve GLX frame buffer config.");
         return FALSE;
     }
 
-    configs = glXChooseFBConfig(myScreenGetXDisplay (screen_info),
-                                screen_info->screen,
-                                visual_attribs,
-                                &n_configs);
-    if (configs == NULL)
+    if (screen_info->has_texture_rectangle)
     {
-        g_warning ("Cannot retrieve frame buffer config, vsync disabled.");
-        return FALSE;
+        screen_info->texture_type = GL_TEXTURE_RECTANGLE_ARB;
+    }
+    else
+    {
+        screen_info->texture_type = GL_TEXTURE_2D;
     }
 
     fb_match = FALSE;
     xvisual_id = XVisualIDFromVisual (screen_info->visual);
     for (i = 0; i < n_configs; i++)
     {
-        XVisualInfo *visual_info;
-
         visual_info = glXGetVisualFromFBConfig (myScreenGetXDisplay (screen_info),
                                                 configs[i]);
-        if (visual_info == NULL)
+        if (!visual_info)
         {
             continue;
         }
-        if (visual_info->visualid == xvisual_id)
+
+        if (visual_info->visualid != xvisual_id)
         {
-            fb_config = configs[i];
-            fb_match = TRUE;
             XFree (visual_info);
-            break;
+            continue;
         }
-
         XFree (visual_info);
+
+        glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
+                              configs[i],
+                              GLX_DRAWABLE_TYPE, &value);
+
+        if (!(value & GLX_PIXMAP_BIT))
+        {
+            continue;
+        }
+
+        glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
+                              configs[i],
+                              GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+                              &value);
+
+        if (screen_info->texture_type == GL_TEXTURE_RECTANGLE_ARB)
+        {
+            if (value & GLX_TEXTURE_RECTANGLE_BIT_EXT)
+            {
+                texture_target = GLX_TEXTURE_RECTANGLE_EXT;
+            }
+            else
+            {
+                continue;
+            }
+        }
+        else if (screen_info->texture_type == GL_TEXTURE_2D)
+        {
+            if (value & GLX_TEXTURE_2D_BIT_EXT)
+            {
+                texture_target = GLX_TEXTURE_2D_EXT;
+            }
+            else
+            {
+                continue;
+            }
+        }
+        else
+        {
+            continue;
+        }
+
+        glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
+                              configs[i],
+                              GLX_BIND_TO_TEXTURE_RGB_EXT,
+                              &value);
+        if (!value)
+        {
+            continue;
+        }
+
+        texture_format = GLX_TEXTURE_FORMAT_RGB_EXT;
+
+        glXGetFBConfigAttrib (myScreenGetXDisplay (screen_info),
+                              configs[i],
+                              GLX_Y_INVERTED_EXT,
+                              &value);
+        if (value == TRUE)
+        {
+            texture_inverted = TRUE;
+        }
+
+        fb_config = configs[i];
+        fb_match = TRUE;
+        break;
     }
     XFree(configs);
 
     if (fb_match == FALSE)
     {
-        g_warning ("Cannot find a matching visual for the frame buffer config, vsync disabled.");
+        g_warning ("Cannot find a matching visual for the frame buffer config.");
         return FALSE;
     }
 
-    screen_info->has_glx_sync_control =
-        epoxy_has_glx_extension (myScreenGetXDisplay (screen_info),
-                                 screen_info->screen,
-                                 "GLX_OML_sync_control");
+    screen_info->texture_target = texture_target;
+    screen_info->texture_format = texture_format;
+    screen_info->texture_inverted = texture_inverted;
+    screen_info->glx_fbconfig = fb_config;
 
-    screen_info->has_glx_video_sync =
-        epoxy_has_glx_extension (myScreenGetXDisplay (screen_info),
-                                 screen_info->screen,
-                                 "GLX_SGI_video_sync");
+    return TRUE;
+}
+
+static gboolean
+init_glx (ScreenInfo *screen_info)
+{
+    int version;
 
+    g_return_val_if_fail (screen_info != NULL, FALSE);
+
+    TRACE ("entering init_glx");
+
+    version = epoxy_glx_version (myScreenGetXDisplay (screen_info), screen_info->screen);
+    if (version < 13)
+    {
+        g_warning ("GLX version %d is too old, GLX support disabled.", version);
+        return FALSE;
+    }
+
+    init_glx_extensions (screen_info);
     if (!screen_info->has_glx_video_sync && !screen_info->has_glx_sync_control)
     {
         g_warning ("Screen is missing required GLX extension, vsync disabled.");
+        /*
+         * Strictly speaking, we /could/ be using GLX without VSync support, but what
+         * would be the point? Chances are we'd be using swrast anyway...
+         */
+        return FALSE;
+    }
+
+    if (!choose_glx_settings (screen_info))
+    {
+        g_warning ("Cannot find a matching GLX config, vsync disabled.");
         return FALSE;
     }
 
-    screen_info->glx_context = glXCreateNewContext(myScreenGetXDisplay (screen_info),
-                                                   fb_config,
-                                                   GLX_RGBA_TYPE,
-                                                   0,
-                                                   TRUE);
+    screen_info->glx_context = glXCreateNewContext (myScreenGetXDisplay (screen_info),
+                                                    screen_info->glx_fbconfig,
+                                                    GLX_RGBA_TYPE,
+                                                    0,
+                                                    TRUE);
 
     screen_info->glx_window = glXCreateWindow (myScreenGetXDisplay (screen_info),
-                                               fb_config,
+                                               screen_info->glx_fbconfig,
                                                screen_info->output,
                                                NULL);
+    glXMakeCurrent (myScreenGetXDisplay (screen_info),
+                    screen_info->glx_window,
+                    screen_info->glx_context);
+
+    if (!check_glx_renderer (screen_info))
+    {
+        g_warning ("Screen is missing required OpenGL renderer, OpenGL support disabled.");
+
+        glXDestroyContext (myScreenGetXDisplay (screen_info), screen_info->glx_context);
+        screen_info->glx_context = None;
 
-    glXMakeContextCurrent (myScreenGetXDisplay (screen_info),
-                           screen_info->glx_window,
-                           screen_info->glx_window,
-                           screen_info->glx_context);
+        glXDestroyWindow (myScreenGetXDisplay (screen_info), screen_info->glx_window);
+        screen_info->glx_window = None;
+
+        return FALSE;
+    }
+
+    glLoadIdentity();
 
     return TRUE;
 }
 
 /* Following routine is taken from gdk GL context code by Alexander Larsson */
 static void
-wait_vblank (ScreenInfo *screen_info)
+wait_glx_vblank (ScreenInfo *screen_info)
 {
     guint32 current_count;
 
+    g_return_if_fail (screen_info != NULL);
+
+    TRACE ("entering wait_glx_vblank");
+
     if (screen_info->has_glx_sync_control)
     {
         gint64 ust, msc, sbc;
@@ -1118,6 +1302,135 @@ wait_vblank (ScreenInfo *screen_info)
         glXWaitVideoSyncSGI (2, (current_count + 1) % 2, &current_count);
     }
 }
+
+static GLXDrawable
+create_glx_drawable (ScreenInfo *screen_info, Pixmap pixmap)
+{
+    int pixmap_attribs[] = {
+        GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+        GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
+        None
+    };
+    GLXDrawable glx_drawable;
+
+    g_return_val_if_fail (screen_info != NULL, None);
+    g_return_val_if_fail (pixmap != None, None);
+
+    TRACE ("entering create_glx_drawable");
+
+    pixmap_attribs[1] = screen_info->texture_target;
+    pixmap_attribs[3] = screen_info->texture_format;
+
+    glx_drawable = glXCreatePixmap (myScreenGetXDisplay (screen_info),
+                                    screen_info->glx_fbconfig,
+                                    pixmap, pixmap_attribs);
+
+    return glx_drawable;
+}
+
+static void
+unbind_glx_texture (ScreenInfo *screen_info)
+{
+    g_return_if_fail (screen_info != NULL);
+
+    TRACE ("entering unbind_glx_texture");
+
+    if (screen_info->glx_drawable)
+    {
+        glXReleaseTexImageEXT (myScreenGetXDisplay (screen_info),
+                               screen_info->glx_drawable, GLX_FRONT_EXT);
+        glXDestroyPixmap(myScreenGetXDisplay (screen_info), screen_info->glx_drawable);
+        screen_info->glx_drawable = None;
+    }
+
+    if (screen_info->rootTexture)
+    {
+        glBindTexture (GL_TEXTURE_2D, None);
+        glDeleteTextures (1, &screen_info->rootTexture);
+        screen_info->rootTexture = None;
+    }
+}
+
+static void
+bind_glx_texture (ScreenInfo *screen_info, Pixmap pixmap)
+{
+    g_return_if_fail (screen_info != NULL);
+    g_return_if_fail (pixmap != None);
+
+    TRACE ("entering bind_glx_texture");
+
+    if (screen_info->rootTexture == None)
+    {
+        glGenTextures(1, &screen_info->rootTexture);
+    }
+
+    glBindTexture (GL_TEXTURE_2D, screen_info->rootTexture);
+
+    if (screen_info->glx_drawable == None)
+    {
+        screen_info->glx_drawable = create_glx_drawable (screen_info, pixmap);
+        glEnable(GL_TEXTURE_2D);
+    }
+    else
+    {
+        glXReleaseTexImageEXT (myScreenGetXDisplay (screen_info),
+                               screen_info->glx_drawable, GLX_FRONT_EXT);
+    }
+
+    glXBindTexImageEXT (myScreenGetXDisplay (screen_info),
+                        screen_info->glx_drawable, GLX_FRONT_EXT, NULL);
+
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, screen_info->texture_filter);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, screen_info->texture_filter);
+}
+
+static void
+redraw_glx_texture (ScreenInfo *screen_info)
+{
+    g_return_if_fail (screen_info != NULL);
+
+    TRACE ("entering redraw_glx_texture");
+
+    glPushMatrix();
+
+    if (screen_info->zoomed)
+    {
+        /* Reuse the values from the XRender matrix */
+        XFixed zf = screen_info->transform.matrix[0][0];
+        XFixed xp = screen_info->transform.matrix[0][2];
+        XFixed yp = screen_info->transform.matrix[1][2];
+
+        double zoom = XFixedToDouble (zf);
+        double x = (2.0 * XFixedToDouble (xp)) / screen_info->width - (1.0 - zoom);
+        double y = (2.0 * XFixedToDouble (yp)) / screen_info->height -  (1.0 - zoom);
+
+        glScaled(1.0 / zoom, 1.0 / zoom, 1.0);
+        glTranslated (-x, y, 0.0);
+    }
+    else
+    {
+        glScaled(1.0, 1.0, 1.0);
+        glTranslated (0.0, 0.0, 0.0);
+    }
+
+    glViewport(0, 0, screen_info->width, screen_info->height);
+
+    glBegin(GL_QUADS);
+    glTexCoord2f(0.0, screen_info->texture_inverted ? 1.0 : 0.0);
+    glVertex3f(-1.0,  1.0, 0.0);
+    glTexCoord2f(1.0, screen_info->texture_inverted ? 1.0 : 0.0);
+    glVertex3f( 1.0,  1.0, 0.0);
+    glTexCoord2f(1.0, screen_info->texture_inverted ? 0.0 : 1.0);
+    glVertex3f( 1.0, -1.0, 0.0);
+    glTexCoord2f(0.0, screen_info->texture_inverted ? 0.0 : 1.0);
+    glVertex3f(-1.0, -1.0, 0.0);
+    glEnd();
+
+    glPopMatrix();
+
+    glXSwapBuffers (myScreenGetXDisplay (screen_info),
+                    screen_info->glx_window);
+}
 #endif /* HAVE_EPOXY */
 
 #ifdef HAVE_PRESENT_EXTENSION
@@ -1126,6 +1439,12 @@ present_flip (ScreenInfo *screen_info, XserverRegion region, Pixmap pixmap)
 {
     static guint32 present_serial;
 
+    g_return_if_fail (screen_info != NULL);
+    g_return_if_fail (region != None);
+    g_return_if_fail (pixmap != None);
+
+    TRACE ("entering present_flip (serial %d)", present_serial);
+
     XPresentPixmap (myScreenGetXDisplay (screen_info), screen_info->output,
                     pixmap, present_serial++, None, region, 0, 0, None, None, None,
                     PresentOptionNone, 0, 1, 0, NULL, 0);
@@ -1527,16 +1846,16 @@ paint_all (ScreenInfo *screen_info, XserverRegion region, gushort buffer)
             create_root_buffer (screen_info, screen_info->rootPixmap[buffer]);
     }
 
-    if (screen_info->zoomBuffer == None)
+    if (screen_info->zoomed && !screen_info->use_glx)
     {
-        Pixmap pixmap;
+        if (screen_info->zoomBuffer == None)
+        {
+            Pixmap pixmap;
 
-        pixmap = create_root_pixmap (screen_info);
-        screen_info->zoomBuffer = create_root_buffer (screen_info, pixmap);
-        XFreePixmap (display_info->dpy, pixmap);
-    }
-    if (screen_info->zoomed)
-    {
+            pixmap = create_root_pixmap (screen_info);
+            screen_info->zoomBuffer = create_root_buffer (screen_info, pixmap);
+            XFreePixmap (display_info->dpy, pixmap);
+        }
         paint_buffer = screen_info->zoomBuffer;
     }
     else
@@ -1672,25 +1991,30 @@ paint_all (ScreenInfo *screen_info, XserverRegion region, gushort buffer)
     }
 
     TRACE ("Copying data back to screen");
-    if (screen_info->zoomed)
+    if (screen_info->use_glx)
     {
-        /* Fixme: copy back whole screen if zoomed
-           It would be better to scale the clipping region if possible. */
+        /* Set clipping back to the given region */
+        if (screen_info->zoomed)
+        {
+            paint_cursor (screen_info, region, screen_info->rootBuffer[buffer]);
+        }
         XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer[buffer],
-                                    0, 0, None);
-        paint_cursor (screen_info, region, screen_info->zoomBuffer);
-        XFixesSetPictureClipRegion (dpy, screen_info->zoomBuffer,
-                                    0, 0, None);
+                                    0, 0, region);
     }
     else
     {
-        /* Set clipping back to the given region */
         XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer[buffer],
-                                    0, 0, region);
+                                    0, 0, None);
+        if (screen_info->zoomed)
+        {
+            paint_cursor (screen_info, region, paint_buffer);
+            XFixesSetPictureClipRegion (dpy, paint_buffer,
+                                        0, 0, None);
+        }
     }
 
 #ifdef HAVE_PRESENT_EXTENSION
-    if (display_info->have_present)
+    if (screen_info->use_present) /* present first if available */
     {
         if (screen_info->zoomed)
         {
@@ -1701,20 +2025,38 @@ paint_all (ScreenInfo *screen_info, XserverRegion region, gushort buffer)
         }
         present_flip (screen_info, region, screen_info->rootPixmap[buffer]);
         screen_info->present_pending = TRUE;
+        DBG ("present flip requested, present pending...");
     }
     else
 #endif /* HAVE_PRESENT_EXTENSION */
-    {
 #ifdef HAVE_EPOXY
+    if (screen_info->use_glx) /* then glx if available */
+    {
+        XFlush (dpy);
         if (vblank_enabled (screen_info))
         {
-            XFlush (dpy);
-            wait_vblank (screen_info);
+            wait_glx_vblank (screen_info);
         }
+        bind_glx_texture (screen_info,
+                          screen_info->rootPixmap[buffer]);
+        redraw_glx_texture (screen_info);
+    }
+    else
 #endif /* HAVE_EPOXY */
-        XRenderComposite (dpy, PictOpSrc, paint_buffer,
-                          None, screen_info->rootPicture,
-                          0, 0, 0, 0, 0, 0, screen_width, screen_height);
+    {
+        if (screen_info->zoomed)
+        {
+            XRenderComposite (dpy, PictOpSrc,
+                              screen_info->zoomBuffer,
+                              None,  screen_info->rootPicture,
+                              0, 0, 0, 0, 0, 0, screen_width, screen_height);
+        }
+        else
+        {
+            XRenderComposite (dpy, PictOpSrc, paint_buffer,
+                              None, screen_info->rootPicture,
+                              0, 0, 0, 0, 0, 0, screen_width, screen_height);
+        }
         XFlush (dpy);
     }
 
@@ -1750,7 +2092,7 @@ repair_screen (ScreenInfo *screen_info)
     if (screen_info->allDamage)
     {
 #ifdef HAVE_PRESENT_EXTENSION
-        if (display_info->have_present)
+        if (screen_info->use_present)
         {
             if (!screen_info->present_pending)
             {
@@ -2637,7 +2979,6 @@ recenter_zoomed_area (ScreenInfo *screen_info, int x_root, int y_root)
 {
     int zf = screen_info->transform.matrix[0][0];
     double zoom = XFixedToDouble (zf);
-    Display *dpy = screen_info->display_info->dpy;
 
     if (screen_info->zoomed)
     {
@@ -2648,11 +2989,26 @@ recenter_zoomed_area (ScreenInfo *screen_info, int x_root, int y_root)
     }
 
     if (zf > (1 << 14) && zf < (1 << 16))
-        XRenderSetPictureFilter (dpy, screen_info->zoomBuffer, FilterBilinear, NULL, 0);
+    {
+        XRenderSetPictureFilter (myScreenGetXDisplay (screen_info),
+                                 screen_info->zoomBuffer,
+                                 FilterBilinear, NULL, 0);
+#ifdef HAVE_EPOXY
+        screen_info->texture_filter = GL_LINEAR;
+#endif /* HAVE_EPOXY */
+    }
     else
-        XRenderSetPictureFilter (dpy, screen_info->zoomBuffer, FilterNearest, NULL, 0);
-
-    XRenderSetPictureTransform (dpy, screen_info->zoomBuffer, &screen_info->transform);
+    {
+        XRenderSetPictureFilter (myScreenGetXDisplay (screen_info),
+                                 screen_info->zoomBuffer,
+                                 FilterNearest, NULL, 0);
+#ifdef HAVE_EPOXY
+        screen_info->texture_filter = GL_NEAREST;
+#endif /* HAVE_EPOXY */
+    }
+    XRenderSetPictureTransform (myScreenGetXDisplay (screen_info),
+                                screen_info->zoomBuffer,
+                                &screen_info->transform);
 
     damage_screen (screen_info);
 }
@@ -2668,6 +3024,14 @@ zoom_timeout_cb (gpointer data)
     if (!screen_info->zoomed)
     {
         screen_info->zoom_timeout_id = 0;
+
+        if (screen_info->zoomBuffer)
+        {
+            XRenderFreePicture (myScreenGetXDisplay (screen_info),
+                                screen_info->zoomBuffer);
+            screen_info->zoomBuffer = None;
+        }
+
         return FALSE; /* stop calling this callback */
     }
 
@@ -3061,6 +3425,7 @@ compositorHandlePresentCompleteNotify (DisplayInfo *display_info, XPresentComple
         screen_info = (ScreenInfo *) list->data;
         if (screen_info->output == ev->window)
         {
+             DBG ("present completed, present pending cleared");
              screen_info->present_pending = FALSE;
              break;
         }
@@ -3602,9 +3967,9 @@ compositorInitDisplay (DisplayInfo *display_info)
 
 #ifdef HAVE_PRESENT_EXTENSION
     if (!XPresentQueryExtension (display_info->dpy,
-                            &display_info->present_opcode,
-                            &display_info->present_event_base,
-                            &display_info->present_error_base))
+                                 &display_info->present_opcode,
+                                 &display_info->present_event_base,
+                                 &display_info->present_error_base))
     {
         g_warning ("The display does not support the XPresent extension.");
         display_info->have_present = FALSE;
@@ -3780,19 +4145,35 @@ compositorManageScreen (ScreenInfo *screen_info)
     XClearArea (display_info->dpy, screen_info->output, 0, 0, 0, 0, TRUE);
     TRACE ("Manual compositing enabled");
 
-#ifdef HAVE_EPOXY
-    screen_info->glx_context = None;
-    screen_info->glx_window = None;
-    vblank_init (screen_info);
-#endif /* HAVE_EPOXY */
-
 #ifdef HAVE_PRESENT_EXTENSION
-    screen_info->present_pending = FALSE;
-    XPresentSelectInput (display_info->dpy,
-                         screen_info->output,
-                         PresentCompleteNotifyMask);
+    /* Prefer present over glx if available (it's faster on my hardware) */
+    screen_info->use_present = display_info->have_present;
+    if (screen_info->use_present)
+    {
+        screen_info->present_pending = FALSE;
+        XPresentSelectInput (display_info->dpy,
+                             screen_info->output,
+                             PresentCompleteNotifyMask);
+    }
+#else /* HAVE_PRESENT_EXTENSION */
+    screen_info->use_present = FALSE;
 #endif /* HAVE_PRESENT_EXTENSION */
 
+#ifdef HAVE_EPOXY
+    screen_info->use_glx = !screen_info->use_present;
+    if (screen_info->use_glx)
+    {
+        screen_info->glx_context = None;
+        screen_info->glx_window = None;
+        screen_info->rootTexture = None;
+        screen_info->glx_drawable = None;
+        screen_info->texture_filter = GL_LINEAR;
+        screen_info->use_glx = init_glx (screen_info);
+    }
+#else /* HAVE_EPOXY */
+    screen_info->use_glx = FALSE;
+#endif /* HAVE_EPOXY */
+
     XFixesSelectCursorInput (display_info->dpy,
                              screen_info->xroot,
                              XFixesDisplayCursorNotifyMask);
@@ -3854,6 +4235,25 @@ compositorUnmanageScreen (ScreenInfo *screen_info)
     }
 #endif /* HAVE_OVERLAYS */
 
+#ifdef HAVE_EPOXY
+    if (screen_info->use_glx)
+    {
+        unbind_glx_texture (screen_info);
+    }
+
+    if (screen_info->glx_context)
+    {
+        glXDestroyContext (display_info->dpy, screen_info->glx_context);
+        screen_info->glx_context = None;
+    }
+
+    if (screen_info->glx_window)
+    {
+        glXDestroyWindow (display_info->dpy, screen_info->glx_window);
+        screen_info->glx_window = None;
+    }
+#endif /* HAVE_EPOXY */
+
     for (buffer = 0; buffer < 2; buffer++)
     {
         if (screen_info->rootPixmap[buffer])
@@ -3921,20 +4321,6 @@ compositorUnmanageScreen (ScreenInfo *screen_info)
         screen_info->gaussianMap = NULL;
     }
 
-#ifdef HAVE_EPOXY
-    if (screen_info->glx_context)
-    {
-        glXDestroyContext (display_info->dpy, screen_info->glx_context);
-        screen_info->glx_context = None;
-    }
-
-    if (screen_info->glx_window)
-    {
-        glXDestroyWindow (display_info->dpy, screen_info->glx_window);
-        screen_info->glx_window = None;
-    }
-#endif /* HAVE_EPOXY */
-
     screen_info->gaussianSize = -1;
     screen_info->wins_unredirected = 0;
 
@@ -4048,6 +4434,13 @@ compositorUpdateScreenSize (ScreenInfo *screen_info)
         screen_info->zoomBuffer = None;
     }
 
+#ifdef HAVE_EPOXY
+    if (screen_info->use_glx)
+    {
+        unbind_glx_texture (screen_info);
+    }
+#endif /* HAVE_EPOXY */
+
     for (buffer = 0; buffer < 2; buffer++)
     {
         if (screen_info->rootPixmap[buffer])
@@ -4061,6 +4454,7 @@ compositorUpdateScreenSize (ScreenInfo *screen_info)
             screen_info->rootBuffer[buffer] = None;
         }
     }
+
     damage_screen (screen_info);
 #endif /* HAVE_COMPOSITOR */
 }
diff --git a/src/screen.h b/src/screen.h
index c14bded..d92f8ad 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -203,10 +203,24 @@ struct _ScreenInfo
     XTransform transform;
     gboolean zoomed;
     guint zoom_timeout_id;
+    gboolean use_glx;
+    gboolean use_present;
 
 #ifdef HAVE_EPOXY
     gboolean has_glx_sync_control;
     gboolean has_glx_video_sync;
+    gboolean has_texture_from_pixmap;
+    gboolean has_texture_rectangle;
+    gboolean has_texture_non_power_of_two;
+    gboolean texture_inverted;
+
+    GLuint rootTexture;
+    GLenum texture_format;
+    GLenum texture_target;
+    GLenum texture_type;
+    GLfloat texture_filter;
+    GLXDrawable glx_drawable;
+    GLXFBConfig glx_fbconfig;
     GLXContext glx_context;
     GLXWindow glx_window;
 #endif /* HAVE_EPOXY */

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


More information about the Xfce4-commits mailing list