[PATCH] Use new pixman_glyph_cache_t API that will be in pixman 0.28.0
Aaron Plattner
aplattner at nvidia.com
Wed Sep 12 07:33:02 PDT 2012
I ran some cairo-perf-trace numbers on Xorg with an accelerated driver.
xorg-server-1.13.0, glyph cache disabled:
[ # ] backend test min(s) median(s) stddev. count
[ 0] xlib firefox-particles 40.857 40.865 0.02% 6/6
[ 1] xlib firefox-paintball 11.768 11.808 0.19% 6/6
[ 2] xlib firefox-canvas-alpha 16.479 16.526 0.12% 5/6
[ 3] xlib poppler 11.352 11.366 0.14% 6/6
[ 4] xlib firefox-fishtank 17.543 18.228 1.71% 6/6
[ 5] xlib grads-heat-map 1.027 1.029 0.39% 6/6
[ 6] xlib firefox-planet-gnome 65.004 65.774 0.52% 6/6
[ 7] xlib firefox-asteroids 5.264 5.351 0.73% 6/6
[ 8] xlib gvim 32.072 32.174 0.13% 6/6
[ 9] xlib firefox-fishbowl 21.931 22.005 0.22% 6/6
[ 10] xlib xfce4-terminal-a1 52.258 52.264 0.01% 6/6
[ 11] xlib swfdec-youtube 1.145 1.151 0.64% 6/6
[ 12] xlib gnome-system-monitor 0.981 0.985 0.44% 6/6
[ 13] xlib firefox-talos-gfx 289.889 290.303 0.06% 6/6
[ 14] xlib firefox-canvas 19.338 19.432 0.25% 6/6
[ 15] xlib chromium-tabs 0.882 0.882 0.23% 6/6
[ 16] xlib ocitysmap 2.443 2.449 0.20% 6/6
[ 17] xlib firefox-chalkboard 40.415 40.523 0.21% 6/6
[ 18] xlib swfdec-giant-steps 0.943 0.951 0.38% 6/6
[ 19] xlib gnome-terminal-vim 52.718 53.061 0.30% 6/6
[ 20] xlib midori-zoomed 2.273 2.333 1.90% 6/6
[ 21] xlib poppler-reseau 1.310 1.320 0.47% 6/6
[ 22] xlib firefox-scrolling 43.793 43.857 0.07% 6/6
[ 23] xlib evolution 22.583 22.641 0.41% 6/6
[ 24] xlib firefox-talos-svg 9.642 9.675 0.21% 6/6
Patched server, glyph cache disabled:
[ # ] backend test min(s) median(s) stddev. count
[ 0] xlib firefox-particles 43.594 43.776 0.17% 6/6
[ 1] xlib firefox-paintball 168.643 231.273 18.26% 15/15
[ 2] xlib firefox-canvas-alpha 23.311 26.393 7.42% 15/15
[ 3] xlib poppler 51.008 297.202 78.74% 15/15
[ 4] xlib firefox-fishtank 21.156 22.360 3.15% 9/10
[ 5] xlib grads-heat-map 1.281 1.293 1.18% 6/6
[ 6] xlib firefox-planet-gnome 329.353 409.242 23.40% 13/15
[ 7] xlib firefox-asteroids 6.670 8.161 30.56% 13/15
[ 8] xlib gvim 84.067 123.407 22.94% 15/15
[ 9] xlib firefox-fishbowl 26.213 32.346 22.61% 14/15
[ 10] xlib xfce4-terminal-a1 28.574 52.436 54.31% 14/15
[ 11] xlib swfdec-youtube 1.282 1.338 4.44% 6/6
[ 12] xlib gnome-system-monitor 1.642 1.937 10.61% 12/15
[ 13] xlib firefox-talos-gfx 2220.084 10429.123 54.35% 6/62 (killed due to impatience)
[ 1] xlib firefox-canvas 22.100 22.502 0.83% 6/6
[ 2] xlib chromium-tabs 0.950 1.744 37.14% 15/15
[ 3] xlib ocitysmap 3.102 3.432 8.10% 13/15
[ 4] xlib firefox-chalkboard 42.544 45.774 4.40% 11/11
[ 5] xlib swfdec-giant-steps 1.057 1.078 0.86% 6/6
[ 6] xlib gnome-terminal-vim 233.452 456.153 69.32% 15/15
[ 7] xlib midori-zoomed 11.872 17.229 13.06% 12/15
[ 8] xlib poppler-reseau 1.775 1.857 3.89% 6/6
[ 9] xlib firefox-scrolling 563.500 654.048 21.18% 13/15
[ 10] xlib evolution 76.294 133.114 33.33% 13/15
[ 11] xlib firefox-talos-svg 19.806 22.824 19.78% 13/15
That's pretty dire. Thankfully, the glyph cache is enabled by default and works most of the time, but there are a few corner cases where it might fall back and this seems like a pretty severe penalty for that happening.
-- Aaron
On 09/06/2012 04:45 PM, Søren Sandmann Pedersen wrote:
> This new API allows glyphs to be cached in a data structure in pixman,
> and entire glyph strings to be composited in one go.
>
> Also bump pixman dependency to 0.27.2.
>
> Results from the cairo peformance test suite running against Xvfb with
> a screen size of 1680x1050 at 32bpp:
>
> Speedups
> ========
> xlib firefox-talos-gfx 12416.63 -> 3603.93 3.45x speedup
> ██▌
> xlib xfce4-terminal-a1 1727.57 -> 1048.85: 1.65x speedup
> ▋
> xlib evolution 1370.49 -> 869.34: 1.58x speedup
> ▋
> xlib gnome-terminal-vim 1832.83 -> 1251.94: 1.46x speedup
> ▌
> xlib poppler 1519.70 -> 1204.05: 1.26x speedup
> ▎
> xlib firefox-planet-gnome 6982.55 -> 5598.16: 1.25x speedup
> ▎
> xlib ocitysmap 1142.77 -> 1071.53: 1.07x speedup
> ▏
>
> No slowdowns were reported.
>
> Results of x11perf -aa10text:
>
> Before:
>
> 8000000 reps @ 0.0007 msec (1450000.0/sec)
> 8000000 reps @ 0.0007 msec (1460000.0/sec)
> 8000000 reps @ 0.0007 msec (1460000.0/sec)
> 8000000 reps @ 0.0007 msec (1470000.0/sec)
> 8000000 reps @ 0.0007 msec (1480000.0/sec)
> 40000000 trep @ 0.0007 msec (1460000.0/sec)
>
> After:
>
> 32000000 reps @ 0.0002 msec (4910000.0/sec)
> 32000000 reps @ 0.0002 msec (4830000.0/sec)
> 32000000 reps @ 0.0002 msec (4890000.0/sec)
> 32000000 reps @ 0.0002 msec (4830000.0/sec)
> 32000000 reps @ 0.0002 msec (4900000.0/sec)
> 160000000 trep @ 0.0002 msec (4870000.0/sec)
>
> Signed-off-by: Soren Sandmann <ssp at redhat.com>
> ---
> configure.ac | 2 +-
> fb/fbpict.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 143 insertions(+), 2 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index ac3bf26..ca1b438 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -812,7 +812,7 @@ LIBPCIACCESS="pciaccess >= 0.12.901"
> LIBUDEV="libudev >= 143"
> LIBSELINUX="libselinux >= 2.0.86"
> LIBDBUS="dbus-1 >= 1.0"
> -LIBPIXMAN="pixman-1 >= 0.21.8"
> +LIBPIXMAN="pixman-1 >= 0.27.2"
>
> dnl Pixman is always required, but we separate it out so we can link
> dnl specific modules against it
> diff --git a/fb/fbpict.c b/fb/fbpict.c
> index 097a1a6..a70fa18 100644
> --- a/fb/fbpict.c
> +++ b/fb/fbpict.c
> @@ -70,6 +70,146 @@ fbComposite(CARD8 op,
> free_pixman_pict(pDst, dest);
> }
>
> +static pixman_glyph_cache_t *glyphCache;
> +
> +static void
> +fbUnrealizeGlyph(ScreenPtr pScreen,
> + GlyphPtr pGlyph)
> +{
> + if (glyphCache)
> + pixman_glyph_cache_remove (glyphCache, pGlyph, NULL);
> +}
> +
> +static void
> +fbGlyphs(CARD8 op,
> + PicturePtr pSrc,
> + PicturePtr pDst,
> + PictFormatPtr maskFormat,
> + INT16 xSrc,
> + INT16 ySrc, int nlist,
> + GlyphListPtr list,
> + GlyphPtr *glyphs)
> +{
> +#define N_STACK_GLYPHS 512
> + ScreenPtr pScreen = pDst->pDrawable->pScreen;
> + pixman_glyph_t stack_glyphs[N_STACK_GLYPHS];
> + pixman_glyph_t *pglyphs = stack_glyphs;
> + pixman_image_t *srcImage, *dstImage;
> + int srcXoff, srcYoff, dstXoff, dstYoff;
> + GlyphPtr glyph;
> + int n_glyphs;
> + int x, y;
> + int i, n;
> + int xDst = list->xOff, yDst = list->yOff;
> +
> + miCompositeSourceValidate(pSrc);
> +
> + n_glyphs = 0;
> + for (i = 0; i < nlist; ++i)
> + n_glyphs += list[i].len;
> +
> + if (!glyphCache)
> + glyphCache = pixman_glyph_cache_create();
> +
> + pixman_glyph_cache_freeze (glyphCache);
> +
> + if (n_glyphs > N_STACK_GLYPHS) {
> + if (!(pglyphs = malloc (n_glyphs * sizeof (pixman_glyph_t))))
> + goto out;
> + }
> +
> + i = 0;
> + x = y = 0;
> + while (nlist--) {
> + x += list->xOff;
> + y += list->yOff;
> + n = list->len;
> + while (n--) {
> + const void *g;
> +
> + glyph = *glyphs++;
> +
> + if (!(g = pixman_glyph_cache_lookup (glyphCache, glyph, NULL))) {
> + pixman_image_t *glyphImage;
> + PicturePtr pPicture;
> + int xoff, yoff;
> +
> + pPicture = GetGlyphPicture(glyph, pScreen);
> + if (!pPicture) {
> + n_glyphs--;
> + goto next;
> + }
> +
> + if (!(glyphImage = image_from_pict(pPicture, FALSE, &xoff, &yoff)))
> + goto out;
> +
> + g = pixman_glyph_cache_insert(glyphCache, glyph, NULL,
> + glyph->info.x,
> + glyph->info.y,
> + glyphImage);
> +
> + free_pixman_pict(pPicture, glyphImage);
> +
> + if (!g)
> + goto out;
> + }
> +
> + pglyphs[i].x = x;
> + pglyphs[i].y = y;
> + pglyphs[i].glyph = g;
> + i++;
> +
> + next:
> + x += glyph->info.xOff;
> + y += glyph->info.yOff;
> + }
> + list++;
> + }
> +
> + if (!(srcImage = image_from_pict(pSrc, FALSE, &srcXoff, &srcYoff)))
> + goto out;
> +
> + if (!(dstImage = image_from_pict(pDst, TRUE, &dstXoff, &dstYoff)))
> + goto out_free_src;
> +
> + if (maskFormat) {
> + pixman_format_code_t format;
> + pixman_box32_t extents;
> + int x, y;
> +
> + format = maskFormat->format | (maskFormat->depth << 24);
> +
> + pixman_glyph_get_extents(glyphCache, n_glyphs, pglyphs, &extents);
> +
> + x = extents.x1;
> + y = extents.y1;
> +
> + pixman_composite_glyphs(op, srcImage, dstImage, format,
> + xSrc + srcXoff + xDst, ySrc + srcYoff + yDst,
> + x, y,
> + x + dstXoff, y + dstYoff,
> + extents.x2 - extents.x1,
> + extents.y2 - extents.y1,
> + glyphCache, n_glyphs, pglyphs);
> + }
> + else {
> + pixman_composite_glyphs_no_mask(op, srcImage, dstImage,
> + xSrc + srcXoff - xDst, ySrc + srcYoff - yDst,
> + dstXoff, dstYoff,
> + glyphCache, n_glyphs, pglyphs);
> + }
> +
> + free_pixman_pict(pDst, dstImage);
> +
> +out_free_src:
> + free_pixman_pict(pSrc, srcImage);
> +
> +out:
> + pixman_glyph_cache_thaw(glyphCache);
> + if (pglyphs != stack_glyphs)
> + free(pglyphs);
> +}
> +
> static pixman_image_t *
> create_solid_fill_image(PicturePtr pict)
> {
> @@ -357,7 +497,8 @@ fbPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
> return FALSE;
> ps = GetPictureScreen(pScreen);
> ps->Composite = fbComposite;
> - ps->Glyphs = miGlyphs;
> + ps->Glyphs = fbGlyphs;
> + ps->UnrealizeGlyph = fbUnrealizeGlyph;
> ps->CompositeRects = miCompositeRects;
> ps->RasterizeTrapezoid = fbRasterizeTrapezoid;
> ps->Trapezoids = fbTrapezoids;
>
More information about the xorg-devel
mailing list