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) {