[cairo-commit] 2 commits - src/cairo-xlib-display.c src/cairo-xlib-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Sun Sep 20 12:15:02 PDT 2009


 src/cairo-xlib-display.c |   23 ++++-
 src/cairo-xlib-surface.c |  197 +++++++++++++++++++++--------------------------
 2 files changed, 110 insertions(+), 110 deletions(-)

New commits:
commit 9b7c5d95055c4ea5da46c53263050d6ec1331c08
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 20 18:46:19 2009 +0100

    [xlib] Cleanse creation of similar surfaces.
    
    Reduce two nearly identical routines to one.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 4b2fd1f..88bad87 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -215,53 +215,6 @@ _cairo_xlib_surface_set_clip_region (cairo_xlib_surface_t *surface,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_surface_t *
-_cairo_xlib_surface_create_similar_with_format (void	       *abstract_src,
-						cairo_format_t	format,
-						int		width,
-						int		height)
-{
-    cairo_xlib_surface_t *src = abstract_src;
-    Display *dpy = src->dpy;
-    Pixmap pix;
-    cairo_xlib_surface_t *surface;
-    XRenderPictFormat *xrender_format;
-
-    assert (width <= XLIB_COORD_MAX && height <= XLIB_COORD_MAX);
-
-    /* As a good first approximation, if the display doesn't have even
-     * the most elementary RENDER operation, then we're better off
-     * using image surfaces for all temporary operations, so return NULL
-     * and let the fallback code happen.
-     */
-    if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
-	return NULL;
-
-    xrender_format = _cairo_xlib_display_get_xrender_format (src->display,
-							     format);
-    if (xrender_format == NULL)
-	return NULL;
-
-    pix = XCreatePixmap (dpy, src->drawable,
-			 width <= 0 ? 1 : width, height <= 0 ? 1 : height,
-			 xrender_format->depth);
-
-    surface = (cairo_xlib_surface_t *)
-	      _cairo_xlib_surface_create_internal (src->screen, pix,
-						   NULL,
-						   xrender_format,
-						   width, height,
-						   xrender_format->depth);
-    if (unlikely (surface->base.status)) {
-	XFreePixmap (dpy, pix);
-	return &surface->base;
-    }
-
-    surface->owns_pixmap = TRUE;
-
-    return &surface->base;
-}
-
 static cairo_content_t
 _xrender_format_to_content (XRenderPictFormat *xrender_format)
 {
@@ -301,6 +254,9 @@ _cairo_xlib_surface_create_similar (void	       *abstract_src,
     if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
 	return NULL;
 
+    if (! CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (src))
+	return NULL;
+
     _cairo_xlib_display_notify (src->display);
 
     /* If we never found an XRenderFormat or if it isn't compatible
@@ -309,27 +265,60 @@ _cairo_xlib_surface_create_similar (void	       *abstract_src,
      * arbitrarily pick a visual/depth for the similar surface.
      */
     xrender_format = src->xrender_format;
-    if (xrender_format == NULL ||
-	_xrender_format_to_content (xrender_format) != content)
+    if ((xrender_format != NULL &&
+	_xrender_format_to_content (xrender_format) == content) ||
+	(xrender_format =
+	 _cairo_xlib_display_get_xrender_format (src->display,
+						 _cairo_format_from_content (content))))
     {
-	return _cairo_xlib_surface_create_similar_with_format (abstract_src,
-							       _cairo_format_from_content (content),
-							       width, height);
+	Visual *visual;
+
+	/* We've got a compatible XRenderFormat now, which means the
+	 * similar surface will match the existing surface as closely in
+	 * visual/depth etc. as possible. */
+	pix = XCreatePixmap (src->dpy, src->drawable,
+			     width <= 0 ? 1 : width, height <= 0 ? 1 : height,
+			     xrender_format->depth);
+
+	visual = NULL;
+	if (xrender_format == src->xrender_format)
+	    visual = src->visual;
+
+	surface = (cairo_xlib_surface_t *)
+		  _cairo_xlib_surface_create_internal (src->screen, pix,
+						       visual,
+						       xrender_format,
+						       width, height,
+						       xrender_format->depth);
+    }
+    else
+    {
+#ifdef DEBUG_FORCE_FALLBACKS
+	Screen *screen = src->screen->screen;
+	int depth;
+
+	/* No compatabile XRenderFormat, see if we can make an ordinary pixmap,
+	 * so that we can still accelerate blits with XCopyArea(). */
+	if (content != CAIRO_CONTENT_COLOR)
+	    return NULL;
+
+	depth = DefaultDepthOfScreen (screen);
+
+	pix = XCreatePixmap (src->dpy, RootWindowOfScreen (screen),
+			     width <= 0 ? 1 : width, height <= 0 ? 1 : height,
+			     depth);
+
+	surface = (cairo_xlib_surface_t *)
+		  _cairo_xlib_surface_create_internal (src->screen, pix,
+						       DefaultVisualOfScreen (screen),
+						       NULL,
+						       width, height, depth);
+#else
+	/* No compatabile XRenderFormat, just say no. */
+	return NULL;
+#endif
     }
 
-    /* We've got a compatible XRenderFormat now, which means the
-     * similar surface will match the existing surface as closely in
-     * visual/depth etc. as possible. */
-    pix = XCreatePixmap (src->dpy, src->drawable,
-			 width <= 0 ? 1 : width, height <= 0 ? 1 : height,
-			 xrender_format->depth);
-
-    surface = (cairo_xlib_surface_t *)
-	      _cairo_xlib_surface_create_internal (src->screen, pix,
-		                                   src->visual,
-						   xrender_format,
-						   width, height,
-						   xrender_format->depth);
     if (unlikely (surface->base.status)) {
 	XFreePixmap (src->dpy, pix);
 	return &surface->base;
@@ -1032,15 +1021,14 @@ _draw_image_surface (cairo_xlib_surface_t   *surface,
 	cairo_bool_t true_color;
 	int ret;
 
-	if (surface->depth > 16) {
+	if (surface->depth > 16)
 	    ximage.bits_per_pixel = 32;
-	} else if (surface->depth > 8) {
+	else if (surface->depth > 8)
 	    ximage.bits_per_pixel = 16;
-	} else if (surface->depth > 1) {
+	else if (surface->depth > 1)
 	    ximage.bits_per_pixel = 8;
-	} else {
+	else
 	    ximage.bits_per_pixel = 1;
-	}
 	stride = CAIRO_STRIDE_FOR_WIDTH_BPP (ximage.width,
 					     ximage.bits_per_pixel);
 	ximage.bytes_per_line = stride;
@@ -1270,21 +1258,14 @@ _cairo_xlib_surface_clone_similar (void			*abstract_surface,
 	}
     } else if (_cairo_surface_is_image (src)) {
 	cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
-	cairo_format_t format;
 
 	if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
 	    return UNSUPPORTED ("roi too large for xlib");
 
-	format = image_src->format;
-	if (format == CAIRO_FORMAT_INVALID ||
-	    (_cairo_content_from_format (format) & ~content))
-	{
-	    format = _cairo_format_from_content (image_src->base.content & content);
-	}
 	clone = (cairo_xlib_surface_t *)
-	    _cairo_xlib_surface_create_similar_with_format (surface,
-							    format,
-							    width, height);
+	    _cairo_xlib_surface_create_similar (surface,
+						image_src->base.content & content,
+						width, height);
 	if (clone == NULL)
 	    return UNSUPPORTED ("unhandled image format, no similar surface");
 
@@ -2777,34 +2758,42 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t	*screen,
 
     CAIRO_MUTEX_INITIALIZE ();
 
-    if (xrender_format) {
-	depth = xrender_format->depth;
+    if (depth == 0) {
+	if (xrender_format) {
+	    depth = xrender_format->depth;
 
-	/* XXX find matching visual for core/dithering fallbacks? */
-    } else if (visual) {
-	Screen *scr = screen->screen;
-	int j, k;
+	    /* XXX find matching visual for core/dithering fallbacks? */
+	} else if (visual) {
+	    Screen *scr = screen->screen;
 
-	/* This is ugly, but we have to walk over all visuals
-	 * for the display to find the correct depth.
-	 */
-	depth = 0;
-	for (j = 0; j < scr->ndepths; j++) {
-	    Depth *d = &scr->depths[j];
-	    for (k = 0; k < d->nvisuals; k++) {
-		if (&d->visuals[k] == visual) {
-		    depth = d->depth;
-		    goto found;
+	    if (visual == DefaultVisualOfScreen (scr)) {
+		depth = DefaultDepthOfScreen (scr);
+	    } else  {
+		int j, k;
+
+		/* This is ugly, but we have to walk over all visuals
+		 * for the display to find the correct depth.
+		 */
+		depth = 0;
+		for (j = 0; j < scr->ndepths; j++) {
+		    Depth *d = &scr->depths[j];
+		    for (k = 0; k < d->nvisuals; k++) {
+			if (&d->visuals[k] == visual) {
+			    depth = d->depth;
+			    goto found;
+			}
+		    }
 		}
 	    }
 	}
-    found:
+
+	if (depth == 0)
+	    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
+
+found:
 	;
     }
 
-    if (depth == 0)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
-
     surface = malloc (sizeof (cairo_xlib_surface_t));
     if (unlikely (surface == NULL))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
@@ -2830,11 +2819,7 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t	*screen,
 	    }
 	}
     } else {
-	xrender_format = NULL;
-    }
-
-    /* we cannot use XRender for this surface, so ensure we don't try */
-    if (xrender_format == NULL) {
+	/* we cannot use XRender for this surface, so ensure we don't try */
 	surface->render_major = -1;
 	surface->render_minor = -1;
     }
@@ -2914,7 +2899,7 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t	*screen,
 	surface->b_mask = 0;
     }
 
-    return (cairo_surface_t *) surface;
+    return &surface->base;
 }
 
 static Screen *
commit 878cef62b525e9f13ab2a8ab562ba8b6628aaa1f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 20 18:45:09 2009 +0100

    [xlib] Interim CAIRO_DEBUG variable to specify xrender level
    
    Use CAIRO_DEBUG=xrender-version=x.y to override what the server reports.
    Useful to test cairo's behaviour against older servers.

diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index b517fbf..56ea7c8 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -237,7 +237,7 @@ _cairo_xlib_display_get (Display *dpy,
     cairo_xlib_display_t *display;
     cairo_xlib_display_t **prev;
     XExtCodes *codes;
-    int render_major, render_minor;
+    const char *env;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
     /* There is an apparent deadlock between this mutex and the
@@ -281,7 +281,24 @@ _cairo_xlib_display_get (Display *dpy,
      * add our hook. For now, that means Render, so we call into its
      * QueryVersion function to ensure it gets initialized.
      */
-    XRenderQueryVersion (dpy, &render_major, &render_minor);
+    display->render_major = display->render_minor = -1;
+    XRenderQueryVersion (dpy, &display->render_major, &display->render_minor);
+    env = getenv ("CAIRO_DEBUG");
+    if (env != NULL && (env = strstr (env, "xrender-version=")) != NULL) {
+	int max_render_major, max_render_minor;
+
+	env += sizeof ("xrender-version=") - 1;
+	if (sscanf (env, "%d.%d", &max_render_major, &max_render_minor) != 2)
+	    max_render_major = max_render_minor = -1;
+
+	if (max_render_major < display->render_major ||
+	    (max_render_major == display->render_major &&
+	     max_render_minor < display->render_minor))
+	{
+	    display->render_major = max_render_major;
+	    display->render_minor = max_render_minor;
+	}
+    }
 
     codes = XAddExtension (dpy);
     if (unlikely (codes == NULL)) {
@@ -303,8 +320,6 @@ _cairo_xlib_display_get (Display *dpy,
     display->close_display_hooks = NULL;
     display->closed = FALSE;
 
-    display->render_major = render_major;
-    display->render_minor = render_minor;
     memset (display->cached_xrender_formats, 0,
 	    sizeof (display->cached_xrender_formats));
 


More information about the cairo-commit mailing list