diff options
author | Uli Schlachter <psychon@znc.in> | 2011-07-08 16:51:19 +0200 |
---|---|---|
committer | Uli Schlachter <psychon@znc.in> | 2011-07-09 09:42:22 +0200 |
commit | 4153de46892b47b5b21fbef8939ef732935bfe03 (patch) | |
tree | dd7fe4f15c0d81db90c90e36b30d9dbf5347814b | |
parent | e775db35d9306b74867f981a08d253562b15cffd (diff) |
xcb: Track cairo_xcb_picture_t surfaces
When e.g. using an image surface as the source for a xcb surface, a
cairo_xcb_picture_t is created and attached to that image surface as a snapshot.
This contains the Picture that was created on the X11 server.
However, as soon as the cairo_xcb_picture_t's cairo_xcb_screen_t is finished and
destroyed, this picture can't be used anymore. This commit now makes sure all
these Pictures are freed when the screen is finished.
This was found because my X server's memory usage grew quite large. Every time
the app was done drawing, it destroyed its last surface which also destroyed the
last reference to the cairo_xcb_screen_t. This meant that the existing Picture
snapshots couldn't be used anymore, but they were still kept around and used up
memory until there wasn't any free memory left.
Signed-off-by: Uli Schlachter <psychon@znc.in>
-rw-r--r-- | src/cairo-xcb-private.h | 3 | ||||
-rw-r--r-- | src/cairo-xcb-screen.c | 13 | ||||
-rw-r--r-- | src/cairo-xcb-surface-render.c | 3 |
3 files changed, 19 insertions, 0 deletions
diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h index 82e05c3c..3f085e0d 100644 --- a/src/cairo-xcb-private.h +++ b/src/cairo-xcb-private.h @@ -123,6 +123,8 @@ struct _cairo_xcb_picture { int x0, y0; int x, y; + + cairo_list_t link; }; #if CAIRO_HAS_XLIB_XCB_FUNCTIONS @@ -189,6 +191,7 @@ struct _cairo_xcb_screen { cairo_list_t link; cairo_list_t surfaces; + cairo_list_t pictures; }; struct _cairo_xcb_connection { diff --git a/src/cairo-xcb-screen.c b/src/cairo-xcb-screen.c index b61f20b7..efe42cf9 100644 --- a/src/cairo-xcb-screen.c +++ b/src/cairo-xcb-screen.c @@ -62,6 +62,18 @@ _cairo_xcb_screen_finish (cairo_xcb_screen_t *screen) cairo_surface_destroy (surface); } + while (! cairo_list_is_empty (&screen->pictures)) { + cairo_surface_t *surface; + + surface = &cairo_list_first_entry (&screen->pictures, + cairo_xcb_picture_t, + link)->base; + + cairo_surface_reference (surface); + cairo_surface_finish (surface); + cairo_surface_destroy (surface); + } + for (i = 0; i < screen->solid_cache_size; i++) cairo_surface_destroy (screen->solid_cache[i].picture); @@ -231,6 +243,7 @@ _cairo_xcb_screen_get (xcb_connection_t *xcb_connection, sizeof (struct pattern_cache_entry)); cairo_list_init (&screen->link); cairo_list_init (&screen->surfaces); + cairo_list_init (&screen->pictures); if (connection->flags & CAIRO_XCB_HAS_DRI2) screen->device = _xcb_drm_device (xcb_connection, xcb_screen); diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c index 0c31820c..e8d6c52d 100644 --- a/src/cairo-xcb-surface-render.c +++ b/src/cairo-xcb-surface-render.c @@ -85,6 +85,7 @@ _cairo_xcb_picture_finish (void *abstract_surface) cairo_status_t status; status = _cairo_xcb_connection_acquire (connection); + cairo_list_del (&surface->link); if (unlikely (status)) return status; @@ -125,6 +126,8 @@ _cairo_xcb_picture_create (cairo_xcb_screen_t *screen, &screen->connection->device, _cairo_content_from_pixman_format (pixman_format)); + cairo_list_add (&surface->link, &screen->pictures); + surface->screen = screen; surface->picture = _cairo_xcb_connection_get_xid (screen->connection); surface->pixman_format = pixman_format; |