diff --git a/configure.in b/configure.in
index 2596876..813b4eb 100644
--- a/configure.in
+++ b/configure.in
@@ -340,6 +340,10 @@ CAIRO_BACKEND_ENABLE(xlib, Xlib, xlib, XLIB_SURFACE, auto, [
 		     fi])
 ])
 
+CAIRO_BACKEND_ENABLE(xlib_shm, Xlib shm, xlib-shm, XLIB_SHM_SURFACE, no, [
+    use_xlib_shm=$use_xlib
+])
+
 CAIRO_BACKEND_ENABLE(xlib_xrender, Xlib Xrender, xlib-xrender, XLIB_XRENDER_SURFACE, auto, [
   if test "x$use_xlib" != "xyes"; then
     use_xlib_xrender="no (requires --enable-xlib)"
@@ -1097,6 +1101,7 @@ echo ""
 echo "cairo (version $V) will be compiled with the following surface backends:"
 echo "  image:         yes (always builtin)"
 echo "  Xlib:          $use_xlib"
+echo "  Xlib Xshm:     $use_xlib_shm"
 echo "  Xlib Xrender:  $use_xlib_xrender"
 echo "  Quartz:        $use_quartz"
 echo "  Quartz-image:  $use_quartz_image"
diff --git a/src/Makefile.am b/src/Makefile.am
index 6c467bb..0521607 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -170,6 +170,16 @@ cairo_sources += $(xlib_sources)
 backend_pkgconfigs += cairo-xlib.pc
 endif
 
+xlib_shm_headers =  cairo-xlib-shm.h
+xlib_shm_sources =  cairo-xlib-shm-surface-private.h \
+		cairo-xlib-shm-surface.c
+cairo_all_sources += $(xlib_shm_headers) $(xlib_shm_sources)
+if CAIRO_HAS_XLIB_SHM_SURFACE
+cairo_headers += $(xlib_shm_headers)
+cairo_sources += $(xlib_shm_sources)
+backend_pkgconfigs += cairo-xlib-shm.pc
+endif
+
 xlib_xrender_headers = cairo-xlib-xrender.h
 cairo_all_sources += $(xlib_xrender_headers)
 if CAIRO_HAS_XLIB_XRENDER_SURFACE
diff --git a/src/cairo-xlib-shm-surface-private.h b/src/cairo-xlib-shm-surface-private.h
new file mode 100644
index 0000000..7567495
--- /dev/null
+++ b/src/cairo-xlib-shm-surface-private.h
@@ -0,0 +1,66 @@
+/* cairo - a vector graphics library with display and print output 
+ * 
+ * Copyright © 2008 Mozilla Corporation 
+ * 
+ * This library is free software; you can redistribute it and/or 
+ * modify it either under the terms of the GNU Lesser General Public 
+ * License version 2.1 as published by the Free Software Foundation 
+ * (the "LGPL") or, at your option, under the terms of the Mozilla 
+ * Public License Version 1.1 (the "MPL"). If you do not alter this 
+ * notice, a recipient may use your version of this file under either 
+ * the MPL or the LGPL. 
+ * 
+ * You should have received a copy of the LGPL along with this library 
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * You should have received a copy of the MPL along with this library 
+ * in the file COPYING-MPL-1.1 
+ * 
+ * The contents of this file are subject to the Mozilla Public License 
+ * Version 1.1 (the "License"); you may not use this file except in 
+ * compliance with the License. You may obtain a copy of the License at 
+ * http://www.mozilla.org/MPL/ 
+ * 
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY 
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for 
+ * the specific language governing rights and limitations. 
+ * 
+ * The Original Code is the cairo graphics library. 
+ * 
+ * The Initial Developer of the Original Code is Mozilla Corporation. 
+ * 
+ * Contributor(s): 
+ *      Eric Butler <ebutler@mozilla.com> 
+ */
+
+#ifndef CAIRO_XLIB_SHM_PRIVATE_H
+#define CAIRO_XLIB_SHM_PRIVATE_H
+
+#if CAIRO_HAS_XLIB_SHM_SURFACE
+
+#include "cairo-xlib-shm.h"
+
+#include <X11/extensions/XShm.h>
+
+typedef struct _cairo_xlib_shm_surface cairo_xlib_shm_surface_t;
+
+struct _cairo_xlib_shm_surface {
+    cairo_surface_t base;
+
+    XShmSegmentInfo shm_info;
+    cairo_rectangle_int_t extents;
+    Display *dpy;
+    /* XXX: not sure if it's a good idea to hold onto the visual, but need it
+     * for create_similar.
+     */
+    Visual *visual; 
+    XImage *ximage;
+    cairo_format_t format;
+};
+
+cairo_bool_t
+_cairo_surface_is_xlib_shm (const cairo_surface_t *surface);
+
+#endif /* CAIRO_HAS_XLIB_SHM_SURFACE */
+
+#endif /* CAIRO_XLIB_SHM_PRIVATE_H */
diff --git a/src/cairo-xlib-shm-surface.c b/src/cairo-xlib-shm-surface.c
new file mode 100644
index 0000000..ee32e6a
--- /dev/null
+++ b/src/cairo-xlib-shm-surface.c
@@ -0,0 +1,460 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2008 Mozilla Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ *
+ * Contributor(s):
+ *      Eric Butler <ebutler@mozilla.com>
+ */
+
+#include "cairoint.h"
+
+#ifdef CAIRO_HAS_XLIB_SHM_SURFACE
+
+#include "cairo-xlib-shm-surface-private.h"
+
+#include <sys/shm.h>
+#include <sys/ipc.h>
+#include <X11/Xutil.h>
+
+/*
+ * 0 represents an unsupported value.
+ */
+static int
+_cairo_format_to_depth (cairo_format_t format)
+{
+    switch (format) {
+    case CAIRO_FORMAT_ARGB32:
+        return 32;
+    case CAIRO_FORMAT_RGB24:
+        return 24;
+    case CAIRO_FORMAT_A1:
+    case CAIRO_FORMAT_A8:
+    /* XXX: don't really know if A8 works... A1 certainly doesn't
+     * so for now don't support either
+     */
+    default:
+        return 0;
+    }
+}
+
+static cairo_content_t
+_cairo_format_to_content (cairo_format_t format)
+{
+    switch (format) {
+    case CAIRO_FORMAT_ARGB32:
+    default:
+        return CAIRO_CONTENT_COLOR_ALPHA;
+    case CAIRO_FORMAT_RGB24:
+        return CAIRO_CONTENT_COLOR;
+    case CAIRO_FORMAT_A1:
+    case CAIRO_FORMAT_A8:
+        return CAIRO_CONTENT_ALPHA;
+    }
+}
+
+static cairo_surface_t *
+_cairo_xlib_shm_surface_create_internal (Display *dpy,
+                                         Visual *visual,
+                                         cairo_format_t format,
+                                         int width,
+                                         int height);
+
+static cairo_surface_t *
+_cairo_xlib_shm_surface_create_similar (void *asurface,
+                                        cairo_content_t content,
+                                        int width,
+                                        int height)
+{
+    cairo_xlib_shm_surface_t *surface = (cairo_xlib_shm_surface_t *) asurface;
+
+    return _cairo_xlib_shm_surface_create_internal (surface->dpy,
+                                                    surface->visual,
+                                                    _cairo_format_from_content (content),
+                                                    width,
+                                                    height);
+}
+
+static cairo_status_t
+_cairo_xlib_shm_surface_finish (void *asurface)
+{
+    cairo_xlib_shm_surface_t *surface = (cairo_xlib_shm_surface_t *) asurface;
+
+    /* detach the shm segment and free it */
+    XShmDetach (surface->dpy, &surface->shm_info);
+    shmdt (surface->shm_info.shmaddr);
+    shmctl (surface->shm_info.shmid, IPC_RMID, 0);
+    XDestroyImage (surface->ximage);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_xlib_shm_surface_acquire_source_image (void *asurface,
+                                              cairo_image_surface_t **image_out,
+                                              void **image_extra)
+{
+    cairo_surface_t *out;
+    cairo_xlib_shm_surface_t *surface = (cairo_xlib_shm_surface_t *) asurface;
+
+    /* just create an image that points to the same data */
+    out = cairo_image_surface_create_for_data ((unsigned char *) surface->ximage->data,
+                                               surface->format,
+                                               surface->ximage->width,
+                                               surface->ximage->height,
+                                               surface->ximage->bytes_per_line);
+
+    *image_out = (cairo_image_surface_t *) out;
+    *image_extra = NULL;
+
+    return cairo_surface_status(out);
+}
+
+static void
+_cairo_xlib_shm_surface_release_source_image (void *asurface,
+                                              cairo_image_surface_t *image,
+                                              void *image_extra)
+{
+    cairo_surface_destroy(&image->base);
+}
+
+static cairo_status_t
+_cairo_xlib_shm_surface_acquire_dest_image (void *asurface,
+                                            cairo_rectangle_int_t *intersect_rect,
+                                            cairo_image_surface_t **image_out,
+                                            cairo_rectangle_int_t *image_rect_out,
+                                            void **image_extra)
+{
+    cairo_surface_t *out;
+
+    cairo_xlib_shm_surface_t *surface = (cairo_xlib_shm_surface_t *) asurface;
+
+    /* create an image that points to the same data */
+    out = cairo_image_surface_create_for_data ((unsigned char *) surface->ximage->data,
+                                                      surface->format,
+                                                      surface->ximage->width,
+                                                      surface->ximage->height,
+                                                      surface->ximage->bytes_per_line);
+
+    *image_out = (cairo_image_surface_t *) out;
+    *image_extra = NULL;
+    image_rect_out->x = 0;
+    image_rect_out->y = 0;
+    image_rect_out->width = surface->ximage->width;
+    image_rect_out->height = surface->ximage->height;
+
+    return cairo_surface_status(out);
+}
+
+static void
+_cairo_xlib_shm_surface_release_dest_image (void *asurface,
+                                            cairo_rectangle_int_t *intersect_rect,
+                                            cairo_image_surface_t *image,
+                                            cairo_rectangle_int_t *image_rect,
+                                            void *image_extra)
+{
+    cairo_surface_destroy(&image->base);
+}
+
+static cairo_int_status_t
+_cairo_xlib_shm_surface_get_extents (void *asurface,
+                                     cairo_rectangle_int_t *extents)
+{
+    cairo_xlib_shm_surface_t *surface = (cairo_xlib_shm_surface_t *) asurface;
+    *extents = surface->extents;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static const cairo_surface_backend_t cairo_xlib_shm_surface_backend = {
+    CAIRO_SURFACE_TYPE_XLIB_SHM,
+    _cairo_xlib_shm_surface_create_similar,
+    _cairo_xlib_shm_surface_finish,
+    _cairo_xlib_shm_surface_acquire_source_image,
+    _cairo_xlib_shm_surface_release_source_image,
+    _cairo_xlib_shm_surface_acquire_dest_image,
+    _cairo_xlib_shm_surface_release_dest_image,
+    NULL, /* clone_similar */
+    NULL, /* composite */
+    NULL, /* fill_rectangles */
+    NULL, /* composite_trapezoids */
+    NULL, /* copy_page */
+    NULL, /* show_page */
+    NULL, /* set_clip_region */
+    NULL, /* intersect_clip_path */
+    _cairo_xlib_shm_surface_get_extents,
+    NULL, /* old_show_glyphs */
+    NULL, /* get_font_options */
+    NULL, /* flush */
+    NULL, /* mark_dirty_rectangle */
+    NULL, /* scaled_font_fini */
+    NULL, /* scaled_glyph_fini */
+
+    NULL, /* paint */
+    NULL, /* mask */
+    NULL, /* stroke */
+    NULL, /* fill */
+    NULL, /* surface_show_glyphs */
+    NULL, /* snapshot */
+    NULL, /* is_similar */
+    NULL, /* reset */
+    NULL  /* fill_stroke */
+
+};
+
+static cairo_bool_t
+_native_byte_order_lsb (void)
+{
+    int x = 1;
+    return *((char *) &x) == 1;
+}
+
+static cairo_surface_t *
+_cairo_xlib_shm_surface_create_internal (Display *dpy,
+                                         Visual *visual,
+                                         cairo_format_t format,
+                                         int width,
+                                         int height)
+{
+    cairo_xlib_shm_surface_t *surface;
+    int size;
+
+    int depth = _cairo_format_to_depth (format);
+
+    if (depth == 0)
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+
+    /* make sure extension is usable */
+    if (!XShmQueryExtension (dpy))
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    /* check for overflow */
+    size = width * height;
+    if (size / height != width || (size * (depth/4)) / (depth/4) != size)
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    surface = malloc (sizeof (cairo_xlib_shm_surface_t));
+    if (surface == NULL)
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    surface->dpy = dpy;
+    surface->visual = visual;
+    surface->format = format;
+
+    surface->ximage = XShmCreateImage (dpy, visual, depth, ZPixmap, NULL,
+                                       &surface->shm_info, width, height);
+
+    if (!surface->ximage) {
+        free (surface);
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    /* check for overflow and incorrect bpp */
+    size = surface->ximage->bytes_per_line * height;
+    /* have no way to force bpp to a certain value, so just have to hope
+     * that CreateImage gives us one that is 32
+     */ 
+    if (size / surface->ximage->bytes_per_line != height ||
+            surface->ximage->bits_per_pixel != 32) {
+        free (surface);
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    /* create the shm segment */
+    surface->shm_info.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT|0777);
+    if (surface->shm_info.shmid == -1) {
+        free (surface);
+        XDestroyImage (surface->ximage);
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    surface->shm_info.shmaddr = surface->ximage->data =
+            shmat (surface->shm_info.shmid, NULL, 0);
+    surface->shm_info.readOnly = False;
+
+    if (!XShmAttach (dpy, &surface->shm_info)) {
+        shmdt (surface->shm_info.shmaddr);
+        shmctl (surface->shm_info.shmid, IPC_RMID, 0);
+        XDestroyImage (surface->ximage);
+        free (surface);
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    /* XXX: XSync MAY need to be called after XShmAttach, but leave it up to
+     * the caller for now, because XSync will mess with their event loop
+     */
+
+    _cairo_surface_init (&surface->base, &cairo_xlib_shm_surface_backend,
+                         _cairo_format_to_content (format));
+
+    surface->extents.x = surface->extents.y = 0;
+    surface->extents.width = width;
+    surface->extents.height = height;
+
+    return (cairo_surface_t *) surface;
+}
+
+/**
+ * cairo_xlib_shm_surface_create
+ * @dpy The connection to the X server
+ * @visual The visual structure
+ * @format Format of pixels in the surface to create
+ * @width Width of the surface, in pixels
+ * @height Height of the surface, in pixels
+ *
+ * Creates a surface backed by an XImage that uses the shared memory extension.
+ * The resulting surface can be rendered quickly to a #cairo_xlib_surface. The
+ * surface is intended for use in rendering images quickly. It is designed such
+ * that the user decodes image data directly into the surface. When
+ * rendered to an xlib surface, there is no event sent to the X event queue to
+ * indicate that the rendering is complete, so destroying the image soon after
+ * it is used as a source could cause part of the image to not be rendered.
+ * This function calls #XSync after attaching the shared memory segment.
+ *
+ * Return value: Pointer to the newly created surface. May return a surface
+ * with an error if out of memory occurs or the shared memory extension is
+ * unavailable for some reason.
+ */
+cairo_surface_t *
+cairo_xlib_shm_surface_create (Display *dpy,
+                               Visual *visual,
+                               cairo_format_t format,
+                               int width,
+                               int height)
+{
+    return  _cairo_xlib_shm_surface_create_internal (dpy, visual, format,
+                                                     width, height);
+}
+
+/**
+ * cairo_xlib_shm_surface_get_data
+ * @surface A #cairo_xlib_shm_surface_t
+ *
+ * Get a pointer to the data of the surface, for direct inspection or
+ * modification.
+ *
+ * Return value: A pointer to the data of this surface of #NULL if @surface is
+ * not an xlib shm surface.
+ */
+unsigned char*
+cairo_xlib_shm_surface_get_data (cairo_surface_t *surface)
+{
+    if (!_cairo_surface_is_xlib_shm (surface)) {
+        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+        return NULL;
+    }
+
+    return (unsigned char*) ((cairo_xlib_shm_surface_t *)surface)->ximage->data;
+}
+
+/**
+ * cairo_xlib_shm_surface_get_format
+ * @surface A #cairo_xlib_shm_surface_t
+ *
+ * Get the format of the surface.
+ *
+ * Return value: The format of the surface.
+ */
+cairo_format_t
+cairo_xlib_shm_surface_get_format (cairo_surface_t *surface)
+{
+    if (!_cairo_surface_is_xlib_shm (surface)) {
+        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+        return 0;
+    }
+
+    return ((cairo_xlib_shm_surface_t *)surface)->format;
+}
+
+/**
+ * cairo_xlib_shm_surface_get_width
+ * @surface A #cairo_xlib_shm_surface_t
+ *
+ * Get the width of the surface in pixels.
+ *
+ * Return value: The width of the surface in pixels.
+ */
+int
+cairo_xlib_shm_surface_get_width (cairo_surface_t *surface)
+{
+    if (!_cairo_surface_is_xlib_shm (surface)) {
+        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+        return 0;
+    }
+
+    return ((cairo_xlib_shm_surface_t *)surface)->ximage->width;
+}
+
+/**
+ * cairo_xlib_shm_surface_get_height
+ * @surface A #cairo_xlib_shm_surface_t
+ *
+ * Get the height of the surface in pixels.
+ *
+ * Return value: The height of the surface in pixels.
+ */
+int
+cairo_xlib_shm_surface_get_height (cairo_surface_t *surface)
+{
+    if (!_cairo_surface_is_xlib_shm (surface)) {
+        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+        return 0;
+    }
+
+    return ((cairo_xlib_shm_surface_t *)surface)->ximage->height;
+}
+
+/**
+ * cairo_xlib_shm_surface_get_stride
+ * @surface A #cairo_xlib_shm_surface_t
+ *
+ * Get the stride of the surface in bytes.
+ *
+ * Return value: The strude of the image surface in bytes (or 0 if @surface) is
+ * not an image surface). The stride is the distance in bytes from the
+ * beginning of one row of the image data to the beginning of the next row.
+ */
+int
+cairo_xlib_shm_surface_get_stride (cairo_surface_t *surface)
+{
+    if (!_cairo_surface_is_xlib_shm (surface)) {
+        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+        return 0;
+    }
+
+    return ((cairo_xlib_shm_surface_t *)surface)->ximage->bytes_per_line;
+}
+
+cairo_bool_t
+_cairo_surface_is_xlib_shm (const cairo_surface_t *surface)
+{
+    return surface->backend == &cairo_xlib_shm_surface_backend;
+}
+
+#endif /* CAIRO_HAS_XLIB_SHM_SURFACE */
+
diff --git a/src/cairo-xlib-shm.h b/src/cairo-xlib-shm.h
new file mode 100644
index 0000000..60833f5
--- /dev/null
+++ b/src/cairo-xlib-shm.h
@@ -0,0 +1,76 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2008 Mozilla Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ *
+ * Contributor(s):
+ *      Eric Butler <ebutler@mozilla.com>
+ */
+
+#ifndef CAIRO_XLIB_SHM_H
+#define CAIRO_XLIB_SHM_H
+
+#include "cairo.h"
+
+#if CAIRO_HAS_XLIB_SHM_SURFACE
+
+#include <X11/Xlib.h>
+
+CAIRO_BEGIN_DECLS
+
+cairo_public cairo_surface_t *
+cairo_xlib_shm_surface_create (Display *dpy,
+                               Visual *visual,
+                               cairo_format_t format,
+                               int width,
+                               int height);
+
+cairo_public unsigned char*
+cairo_xlib_shm_surface_get_data (cairo_surface_t *surface);
+
+cairo_public cairo_format_t
+cairo_xlib_shm_surface_get_format (cairo_surface_t *surface);
+
+cairo_public int
+cairo_xlib_shm_surface_get_width (cairo_surface_t *surface);
+
+cairo_public int
+cairo_xlib_shm_surface_get_height (cairo_surface_t *surface);
+
+cairo_public int
+cairo_xlib_shm_surface_get_stride (cairo_surface_t *surface);
+
+CAIRO_END_DECLS
+
+#else  /* CAIRO_HAS_XLIB_SHM_SURFACE */
+# error Cairo was not compiled with support for the xlib-shm backend
+#endif /* CAIRO_HAS_XLIB_SHM_SURFACE */
+
+#endif /* CAIRO_XLIB_SHM_H */
+
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 7397573..f03863b 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -40,6 +40,7 @@
 
 #include "cairo-xlib-private.h"
 #include "cairo-xlib-surface-private.h"
+#include "cairo-xlib-shm-surface-private.h"
 #include "cairo-clip-private.h"
 #include "cairo-scaled-font-private.h"
 
@@ -808,6 +809,37 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
     return CAIRO_STATUS_SUCCESS;
 }
 
+#if CAIRO_HAS_XLIB_SHM_SURFACE
+
+static cairo_status_t
+_draw_xlib_shm_surface (cairo_xlib_surface_t *surface,
+                        cairo_xlib_shm_surface_t *image,
+                        int src_x,
+                        int src_y,
+                        int width,
+                        int height,
+                        int dst_x,
+                        int dst_y)
+{
+    cairo_status_t status = _cairo_xlib_surface_ensure_gc (surface);
+    if (status)
+	return status;
+
+    /* XXX: passing false as the last arg means that the server doesn't
+     * notify the client when the drawing is done. Should perhaps add an
+     * option to have True passed, which would put an event in the X event
+     * queue
+     */
+
+    XShmPutImage(surface->dpy, surface->drawable, surface->gc,
+                 image->ximage, src_x, src_y, dst_x, dst_y,
+                 width, height, False);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+#endif /* CAIRO_HAS_XLIB_SHM_SURFACE */
+
 static cairo_status_t
 _draw_image_surface (cairo_xlib_surface_t   *surface,
 		     cairo_image_surface_t  *image,
@@ -1064,6 +1096,34 @@ _cairo_xlib_surface_clone_similar (void			*abstract_surface,
 
 	return CAIRO_STATUS_SUCCESS;
     }
+#if CAIRO_HAS_XLIB_SHM_SURFACE
+    else if (_cairo_surface_is_xlib_shm (src)) {
+        cairo_xlib_shm_surface_t *xshm_src = (cairo_xlib_shm_surface_t *) src;
+
+        if (! CAIRO_FORMAT_VALID (xshm_src->format))
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	clone = (cairo_xlib_surface_t *)
+	    _cairo_xlib_surface_create_similar_with_format (surface, xshm_src->format,
+						xshm_src->ximage->width, xshm_src->ximage->height);
+	if (clone == NULL)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	if (clone->base.status)
+	    return clone->base.status;
+
+	status = _draw_xlib_shm_surface (clone, xshm_src, src_x, src_y,
+			                 width, height, src_x, src_y);
+	if (status) {
+	    cairo_surface_destroy (&clone->base);
+	    return status;
+	}
+
+	*clone_out = &clone->base;
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+#endif /* CAIRO_HAS_XLIB_SHM_SURFACE */
 
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
diff --git a/src/cairo.h b/src/cairo.h
index b00420c..fd02b7c 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1703,6 +1703,7 @@ cairo_surface_status (cairo_surface_t *surface);
  * @CAIRO_SURFACE_TYPE_OS2: The surface is of type os2
  * @CAIRO_SURFACE_TYPE_WIN32_PRINTING: The surface is a win32 printing surface
  * @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image
+ * @CAIRO_SURFACE_TYPE_XLIB_SHM: The surface is of type xlib_shm
  *
  * #cairo_surface_type_t is used to describe the type of a given
  * surface. The surface types are also known as "backends" or "surface
@@ -1741,7 +1742,8 @@ typedef enum _cairo_surface_type {
     CAIRO_SURFACE_TYPE_SVG,
     CAIRO_SURFACE_TYPE_OS2,
     CAIRO_SURFACE_TYPE_WIN32_PRINTING,
-    CAIRO_SURFACE_TYPE_QUARTZ_IMAGE
+    CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
+    CAIRO_SURFACE_TYPE_XLIB_SHM
 } cairo_surface_type_t;
 
 cairo_public cairo_surface_type_t
