diff options
-rw-r--r-- | packages/cairo/cairo_1.3.12.bb | 4 | ||||
-rw-r--r-- | packages/cairo/files/cairo-surface-cache-3.patch | 371 | ||||
-rw-r--r-- | packages/cairo/files/cairo-surface-cache.patch | 91 |
3 files changed, 373 insertions, 93 deletions
diff --git a/packages/cairo/cairo_1.3.12.bb b/packages/cairo/cairo_1.3.12.bb index b6a6a482bf..cb83b8e4a2 100644 --- a/packages/cairo/cairo_1.3.12.bb +++ b/packages/cairo/cairo_1.3.12.bb @@ -4,7 +4,7 @@ DEFAULT_PREFERENCE = "-1" require cairo.inc SRC_URI = "http://cairographics.org/snapshots/cairo-${PV}.tar.gz \ - file://cairo-surface-cache.patch;patch=1" + file://cairo-surface-cache-3.patch;patch=1" -PR = "r1" +PR = "r2" diff --git a/packages/cairo/files/cairo-surface-cache-3.patch b/packages/cairo/files/cairo-surface-cache-3.patch new file mode 100644 index 0000000000..ba714359a6 --- /dev/null +++ b/packages/cairo/files/cairo-surface-cache-3.patch @@ -0,0 +1,371 @@ +diff --git a/src/cairo-clip.c b/src/cairo-clip.c +diff --git a/src/cairo-color.c b/src/cairo-color.c +index a348839..0688167 100644 +--- a/src/cairo-color.c ++++ b/src/cairo-color.c +@@ -159,3 +159,10 @@ _cairo_color_get_rgba_premultiplied (cai + *blue = color->blue * color->alpha; + *alpha = color->alpha; + } ++ ++cairo_bool_t ++_cairo_color_equal (cairo_color_t *color_a, ++ cairo_color_t *color_b) ++{ ++ return (memcmp (color_a, color_b, sizeof (cairo_color_t)) == 0); ++} +diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c +index 686510d..96ee212 100644 +--- a/src/cairo-directfb-surface.c ++++ b/src/cairo-directfb-surface.c +@@ -1514,6 +1514,15 @@ _cairo_directfb_surface_show_glyphs ( vo + } + #endif /* DFB_SHOW_GLYPHS */ + ++static cairo_bool_t ++_cairo_directfb_surface_is_compatible (void *surface_a, ++ void *surface_b) ++{ ++ cairo_directfb_surface_t *a = (cairo_directfb_surface_t*) surface_a; ++ cairo_directfb_surface_t *b = (cairo_directfb_surface_t*) surface_b; ++ ++ return (a->dfb == b->dfb); ++} + + static cairo_surface_backend_t cairo_directfb_surface_backend = { + CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/ +@@ -1564,7 +1573,8 @@ #if DFB_SHOW_GLYPHS + #else + NULL, /* show_glyphs */ + #endif +- NULL /* snapshot */ ++ NULL, /* snapshot */ ++ _cairo_directfb_is_compatible + }; + + +diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c +diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c +index f492739..79e0162 100644 +--- a/src/cairo-glitz-surface.c ++++ b/src/cairo-glitz-surface.c +@@ -1799,6 +1799,19 @@ _cairo_glitz_surface_scaled_glyph_fini ( + } + } + ++static cairo_bool_t ++_cairo_glitz_surface_is_compatible (void *surface_a, ++ void *surface_b) ++{ ++ cairo_glitz_surface_t *a = (cairo_glitz_surface_t*) surface_a; ++ cairo_glitz_surface_t *b = (cairo_glitz_surface_t*) surface_b; ++ ++ glitz_drawable *drawable_a = glitz_surface_get_drawable (a->surface); ++ glitz_drawable *drawable_b = glitz_surface_get_drawable (b->surface); ++ ++ return (drawable_a == drawable_b); ++} ++ + #define FIXED_TO_FLOAT(f) (((glitz_float_t) (f)) / 65536) + + static cairo_status_t +@@ -2194,7 +2207,16 @@ static const cairo_surface_backend_t cai + _cairo_glitz_surface_flush, + NULL, /* mark_dirty_rectangle */ + _cairo_glitz_surface_scaled_font_fini, +- _cairo_glitz_surface_scaled_glyph_fini ++ _cairo_glitz_surface_scaled_glyph_fini, ++ ++ NULL, /* paint */ ++ NULL, /* mask */ ++ NULL, /* stroke */ ++ NULL, /* fill */ ++ NULL, /* show_glyphs */ ++ ++ NULL, /* snapshot */ ++ _cairo_glitz_surface_is_compatible + }; + + static const cairo_surface_backend_t * +diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c +diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c +diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c +index b488d1f..28f8561 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,12 +1032,59 @@ _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) +- return CAIRO_STATUS_NO_MEMORY; ++ /* 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; ++ static int i = 0; ++ CAIRO_MUTEX_DECLARE (cache_lock); ++ ++ cairo_surface_t *surface; ++ cairo_status_t status; ++ ++ CAIRO_MUTEX_LOCK (cache_lock); ++ ++ /* Check cache first */ ++ if (i < cache_size) ++ if (_cairo_color_equal (&cache[i].color, &pattern->color) && ++ _cairo_surface_is_compatible (cache[i].surface, dst)) ++ goto DONE; ++ ++ for (i = 0; i < cache_size; i++) ++ if (_cairo_color_equal (&cache[i].color, &pattern->color) && ++ _cairo_surface_is_compatible (cache[i].surface, dst)) ++ 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) { ++ status = CAIRO_STATUS_NO_MEMORY; ++ ++ goto UNLOCK; ++ } ++ ++ /* Cache new */ ++ if (cache_size < MAX_CACHE_SIZE) ++ cache_size++; ++ else { ++ i = rand () % 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); +@@ -1043,7 +1092,13 @@ _cairo_pattern_acquire_surface_for_solid + attribs->filter = CAIRO_FILTER_NEAREST; + attribs->acquired = FALSE; + +- return CAIRO_STATUS_SUCCESS; ++ status = CAIRO_STATUS_SUCCESS; ++ ++UNLOCK: ++ ++ CAIRO_MUTEX_UNLOCK (cache_lock); ++ ++ return status; + } + + /** +diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c +diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c +diff --git a/src/cairo-surface.c b/src/cairo-surface.c +index 2bff0da..78cad9b 100644 +--- a/src/cairo-surface.c ++++ b/src/cairo-surface.c +@@ -1078,6 +1078,32 @@ _cairo_surface_snapshot (cairo_surface_t + return _cairo_surface_fallback_snapshot (surface); + } + ++/** ++ * _cairo_surface_is_compatible ++ * @surface_a: a #cairo_surface_t ++ * @surface_b: a #cairo_surface_t ++ * ++ * Find out whether the given surfaces share the same backend, ++ * and if so, whether they can be considered compatible. ++ * ++ * The definition of "compatible" depends on the backend. In the ++ * xlib case, it means the surfaces share the same display. ++ * ++ * Return value: TRUE if the surfaces are compatible. ++ **/ ++cairo_bool_t ++_cairo_surface_is_compatible (cairo_surface_t *surface_a, ++ cairo_surface_t *surface_b) ++{ ++ if (surface_a->backend != surface_b->backend) ++ return FALSE; ++ ++ if (surface_a->backend->is_compatible) ++ return surface_a->backend->is_compatible (surface_a, surface_b); ++ ++ return TRUE; ++} ++ + cairo_status_t + _cairo_surface_composite (cairo_operator_t op, + cairo_pattern_t *src, +diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c +index be7e706..81eb916 100644 +--- a/src/cairo-win32-surface.c ++++ b/src/cairo-win32-surface.c +@@ -1609,6 +1609,16 @@ _cairo_win32_surface_show_glyphs (void + return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED; + } + ++static cairo_bool_t ++_cairo_win32_surface_is_compatible (void *surface_a, ++ void *surface_b) ++{ ++ cairo_win32_surface_t *a = (cairo_win32_surface_t*) surface_a; ++ cairo_win32_surface_t *b = (cairo_win32_surface_t*) surface_b; ++ ++ return (a->dc == b->dc); ++} ++ + #undef STACK_GLYPH_SIZE + + /** +@@ -1879,7 +1889,8 @@ static const cairo_surface_backend_t cai + NULL, /* fill */ + _cairo_win32_surface_show_glyphs, + +- NULL /* snapshot */ ++ NULL, /* snapshot */ ++ _cairo_win32_surface_is_compatible + }; + + /* +diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c +index 2fdf8a1..8df859d 100644 +--- a/src/cairo-xcb-surface.c ++++ b/src/cairo-xcb-surface.c +@@ -1578,6 +1578,10 @@ _cairo_xcb_surface_show_glyphs (void + int num_glyphs, + cairo_scaled_font_t *scaled_font); + ++static cairo_bool_t ++_cairo_xcb_surface_is_compatible (void *surface_a, ++ void *surface_b); ++ + /* XXX: move this to the bottom of the file, XCB and Xlib */ + + static const cairo_surface_backend_t cairo_xcb_surface_backend = { +@@ -1609,7 +1613,8 @@ static const cairo_surface_backend_t cai + NULL, /* stroke */ + NULL, /* fill */ + _cairo_xcb_surface_show_glyphs, +- NULL /* snapshot */ ++ NULL, /* snapshot */ ++ _cairo_xcb_surface_is_compatible + }; + + /** +@@ -2451,3 +2456,13 @@ _cairo_xcb_surface_show_glyphs (void + + return status; + } ++ ++static cairo_bool_t ++_cairo_xcb_surface_is_compatible (void *surface_a, ++ void *surface_b) ++{ ++ cairo_xcb_surface_t *a = (cairo_xcb_surface_t*) surface_a; ++ cairo_xcb_surface_t *b = (cairo_xcb_surface_t*) surface_b; ++ ++ return (a->dpy == b->dpy); ++} +diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c +index 6a0d3e4..9228c95 100644 +--- a/src/cairo-xlib-surface.c ++++ b/src/cairo-xlib-surface.c +@@ -74,6 +74,10 @@ _cairo_xlib_surface_show_glyphs (void + int num_glyphs, + cairo_scaled_font_t *scaled_font); + ++static cairo_bool_t ++_cairo_xlib_surface_is_compatible (void *surface_a, ++ void *surface_b); ++ + /* + * Instead of taking two round trips for each blending request, + * assume that if a particular drawable fails GetImage that it will +@@ -1783,7 +1787,8 @@ static const cairo_surface_backend_t cai + NULL, /* stroke */ + NULL, /* fill */ + _cairo_xlib_surface_show_glyphs, +- NULL /* snapshot */ ++ NULL, /* snapshot */ ++ _cairo_xlib_surface_is_compatible + }; + + /** +@@ -2913,3 +2918,13 @@ _cairo_xlib_surface_show_glyphs (void + + return status; + } ++ ++static cairo_bool_t ++_cairo_xlib_surface_is_compatible (void *surface_a, ++ void *surface_b) ++{ ++ cairo_xlib_surface_t *a = (cairo_xlib_surface_t*) surface_a; ++ cairo_xlib_surface_t *b = (cairo_xlib_surface_t*) surface_b; ++ ++ return (a->dpy == b->dpy); ++} +diff --git a/src/cairo.c b/src/cairo.c +diff --git a/src/cairoint.h b/src/cairoint.h +index 060b988..01c0e2a 100755 +--- a/src/cairoint.h ++++ b/src/cairoint.h +@@ -933,6 +933,10 @@ struct _cairo_surface_backend { + + cairo_surface_t * + (*snapshot) (void *surface); ++ ++ cairo_bool_t ++ (*is_compatible) (void *surface_a, ++ void *surface_b); + }; + + typedef struct _cairo_format_masks { +@@ -1497,6 +1501,10 @@ _cairo_color_get_rgba_premultiplied (cai + double *blue, + double *alpha); + ++cairo_private cairo_bool_t ++_cairo_color_equal (cairo_color_t *color_a, ++ cairo_color_t *color_b); ++ + /* cairo-font.c */ + + cairo_private void +@@ -1922,6 +1930,10 @@ _cairo_surface_clone_similar (cairo_surf + cairo_private cairo_surface_t * + _cairo_surface_snapshot (cairo_surface_t *surface); + ++cairo_private cairo_bool_t ++_cairo_surface_is_compatible (cairo_surface_t *surface_a, ++ cairo_surface_t *surface_b); ++ + cairo_private unsigned int + _cairo_surface_get_current_clip_serial (cairo_surface_t *surface); + diff --git a/packages/cairo/files/cairo-surface-cache.patch b/packages/cairo/files/cairo-surface-cache.patch deleted file mode 100644 index ee9fc3a46e..0000000000 --- a/packages/cairo/files/cairo-surface-cache.patch +++ /dev/null @@ -1,91 +0,0 @@ -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; |