summaryrefslogtreecommitdiff
path: root/packages/cairo
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cairo')
-rw-r--r--packages/cairo/cairo_1.3.12.bb5
-rw-r--r--packages/cairo/files/cairo-surface-cache.patch91
2 files changed, 95 insertions, 1 deletions
diff --git a/packages/cairo/cairo_1.3.12.bb b/packages/cairo/cairo_1.3.12.bb
index 883884d15f..b6a6a482bf 100644
--- a/packages/cairo/cairo_1.3.12.bb
+++ b/packages/cairo/cairo_1.3.12.bb
@@ -3,5 +3,8 @@ DEFAULT_PREFERENCE = "-1"
require cairo.inc
-SRC_URI = "http://cairographics.org/snapshots/cairo-${PV}.tar.gz"
+SRC_URI = "http://cairographics.org/snapshots/cairo-${PV}.tar.gz \
+ file://cairo-surface-cache.patch;patch=1"
+
+PR = "r1"
diff --git a/packages/cairo/files/cairo-surface-cache.patch b/packages/cairo/files/cairo-surface-cache.patch
new file mode 100644
index 0000000000..ee9fc3a46e
--- /dev/null
+++ b/packages/cairo/files/cairo-surface-cache.patch
@@ -0,0 +1,91 @@
+Hi,
+
+Last month, Xan xtraced[1] cairo text drawing (using xlib), and noticed
+that cairo creates (and afterward destroys) a 1x1 pixmap (a cairo
+surface) every time it draws some text. Xft doesn't do this.
+
+Carl and Behdad suggested ways to, like Xft, cache surfaces so as not to
+have to recreate them all the time.
+
+As suggested by Carl in the same thread, I first investigated
+per-pattern caching of acquired surfaces. This didn't work as patterns
+mostly get copied before their surfaces are requested.
+
+Attached patch adds a simple 16-entry static cache to
+_cairo_pattern_acquire_surface_for_solid(). It still needs work, however
+this already yields a speedup[2] of 12% when drawing text using GTK+
+2.10, exceeding the performance of GTK+ 2.6. Yay!
+
+Comments appreciated,
+
+Jorn
+
+diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
+index b488d1f..be63faf 100644
+--- a/src/cairo-pattern.c
++++ b/src/cairo-pattern.c
+@@ -1020,6 +1020,8 @@ _cairo_pattern_acquire_surface_for_gradi
+ return status;
+ }
+
++#define MAX_CACHE_SIZE 16
++
+ static cairo_int_status_t
+ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
+ cairo_surface_t *dst,
+@@ -1030,13 +1032,50 @@ _cairo_pattern_acquire_surface_for_solid
+ cairo_surface_t **out,
+ cairo_surface_attributes_t *attribs)
+ {
+- *out = _cairo_surface_create_similar_solid (dst,
+- CAIRO_CONTENT_COLOR_ALPHA,
+- 1, 1,
+- &pattern->color);
+- if ((*out)->status)
++ /* We have a small cache here, because we don't want to constantly
++ * recreate surfaces for simple solid colors */
++ static struct {
++ cairo_color_t color;
++ cairo_surface_t *surface;
++ } cache[MAX_CACHE_SIZE];
++ static int cache_size = 0;
++
++ cairo_surface_t *surface;
++ int i;
++
++ /* Check cache first */
++ for (i = 0; i < cache_size; i++)
++ if (cache[i].surface->backend == dst->backend &&
++ memcmp (&cache[i].color,
++ &pattern->color,
++ sizeof (cairo_color_t)) == 0)
++ goto DONE;
++
++ /* Not cached, need to create new */
++ surface = _cairo_surface_create_similar_solid (dst,
++ CAIRO_CONTENT_COLOR_ALPHA,
++ 1, 1,
++ &pattern->color);
++ if (surface->status)
+ return CAIRO_STATUS_NO_MEMORY;
+
++ /* Cache new */
++ if (cache_size < MAX_CACHE_SIZE)
++ cache_size++;
++ else {
++ i = random () % MAX_CACHE_SIZE;
++
++ /* Evict old */
++ cairo_surface_destroy (cache[i].surface);
++ }
++
++ cache[i].color = pattern->color;
++ cache[i].surface = surface;
++
++DONE:
++
++ *out = cairo_surface_reference (cache[i].surface);
++
+ attribs->x_offset = attribs->y_offset = 0;
+ cairo_matrix_init_identity (&attribs->matrix);
+ attribs->extend = CAIRO_EXTEND_REPEAT;