[PATCH] Use new pixman_glyph_cache_t API that will be in pixman 0.28.0
Søren Sandmann
sandmann at cs.au.dk
Wed May 30 17:27:02 PDT 2012
From: Søren Sandmann Pedersen <ssp at redhat.com>
This new API allows glyphs to be cached in a data structure in pixman,
and entire glyph strings to be composited in one go.
Results from the cairo peformance test suite running against Xvfb with
a screen size of 1680x1050 at 32bpp:
Speedups
========
xlib firefox-talos-gfx 13669.42 -> 3717.03: 3.68x speedup
██▋
xlib xfce4-terminal-a1 1842.63 -> 1086.13: 1.70x speedup
▊
xlib evolution 1401.95 -> 897.70: 1.56x speedup
▌
xlib gnome-terminal-vim 1859.13 -> 1192.92: 1.56x speedup
▌
xlib poppler 1650.37 -> 1244.72: 1.33x speedup
▍
xlib firefox-planet-gnome 7300.14 -> 5751.90: 1.27x speedup
▎
xlib gvim 1385.19 -> 1284.40: 1.08x speedup
▏
No slowdowns were reported.
Results of x11perf -aa10text:
Before:
7200000 reps @ 0.0007 msec (1430000.0/sec)
7200000 reps @ 0.0007 msec (1420000.0/sec)
7200000 reps @ 0.0007 msec (1420000.0/sec)
7200000 reps @ 0.0007 msec (1420000.0/sec)
7200000 reps @ 0.0007 msec (1420000.0/sec)
36000000 trep @ 0.0007 msec (1420000.0/sec)
After:
32000000 reps @ 0.0002 msec (5310000.0/sec)
32000000 reps @ 0.0002 msec (5380000.0/sec)
32000000 reps @ 0.0002 msec (5310000.0/sec)
32000000 reps @ 0.0002 msec (5400000.0/sec)
32000000 reps @ 0.0002 msec (5290000.0/sec)
160000000 trep @ 0.0002 msec (5340000.0/sec)
---
fb/fbpict.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 142 insertions(+), 1 deletion(-)
diff --git a/fb/fbpict.c b/fb/fbpict.c
index 097a1a6..b58f476 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;
--
1.7.10.2
More information about the xorg-devel
mailing list