diff options
Diffstat (limited to 'gfx/cairo/no-pixman-image-reuse-across-threads.patch')
-rw-r--r-- | gfx/cairo/no-pixman-image-reuse-across-threads.patch | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/gfx/cairo/no-pixman-image-reuse-across-threads.patch b/gfx/cairo/no-pixman-image-reuse-across-threads.patch new file mode 100644 index 0000000000..ccaf5a5e63 --- /dev/null +++ b/gfx/cairo/no-pixman-image-reuse-across-threads.patch @@ -0,0 +1,242 @@ +From +https://cgit.freedesktop.org/cairo/commit/?id=71e8a4c23019b01aa43b334fcb2784c70daae9b5 +https://bugs.freedesktop.org/show_bug.cgi?id=34177 + +diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c +--- a/gfx/cairo/cairo/src/cairo-image-surface.c ++++ b/gfx/cairo/cairo/src/cairo-image-surface.c +@@ -870,17 +870,17 @@ static cairo_bool_t + *ty = _pixman_nearest_sample (*ty); + } else { + if (*tx != floor (*tx) || *ty != floor (*ty)) + return FALSE; + } + return fabs (*tx) < PIXMAN_MAX_INT && fabs (*ty) < PIXMAN_MAX_INT; + } + +-#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; + + static pixman_image_t * + _pixman_transparent_image (void) + { + pixman_image_t *image; +@@ -964,56 +964,59 @@ static pixman_image_t * + 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; + ++#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; + } + + if (__pixman_black_image) { + pixman_image_unref (__pixman_black_image); + __pixman_black_image = NULL; +@@ -1026,19 +1029,20 @@ void + #endif + } + + static pixman_image_t * + _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 (); + + if (pattern->color.alpha_short >= 0xff00) { + if (pattern->color.red_short <= 0x00ff && + pattern->color.green_short <= 0x00ff && + pattern->color.blue_short <= 0x00ff) + { +@@ -1047,46 +1051,48 @@ static pixman_image_t * + + 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; + } + } ++#endif + + color.red = pattern->color.red_short; + color.green = pattern->color.green_short; + color.blue = pattern->color.blue_short; + color.alpha = pattern->color.alpha_short; + + image = pixman_image_create_solid_fill (&color); ++#if PIXMAN_HAS_ATOMIC_OPS + 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); ++#endif + return image; + } + + static double + clamp (double val, double min, double max) + { + return val < min ? min : (val > max ? max : val); + } +@@ -1423,25 +1429,27 @@ static pixman_image_t * + return _pixman_transparent_image (); + } + else + { + return _pixel_to_solid (source, sample.x, sample.y); + } + } + ++#if PIXMAN_HAS_ATOMIC_OPS + /* avoid allocating a 'pattern' image if we can reuse the original */ + if (extend == CAIRO_EXTEND_NONE && + _cairo_matrix_is_translation (&pattern->base.matrix) && + _nearest_sample (filter, &tx, &ty)) + { + *ix = tx; + *iy = ty; + return pixman_image_ref (source->pixman_image); + } ++#endif + + pixman_image = pixman_image_create_bits (source->pixman_format, + source->width, + source->height, + (uint32_t *) source->data, + source->stride); + if (unlikely (pixman_image == NULL)) + return NULL; +@@ -1466,31 +1474,36 @@ static pixman_image_t * + sub->extents.x + sample.x, + sub->extents.y + sample.y); + } else { + if (extend == CAIRO_EXTEND_NONE) + return _pixman_transparent_image (); + } + } + ++#if PIXMAN_HAS_ATOMIC_OPS + if (is_contained && + _cairo_matrix_is_translation (&pattern->base.matrix) && + _nearest_sample (filter, &tx, &ty)) + { + *ix = tx + sub->extents.x; + *iy = ty + sub->extents.y; + 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; + } + } + } + + if (pixman_image == NULL) { |