bug 1273701 don't reuse pixman images when not thread-safe r=jrmuizel

From
https://cgit.freedesktop.org/cairo/commit/?id=71e8a4c23019b01aa43b334fcb2784c70daae9b5
https://bugs.freedesktop.org/show_bug.cgi?id=34177

--HG--
extra : amend_source : f0d0f6d62a9c3c1dd00b803463b812db690f756e
extra : transplant_source : %A9v%1Cx4%24%C8i%E8%AF%97U%CB%E2%7C%D2%5E%EARe
This commit is contained in:
Karl Tomlinson 2016-05-18 11:55:29 +12:00
parent dc5be18932
commit 2ed4bd01ae
3 changed files with 279 additions and 22 deletions

View File

@ -214,6 +214,8 @@ ft-no-subpixel-if-surface-disables.patch: bug 929451, don't use subpixel aa for
win32-printing-axis-swap.patch: bug 1205854, workaround for Windows printer drivers that can't handle swapped X and Y axes
no-pixman-image-reuse-across-threads.patch: bug 1273701, picked from 71e8a4c23019b01aa43b334fcb2784c70daae9b5
==== pixman patches ====
pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.

View File

@ -875,7 +875,7 @@ _nearest_sample (cairo_filter_t filter, double *tx, double *ty)
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;
@ -969,23 +969,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)
@ -1002,13 +985,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;
@ -1031,9 +1034,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 ();
@ -1052,7 +1056,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++) {
@ -1061,6 +1064,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;
@ -1068,6 +1072,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;
@ -1082,6 +1087,7 @@ _pixman_image_for_solid (const cairo_solid_pattern_t *pattern)
UNLOCK:
CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex);
#endif
return image;
}
@ -1428,6 +1434,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 */
if (extend == CAIRO_EXTEND_NONE &&
_cairo_matrix_is_translation (&pattern->base.matrix) &&
@ -1437,6 +1444,7 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
*iy = ty;
return pixman_image_ref (source->pixman_image);
}
#endif
pixman_image = pixman_image_create_bits (source->pixman_format,
source->width,
@ -1471,6 +1479,7 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
}
}
#if PIXMAN_HAS_ATOMIC_OPS
if (is_contained &&
_cairo_matrix_is_translation (&pattern->base.matrix) &&
_nearest_sample (filter, &tx, &ty))
@ -1479,13 +1488,17 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
*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;

View File

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