summaryrefslogtreecommitdiff
path: root/src/cairo-image-surface.c
diff options
context:
space:
mode:
authorM Joonas Pihlaja <jpihlaja@cc.helsinki.fi>2011-02-19 17:46:45 +0200
committerM Joonas Pihlaja <jpihlaja@cc.helsinki.fi>2011-02-19 18:01:27 +0200
commit71e8a4c23019b01aa43b334fcb2784c70daae9b5 (patch)
tree750744afa0f48fe4b281b7b3aaab980416ac381a /src/cairo-image-surface.c
parent48774c09d04a0b8d3533bdd6d5de6cfe58f54c2b (diff)
image: Avoid reusing pixman images for threadsafety.
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 by wrapping them in a PIXMAN_HAS_ATOMIC_OPS conditional. There is no automatic test this, so we will have to manually turn this code back on when pixman does gain atomic ops. The only two remaining calls to pixman_image_ref() are done on locally created images so they are safe. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=34177
Diffstat (limited to 'src/cairo-image-surface.c')
-rw-r--r--src/cairo-image-surface.c60
1 files changed, 36 insertions, 24 deletions
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index ea6b44905..9006492bb 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -861,7 +861,7 @@ _cairo_image_surface_unset_clip_region (cairo_image_surface_t *surface)
pixman_image_set_clip_region32 (surface->pixman_image, NULL);
}
-#if HAS_ATOMIC_OPS
+#if PIXMAN_HAS_ATOMIC_OPS
static pixman_image_t *__pixman_transparent_image;
static pixman_image_t *__pixman_black_image;
static pixman_image_t *__pixman_white_image;
@@ -955,23 +955,6 @@ _pixman_white_image (void)
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)
@@ -988,13 +971,33 @@ static struct {
} cache[16];
static int n_cached;
+#else /* !PIXMAN_HAS_ATOMIC_OPS */
+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 /* !PIXMAN_HAS_ATOMIC_OPS */
+
void
_cairo_image_reset_static_data (void)
{
+#if PIXMAN_HAS_ATOMIC_OPS
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;
@@ -1017,9 +1020,10 @@ _pixman_image_for_solid (const cairo_solid_pattern_t *pattern)
{
pixman_color_t color;
pixman_image_t *image;
+
+#if PIXMAN_HAS_ATOMIC_OPS
int i;
-#if HAS_ATOMIC_OPS
if (pattern->color.alpha_short <= 0x00ff)
return _pixman_transparent_image ();
@@ -1038,7 +1042,6 @@ _pixman_image_for_solid (const cairo_solid_pattern_t *pattern)
return _pixman_white_image ();
}
}
-#endif
CAIRO_MUTEX_LOCK (_cairo_image_solid_cache_mutex);
for (i = 0; i < n_cached; i++) {
@@ -1047,6 +1050,7 @@ _pixman_image_for_solid (const cairo_solid_pattern_t *pattern)
goto UNLOCK;
}
}
+#endif
color.red = pattern->color.red_short;
color.green = pattern->color.green_short;
@@ -1054,6 +1058,7 @@ _pixman_image_for_solid (const cairo_solid_pattern_t *pattern)
color.alpha = pattern->color.alpha_short;
image = pixman_image_create_solid_fill (&color);
+#if PIXMAN_HAS_ATOMIC_OPS
if (image == NULL)
goto UNLOCK;
@@ -1068,6 +1073,7 @@ _pixman_image_for_solid (const cairo_solid_pattern_t *pattern)
UNLOCK:
CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex);
+#endif
return image;
}
@@ -1302,6 +1308,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,6 +1346,7 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
}
}
+#if PIXMAN_HAS_ATOMIC_OPS
/* avoid allocating a 'pattern' image if we can reuse the original */
*ix = *iy = 0;
if (extend == CAIRO_EXTEND_NONE &&
@@ -1347,6 +1355,7 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
{
return pixman_image_ref (source->pixman_image);
}
+#endif
pixman_image = pixman_image_create_bits (source->pixman_format,
source->width,
@@ -1381,6 +1390,7 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
}
}
+#if PIXMAN_HAS_ATOMIC_OPS
*ix = sub->extents.x;
*iy = sub->extents.y;
if (is_contained &&
@@ -1389,13 +1399,17 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
{
return pixman_image_ref (source->pixman_image);
}
+#endif
/* 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 +1417,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;