diff --git a/gfx/cairo/README b/gfx/cairo/README
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -71,16 +71,18 @@ quartz-cache-CGImageRef.patch: cache CGI
 quartz-remove-snapshot.patch: remove broken implementation of backend snapshot
 
 quartz-cglayers.patch: add support for cairo surfaces backed by CGLayers
 
 quartz-cglayers-fix-fallback.patch: Bug 572912; fix bug in fallback code in previous patch
 
 quartz-get-image.patch: Bug 575521; add a way to get the image surface associated with a surface
 
+quartz-create-for-data.patch: Bug 575521; add a way to create quartz surfaces backed with application-provided data
+
 premultiply-alpha-solid-gradients.patch: bug 539165; multiply the solid color by the alpha component before using it for a solid surface
 
 xlib-initialize-members.path: bug 548793; initialize XRender version if the server doesn't have the extension
 
 remove-comma: remove a comma from enum
 
 d2d.patch: add d2d support
 
diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h
--- a/gfx/cairo/cairo/src/cairo-quartz-private.h
+++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
@@ -63,16 +63,18 @@ typedef struct cairo_quartz_surface {
     CGImageRef bitmapContextImage;
 
     /**
      * If non-null, this is the CGLayer for the surface.
      */
     CGLayerRef cgLayer;
 
     cairo_rectangle_int_t extents;
+
+    cairo_bool_t ownsData;
 } cairo_quartz_surface_t;
 
 typedef struct cairo_quartz_image_surface {
     cairo_surface_t base;
 
     cairo_rectangle_int_t extents;
 
     CGImageRef image;
diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
@@ -1880,20 +1880,21 @@ _cairo_quartz_surface_finish (void *abst
     surface->cgContext = NULL;
 
     if (surface->bitmapContextImage) {
         CGImageRelease (surface->bitmapContextImage);
         surface->bitmapContextImage = NULL;
     }
 
     if (surface->imageSurfaceEquiv) {
-	_cairo_image_surface_assume_ownership_of_data (surface->imageSurfaceEquiv);
+        if (surface->ownsData)
+            _cairo_image_surface_assume_ownership_of_data (surface->imageSurfaceEquiv);
 	cairo_surface_destroy (surface->imageSurfaceEquiv);
 	surface->imageSurfaceEquiv = NULL;
-    } else if (surface->imageData) {
+    } else if (surface->imageData && surface->ownsData) {
         free (surface->imageData);
     }
 
     surface->imageData = NULL;
 
     if (surface->cgLayer) {
         CGLayerRelease (surface->cgLayer);
     }
@@ -2888,16 +2889,17 @@ _cairo_quartz_surface_create_internal (C
 
     surface->cgContext = cgContext;
     surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
 
     surface->imageData = NULL;
     surface->imageSurfaceEquiv = NULL;
     surface->bitmapContextImage = NULL;
     surface->cgLayer = NULL;
+    surface->ownsData = TRUE;
 
     return surface;
 }
 
 /**
  * cairo_quartz_surface_create_for_cg_context
  * @cgContext: the existing CGContext for which to create the surface
  * @width: width of the surface, in pixels
@@ -3031,23 +3033,103 @@ cairo_quartz_surface_create_cg_layer (ca
  *
  * Since: 1.4
  **/
 cairo_surface_t *
 cairo_quartz_surface_create (cairo_format_t format,
 			     unsigned int width,
 			     unsigned int height)
 {
+    int stride;
+    unsigned char *data;
+
+    if (!_cairo_quartz_verify_surface_size(width, height))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
+
+    if (width == 0 || height == 0) {
+	return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format),
+									 width, height);
+    }
+
+    if (format == CAIRO_FORMAT_ARGB32 ||
+	format == CAIRO_FORMAT_RGB24)
+    {
+	stride = width * 4;
+    } else if (format == CAIRO_FORMAT_A8) {
+	stride = width;
+    } else if (format == CAIRO_FORMAT_A1) {
+	/* I don't think we can usefully support this, as defined by
+	 * cairo_format_t -- these are 1-bit pixels stored in 32-bit
+	 * quantities.
+	 */
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+    } else {
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+    }
+
+    /* The Apple docs say that for best performance, the stride and the data
+     * pointer should be 16-byte aligned.  malloc already aligns to 16-bytes,
+     * so we don't have to anything special on allocation.
+     */
+    stride = (stride + 15) & ~15;
+
+    data = _cairo_malloc_ab (height, stride);
+    if (!data) {
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
+
+    /* zero the memory to match the image surface behaviour */
+    memset (data, 0, height * stride);
+
+    cairo_quartz_surface_t *surf;
+    surf = (cairo_quartz_surface_t *) cairo_quartz_surface_create_for_data
+                                           (data, format, width, height, stride);
+    if (surf->base.status) {
+        free (data);
+        return (cairo_surface_t *) surf;
+    }
+
+    // We created this data, so we can delete it.
+    surf->ownsData = TRUE;
+
+    return (cairo_surface_t *) surf;
+}
+
+/**
+ * cairo_quartz_surface_create_for_data
+ * @data: a pointer to a buffer supplied by the application in which
+ *     to write contents. This pointer must be suitably aligned for any
+ *     kind of variable, (for example, a pointer returned by malloc).
+ * @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 Quartz surface backed by a CGBitmap.  The surface is
+ * created using the Device RGB (or Device Gray, for A8) color space.
+ * All Cairo operations, including those that require software
+ * rendering, will succeed on this surface.
+ *
+ * Return value: the newly created surface.
+ *
+ * Since: 1.12
+ **/
+cairo_surface_t *
+cairo_quartz_surface_create_for_data (unsigned char *data,
+				      cairo_format_t format,
+				      unsigned int width,
+				      unsigned int height,
+				      unsigned int stride)
+{
     cairo_quartz_surface_t *surf;
     CGContextRef cgc;
     CGColorSpaceRef cgColorspace;
     CGBitmapInfo bitinfo;
-    void *imageData;
-    int stride;
+    void *imageData = data;
     int bitsPerComponent;
+    unsigned int i;
 
     // verify width and height of surface
     if (!_cairo_quartz_verify_surface_size(width, height))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
 
     if (width == 0 || height == 0) {
 	return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format),
 									 width, height);
@@ -3058,47 +3140,30 @@ cairo_quartz_surface_create (cairo_forma
     {
 	cgColorspace = CGColorSpaceCreateDeviceRGB();
 	bitinfo = kCGBitmapByteOrder32Host;
 	if (format == CAIRO_FORMAT_ARGB32)
 	    bitinfo |= kCGImageAlphaPremultipliedFirst;
 	else
 	    bitinfo |= kCGImageAlphaNoneSkipFirst;
 	bitsPerComponent = 8;
-	stride = width * 4;
     } else if (format == CAIRO_FORMAT_A8) {
 	cgColorspace = NULL;
-	stride = width;
 	bitinfo = kCGImageAlphaOnly;
 	bitsPerComponent = 8;
     } else if (format == CAIRO_FORMAT_A1) {
 	/* I don't think we can usefully support this, as defined by
 	 * cairo_format_t -- these are 1-bit pixels stored in 32-bit
 	 * quantities.
 	 */
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
     } else {
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
     }
 
-    /* The Apple docs say that for best performance, the stride and the data
-     * pointer should be 16-byte aligned.  malloc already aligns to 16-bytes,
-     * so we don't have to anything special on allocation.
-     */
-    stride = (stride + 15) & ~15;
-
-    imageData = _cairo_malloc_ab (height, stride);
-    if (!imageData) {
-	CGColorSpaceRelease (cgColorspace);
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-    }
-
-    /* zero the memory to match the image surface behaviour */
-    memset (imageData, 0, height * stride);
-
     cgc = CGBitmapContextCreate (imageData,
 				 width,
 				 height,
 				 bitsPerComponent,
 				 stride,
 				 cgColorspace,
 				 bitinfo);
     CGColorSpaceRelease (cgColorspace);
@@ -3118,16 +3183,17 @@ cairo_quartz_surface_create (cairo_forma
 	CGContextRelease (cgc);
 	free (imageData);
 	// create_internal will have set an error
 	return (cairo_surface_t*) surf;
     }
 
     surf->imageData = imageData;
     surf->imageSurfaceEquiv = cairo_image_surface_create_for_data (imageData, format, width, height, stride);
+    surf->ownsData = FALSE;
 
     return (cairo_surface_t *) surf;
 }
 
 /**
  * cairo_quartz_surface_get_cg_context
  * @surface: the Cairo Quartz surface
  *
diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h
--- a/gfx/cairo/cairo/src/cairo-quartz.h
+++ b/gfx/cairo/cairo/src/cairo-quartz.h
@@ -45,16 +45,23 @@
 CAIRO_BEGIN_DECLS
 
 cairo_public cairo_surface_t *
 cairo_quartz_surface_create (cairo_format_t format,
                              unsigned int width,
                              unsigned int height);
 
 cairo_public cairo_surface_t *
+cairo_quartz_surface_create_for_data (unsigned char *data,
+				      cairo_format_t format,
+				      unsigned int width,
+				      unsigned int height,
+				      unsigned int stride);
+
+cairo_public cairo_surface_t *
 cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface,
                                       unsigned int width,
                                       unsigned int height);
 
 cairo_public cairo_surface_t *
 cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
                                             unsigned int width,
                                             unsigned int height);
diff --git a/gfx/cairo/cairo/src/cairo-rename.h b/gfx/cairo/cairo/src/cairo-rename.h
--- a/gfx/cairo/cairo/src/cairo-rename.h
+++ b/gfx/cairo/cairo/src/cairo-rename.h
@@ -176,16 +176,17 @@
 #define cairo_qpainter_surface_get_image _moz_cairo_qpainter_surface_get_image
 #define cairo_qpainter_surface_get_qimage _moz_cairo_qpainter_surface_get_qimage
 #define cairo_qpainter_surface_get_qpainter _moz_cairo_qpainter_surface_get_qpainter
 #define cairo_quartz_font_face_create_for_atsu_font_id _moz_cairo_quartz_font_face_create_for_atsu_font_id
 #define cairo_quartz_font_face_create_for_cgfont _moz_cairo_quartz_font_face_create_for_cgfont
 #define cairo_quartz_image_surface_create _moz_cairo_quartz_image_surface_create
 #define cairo_quartz_image_surface_get_image _moz_cairo_quartz_image_surface_get_image
 #define cairo_quartz_surface_create _moz_cairo_quartz_surface_create
+#define cairo_quartz_surface_create_for_data _moz_cairo_quartz_surface_create_for_data
 #define cairo_quartz_surface_create_for_cg_context _moz_cairo_quartz_surface_create_for_cg_context
 #define cairo_quartz_surface_get_cg_context _moz_cairo_quartz_surface_get_cg_context
 #define cairo_quartz_surface_get_image _moz_cairo_quartz_surface_get_image
 #define cairo_rectangle _moz_cairo_rectangle
 #define cairo_rectangle_list_destroy _moz_cairo_rectangle_list_destroy
 #define cairo_reference _moz_cairo_reference
 #define cairo_rel_curve_to _moz_cairo_rel_curve_to
 #define cairo_rel_line_to _moz_cairo_rel_line_to
