bug 1273701 don't reuse pixman images when not thread-safe r=jrmuizel a=ritu
authorKarl Tomlinson <karlt+@karlt.net>
Wed, 18 May 2016 11:55:29 +1200
changeset 326349 256e89214e1801962d7647e7933c6409b2d61627
parent 326348 59dbf171604d52960e6e54cbefdb52d7bbcb989d
child 326350 f7d5d9e9a35ff1280f4ee7d84ec5aa62f0da279a
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel, ritu
bugs1273701, 34177
milestone47.0
bug 1273701 don't reuse pixman images when not thread-safe r=jrmuizel a=ritu From https://cgit.freedesktop.org/cairo/commit/?id=71e8a4c23019b01aa43b334fcb2784c70daae9b5 https://bugs.freedesktop.org/show_bug.cgi?id=34177
gfx/cairo/README
gfx/cairo/cairo/src/cairo-image-surface.c
gfx/cairo/no-pixman-image-reuse-across-threads.patch
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -209,16 +209,18 @@ xlib-flush-glyphs.patch: bug 839745, flu
 dasharray-zero-gap.patch: bug 885585, ensure strokes get painted when the gaps in a dash array are all zero length
 
 cairo-mask-extends-bug.patch: bug 918671, sometimes when building a mask we wouldn't clear it properly. This is fixed in cairo 1.12
 
 ft-no-subpixel-if-surface-disables.patch: bug 929451, don't use subpixel aa for ft fonts on surfaces that don't support it
 
 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.
 
 pixman-rename-and-endian.patch: include cairo-platform.h for renaming of external symbols and endian macros
 
 NOTE: we previously supported ARM assembler on MSVC, this has been removed because of the maintenance burden
 
--- 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) {
new file mode 100644
--- /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) {