summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorM Joonas Pihlaja <jpihlaja@cc.helsinki.fi>2011-02-11 19:41:49 +0200
committerM Joonas Pihlaja <jpihlaja@cc.helsinki.fi>2011-02-11 19:41:49 +0200
commitaf403a204a88d882317a3e91abe8f0cc454852a4 (patch)
tree2786f45d29364eaf6b3cc9d3dda5681390014be6
parenta8e8d2aba811487dbb5b682c4f55065008e7ebbd (diff)
image: Avoid reusing pixman images for threadsafety.no-pixman-ref
The pixman_image_ref() and pixman_image_unref() functions aren't threadsafe in current pixman, so we can't share pixman images across contexts where they may end up moving between threads. The main use of these functions is in keeping a global cache of pixman_image_ts for solid colours and reusing the same pixman_image_t for patterns pointing to the same image data where possible. This patch removes those uses from cairo. The only two remaining calls to pixman_image_ref() are done on locally created images
-rw-r--r--src/cairo-debug.c2
-rw-r--r--src/cairo-image-surface.c207
-rw-r--r--src/cairoint.h3
3 files changed, 7 insertions, 205 deletions
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index b8bdfd1f..adf93ae6 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -81,8 +81,6 @@ cairo_debug_reset_static_data (void)
_cairo_clip_reset_static_data ();
- _cairo_image_reset_static_data ();
-
#if CAIRO_HAS_DRM_SURFACE
_cairo_drm_device_reset_static_data ();
#endif
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 6082215f..f3745481 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -861,192 +861,29 @@ _cairo_image_surface_unset_clip_region (cairo_image_surface_t *surface)
pixman_image_set_clip_region32 (surface->pixman_image, NULL);
}
-#if HAS_ATOMIC_OPS
-static pixman_image_t *__pixman_transparent_image;
-static pixman_image_t *__pixman_black_image;
-static pixman_image_t *__pixman_white_image;
-
-static pixman_image_t *
-_pixman_transparent_image (void)
-{
- pixman_image_t *image;
-
- image = __pixman_transparent_image;
- if (unlikely (image == NULL)) {
- pixman_color_t color;
-
- color.red = 0x00;
- color.green = 0x00;
- color.blue = 0x00;
- color.alpha = 0x00;
-
- image = pixman_image_create_solid_fill (&color);
- if (unlikely (image == NULL))
- return NULL;
-
- if (_cairo_atomic_ptr_cmpxchg (&__pixman_transparent_image,
- NULL, image))
- {
- pixman_image_ref (image);
- }
- } else {
- pixman_image_ref (image);
- }
-
- return image;
-}
-
-static pixman_image_t *
-_pixman_black_image (void)
-{
- pixman_image_t *image;
-
- image = __pixman_black_image;
- if (unlikely (image == NULL)) {
- pixman_color_t color;
-
- color.red = 0x00;
- color.green = 0x00;
- color.blue = 0x00;
- color.alpha = 0xffff;
-
- image = pixman_image_create_solid_fill (&color);
- if (unlikely (image == NULL))
- return NULL;
-
- if (_cairo_atomic_ptr_cmpxchg (&__pixman_black_image,
- NULL, image))
- {
- pixman_image_ref (image);
- }
- } else {
- pixman_image_ref (image);
- }
-
- return image;
-}
-
-static pixman_image_t *
-_pixman_white_image (void)
-{
- pixman_image_t *image;
-
- image = __pixman_white_image;
- if (unlikely (image == NULL)) {
- pixman_color_t color;
-
- color.red = 0xffff;
- color.green = 0xffff;
- color.blue = 0xffff;
- color.alpha = 0xffff;
-
- image = pixman_image_create_solid_fill (&color);
- if (unlikely (image == NULL))
- return NULL;
-
- if (_cairo_atomic_ptr_cmpxchg (&__pixman_white_image,
- NULL, image))
- {
- pixman_image_ref (image);
- }
- } else {
- pixman_image_ref (image);
- }
-
- return image;
-}
-#else
static pixman_image_t *
_pixman_transparent_image (void)
{
return _pixman_image_for_solid (&_cairo_pattern_clear);
}
+
static pixman_image_t *
_pixman_black_image (void)
{
return _pixman_image_for_solid (&_cairo_pattern_black);
}
+
static pixman_image_t *
_pixman_white_image (void)
{
return _pixman_image_for_solid (&_cairo_pattern_white);
}
-#endif
-
-static uint32_t
-hars_petruska_f54_1_random (void)
-{
-#define rol(x,k) ((x << k) | (x >> (32-k)))
- static uint32_t x;
- return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
-#undef rol
-}
-
-static struct {
- cairo_color_t color;
- pixman_image_t *image;
-} cache[16];
-static int n_cached;
-
-void
-_cairo_image_reset_static_data (void)
-{
- while (n_cached)
- pixman_image_unref (cache[--n_cached].image);
-
-#if HAS_ATOMIC_OPS
- if (__pixman_transparent_image) {
- pixman_image_unref (__pixman_transparent_image);
- __pixman_transparent_image = NULL;
- }
-
- if (__pixman_black_image) {
- pixman_image_unref (__pixman_black_image);
- __pixman_black_image = NULL;
- }
-
- if (__pixman_white_image) {
- pixman_image_unref (__pixman_white_image);
- __pixman_white_image = NULL;
- }
-#endif
-}
static pixman_image_t *
_pixman_image_for_solid (const cairo_solid_pattern_t *pattern)
{
pixman_color_t color;
pixman_image_t *image;
- int i;
-
-#if HAS_ATOMIC_OPS
- if (pattern->color.alpha_short <= 0x00ff)
- return _pixman_transparent_image ();
-
- if (pattern->color.alpha_short >= 0xff00) {
- if (pattern->color.red_short <= 0x00ff &&
- pattern->color.green_short <= 0x00ff &&
- pattern->color.blue_short <= 0x00ff)
- {
- return _pixman_black_image ();
- }
-
- if (pattern->color.red_short >= 0xff00 &&
- pattern->color.green_short >= 0xff00 &&
- pattern->color.blue_short >= 0xff00)
- {
- return _pixman_white_image ();
- }
- }
-#endif
-
- CAIRO_MUTEX_LOCK (_cairo_image_solid_cache_mutex);
- for (i = 0; i < n_cached; i++) {
- if (_cairo_color_equal (&cache[i].color, &pattern->color)) {
- image = pixman_image_ref (cache[i].image);
- goto UNLOCK;
- }
- }
color.red = pattern->color.red_short;
color.green = pattern->color.green_short;
@@ -1054,20 +891,6 @@ _pixman_image_for_solid (const cairo_solid_pattern_t *pattern)
color.alpha = pattern->color.alpha_short;
image = pixman_image_create_solid_fill (&color);
- if (image == NULL)
- goto UNLOCK;
-
- if (n_cached < ARRAY_LENGTH (cache)) {
- i = n_cached++;
- } else {
- i = hars_petruska_f54_1_random () % ARRAY_LENGTH (cache);
- pixman_image_unref (cache[i].image);
- }
- cache[i].image = pixman_image_ref (image);
- cache[i].color = pattern->color;
-
-UNLOCK:
- CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex);
return image;
}
@@ -1302,6 +1125,7 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
extend = pattern->base.extend;
filter = sampled_area (pattern, extents, &sample);
+ *ix = *iy = 0;
pixman_image = NULL;
if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE &&
(! is_mask || ! pattern->base.has_component_alpha ||
@@ -1339,15 +1163,6 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
}
}
- /* avoid allocating a 'pattern' image if we can reuse the original */
- *ix = *iy = 0;
- if (extend == CAIRO_EXTEND_NONE &&
- _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
- filter, ix, iy))
- {
- return pixman_image_ref (source->pixman_image);
- }
-
pixman_image = pixman_image_create_bits (source->pixman_format,
source->width,
source->height,
@@ -1381,21 +1196,15 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
}
}
- *ix = sub->extents.x;
- *iy = sub->extents.y;
- if (is_contained &&
- _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
- filter, ix, iy))
- {
- return pixman_image_ref (source->pixman_image);
- }
-
/* Avoid sub-byte offsets, force a copy in that case. */
if (PIXMAN_FORMAT_BPP (source->pixman_format) >= 8) {
+ void *data = source->data
+ + sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8
+ + sub->extents.y * source->stride;
pixman_image = pixman_image_create_bits (source->pixman_format,
sub->extents.width,
sub->extents.height,
- (uint32_t *) (source->data + sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8 + sub->extents.y * source->stride),
+ data,
source->stride);
if (unlikely (pixman_image == NULL))
return NULL;
@@ -1403,8 +1212,6 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
}
}
- *ix = *iy = 0;
-
if (pixman_image == NULL) {
struct acquire_source_cleanup *cleanup;
cairo_image_surface_t *image;
diff --git a/src/cairoint.h b/src/cairoint.h
index f203ec53..3afe76b1 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1905,9 +1905,6 @@ cairo_private cairo_bool_t
_pixman_format_to_masks (pixman_format_code_t pixman_format,
cairo_format_masks_t *masks);
-cairo_private void
-_cairo_image_reset_static_data (void);
-
cairo_private cairo_surface_t *
_cairo_image_surface_create_with_pixman_format (unsigned char *data,
pixman_format_code_t pixman_format,