[cairo-commit] 3 commits - src/cairo-pattern.c test/Makefile.am test/solid-pattern-cache-stress.c test/solid-pattern-cache-stress-ref.png test/xlib-surface-source.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Jun 19 04:30:52 PDT 2008


 src/cairo-pattern.c                     |    9 +
 test/Makefile.am                        |    1 
 test/solid-pattern-cache-stress-ref.png |binary
 test/solid-pattern-cache-stress.c       |  148 +++++++++++++++++++++++++-------
 test/xlib-surface-source.c              |    4 
 5 files changed, 129 insertions(+), 33 deletions(-)

New commits:
commit 565644e616ea64f97769d8939beb155f4031da2f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 19 11:42:43 2008 +0100

    [cairo-pattern] Band-aid for the solid surface cache.
    
    Behdad noticed that the mixing of dissimilar surfaces within the cache
    was fubar
    (http://lists.cairographics.org/archives/cairo/2008-June/014348.html).
    
    This corrects the dereferencing of the evicted surface, but leaves open
    the question of the future of the cache.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 89e92ca..b9f068a 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1453,9 +1453,10 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t	     *pattern,
 					   &pattern->base);
 	    if (status)
 		goto UNLOCK;
+
+	    cairo_surface_reference (surface);
 	} else {
 	    /* Unable to reuse, evict */
-	    cairo_surface_destroy (surface);
 	    surface = NULL;
 	}
     }
@@ -1485,6 +1486,7 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t	     *pattern,
 	i = solid_surface_cache.size++;
 
     solid_surface_cache.cache[i].color   = pattern->color;
+    cairo_surface_destroy (solid_surface_cache.cache[i].surface);
     solid_surface_cache.cache[i].surface = surface;
 
 DONE:
