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

Chris Wilson ickle at kemper.freedesktop.org
Sun Aug 10 00:46:25 PDT 2008


 src/cairo-xlib-surface.c |   87 ++++++++++++++++++++++++++++-------------------
 1 file changed, 52 insertions(+), 35 deletions(-)

New commits:
commit fef03ef98a116021a688d9f39b80844bc1c332e6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Aug 10 08:31:19 2008 +0100

    [xlib] Check for depth == 0 in create_surface_internal().
    
    Validate that we find an appropriate depth for the Xlib surface, before
    attempting to create the surface. This was manifesting itself with
    XInitImage() failures during _draw_image_surface() (actually detected as
    a segmentation fault in XPutPixel() due to an incomplete XImage).  So we
    also add a couple of asserts to ensure that XInitImage() is successful -
    which to the best of our knowledge, they should always be.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 36494a1..0ad279b 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -909,11 +909,15 @@ _draw_image_surface (cairo_xlib_surface_t   *surface,
 	image_masks.green_mask == surface->g_mask &&
 	image_masks.blue_mask  == surface->b_mask)
     {
+	int ret;
+
 	ximage.bits_per_pixel = image_masks.bpp;
 	ximage.bytes_per_line = image->stride;
 	ximage.data = (char *)image->data;
 	own_data = FALSE;
-	XInitImage (&ximage);
+
+	ret = XInitImage (&ximage);
+	assert (ret != 0);
     } else {
 	unsigned int stride, rowstride;
 	int x, y, x0, y0, x_off, y_off;
@@ -923,6 +927,8 @@ _draw_image_surface (cairo_xlib_surface_t   *surface,
 	int o_a_width=0, o_r_width=0, o_g_width=0, o_b_width=0;
 	int o_a_shift=0, o_r_shift=0, o_g_shift=0, o_b_shift=0;
 	cairo_xlib_visual_info_t *visual_info = NULL;
+	cairo_bool_t true_color;
+	int ret;
 
 	if (surface->depth > 16) {
 	    ximage.bits_per_pixel = 32;
@@ -942,28 +948,27 @@ _draw_image_surface (cairo_xlib_surface_t   *surface,
 
 	own_data = TRUE;
 
-	XInitImage (&ximage);
+	ret = XInitImage (&ximage);
+	assert (ret != 0);
 
 	_characterize_field (image_masks.alpha_mask, &i_a_width, &i_a_shift);
 	_characterize_field (image_masks.red_mask  , &i_r_width, &i_r_shift);
 	_characterize_field (image_masks.green_mask, &i_g_width, &i_g_shift);
 	_characterize_field (image_masks.blue_mask , &i_b_width, &i_b_shift);
 
-	if (surface->visual == NULL || surface->visual->class == TrueColor) {
-
+	true_color = surface->visual == NULL ||
+	             surface->visual->class == TrueColor;
+	if (true_color) {
 	    _characterize_field (surface->a_mask, &o_a_width, &o_a_shift);
 	    _characterize_field (surface->r_mask, &o_r_width, &o_r_shift);
 	    _characterize_field (surface->g_mask, &o_g_width, &o_g_shift);
 	    _characterize_field (surface->b_mask, &o_b_width, &o_b_shift);
-
 	} else {
-
 	    status = _cairo_xlib_screen_get_visual_info (surface->screen_info,
 							 surface->visual,
 							 &visual_info);
 	    if (status)
 		goto BAIL;
-
 	}
 
 	rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
@@ -972,13 +977,15 @@ _draw_image_surface (cairo_xlib_surface_t   *surface,
 	y0 = dst_y + surface->base.device_transform.y0;
 	for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
 	     y < ximage.height;
-	     y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) {
+	     y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern))
+	{
 	    const int8_t *dither_row = dither_pattern[y_off];
+
 	    for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
 		 x < ximage.width;
-		 x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0])) {
+		 x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0]))
+	    {
 		int dither_adjustment = dither_row[x_off];
-
 		int a, r, g, b;
 
 		if (image_masks.bpp <= 8)
@@ -987,20 +994,24 @@ _draw_image_surface (cairo_xlib_surface_t   *surface,
 		    in_pixel = ((uint16_t*)row)[x];
 		else
 		    in_pixel = row[x];
+
 		a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
 		r = _field_to_8 (in_pixel & image_masks.red_mask  , i_r_width, i_r_shift);
 		g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
 		b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
-		if (surface->visual == NULL || surface->visual->class == TrueColor) {
-		    out_pixel = (_field_from_8        (a, o_a_width, o_a_shift) |
-				 _field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) |
-				 _field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) |
-				 _field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment));
+
+		if (true_color) {
+		    out_pixel = _field_from_8        (a, o_a_width, o_a_shift) |
+				_field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) |
+				_field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) |
+				_field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment);
 		} else {
 		    out_pixel = _pseudocolor_from_rgb888_dither (visual_info, r, g, b, dither_adjustment);
 		}
+
 		XPutPixel (&ximage, x, y, out_pixel);
 	    }
+
 	    row += rowstride;
 	}
     }
@@ -1194,9 +1205,9 @@ _cairo_xlib_surface_create_solid_pattern_surface (void                  *abstrac
 	      _cairo_xlib_surface_create_internal (other->dpy,
 						   pixmap,
 						   other->screen, other->visual,
-						   NULL,
+						   other->xrender_format,
 						   image->width, image->height,
-						   0);
+						   other->depth);
     status = surface->base.status;
     if (status)
 	goto BAIL;
@@ -2391,31 +2402,17 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
 
     CAIRO_MUTEX_INITIALIZE ();
 
-    screen_info = _cairo_xlib_screen_info_get (dpy, screen);
-    if (screen_info == NULL)
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
-    surface = malloc (sizeof (cairo_xlib_surface_t));
-    if (surface == NULL) {
-	_cairo_xlib_screen_info_destroy (screen_info);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-    }
-
-    if (! _cairo_xlib_add_close_display_hook (dpy,
-	    _cairo_xlib_surface_detach_display, surface, surface)) {
-	free (surface);
-	_cairo_xlib_screen_info_destroy (screen_info);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-    }
-
     if (xrender_format) {
 	depth = xrender_format->depth;
+
+	/* XXX find matching visual for core/dithering fallbacks? */
     } else if (visual) {
 	int j, k;
 
 	/* This is ugly, but we have to walk over all visuals
-	 * for the display to find the depth.
+	 * for the display to find the correct depth.
 	 */
+	depth = 0;
 	for (j = 0; j < screen->ndepths; j++) {
 	    Depth *d = &screen->depths[j];
 	    for (k = 0; k < d->nvisuals; k++) {
@@ -2429,6 +2426,26 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
 	;
     }
 
+    if (depth == 0)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
+
+    screen_info = _cairo_xlib_screen_info_get (dpy, screen);
+    if (screen_info == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    surface = malloc (sizeof (cairo_xlib_surface_t));
+    if (surface == NULL) {
+	_cairo_xlib_screen_info_destroy (screen_info);
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    if (! _cairo_xlib_add_close_display_hook (dpy,
+	    _cairo_xlib_surface_detach_display, surface, surface)) {
+	free (surface);
+	_cairo_xlib_screen_info_destroy (screen_info);
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
     if (! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) {
 	surface->render_major = -1;
 	surface->render_minor = -1;


More information about the cairo-commit mailing list