diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2011-05-02 11:52:28 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2011-05-02 11:52:28 -0400 |
commit | 5eb61ac775cf5f81dbc28bb9f246e52fc4c45a0f (patch) | |
tree | 3cdfedff26090e05a444a69143c7463fe220e3ee | |
parent | b7be1a10d0d0e40bd303a090793808905562ee7b (diff) |
Initial glyph cachingrender
-rw-r--r-- | fb/fbpict.c | 132 | ||||
-rw-r--r-- | fb/fbtrap.c | 2 |
2 files changed, 133 insertions, 1 deletions
diff --git a/fb/fbpict.c b/fb/fbpict.c index d1fd0cbbd..a91fbfb54 100644 --- a/fb/fbpict.c +++ b/fb/fbpict.c @@ -34,6 +34,7 @@ #include "picturestr.h" #include "mipict.h" #include "fbpict.h" +#include "damage.h" void fbComposite (CARD8 op, @@ -351,6 +352,135 @@ free_pixman_pict (PicturePtr pict, pixman_image_t *image) fbFinishAccess (pict->pDrawable); } +#define N_STACK_GLYPHS (256) + +/* FIXME: clear this when the screen shuts down */ +static pixman_glyph_cache_t *glyph_cache; + +static void +fbUnrealizeGlyph (ScreenPtr pScreen, GlyphPtr pGlyph) +{ + if (glyph_cache) + pixman_glyph_cache_remove (glyph_cache, NULL, pGlyph); +} + +static void +fbGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + pixman_glyph_t stack_glyphs[N_STACK_GLYPHS]; + pixman_glyph_t *pglyphs = stack_glyphs; + ScreenPtr pScreen = pDst->pDrawable->pScreen; + int dst_xoff, dst_yoff; + int src_xoff, src_yoff; + pixman_image_t *src, *dst; + int i; + + if (!glyph_cache) + glyph_cache = pixman_glyph_cache_create(); + + src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff); + dst = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff); + + if (src && dst) + { + int x, y; + int n_glyphs = 0; + + for (i = 0; i < nlist; ++i) + n_glyphs += list[i].len; + + if (n_glyphs > N_STACK_GLYPHS) + { + if (!(pglyphs = malloc (n_glyphs * sizeof (pixman_glyph_t)))) + goto bail; + } + + n_glyphs = 0; + x = 0; + y = 0; + while (nlist--) + { + int n; + + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + + pixman_glyph_cache_freeze (glyph_cache); + while (n--) + { + GlyphPtr glyph = *glyphs++; + + if (!pixman_glyph_cache_contains (glyph_cache, NULL, glyph)) + { + pixman_image_t *glyph_image; + PicturePtr pPicture; + int gx, gy; + + pPicture = GlyphPicture (glyph)[pScreen->myNum]; + if (pPicture) + { + if (!(glyph_image = image_from_pict (pPicture, FALSE, &gx, &gy))) + goto bail; + + pixman_glyph_cache_insert (glyph_cache, NULL, glyph, glyph_image); + + free_pixman_pict (pPicture, glyph_image); + } + } + + pglyphs[n_glyphs].x = x - glyph->info.x; + pglyphs[n_glyphs].y = y - glyph->info.y; + pglyphs[n_glyphs].key = glyph; + n_glyphs++; + + x += glyph->info.xOff; + y += glyph->info.yOff; + } + pixman_glyph_cache_thaw (glyph_cache); + } + + /* FIXME: maybe be a little more precise here */ + DamageRegionAppend (pDst->pDrawable, pDst->pCompositeClip); + + if (maskFormat) + { + int bpp = maskFormat->depth; + + if (bpp == 24) + bpp = 32; + + pixman_composite_glyphs (op, src, dst, maskFormat->format | (bpp << 24), + xSrc, ySrc, dst_xoff, dst_yoff, + glyph_cache, NULL, n_glyphs, pglyphs); + } + else + { + pixman_composite_glyphs_no_mask (op, src, dst, + xSrc, ySrc, dst_xoff, dst_yoff, + glyph_cache, NULL, n_glyphs, pglyphs); + } + + DamageRegionProcessPending (pDst->pDrawable); + } + +bail: + if (pglyphs != stack_glyphs) + free (pglyphs); + + free_pixman_pict (pSrc, src); + free_pixman_pict (pDst, dst); +} + Bool fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) { @@ -368,6 +498,8 @@ fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) ps->AddTraps = fbAddTraps; ps->AddTriangles = fbAddTriangles; ps->Triangles = fbTriangles; + ps->Glyphs = fbGlyphs; + ps->UnrealizeGlyph = fbUnrealizeGlyph; return TRUE; } diff --git a/fb/fbtrap.c b/fb/fbtrap.c index 0b5a6382e..55942aac8 100644 --- a/fb/fbtrap.c +++ b/fb/fbtrap.c @@ -123,7 +123,7 @@ fbShapes (CompositeShapesFunc composite, pixman_format_code_t format; DamageRegionAppend (pDst->pDrawable, pDst->pCompositeClip); - + if (!maskFormat) { int i; |