ProcRenderAddGlyphs: Avoid allocating a glyph just to find it cached

This is a cleanup without any real savings (yet). Previously, the
implementation would allocate a new glyph, then (often) find it in
the cache, and immediately discard the allocated object. This
re-organization first uses a new FindGlyphByHash function and only
allocates the glyph if nothing is found.

This isn't a real savings yet, since FindGlyphByHash currently still
does a temporary glyph allocation, but this is expected to be replaced
immediately as we switch to an alternate hashing mechanism (SHA1).
This commit is contained in:
Carl Worth 2007-07-30 17:31:47 -07:00
parent 4c6abe1c7c
commit 516b96387b
3 changed files with 71 additions and 25 deletions

View File

@ -490,6 +490,31 @@ HashGlyph (GlyphPtr glyph)
glyph->size - sizeof (xGlyphInfo));
}
GlyphPtr
FindGlyphByHash (CARD32 hash,
xGlyphInfo *gi,
CARD8 *bits,
int format)
{
GlyphRefPtr gr;
GlyphPtr template;
/* XXX: Should handle out-of-memory here */
template = AllocateGlyph (gi, format);
memcpy ((CARD8 *) (template + 1), bits,
template->size - sizeof (xGlyphInfo));
gr = FindGlyphRef (&globalGlyphs[format],
hash, TRUE, template);
xfree (template);
if (gr->glyph && gr->glyph != DeletedGlyph)
return gr->glyph;
else
return NULL;
}
#ifdef CHECK_DUPLICATES
void
DuplicateRef (GlyphPtr glyph, char *where)
@ -572,7 +597,7 @@ AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
/* Locate existing matching glyph */
hash = HashGlyph (glyph);
gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph);
if (gr->glyph && gr->glyph != DeletedGlyph)
if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph)
{
PictureScreenPtr ps;
int i;
@ -588,7 +613,7 @@ AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
xfree (glyph);
glyph = gr->glyph;
}
else
else if (gr->glyph != glyph)
{
gr->glyph = glyph;
gr->signature = hash;

View File

@ -129,6 +129,12 @@ FindGlyphHashSet (CARD32 filled);
GlyphRefPtr
FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare);
GlyphPtr
FindGlyphByHash (CARD32 hash,
xGlyphInfo *gi,
CARD8 *bits,
int format);
CARD32
HashGlyphInfoAndBits (xGlyphInfo *gi, CARD8 *data, unsigned int size);

View File

@ -1082,6 +1082,8 @@ ProcRenderFreeGlyphSet (ClientPtr client)
typedef struct _GlyphNew {
Glyph id;
GlyphPtr glyph;
Bool found;
CARD32 hash;
} GlyphNewRec, *GlyphNewPtr;
static int
@ -1090,8 +1092,7 @@ ProcRenderAddGlyphs (ClientPtr client)
GlyphSetPtr glyphSet;
REQUEST(xRenderAddGlyphsReq);
GlyphNewRec glyphsLocal[NLOCALGLYPH];
GlyphNewPtr glyphsBase, glyphs;
GlyphPtr glyph;
GlyphNewPtr glyphsBase, glyphs, glyph_new;
int remain, nglyphs;
CARD32 *gids;
xGlyphInfo *gi;
@ -1115,11 +1116,13 @@ ProcRenderAddGlyphs (ClientPtr client)
if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec))
return BadAlloc;
if (nglyphs <= NLOCALGLYPH)
if (nglyphs <= NLOCALGLYPH) {
memset (glyphsLocal, 0, sizeof (glyphsLocal));
glyphsBase = glyphsLocal;
}
else
{
glyphsBase = (GlyphNewPtr) Xalloc (nglyphs * sizeof (GlyphNewRec));
glyphsBase = (GlyphNewPtr) Xcalloc (nglyphs * sizeof (GlyphNewRec));
if (!glyphsBase)
return BadAlloc;
}
@ -1134,26 +1137,41 @@ ProcRenderAddGlyphs (ClientPtr client)
remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs;
for (i = 0; i < nglyphs; i++)
{
glyph = AllocateGlyph (&gi[i], glyphSet->fdepth);
if (!glyph)
{
err = BadAlloc;
goto bail;
}
glyphs->glyph = glyph;
glyphs->id = gids[i];
size = glyph->size - sizeof (xGlyphInfo);
glyph_new = &glyphs[i];
size = gi[i].height * PixmapBytePad (gi[i].width,
glyphSet->format->depth);
if (remain < size)
break;
memcpy ((CARD8 *) (glyph + 1), bits, size);
glyph_new->hash = HashGlyphInfoAndBits (&gi[i], bits, size);
glyph_new->glyph = FindGlyphByHash (glyph_new->hash,
&gi[i], bits,
glyphSet->fdepth);
if (glyph_new->glyph && glyph_new->glyph != DeletedGlyph)
{
glyph_new->found = TRUE;
}
else
{
glyph_new->found = FALSE;
glyph_new->glyph = AllocateGlyph (&gi[i], glyphSet->fdepth);
if (! glyph_new->glyph)
{
err = BadAlloc;
goto bail;
}
memcpy ((CARD8 *) (glyph_new->glyph + 1), bits, size);
}
glyph_new->id = gids[i];
if (size & 3)
size += 4 - (size & 3);
bits += size;
remain -= size;
glyphs++;
}
if (remain || i < nglyphs)
{
@ -1165,7 +1183,6 @@ ProcRenderAddGlyphs (ClientPtr client)
err = BadAlloc;
goto bail;
}
glyphs = glyphsBase;
for (i = 0; i < nglyphs; i++)
AddGlyph (glyphSet, glyphs[i].glyph, glyphs[i].id);
@ -1173,11 +1190,9 @@ ProcRenderAddGlyphs (ClientPtr client)
Xfree (glyphsBase);
return client->noClientException;
bail:
while (glyphs != glyphsBase)
{
--glyphs;
xfree (glyphs->glyph);
}
for (i = 0; i < nglyphs; i++)
if (glyphs[i].glyph && ! glyphs[i].found)
xfree (glyphs[i].glyph);
if (glyphsBase != glyphsLocal)
Xfree (glyphsBase);
return err;