2
* $XFree86: xc/programs/Xserver/render/glyph.c,v 1.5 2001/01/30 07:01:22 keithp Exp $
4
* Copyright Ā© 2000 SuSE, Inc.
6
* Permission to use, copy, modify, distribute, and sell this software and its
7
* documentation for any purpose is hereby granted without fee, provided that
8
* the above copyright notice appear in all copies and that both that
9
* copyright notice and this permission notice appear in supporting
10
* documentation, and that the name of SuSE not be used in advertising or
11
* publicity pertaining to distribution of the software without specific,
12
* written prior permission. SuSE makes no representations about the
13
* suitability of this software for any purpose. It is provided "as is"
14
* without express or implied warranty.
16
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
18
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Author: Keith Packard, SuSE, Inc.
26
#ifdef HAVE_DIX_CONFIG_H
27
#include <dix-config.h>
31
#include "scrnintstr.h"
33
#include "regionstr.h"
35
#include "windowstr.h"
38
#include "colormapst.h"
39
#include "cursorstr.h"
40
#include "dixstruct.h"
43
#include "picturestr.h"
47
* From Knuth -- a good choice for hash/rehash values is p, p-2 where
48
* p and p-2 are both prime. These tables are sized to have an extra 10%
49
* free to avoid exponential performance degradation as the hash table fills
51
static GlyphHashSetRec glyphHashSets[] = {
61
{ 16384, 18043, 18041 },
62
{ 32768, 36109, 36107 },
63
{ 65536, 72091, 72089 },
64
{ 131072, 144409, 144407 },
65
{ 262144, 288361, 288359 },
66
{ 524288, 576883, 576881 },
67
{ 1048576, 1153459, 1153457 },
68
{ 2097152, 2307163, 2307161 },
69
{ 4194304, 4613893, 4613891 },
70
{ 8388608, 9227641, 9227639 },
71
{ 16777216, 18455029, 18455027 },
72
{ 33554432, 36911011, 36911009 },
73
{ 67108864, 73819861, 73819859 },
74
{ 134217728, 147639589, 147639587 },
75
{ 268435456, 295279081, 295279079 },
76
{ 536870912, 590559793, 590559791 }
79
#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0]))
81
const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 };
83
GlyphHashRec globalGlyphs[GlyphFormatNum];
85
int globalTotalGlyphPrivateSize = 0;
87
static int glyphPrivateCount = 0;
92
glyphPrivateCount = 0;
96
AllocateGlyphPrivateIndex ()
98
return glyphPrivateCount++;
102
AllocateGlyphPrivate (ScreenPtr pScreen,
109
ps = GetPictureScreenIfSet (pScreen);
113
/* Round up sizes for proper alignment */
114
amount = ((amount + (sizeof (DevUnion) - 1)) / sizeof (DevUnion)) *
117
if (index2 >= ps->glyphPrivateLen)
120
nsizes = (unsigned *) xrealloc (ps->glyphPrivateSizes,
121
(index2 + 1) * sizeof (unsigned));
125
while (ps->glyphPrivateLen <= index2)
127
nsizes[ps->glyphPrivateLen++] = 0;
128
ps->totalGlyphPrivateSize += sizeof (DevUnion);
130
ps->glyphPrivateSizes = nsizes;
132
oldamount = ps->glyphPrivateSizes[index2];
133
if (amount > oldamount)
135
ps->glyphPrivateSizes[index2] = amount;
136
ps->totalGlyphPrivateSize += (amount - oldamount);
138
ps->totalGlyphPrivateSize = BitmapBytePad (ps->totalGlyphPrivateSize * 8);
144
SetGlyphScreenPrivateOffsets (void)
150
for (i = 0; i < screenInfo.numScreens; i++)
152
ps = GetPictureScreenIfSet (screenInfo.screens[i]);
153
if (ps && ps->totalGlyphPrivateSize)
155
ps->glyphPrivateOffset = offset;
156
offset += ps->totalGlyphPrivateSize / sizeof (DevUnion);
162
SetGlyphPrivatePointers (GlyphPtr glyph)
172
for (i = 0; i < screenInfo.numScreens; i++)
174
ps = GetPictureScreenIfSet (screenInfo.screens[i]);
175
if (ps && ps->totalGlyphPrivateSize)
177
ppriv = glyph->devPrivates + ps->glyphPrivateOffset;
178
sizes = ps->glyphPrivateSizes;
179
ptr = (char *) (ppriv + ps->glyphPrivateLen);
180
for (len = ps->glyphPrivateLen; --len >= 0; ppriv++, sizes++)
182
if ((size = *sizes) != 0)
184
ppriv->ptr = (pointer) ptr;
188
ppriv->ptr = (pointer) 0;
195
ReallocGlobalGlyphPrivate (GlyphPtr glyph)
198
DevUnion *devPrivates;
202
devPrivates = xalloc (globalTotalGlyphPrivateSize);
206
ptr = (char *) devPrivates;
207
for (i = 0; i < screenInfo.numScreens; i++)
209
ps = GetPictureScreenIfSet (screenInfo.screens[i]);
210
if (ps && ps->totalGlyphPrivateSize)
212
if (ps->glyphPrivateOffset != -1)
214
memcpy (ptr, glyph->devPrivates + ps->glyphPrivateOffset,
215
ps->totalGlyphPrivateSize);
217
else if (ps->totalGlyphPrivateSize)
219
memset (ptr, 0, ps->totalGlyphPrivateSize);
222
ptr += ps->totalGlyphPrivateSize;
226
if (glyph->devPrivates)
227
xfree (glyph->devPrivates);
229
glyph->devPrivates = devPrivates;
235
GlyphInit (ScreenPtr pScreen)
237
PictureScreenPtr ps = GetPictureScreen (pScreen);
239
ps->totalGlyphPrivateSize = 0;
240
ps->glyphPrivateSizes = 0;
241
ps->glyphPrivateLen = 0;
242
ps->glyphPrivateOffset = -1;
248
GlyphFinishInit (ScreenPtr pScreen)
250
PictureScreenPtr ps = GetPictureScreen (pScreen);
252
if (ps->totalGlyphPrivateSize)
257
globalTotalGlyphPrivateSize += ps->totalGlyphPrivateSize;
259
for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
261
if (!globalGlyphs[fdepth].hashSet)
264
for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
266
glyph = globalGlyphs[fdepth].table[i].glyph;
267
if (glyph && glyph != DeletedGlyph)
269
if (!ReallocGlobalGlyphPrivate (glyph))
275
SetGlyphScreenPrivateOffsets ();
277
for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
279
if (!globalGlyphs[fdepth].hashSet)
282
for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
284
glyph = globalGlyphs[fdepth].table[i].glyph;
285
if (glyph && glyph != DeletedGlyph)
287
SetGlyphPrivatePointers (glyph);
289
if (!(*ps->RealizeGlyph) (pScreen, glyph))
296
ps->glyphPrivateOffset = 0;
302
GlyphUninit (ScreenPtr pScreen)
304
PictureScreenPtr ps = GetPictureScreen (pScreen);
308
globalTotalGlyphPrivateSize -= ps->totalGlyphPrivateSize;
310
for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
312
if (!globalGlyphs[fdepth].hashSet)
315
for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
317
glyph = globalGlyphs[fdepth].table[i].glyph;
318
if (glyph && glyph != DeletedGlyph)
320
(*ps->UnrealizeGlyph) (pScreen, glyph);
322
if (globalTotalGlyphPrivateSize)
324
if (!ReallocGlobalGlyphPrivate (glyph))
329
if (glyph->devPrivates)
330
xfree (glyph->devPrivates);
331
glyph->devPrivates = NULL;
337
if (globalTotalGlyphPrivateSize)
338
SetGlyphScreenPrivateOffsets ();
340
for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
342
if (!globalGlyphs[fdepth].hashSet)
345
for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
347
glyph = globalGlyphs[fdepth].table[i].glyph;
348
if (glyph && glyph != DeletedGlyph)
350
if (globalTotalGlyphPrivateSize)
351
SetGlyphPrivatePointers (glyph);
356
if (ps->glyphPrivateSizes)
357
xfree (ps->glyphPrivateSizes);
361
FindGlyphHashSet (CARD32 filled)
365
for (i = 0; i < NGLYPHHASHSETS; i++)
366
if (glyphHashSets[i].entries >= filled)
367
return &glyphHashSets[i];
371
static int _GlyphSetPrivateAllocateIndex = 0;
374
AllocateGlyphSetPrivateIndex (void)
376
return _GlyphSetPrivateAllocateIndex++;
380
ResetGlyphSetPrivateIndex (void)
382
_GlyphSetPrivateAllocateIndex = 0;
386
_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr)
390
if (n > glyphSet->maxPrivate) {
391
if (glyphSet->devPrivates &&
392
glyphSet->devPrivates != (pointer)(&glyphSet[1])) {
393
new = (pointer *) xrealloc (glyphSet->devPrivates,
394
(n + 1) * sizeof (pointer));
398
new = (pointer *) xalloc ((n + 1) * sizeof (pointer));
401
if (glyphSet->devPrivates)
403
glyphSet->devPrivates,
404
(glyphSet->maxPrivate + 1) * sizeof (pointer));
406
glyphSet->devPrivates = new;
407
/* Zero out new, uninitialize privates */
408
while (++glyphSet->maxPrivate < n)
409
glyphSet->devPrivates[glyphSet->maxPrivate] = (pointer)0;
411
glyphSet->devPrivates[n] = ptr;
416
FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare)
420
GlyphRefPtr table, gr, del;
421
CARD32 tableSize = hash->hashSet->size;
424
elt = signature % tableSize;
438
if (glyph == DeletedGlyph)
445
else if (s == signature &&
447
memcmp (&compare->info, &glyph->info, compare->size) == 0))
453
step = signature % hash->hashSet->rehash;
458
if (elt >= tableSize)
465
HashGlyph (GlyphPtr glyph)
467
CARD32 *bits = (CARD32 *) &(glyph->info);
469
int n = glyph->size / sizeof (CARD32);
477
#ifdef CHECK_DUPLICATES
479
DuplicateRef (GlyphPtr glyph, char *where)
481
ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where);
485
CheckDuplicates (GlyphHashPtr hash, char *where)
490
for (i = 0; i < hash->hashSet->size; i++)
492
g = hash->table[i].glyph;
493
if (!g || g == DeletedGlyph)
495
for (j = i + 1; j < hash->hashSet->size; j++)
496
if (hash->table[j].glyph == g)
497
DuplicateRef (g, where);
501
#define CheckDuplicates(a,b)
502
#define DuplicateRef(a,b)
506
FreeGlyph (GlyphPtr glyph, int format)
508
CheckDuplicates (&globalGlyphs[format], "FreeGlyph");
509
if (--glyph->refcnt == 0)
517
for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
518
if (globalGlyphs[format].table[i].glyph == glyph)
521
DuplicateRef (glyph, "FreeGlyph check");
525
gr = FindGlyphRef (&globalGlyphs[format],
526
HashGlyph (glyph), TRUE, glyph);
527
if (gr - globalGlyphs[format].table != first)
528
DuplicateRef (glyph, "Found wrong one");
529
if (gr->glyph && gr->glyph != DeletedGlyph)
531
gr->glyph = DeletedGlyph;
533
globalGlyphs[format].tableEntries--;
536
for (i = 0; i < screenInfo.numScreens; i++)
538
ps = GetPictureScreenIfSet (screenInfo.screens[i]);
540
(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
543
if (glyph->devPrivates)
544
xfree (glyph->devPrivates);
550
AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
555
CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
556
/* Locate existing matching glyph */
557
hash = HashGlyph (glyph);
558
gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph);
559
if (gr->glyph && gr->glyph != DeletedGlyph)
564
for (i = 0; i < screenInfo.numScreens; i++)
566
ps = GetPictureScreenIfSet (screenInfo.screens[i]);
568
(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
570
if (glyph->devPrivates)
571
xfree (glyph->devPrivates);
578
gr->signature = hash;
579
globalGlyphs[glyphSet->fdepth].tableEntries++;
582
/* Insert/replace glyphset value */
583
gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
585
if (gr->glyph && gr->glyph != DeletedGlyph)
586
FreeGlyph (gr->glyph, glyphSet->fdepth);
588
glyphSet->hash.tableEntries++;
591
CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
595
DeleteGlyph (GlyphSetPtr glyphSet, Glyph id)
600
gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
602
if (glyph && glyph != DeletedGlyph)
604
gr->glyph = DeletedGlyph;
605
glyphSet->hash.tableEntries--;
606
FreeGlyph (glyph, glyphSet->fdepth);
613
FindGlyph (GlyphSetPtr glyphSet, Glyph id)
617
glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph;
618
if (glyph == DeletedGlyph)
624
AllocateGlyph (xGlyphInfo *gi, int fdepth)
631
size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]);
632
glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec));
636
glyph->size = size + sizeof (xGlyphInfo);
639
if (globalTotalGlyphPrivateSize)
641
glyph->devPrivates = xalloc (globalTotalGlyphPrivateSize);
642
if (!glyph->devPrivates)
645
SetGlyphPrivatePointers (glyph);
647
glyph->devPrivates = NULL;
649
for (i = 0; i < screenInfo.numScreens; i++)
651
ps = GetPictureScreenIfSet (screenInfo.screens[i]);
654
if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph))
658
ps = GetPictureScreenIfSet (screenInfo.screens[i]);
660
(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
663
if (glyph->devPrivates)
664
xfree (glyph->devPrivates);
675
AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet)
677
hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec));
680
memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec));
681
hash->hashSet = hashSet;
682
hash->tableEntries = 0;
687
ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global)
690
GlyphHashSetPtr hashSet;
691
GlyphHashRec newHash;
698
tableEntries = hash->tableEntries + change;
699
hashSet = FindGlyphHashSet (tableEntries);
700
if (hashSet == hash->hashSet)
703
CheckDuplicates (hash, "ResizeGlyphHash top");
704
if (!AllocateGlyphHash (&newHash, hashSet))
708
oldSize = hash->hashSet->size;
709
for (i = 0; i < oldSize; i++)
711
glyph = hash->table[i].glyph;
712
if (glyph && glyph != DeletedGlyph)
714
s = hash->table[i].signature;
715
gr = FindGlyphRef (&newHash, s, global, glyph);
718
++newHash.tableEntries;
725
CheckDuplicates (hash, "ResizeGlyphHash bottom");
730
ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change)
732
return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) &&
733
ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE));
737
AllocateGlyphSet (int fdepth, PictFormatPtr format)
739
GlyphSetPtr glyphSet;
742
if (!globalGlyphs[fdepth].hashSet)
744
if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0]))
748
size = (sizeof (GlyphSetRec) +
749
(sizeof (pointer) * _GlyphSetPrivateAllocateIndex));
750
glyphSet = xalloc (size);
753
bzero((char *)glyphSet, size);
754
glyphSet->maxPrivate = _GlyphSetPrivateAllocateIndex - 1;
755
if (_GlyphSetPrivateAllocateIndex)
756
glyphSet->devPrivates = (pointer)(&glyphSet[1]);
758
if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0]))
763
glyphSet->refcnt = 1;
764
glyphSet->fdepth = fdepth;
765
glyphSet->format = format;
770
FreeGlyphSet (pointer value,
773
GlyphSetPtr glyphSet = (GlyphSetPtr) value;
775
if (--glyphSet->refcnt == 0)
777
CARD32 i, tableSize = glyphSet->hash.hashSet->size;
778
GlyphRefPtr table = glyphSet->hash.table;
781
for (i = 0; i < tableSize; i++)
783
glyph = table[i].glyph;
784
if (glyph && glyph != DeletedGlyph)
785
FreeGlyph (glyph, glyphSet->fdepth);
787
if (!globalGlyphs[glyphSet->fdepth].tableEntries)
789
xfree (globalGlyphs[glyphSet->fdepth].table);
790
globalGlyphs[glyphSet->fdepth].table = 0;
791
globalGlyphs[glyphSet->fdepth].hashSet = 0;
794
ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE);
797
if (glyphSet->devPrivates &&
798
glyphSet->devPrivates != (pointer)(&glyphSet[1]))
799
xfree(glyphSet->devPrivates);