@@ -1513,8 +1515,11 @@ _cairo_pattern_reset_solid_surface_cache (void)
     /* remove surfaces starting from the end so that solid_surface_cache.cache
      * is always in a consistent state when we release the mutex. */
     while (solid_surface_cache.size) {
-	cairo_surface_t *surface = solid_surface_cache.cache[solid_surface_cache.size-1].surface;
+	cairo_surface_t *surface;
+
 	solid_surface_cache.size--;
+	surface = solid_surface_cache.cache[solid_surface_cache.size].surface;
+	solid_surface_cache.cache[solid_surface_cache.size].surface = NULL;
 
 	/* release the lock to avoid the possibility of a recursive
 	 * deadlock when the scaled font destroy closure gets called */
commit 47d8739ea198510919b2611c34a44aa3c63f3f59
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 19 11:38:38 2008 +0100

    [test/xlib-surface-source] Build under --disable-xlib-xrender.
    
    Add an ifdef to support compiling without XRender.

diff --git a/test/xlib-surface-source.c b/test/xlib-surface-source.c
index 3a70a4d..192dadc 100644
--- a/test/xlib-surface-source.c
+++ b/test/xlib-surface-source.c
@@ -53,6 +53,7 @@ cleanup (void *data)
 static cairo_surface_t *
 create_source_surface (int size)
 {
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
     XRenderPictFormat *xrender_format;
     struct closure *data;
     cairo_surface_t *surface;
@@ -73,4 +74,7 @@ create_source_surface (int size)
     cairo_surface_set_user_data (surface, &closure_key, data, cleanup);
 
     return surface;
+#else
+    return NULL;
+#endif
 }
commit 38c4bcc2da225b36455ee3da396305a7d93d4c1d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 19 09:44:58 2008 +0100

    [test/solid-pattern-cache-stress] Do what it says on the tin.
    
    Actually draw to the surface after setting the source in order to
    trigger use of the solid surface cache.

diff --git a/test/Makefile.am b/test/Makefile.am
index 7dba516..c7c265f 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -638,6 +638,7 @@ REFERENCE_IMAGES = \
 	stroke-image-pdf-ref.png \
 	stroke-image-ps-ref.png \
 	stroke-image-quartz-ref.png \
+	solid-pattern-cache-stress-ref.png	\
 	source-clip-ref.png	\
 	source-clip-scale-quartz-ref.png	\
 	source-clip-scale-ps-argb32-ref.png	\
diff --git a/test/solid-pattern-cache-stress-ref.png b/test/solid-pattern-cache-stress-ref.png
new file mode 100644
index 0000000..e0e8498
Binary files /dev/null and b/test/solid-pattern-cache-stress-ref.png differ
diff --git a/test/solid-pattern-cache-stress.c b/test/solid-pattern-cache-stress.c
index 957b204..39c6454 100644
--- a/test/solid-pattern-cache-stress.c
+++ b/test/solid-pattern-cache-stress.c
@@ -28,24 +28,118 @@
 #endif
 
 #include "cairo-test.h"
+#include <stdlib.h> /* drand48() */
+
+#define LOOPS 10
+#define NRAND 100
+
+#ifndef HAVE_DRAND48
+#define drand48() (rand () / (double) RAND_MAX)
+#endif
 
 static cairo_test_draw_function_t draw;
 
 cairo_test_t test = {
     "solid-pattern-cache-stress",
     "Stress the solid pattern cache and ensure it behaves",
-    0, 0,
+    1, 1,
     draw
 };
-#include <cairo.h>
-#include <stdlib.h>
 
-#define LOOPS 10
-#define NRAND 100
+static cairo_t *
+_cairo_create_similar (cairo_t *cr, int width, int height)
+{
+    cairo_surface_t *similar;
 
-#ifndef HAVE_DRAND48
-#define drand48() (rand () / (double) RAND_MAX)
-#endif
+    similar = cairo_surface_create_similar (cairo_get_target (cr),
+	                                    cairo_surface_get_content (cairo_get_target (cr)),
+				            width, height);
+    cr = cairo_create (similar);
+    cairo_surface_destroy (similar);
+
+    return cr;
+}
+
+static cairo_t *
+_cairo_create_image (cairo_t *cr, cairo_format_t format, int width, int height)
+{
+    cairo_surface_t *image;
+
+    image = cairo_image_surface_create (format, width, height);
+    cr = cairo_create (image);
+    cairo_surface_destroy (image);
+
+    return cr;
+}
+
+static void
+_draw (cairo_t *cr,
+       double red,
+       double green,
+       double blue)
+{
+    cairo_text_extents_t extents;
+
+    cairo_set_source_rgb (cr, red, green, blue);
+    cairo_paint (cr);
+
+    cairo_move_to (cr, 0, 0);
+    cairo_line_to (cr, 1, 1);
+    cairo_stroke (cr);
+
+    cairo_mask (cr, cairo_get_source (cr));
+
+    cairo_text_extents (cr, "cairo", &extents);
+    cairo_move_to (cr,
+	           -extents.x_bearing - .5 * extents.width,
+		   -extents.y_bearing - .5 * extents.height);
+    cairo_show_text (cr, "cairo");
+
+}
+
+static void
+use_similar (cairo_t *cr,
+	    double red,
+	    double green,
+	    double blue)
+{
+    cr = _cairo_create_similar (cr, 1, 1);
+
+    _draw (cr, red, green, blue);
+
+    cairo_destroy (cr);
+}
+
+static void
+use_image (cairo_t *cr,
+	   cairo_format_t format,
+	   double red,
+	   double green,
+	   double blue)
+{
+    cr = _cairo_create_image (cr, format, 1, 1);
+
+    _draw (cr, red, green, blue);
+
+    cairo_destroy (cr);
+}
+
+static void
+use_solid (cairo_t *cr,
+	   double red,
+	   double green,
+	   double blue)
+{
+    /* mix in dissimilar solids */
+    use_image (cr, CAIRO_FORMAT_A1, red, green, blue);
+    use_image (cr, CAIRO_FORMAT_A8, red, green, blue);
+    use_image (cr, CAIRO_FORMAT_RGB24, red, green, blue);
+    use_image (cr, CAIRO_FORMAT_ARGB32, red, green, blue);
+
+    use_similar (cr, red, green, blue);
+
+    _draw (cr, red, green, blue);
+}
 
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
@@ -54,32 +148,25 @@ draw (cairo_t *cr, int width, int height)
     int i;
 
     for (loop = 0; loop < LOOPS; loop++) {
-	cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
-	cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); /* red */
-	cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); /* green */
-	cairo_set_source_rgb (cr, 1.0, 1.0, 0.0); /* yellow */
-	cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */
-	cairo_set_source_rgb (cr, 1.0, 0.0, 1.0); /* magenta */
-	cairo_set_source_rgb (cr, 0.0, 1.0, 1.0); /* cyan */
-	cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
-
-	cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); /* black */
-	cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 1.0); /* red */
-	cairo_set_source_rgba (cr, 0.0, 1.0, 0.0, 1.0); /* green */
-	cairo_set_source_rgba (cr, 1.0, 1.0, 0.0, 1.0); /* yellow */
-	cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 1.0); /* blue */
-	cairo_set_source_rgba (cr, 1.0, 0.0, 1.0, 1.0); /* magenta */
-	cairo_set_source_rgba (cr, 0.0, 1.0, 1.0, 1.0); /* cyan */
-	cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0); /* white */
+	for (i = 0; i < LOOPS; i++) {
+	    use_solid (cr, 0.0, 0.0, 0.0); /* black */
+	    use_solid (cr, 1.0, 0.0, 0.0); /* red */
+	    use_solid (cr, 0.0, 1.0, 0.0); /* green */
+	    use_solid (cr, 1.0, 1.0, 0.0); /* yellow */
+	    use_solid (cr, 0.0, 0.0, 1.0); /* blue */
+	    use_solid (cr, 1.0, 0.0, 1.0); /* magenta */
+	    use_solid (cr, 0.0, 1.0, 1.0); /* cyan */
+	    use_solid (cr, 1.0, 1.0, 1.0); /* white */
+	}
 
 	for (i = 0; i < NRAND; i++)
-	    cairo_set_source_rgba (cr,
-		                   drand48 (),
-				   drand48 (),
-				   drand48 (),
-				   drand48 ());
+	    use_solid (cr, drand48 (), drand48 (), drand48 ());
     }
 
+    /* stress test only, so clear the surface before comparing */
+    cairo_set_source_rgb (cr, 0, 0, 1);
+    cairo_paint (cr);
+
     return CAIRO_TEST_SUCCESS;
 }
 
@@ -88,4 +175,3 @@ main (void)
 {
     return cairo_test (&test);
 }
-


More information about the cairo-commit mailing list