[Xfce4-commits] [xfce/xfwm4] 01/01: Use XRender for scaling down window pixmaps

noreply at xfce.org noreply at xfce.org
Thu Feb 5 21:59:17 CET 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 6a7aff593d752da525aba0098572a2d9d20d0e86
Author: Olivier Fourdan <fourdan at xfce.org>
Date:   Thu Feb 5 21:24:49 2015 +0100

    Use XRender for scaling down window pixmaps
    
    Instead of GdkPixbuf routines, although GdkPixbuf gives much better
    results that XRender, using XRender is much faster on some hardware.
    
    Also add the application icon to the preview compensate the lower
    quality.
    
    Signed-off-by: Olivier Fourdan <fourdan at xfce.org>
---
 src/compositor.c |  111 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 src/compositor.h |    6 ++-
 src/icons.c      |   46 +++++++++++++++++++---
 3 files changed, 147 insertions(+), 16 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 5af29ce..bf3fee9 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -2476,9 +2476,9 @@ recenter_zoomed_area (ScreenInfo *screen_info, int x_root, int y_root)
     }
 
     if (zf > (1 << 14) && zf < (1 << 16))
-        XRenderSetPictureFilter (dpy, screen_info->rootBuffer, "bilinear", NULL, 0);
+        XRenderSetPictureFilter (dpy, screen_info->rootBuffer, FilterBilinear, NULL, 0);
     else
-        XRenderSetPictureFilter (dpy, screen_info->rootBuffer, "nearest", NULL, 0);
+        XRenderSetPictureFilter (dpy, screen_info->rootBuffer, FilterNearest, NULL, 0);
 
     XRenderSetPictureTransform (dpy, screen_info->rootBuffer, &screen_info->transform);
 
@@ -3038,6 +3038,104 @@ compositorWindowPixmapAvailable (ScreenInfo *screen_info)
     return FALSE;
 }
 
+static Pixmap
+compositorScaleWindowPixmap (CWindow *cw, guint *width, guint *height)
+{
+    Display *dpy;
+    ScreenInfo *screen_info;
+    Picture srcPicture, destPicture;
+    Pixmap source, pixmap;
+    XTransform transform;
+    XRenderPictFormat *render_format;
+    double scale;
+    int x, y, src_size, dest_size;
+    unsigned int source_w, source_h;
+    unsigned int dest_w, dest_h;
+    XRenderColor c = { 0, 0, 0, 0 };
+
+    screen_info = cw->screen_info;
+    dpy = myScreenGetXDisplay (screen_info);
+
+    source = None;
+    if (cw->name_window_pixmap != None)
+    {
+        source = cw->name_window_pixmap;
+    }
+    else
+    {
+        source = cw->saved_window_pixmap;
+    }
+    if (!source)
+    {
+        return None;
+    }
+
+    /* Get the source pixmap size to compute the scale */
+    source_w = cw->attr.width;
+    source_h = cw->attr.height;
+    src_size = MAX (source_w, source_h);
+
+    /*/
+     * Caller may pass either NULL or 0.
+     * If 0, we return the actual unscalled size.
+     */
+    dest_w = (width != NULL && *width > 0) ? *width : source_w;
+    dest_h = (height != NULL && *height > 0) ? *height : source_h;
+    dest_size = MIN (dest_w, dest_h);
+
+    scale = (double) dest_size / (double) src_size;
+    dest_w = source_w * scale;
+    dest_h = source_h * scale;
+
+    transform.matrix[0][0] = XDoubleToFixed(1.0);
+    transform.matrix[0][1] = XDoubleToFixed(0.0);
+    transform.matrix[0][2] = XDoubleToFixed(0.0);
+    transform.matrix[1][0] = XDoubleToFixed(0.0);
+    transform.matrix[1][1] = XDoubleToFixed(1.0);
+    transform.matrix[1][2] = XDoubleToFixed(0.0);
+    transform.matrix[2][0] = XDoubleToFixed(0.0);
+    transform.matrix[2][1] = XDoubleToFixed(0.0);
+    transform.matrix[2][2] = XDoubleToFixed(scale);
+
+    pixmap = XCreatePixmap (dpy, screen_info->output, dest_w, dest_h, 32);
+    if (!pixmap)
+    {
+        return None;
+    }
+
+    render_format = get_window_format (cw);
+    if (!render_format)
+    {
+        return None;
+    }
+
+    srcPicture = XRenderCreatePicture (dpy, source, render_format, 0, NULL);
+    XRenderSetPictureFilter (dpy, srcPicture, FilterBilinear, 0, 0);
+    XRenderSetPictureTransform (dpy, srcPicture, &transform);
+
+    render_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
+    destPicture = XRenderCreatePicture (dpy, pixmap, render_format, 0, NULL);
+
+    XRenderFillRectangle (dpy, PictOpSrc, destPicture, &c, 0, 0, dest_w, dest_h);
+    XRenderComposite (dpy, PictOpSrc, srcPicture, None, destPicture,
+                      0, 0, 0, 0, 0, 0, dest_w, dest_h);
+
+    XRenderFreePicture (dpy, srcPicture);
+    XRenderFreePicture (dpy, destPicture);
+
+    /* Update given size if requested */
+    if (width != NULL)
+    {
+        *width = dest_w;
+    }
+    if (height != NULL)
+    {
+        *height = dest_h;
+    }
+
+    return pixmap;
+}
+
 /* May return None if:
  * - The xserver does not support name window pixmaps
  * - The compositor is disabled at run time
@@ -3046,13 +3144,14 @@ compositorWindowPixmapAvailable (ScreenInfo *screen_info)
  * if the window is unmapped.
  */
 Pixmap
