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@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 <[email protected]> > --- > 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; > _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
