[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