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)); 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 #ifdef CHECK_DUPLICATES
void void
DuplicateRef (GlyphPtr glyph, char *where) DuplicateRef (GlyphPtr glyph, char *where)
@ -572,7 +597,7 @@ AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
/* Locate existing matching glyph */ /* Locate existing matching glyph */
hash = HashGlyph (glyph); hash = HashGlyph (glyph);
gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, 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; PictureScreenPtr ps;
int i; int i;
@ -588,7 +613,7 @@ AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
xfree (glyph); xfree (glyph);
glyph = gr->glyph; glyph = gr->glyph;
} }
else else if (gr->glyph != glyph)
{ {
gr->glyph = glyph; gr->glyph = glyph;
gr->signature = hash; gr->signature = hash;

View File

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

View File

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