xcb: Remove _cairo_xcb_picture_copy

All cairo_xcb_picture_t now get their own, private Picture instead of possibly
sharing it with a cairo_xcb_surface_t.

This solves a cyclic dependency which caused cairo_xcb_picture_t to be leaked
until their device was finished.

When an xcb surface was used as a source, a cairo_xcb_picture_t was created
which kept a reference to the surface. This picture was then added as a snapshot
to the surface which caused the surface to own a reference to the picture.

As a result, the Picture and possibly its associated Pixmap were not freed on
the X11 server which could thus run out of memory.

This change causes more Pictures to be created which could possibly slow down
cairo-xcb. There seems to be no measurable difference with cairo-perf-trace. For
the micro benchmarks, this has the most impact on paint_similar-rgba_source.512:

       min(ticks)  min(ms) median(ms) stddev. iterations overhead
before     158732    0.159    0.159  0.11%   4: 1651.49
after      162579    0.163    0.163  0.18%   4: 1612.41

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=34912

Signed-off-by: Uli Schlachter <psychon@znc.in>
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index cb81507..8829dda 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -62,8 +62,6 @@
 typedef struct _cairo_xcb_picture {
     cairo_surface_t base;
 
-    cairo_surface_t *owner;
-
     cairo_xcb_screen_t *screen;
     xcb_render_picture_t picture;
     xcb_render_pictformat_t xrender_format;
@@ -105,16 +103,11 @@
     cairo_xcb_connection_t *connection = _picture_to_connection (surface);
     cairo_status_t status;
 
-    if (surface->owner != NULL)
-	cairo_surface_destroy (surface->owner);
-
     status = _cairo_xcb_connection_acquire (connection);
     if (unlikely (status))
 	return status;
 
-    if (surface->owner == NULL) {
-	_cairo_xcb_connection_render_free_picture (connection, surface->picture);
-    }
+    _cairo_xcb_connection_render_free_picture (connection, surface->picture);
 
     _cairo_xcb_connection_release (connection);
 
@@ -152,7 +145,6 @@
 			 _cairo_content_from_pixman_format (pixman_format));
 
     surface->screen = screen;
-    surface->owner = NULL;
     surface->picture = _cairo_xcb_connection_get_xid (screen->connection);
     surface->pixman_format = pixman_format;
     surface->xrender_format = xrender_format;
@@ -170,41 +162,6 @@
     return surface;
 }
 
-static cairo_xcb_picture_t *
-_cairo_xcb_picture_copy (cairo_xcb_surface_t *target)
-{
-    cairo_xcb_picture_t *surface;
-
-    surface = malloc (sizeof (cairo_xcb_picture_t));
-    if (unlikely (surface == NULL))
-	return (cairo_xcb_picture_t *)
-	    _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
-    _cairo_surface_init (&surface->base,
-			 &_cairo_xcb_picture_backend,
-			 target->base.device,
-			 target->base.content);
-
-    surface->screen = target->screen;
-    surface->owner = cairo_surface_reference (&target->base);
-    _cairo_xcb_surface_ensure_picture (target);
-    surface->picture = target->picture;
-    surface->pixman_format = target->pixman_format;
-    surface->xrender_format = target->xrender_format;
-
-    surface->x0 = surface->y0 = 0;
-    surface->x = surface->y = 0;
-    surface->width = target->width;
-    surface->height = target->height;
-
-    surface->transform = identity_transform;
-    surface->extend = CAIRO_EXTEND_NONE;
-    surface->filter = CAIRO_FILTER_NEAREST;
-    surface->has_component_alpha = FALSE;
-
-    return surface;
-}
-
 static inline cairo_bool_t
 _operator_is_supported (uint32_t flags, cairo_operator_t op)
 {
@@ -978,25 +935,21 @@
     if (source->drm != NULL)
 	cairo_surface_flush (source->drm);
 
-    if (source->owns_pixmap && ! force) {
-	picture = _cairo_xcb_picture_copy (source);
-    } else {
-	picture = _cairo_xcb_picture_create (source->screen,
-					     source->xrender_format,
-					     source->pixman_format,
-					     source->width,
-					     source->height);
-	if (unlikely (picture->base.status))
-	    return picture;
+    picture = _cairo_xcb_picture_create (source->screen,
+					 source->xrender_format,
+					 source->pixman_format,
+					 source->width,
+					 source->height);
+    if (unlikely (picture->base.status))
+	return picture;
 
-	_cairo_xcb_connection_render_create_picture (source->connection,
-						     picture->picture,
-						     source->drawable,
-						     source->xrender_format,
-						     XCB_RENDER_CP_GRAPHICS_EXPOSURE |
-						     XCB_RENDER_CP_SUBWINDOW_MODE,
-						     values);
-    }
+    _cairo_xcb_connection_render_create_picture (source->connection,
+						 picture->picture,
+						 source->drawable,
+						 source->xrender_format,
+						 XCB_RENDER_CP_GRAPHICS_EXPOSURE |
+						 XCB_RENDER_CP_SUBWINDOW_MODE,
+						 values);
 
     return picture;
 }