[cairo-commit] src/cairo-xlib-surface.c

Carl Worth cworth at kemper.freedesktop.org
Thu May 18 14:30:28 PDT 2006


 src/cairo-xlib-surface.c |   54 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 51 insertions(+), 3 deletions(-)

New commits:
diff-tree ea05e027111d5f336b7e3f2170f929b0b1e37692 (from 05b1d2f9c5b827d52f3eb837c6c591c877dde419)
Author: Robert O'Callahan <rocallahan at novell.com>
Date:   Fri May 19 08:26:08 2006 +1200

    [xlib] Have create_similar try harder to create the right surface
    
    I recently discovered that cairo_create_similar on a 16-bit xlib surface
    creates a surface backed by a 24-bit pixmap. This results in absymal
    performance --- I can actually watch a copy from the similar to the
    original move down the screen, on my dual Xeon, NVidia vendor driver
    machine. It also means xlib-based code like GTK themes can't render to
    the surface because it doesn't match the screen depth.
    
    The attached patch makes _cairo_xlib_surface_create_similar match the
    characteristics of the input surface as closely as I know how, and fixes
    my issues.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 7fae110..b92a3f9 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -234,6 +234,22 @@ _cairo_xlib_surface_create_similar_with_
     return &surface->base;
 }
 
+static cairo_bool_t
+_xrender_format_matches_content (XRenderPictFormat *format,
+                                 cairo_content_t   content)
+{
+    cairo_bool_t has_alpha = format->direct.alpha != 0;
+    cairo_bool_t has_color = format->direct.red != 0 ||
+        format->direct.green != 0 || format->direct.blue != 0;
+    if (has_alpha != (content == CAIRO_CONTENT_ALPHA ||
+                      content == CAIRO_CONTENT_COLOR_ALPHA))
+        return False;
+    if (has_color != (content == CAIRO_CONTENT_COLOR ||
+                      content == CAIRO_CONTENT_COLOR_ALPHA))
+        return False;
+    return True;
+}
+
 static cairo_surface_t *
 _cairo_xlib_surface_create_similar (void	       *abstract_src,
 				    cairo_content_t	content,
@@ -241,10 +257,42 @@ _cairo_xlib_surface_create_similar (void
 				    int			height)
 {
     cairo_format_t format = _cairo_format_from_content (content);
+    cairo_xlib_surface_t *src = abstract_src;
+
+    /* Try to create a surface with the same visual and depth as the
+       existing surface.
+       Don't bother if the X server doesn't have COMPOSITE, because we prefer
+       to just fall back to image surfaces in that case. */
+    if (src->visual != NULL && CAIRO_SURFACE_RENDER_HAS_COMPOSITE(src)) {
+        Display *dpy = src->dpy;
+        XRenderPictFormat *xrender_format =
+            XRenderFindVisualFormat (dpy, src->visual);
+        /* Give up if the requested content type isn't compatible with the
+           visual format */
+        if (xrender_format != NULL &&
+            _xrender_format_matches_content (xrender_format, content)) {
+            Pixmap pix = XCreatePixmap (dpy, RootWindowOfScreen (src->screen),
+               width <= 0 ? 1 : width, height <= 0 ? 1 : height,
+               xrender_format->depth);
+    
+            cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)
+                cairo_xlib_surface_create_with_xrender_format (dpy, pix, src->screen,
+                                                               xrender_format,
+                                                               width, height);
+            if (surface->base.status != CAIRO_STATUS_SUCCESS) {
+                 _cairo_error (CAIRO_STATUS_NO_MEMORY);
+                 return (cairo_surface_t*) &_cairo_surface_nil;
+            }
+         
+            surface->owns_pixmap = TRUE;
+            surface->visual = src->visual;
+
+            return &surface->base;
+        }
+    }
+
     return _cairo_xlib_surface_create_similar_with_format (abstract_src,
-							   format,
-							   width,
-							   height);
+							   format, width, height);
 }
 
 static cairo_status_t


More information about the cairo-commit mailing list