-compositorGetWindowPixmap (ScreenInfo *screen_info, Window id)
+compositorGetWindowPixmapAtSize (ScreenInfo *screen_info, Window id, guint *width, guint *height)
 {
 #ifdef HAVE_NAME_WINDOW_PIXMAP
 #ifdef HAVE_COMPOSITOR
     CWindow *cw;
 
     g_return_val_if_fail (id != None, None);
+
     TRACE ("entering compositorGetPixmap: 0x%lx", id);
 
     if (!compositorWindowPixmapAvailable (screen_info))
@@ -3063,11 +3162,7 @@ compositorGetWindowPixmap (ScreenInfo *screen_info, Window id)
     cw = find_cwindow_in_screen (screen_info, id);
     if (cw)
     {
-        if (cw->name_window_pixmap != None)
-        {
-            return cw->name_window_pixmap;
-        }
-        return cw->saved_window_pixmap;
+        return compositorScaleWindowPixmap (cw, width, height);
     }
 #endif /* HAVE_COMPOSITOR */
 #endif /* HAVE_NAME_WINDOW_PIXMAP */
diff --git a/src/compositor.h b/src/compositor.h
index 6629f3e..dc34c48 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -53,8 +53,10 @@ void                     compositorResizeWindow                 (DisplayInfo *,
                                                                  int,
                                                                  int);
 gboolean                 compositorWindowPixmapAvailable        (ScreenInfo *);
-Pixmap                   compositorGetWindowPixmap              (ScreenInfo *,
-                                                                 Window);
+Pixmap                   compositorGetWindowPixmapAtSize        (ScreenInfo *,
+                                                                 Window,
+                                                                 guint *,
+                                                                 guint *);
 void                     compositorHandleEvent                  (DisplayInfo *,
                                                                  XEvent *);
 void                     compositorZoomIn                       (ScreenInfo *,
diff --git a/src/icons.c b/src/icons.c
index 1105107..40ebd41 100644
--- a/src/icons.c
+++ b/src/icons.c
@@ -423,9 +423,9 @@ get_pixbuf_from_pixmap (GdkScreen *gscreen, Pixmap xpixmap, guint src_x, guint s
     }
 
     cmap = get_cmap (drawable, gscreen);
-
-    retval = gdk_pixbuf_get_from_drawable (NULL, drawable, cmap, src_x, src_y,
-                                           dest_x, dest_y, width, height);
+    retval = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+    gdk_pixbuf_get_from_drawable (retval, drawable, cmap, src_x, src_y,
+                                  dest_x, dest_y, width, height);
 
     if (G_LIKELY(cmap))
     {
@@ -583,18 +583,52 @@ getClientIcon (Client *c, guint width, guint height)
     ScreenInfo *screen_info;
     GdkPixbuf *icon_pixbuf;
     GdkPixbuf *icon_pixbuf_stated;
+    guint app_icon_width, app_icon_height;
     Pixmap pixmap;
 
     g_return_val_if_fail (c != NULL, NULL);
 
     screen_info = c->screen_info;
     icon_pixbuf = NULL;
-    pixmap = compositorGetWindowPixmap (screen_info, c->frame);
+    app_icon_width = width; /* Set to 0 to use gdk pixbuf scaling */
+    app_icon_height = height; /* Set to 0 to use gdk pixbuf scaling */
+
+    pixmap = compositorGetWindowPixmapAtSize (screen_info, c->frame, &app_icon_width, &app_icon_height);
     if (pixmap != None)
     {
-        icon_pixbuf = try_pixmap_and_mask (screen_info, pixmap, None, width, height);
+        GdkPixbuf *app_content;
+        GdkPixbuf *small_icon;
+        guint small_icon_size;
+
+        icon_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+        gdk_pixbuf_fill (icon_pixbuf, 0x00);
+
+        app_content = try_pixmap_and_mask (screen_info, pixmap, None, width, height);
+        XFreePixmap (myScreenGetXDisplay (screen_info), pixmap);
+
+        app_icon_width = (guint) gdk_pixbuf_get_width (app_content);
+        app_icon_height = (guint) gdk_pixbuf_get_height (app_content);
+
+        gdk_pixbuf_copy_area (app_content, 0, 0, app_icon_width, app_icon_height, icon_pixbuf,
+                              (width - app_icon_width) / 2, (height - app_icon_height) / 2);
+        g_object_unref (app_content);
+
+        small_icon_size = MIN (width / 4, height / 4);
+        small_icon_size = MIN (small_icon_size, 48);
+
+        small_icon = getAppIcon (screen_info, c->window, small_icon_size, small_icon_size);
+
+        gdk_pixbuf_composite (small_icon, icon_pixbuf,
+                              (width - small_icon_size) / 2, height - small_icon_size,
+                              small_icon_size, small_icon_size,
+                              (width - small_icon_size) / 2, height - small_icon_size,
+                              1.0, 1.0,
+                              GDK_INTERP_BILINEAR,
+                              0xff);
+
+        g_object_unref (small_icon);
     }
-    if (!icon_pixbuf)
+    else
     {
         icon_pixbuf = getAppIcon (screen_info, c->window, width, height);
     }

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


More information about the Xfce4-commits mailing list